dead simple printf/sprintf implementation.
authorMinep <zelong56@gmail.com>
Wed, 23 Feb 2022 22:56:44 +0000 (22:56 +0000)
committerMinep <zelong56@gmail.com>
Wed, 23 Feb 2022 22:56:44 +0000 (22:56 +0000)
.gitignore
lunaix-os/.gitignore
lunaix-os/includes/libc/stdio.h [new file with mode: 0644]
lunaix-os/includes/libc/stdlib.h [new file with mode: 0644]
lunaix-os/includes/libc/string.h
lunaix-os/libs/libc/stdio/printf.c [new file with mode: 0644]
lunaix-os/libs/libc/stdio/sprintf.c [new file with mode: 0644]
lunaix-os/libs/libc/stdlib/itoa.c [new file with mode: 0644]
lunaix-os/libs/libc/string/strcpy.c [new file with mode: 0644]

index a9823a8f05fbe7cd86f4ba9d26398184d8131f58..1aeeb0187411c4ae3e0f3da53a472ebfc7143e4a 100644 (file)
@@ -1,3 +1,4 @@
 slide-resources
 **/.~lock*
 workspace
 slide-resources
 **/.~lock*
 workspace
+playground/
index 6ea7e38e2423c451993953bc0ed8d1613ee100e7..a92c714f805658528d7699b36ac715fbf8401061 100644 (file)
@@ -1,3 +1,3 @@
-dump*
 build/
 build/
+playground/
 .vscode/settings.json
 .vscode/settings.json
diff --git a/lunaix-os/includes/libc/stdio.h b/lunaix-os/includes/libc/stdio.h
new file mode 100644 (file)
index 0000000..65edb9e
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef __LUNAIX_STDIO_H
+#define __LUNAIX_STDIO_H
+#include <stdarg.h>
+
+#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 (file)
index 0000000..05509cd
--- /dev/null
@@ -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 */
index eeade755e200695d7254529fa8bf15a15f0846b7..671fdec08089d0bfa51303a4db6ea057bf55be73 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _STRING_H
-#define _STRING_H 1
+#ifndef __LUNAIX_STRING_H
+#define __LUNAIX_STRING_H
 
 #include <stddef.h>
 
 
 #include <stddef.h>
 
@@ -18,4 +18,7 @@ memset(void*, int, size_t);
 size_t
 strlen(const char* str);
 
 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 (file)
index 0000000..0b3865f
--- /dev/null
@@ -0,0 +1,18 @@
+#define __LUNAIX_LIBC
+#include <libc/stdio.h>
+#include <stdarg.h>
+
+#include <lunaix/tty/tty.h>
+
+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 (file)
index 0000000..15a7fe2
--- /dev/null
@@ -0,0 +1,93 @@
+#define __LUNAIX_LIBC
+#include <libc/stdio.h>
+#include <libc/stdlib.h>
+#include <libc/string.h>
+#include <stdint.h>
+
+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 (file)
index 0000000..3d0699e
--- /dev/null
@@ -0,0 +1,54 @@
+#define __LUNAIX_LIBC
+#include <libc/stdlib.h>
+
+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 (file)
index 0000000..0649802
--- /dev/null
@@ -0,0 +1,14 @@
+#include <libc/string.h>
+
+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