vsnprintf add fieldwidth format strings
authorJack Miller <jack@codezen.org>
Wed, 9 Mar 2016 07:03:20 +0000 (01:03 -0600)
committerJack Miller <jack@codezen.org>
Sat, 19 Mar 2016 19:02:48 +0000 (14:02 -0500)
kernel/string.c

index 52e62e5..3b4e8ae 100644 (file)
@@ -1,3 +1,5 @@
+/* vim: set ts=4 sw=4 sts=4 noet : */
+
 #include <types.h>
 #include <stdarg.h>
 
@@ -28,7 +30,7 @@ int strlen(char *src)
 
 /* Convert a single value into ASCII */
 
-static int convert(char *buf, u32 rem, s32 fieldwidth, unsigned long long val, u32 base)
+static int convert(char *buf, char fill, u32 rem, s32 fieldwidth, unsigned long long val, u32 base)
 {
        char conv[] = "0123456789abcdef";
        /* Largest possible ull in decimal is 39 digits */
@@ -53,13 +55,16 @@ static int convert(char *buf, u32 rem, s32 fieldwidth, unsigned long long val, u
        i = 0;
        if (fieldwidth != -1) {
                for(i = 0; i < (rem - digits); i++)
-                       buf[i] = '0';
+                       buf[i] = fill;
        }
 
        /* Then reverse the digits into buf */
 
-       for( ; i <= (digits - 1) && rem; rem--, i++)
-               buf[i] = tmp[(digits - 1) - i];
+       while (digits && rem) {
+               buf[i++] = tmp[digits - 1];
+               digits--;
+               rem--;
+       }
 
        return i;
 }
@@ -68,10 +73,13 @@ void vsnprintf(char *buf, u32 size, char *format, va_list ap)
 {
        char *str = buf;
        char qualifier[2];
+       char padding[16];
+       char fill;
        char *s;
 
        unsigned long long val;
        s32 fieldwidth = -1;
+       s32 p_len = 0;
        u32 escaped = 0;
        u32 tmp;
        u32 i;
@@ -112,19 +120,49 @@ void vsnprintf(char *buf, u32 size, char *format, va_list ap)
 
                                                  size++;
                                                  break;
+                               case '0':
+                               case '1':
+                               case '2':
+                               case '3':
+                               case '4':
+                               case '5':
+                               case '6':
+                               case '7':
+                               case '8':
+                               case '9':
+                                                 if (p_len < 16)
+                                                         padding[p_len++] = format[i] - '0';
+                                                 size++;
+                                                 break;
                                case 'd':
                                case 'x': if (qualifier[0] == 'l') {
-                                                        if(qualifier[1] == 'l')
-                                                               val = va_arg(ap, unsigned long long);
-                                                        else
-                                                               val = va_arg(ap, unsigned long);
-                                                 } else {
+                                                         if(qualifier[1] == 'l')
+                                                                 val = va_arg(ap, unsigned long long);
+                                                         else
+                                                                 val = va_arg(ap, unsigned long);
+                                                 } else
                                                          val = va_arg(ap, unsigned int);
+
+                                                 if (p_len) {
+                                                         if (padding[0] == 0)
+                                                                 fill = '0';
+                                                         else
+                                                                 fill = ' ';
+
+                                                         tmp = p_len;
+
+                                                         fieldwidth = 0;
+                                                         while(p_len) {
+                                                                 fieldwidth *= 10;
+                                                                 fieldwidth += padding[tmp - p_len];
+                                                                 p_len--;
+                                                         }
                                                  }
+
                                                  if (format[i] == 'x')
-                                                         tmp = convert(str, (size - i), fieldwidth, val, 16);
+                                                         tmp = convert(str, fill, (size - i), fieldwidth, val, 16);
                                                  else
-                                                         tmp = convert(str, (size - i), fieldwidth, val, 10);
+                                                         tmp = convert(str, fill, (size - i), fieldwidth, val, 10);
                                                  str += tmp;
 
                                                  /* tmp were printed, but the format string shouldn't
@@ -133,6 +171,9 @@ void vsnprintf(char *buf, u32 size, char *format, va_list ap)
                                                  size -= (tmp - 1);
 
                                                  escaped = 0;
+                                                 qualifier[0] = 0;
+                                                 p_len = 0;
+                                                 fieldwidth = -1;
                                                  break;
                        }
                }