瀏覽代碼

feat(gblibc): buffered io and printf

greatbridf 2 年之前
父節點
當前提交
652028e079
共有 5 個文件被更改,包括 228 次插入47 次删除
  1. 5 0
      gblibc/include/stdio.h
  2. 12 0
      gblibc/src/arithmetic.c
  3. 210 12
      gblibc/src/stdio.c
  4. 0 19
      user-space-program/lazybox.c
  5. 1 16
      user-space-program/sh.c

+ 5 - 0
gblibc/include/stdio.h

@@ -11,6 +11,8 @@
 extern "C" {
 #endif
 
+int putchar(int character);
+
 int puts(const char* str);
 char* gets(char* str);
 
@@ -18,6 +20,9 @@ int vsnprintf(char* buf, size_t bufsize, const char* fmt, va_list args);
 int snprintf(char* buf, size_t bufsize, const char* fmt, ...);
 int sprintf(char* buf, const char* fmt, ...);
 
+int vprintf(const char* fmt, va_list args);
+int printf(const char* fmt, ...);
+
 #ifdef __cplusplus
 }
 #endif

+ 12 - 0
gblibc/src/arithmetic.c

@@ -51,3 +51,15 @@ int64_t __moddi3(int64_t a, int64_t b)
     do_div_s(a, b, &remainder);
     return remainder;
 }
+
+uint64_t __udivdi3(uint64_t a, uint64_t b)
+{
+    return do_div(a, b, NULL);
+}
+
+uint64_t __umoddi3(uint64_t a, uint64_t b)
+{
+    uint64_t rem = 0;
+    do_div(a, b, &rem);
+    return rem;
+}

+ 210 - 12
gblibc/src/stdio.c

@@ -5,6 +5,23 @@
 #include <string.h>
 #include <unistd.h>
 
+#define BUFSIZ (4096)
+static char __stdout_buf[BUFSIZ];
+static size_t __stdout_buf_cnt;
+
+static inline void __buf_flush(void)
+{
+    write(STDOUT_FILENO, __stdout_buf, __stdout_buf_cnt);
+    __stdout_buf_cnt = 0;
+}
+
+static inline void __buf_put(int c)
+{
+    __stdout_buf[__stdout_buf_cnt++] = c;
+    if (__stdout_buf_cnt == BUFSIZ || c == '\n')
+        __buf_flush();
+}
+
 // where n is in the range of [0, 9]
 static inline char d_to_c(int32_t n)
 {
@@ -368,18 +385,14 @@ int sprintf(char* buf, const char* fmt, ...)
 
 int puts(const char* str)
 {
-    int len = 0;
-
-    int ret = write(STDOUT_FILENO, str, strlen(str));
-    if (ret < 0)
-        return EOF;
-    len += ret;
-
-    ret = write(STDOUT_FILENO, "\n", 1);
-    if (ret < 0)
-        return EOF;
-    len += ret;
-
+    // 1 is for \n at the end
+    int len = 1;
+
+    // TODO: FILE*
+    for (const char* p = str; *p; ++p, ++len)
+        __buf_put(*p);
+    
+    __buf_put('\n');
     return len;
 }
 
@@ -395,3 +408,188 @@ char* gets(char* buf)
     }
     return NULL;
 }
+
+int vprintf_u32(uint32_t num)
+{
+    if (num <= 9) {
+        __buf_put(d_to_c(num));
+        return 1;
+    }
+
+    int ret = vprintf_u32(num / 10);
+    __buf_put(d_to_c(num % 10));
+    return ret + 1;
+}
+
+int vprintf_d32(int32_t num)
+{
+    if (num < 0) {
+        __buf_put('-');
+        return vprintf_u32(-num) + 1;
+    }
+    return vprintf_u32(num);
+}
+
+int vprintf_u64(uint64_t num)
+{
+    if (num <= 9) {
+        __buf_put(d_to_c(num));
+        return 1;
+    }
+
+    int ret = vprintf_u64(num / 10);
+    __buf_put(d_to_c(num % 10));
+    return ret + 1;
+}
+
+int vprintf_d64(int64_t num)
+{
+    if (num < 0) {
+        __buf_put('-');
+        return vprintf_u64(-num) + 1;
+    }
+    return vprintf_u64(num);
+}
+
+int vprintf_x32(uint32_t num, int off)
+{
+    // print leading 0x
+    if (off & 1) {
+        --off;
+        __buf_put('0');
+        __buf_put('X' + off);
+        return vprintf_x32(num, off) + 2;
+    }
+
+    if (num <= 15) {
+        __buf_put(X_to_c(num) + off);
+        return 1;
+    }
+
+    int ret = vprintf_x32(num >> 4, off);
+    __buf_put(X_to_c(num & 0xf) + off);
+    return ret + 1;
+}
+
+int vprintf_x64(uint64_t num, int off)
+{
+    // print leading 0x
+    if (off & 1) {
+        --off;
+        __buf_put('0');
+        __buf_put('X' + off);
+        return vprintf_x64(num, off) + 2;
+    }
+
+    if (num <= 15) {
+        __buf_put(X_to_c(num) + off);
+        return 1;
+    }
+
+    int ret = vprintf_x64(num >> 4, off);
+    __buf_put(X_to_c(num & 0xf) + off);
+    return ret + 1;
+}
+
+int vprintf(const char* fmt, va_list args)
+{
+    int n = 0;
+
+    for (char c = 0; (c = *fmt) != 0x00; ++fmt) {
+        if (c == '%') {
+            switch (*(++fmt)) {
+
+            // int
+            case 'd':
+                n += vprintf_d32(va_arg(args, int));
+                break;
+
+            case 'x':
+                n += vprintf_x32(va_arg(args, unsigned int), 'a' - 'A' + 1);
+                break;
+
+            case 'X':
+                n += vprintf_x32(va_arg(args, unsigned int), 1);
+                break;
+
+            // long decimal
+            case 'l':
+                switch (*(++fmt)) {
+                // long long aka int64
+                case 'l':
+                    switch (*(++fmt)) {
+                    case 'd':
+                        n += vprintf_d64(va_arg(args, long long));
+                        break;
+                    case 'x':
+                        n += vprintf_x64(va_arg(args, unsigned long long), 'a' - 'A' + 1);
+                        break;
+                    case 'X':
+                        n += vprintf_x64(va_arg(args, unsigned long long), 'a' - 'A' + 1);
+                        break;
+                    }
+                    break;
+                // long int aka int32
+                case 'd':
+                    n += vprintf_d32(va_arg(args, int));
+                    break;
+                case 'x':
+                    n += vprintf_x32(va_arg(args, unsigned int), 'a' - 'A' + 1);
+                    break;
+
+                case 'X':
+                    n += vprintf_x32(va_arg(args, unsigned int), 1);
+                    break;
+                }
+                break;
+
+            // c string
+            case 's':
+                n += printf(va_arg(args, const char*));
+                break;
+
+            // int8 char
+            case 'c':
+                ++n;
+                __buf_put(va_arg(args, int));
+                break;
+
+            // pointer
+            case 'p':
+#ifdef __32bit_system
+                n += vprintf_x32(va_arg(args, size_t), 'a' - 'A' + 1);
+#else
+                n += vprintf_x64(va_arg(args, size_t), 'a' - 'A' + 1);
+#endif
+                break;
+
+            default:
+                ++n;
+                __buf_put(*(fmt - 1));
+                break;
+            }
+        } else {
+            ++n;
+            __buf_put(c);
+        }
+    }
+
+    return n;
+}
+
+int printf(const char* fmt, ...)
+{
+    va_list args;
+    va_start(args, fmt);
+
+    int ret = vprintf(fmt, args);
+
+    va_end(args);
+    return ret;
+}
+
+int putchar(int c)
+{
+    __buf_put(c);
+    return c;
+}

+ 0 - 19
user-space-program/lazybox.c

@@ -10,25 +10,6 @@ struct applet {
     int (*func)(const char** args);
 };
 
-int putchar(int c)
-{
-    write(STDOUT_FILENO, &c, 1);
-    return c;
-}
-
-int printf(const char* fmt, ...)
-{
-    va_list args;
-    va_start(args, fmt);
-
-    char buf[128];
-    int n = vsnprintf(buf, sizeof(buf), fmt, args);
-    n = write(STDOUT_FILENO, buf, n);
-
-    va_end(args);
-    return n;
-}
-
 int lazybox_version(const char** _)
 {
     (void)_;

+ 1 - 16
user-space-program/sh.c

@@ -7,21 +7,6 @@
 #include <unistd.h>
 #include <stdlib.h>
 
-int printf(const char* fmt, ...)
-{
-    va_list args;
-    va_start(args, fmt);
-
-    char buf[256] = {};
-    int len = vsnprintf(buf, sizeof(buf), fmt, args);
-
-    len = write(STDOUT_FILENO, buf, len);
-
-    va_end(args);
-
-    return len;
-}
-
 // Parsed command representation
 #define EXEC  1
 #define REDIR 2
@@ -153,7 +138,7 @@ runcmd(struct cmd *cmd)
 int
 getcmd(char *buf, int nbuf)
 {
-  printf("$ ");
+  printf("[root@localhost] #\n");
   memset(buf, 0, nbuf);
   gets(buf);
   if(buf[0] == 0) // EOF