From 84d85ea7b7bba78431600369cf1717166e156cd0 Mon Sep 17 00:00:00 2001 From: Minep Date: Wed, 23 Feb 2022 22:56:44 +0000 Subject: [PATCH 1/1] dead simple printf/sprintf implementation. --- .gitignore | 1 + lunaix-os/.gitignore | 2 +- lunaix-os/includes/libc/stdio.h | 12 ++++ lunaix-os/includes/libc/stdlib.h | 10 ++++ lunaix-os/includes/libc/string.h | 9 ++- lunaix-os/libs/libc/stdio/printf.c | 18 ++++++ lunaix-os/libs/libc/stdio/sprintf.c | 93 +++++++++++++++++++++++++++++ lunaix-os/libs/libc/stdlib/itoa.c | 54 +++++++++++++++++ lunaix-os/libs/libc/string/strcpy.c | 14 +++++ 9 files changed, 209 insertions(+), 4 deletions(-) create mode 100644 lunaix-os/includes/libc/stdio.h create mode 100644 lunaix-os/includes/libc/stdlib.h create mode 100644 lunaix-os/libs/libc/stdio/printf.c create mode 100644 lunaix-os/libs/libc/stdio/sprintf.c create mode 100644 lunaix-os/libs/libc/stdlib/itoa.c create mode 100644 lunaix-os/libs/libc/string/strcpy.c diff --git a/.gitignore b/.gitignore index a9823a8..1aeeb01 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ slide-resources **/.~lock* workspace +playground/ diff --git a/lunaix-os/.gitignore b/lunaix-os/.gitignore index 6ea7e38..a92c714 100644 --- a/lunaix-os/.gitignore +++ b/lunaix-os/.gitignore @@ -1,3 +1,3 @@ -dump* build/ +playground/ .vscode/settings.json diff --git a/lunaix-os/includes/libc/stdio.h b/lunaix-os/includes/libc/stdio.h new file mode 100644 index 0000000..65edb9e --- /dev/null +++ b/lunaix-os/includes/libc/stdio.h @@ -0,0 +1,12 @@ +#ifndef __LUNAIX_STDIO_H +#define __LUNAIX_STDIO_H +#include + +#ifdef __LUNAIX_LIBC +void __sprintf_internal(char* buffer, char* fmt, va_list args); +#endif + +void sprintf(char* buffer, char* fmt, ...); +void printf(char* fmt, ...); + +#endif /* __LUNAIX_STDIO_H */ diff --git a/lunaix-os/includes/libc/stdlib.h b/lunaix-os/includes/libc/stdlib.h new file mode 100644 index 0000000..05509cd --- /dev/null +++ b/lunaix-os/includes/libc/stdlib.h @@ -0,0 +1,10 @@ +#ifndef __LUNAIX_STDLIB_H +#define __LUNAIX_STDLIB_H + +#ifdef __LUNAIX_LIBC +char* __uitoa_internal(unsigned int value, char* str, int base, unsigned int* size); +char* __itoa_internal(int value, char* str, int base, unsigned int* size); +#endif +char* itoa(int value, char* str, int base); + +#endif /* __LUNAIX_STDLIB_H */ diff --git a/lunaix-os/includes/libc/string.h b/lunaix-os/includes/libc/string.h index eeade75..671fdec 100644 --- a/lunaix-os/includes/libc/string.h +++ b/lunaix-os/includes/libc/string.h @@ -1,5 +1,5 @@ -#ifndef _STRING_H -#define _STRING_H 1 +#ifndef __LUNAIX_STRING_H +#define __LUNAIX_STRING_H #include @@ -18,4 +18,7 @@ memset(void*, int, size_t); size_t strlen(const char* str); -#endif \ No newline at end of file +char* +strcpy(char* dest, const char* src); + +#endif /* __LUNAIX_STRING_H */ diff --git a/lunaix-os/libs/libc/stdio/printf.c b/lunaix-os/libs/libc/stdio/printf.c new file mode 100644 index 0000000..0b3865f --- /dev/null +++ b/lunaix-os/libs/libc/stdio/printf.c @@ -0,0 +1,18 @@ +#define __LUNAIX_LIBC +#include +#include + +#include + +void +printf(char* fmt, ...) +{ + char buffer[1024]; + va_list args; + va_start(args, fmt); + __sprintf_internal(buffer, fmt, args); + va_end(args); + + // 啊哈,直接操纵framebuffer。日后须改进(FILE* ?) + tty_put_str(buffer); +} \ No newline at end of file diff --git a/lunaix-os/libs/libc/stdio/sprintf.c b/lunaix-os/libs/libc/stdio/sprintf.c new file mode 100644 index 0000000..15a7fe2 --- /dev/null +++ b/lunaix-os/libs/libc/stdio/sprintf.c @@ -0,0 +1,93 @@ +#define __LUNAIX_LIBC +#include +#include +#include +#include + +void +__sprintf_internal(char* buffer, char* fmt, va_list args) +{ + char c; + int num; + unsigned int ptr = 0; + unsigned int adv = 0; + while ((c = *fmt)) { + if (c != '%') { + buffer[ptr] = c; + adv = 1; + } else { + adv = 0; + fmt++; + switch (c = *fmt) { + case 'c': { + buffer[ptr] = (char)va_arg(args, int); + adv = 1; + break; + } + case 's': { + char* str = va_arg(args, char*); + strcpy(buffer + ptr, str); + adv = strlen(str); + break; + } + case 'i': + // fall through + case 'd': { + num = va_arg(args, int); + __itoa_internal(num, buffer + ptr, 10, &adv); + break; + } + case 'u': { + unsigned int unum = va_arg(args, unsigned int); + __uitoa_internal(unum, buffer + ptr, 10, &adv); + break; + } + case 'o': { + num = va_arg(args, int); + __itoa_internal(num, buffer + ptr, 8, &adv); + break; + } + case 'x': + // fall through + case 'X': { + num = va_arg(args, int); + __itoa_internal(num, buffer + ptr, 16, &adv); + if (c == 'X') { + int p = ptr; + char c_; + while ((c_ = buffer[p])) { + buffer[p] = c_ & ~((c_ & 0x40) >> 1); + p++; + } + } + break; + } + case 'p': { + uintptr_t dptr = va_arg(args, uintptr_t); + __itoa_internal((int)dptr, buffer + ptr, 16, &adv); + break; + } + case '%': { + buffer[ptr] = c; + adv = 1; + break; + } + default: + // unknown + break; + } + } + fmt++; + ptr += adv; + } + buffer[ptr] = '\0'; +} + +void +sprintf(char* buffer, char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + __sprintf_internal(buffer, fmt, args); + va_end(args); +} \ No newline at end of file diff --git a/lunaix-os/libs/libc/stdlib/itoa.c b/lunaix-os/libs/libc/stdlib/itoa.c new file mode 100644 index 0000000..3d0699e --- /dev/null +++ b/lunaix-os/libs/libc/stdlib/itoa.c @@ -0,0 +1,54 @@ +#define __LUNAIX_LIBC +#include + +char base_char[] = "0123456789abcdefghijklmnopqrstuvwxyz"; + +char* +__uitoa_internal(unsigned int value, char* str, int base, unsigned int* size) +{ + unsigned int ptr = 0; + if (value == 0) { + str[0] = '0'; + ptr++; + } else { + while (value) { + str[ptr] = base_char[value % base]; + value = value / base; + ptr++; + } + + for (unsigned int i = 0; i < (ptr >> 1); i++) { + char c = str[i]; + str[i] = str[ptr - i - 1]; + str[ptr - i - 1] = c; + } + + } + str[ptr] = '\0'; + if (size) { + *size = ptr; + } + return str; +} + +char* +__itoa_internal(int value, char* str, int base, unsigned int* size) +{ + if (value < 0 && base == 10) { + unsigned int msk = value >> 31; + // evil bit level hack for abs() + unsigned int _v = (unsigned int)((value + msk) ^ msk); + str[0] = '-'; + __uitoa_internal(_v, str + 1, base, size); + } else { + __uitoa_internal(value, str, base, size); + } + + return str; +} + +char* +itoa(int value, char* str, int base) +{ + return __itoa_internal(value, str, base, (void*)0); +} \ No newline at end of file diff --git a/lunaix-os/libs/libc/string/strcpy.c b/lunaix-os/libs/libc/string/strcpy.c new file mode 100644 index 0000000..0649802 --- /dev/null +++ b/lunaix-os/libs/libc/string/strcpy.c @@ -0,0 +1,14 @@ +#include + +char* +strcpy(char* dest, const char* src) { + char c; + unsigned int i = 0; + while ((c = src[i])) + { + dest[i] = c; + i++; + } + dest[i] = '\0'; + return dest; +} \ No newline at end of file -- 2.27.0