Hi,

I always stumble upon missing zero-padding every time I do something in
the bootloader.  This time I really need it so that I can load a file
depending on a number.  The files are named %02x-%02x-%02x if you were
wondering.

This implements the bare minimum to make it work.  I don't claim it
fulfills a specific standard.  It's based on the code in our kernel
printf.

Opinions?

Patrick

diff --git a/sys/lib/libsa/printf.c b/sys/lib/libsa/printf.c
index 0b3b5402a55..c48d31fb0a8 100644
--- a/sys/lib/libsa/printf.c
+++ b/sys/lib/libsa/printf.c
@@ -60,9 +60,16 @@
 
 #include "stand.h"
 
-void kprintn(void (*)(int), u_long, int);
+/*
+ * macros for converting digits to letters and vice versa
+ */
+#define        to_digit(c)     ((c) - '0')
+#define        is_digit(c)     ((unsigned)to_digit(c) <= 9)
+#define        to_char(n)      ((n) + '0')
+
+void kprintn(void (*)(int), u_long, int, int);
 #ifdef LIBSA_LONGLONG_PRINTF
-void kprintn64(void (*)(int), u_int64_t, int);
+void kprintn64(void (*)(int), u_int64_t, int, int);
 #endif
 void kdoprnt(void (*)(int), const char *, va_list);
 
@@ -91,7 +98,7 @@ kdoprnt(void (*put)(int), const char *fmt, va_list ap)
        u_int64_t ull;
 #endif
        unsigned long ul;
-       int ch, lflag;
+       int ch, lflag, zeropad, width, n;
        char *p;
 
        for (;;) {
@@ -101,10 +108,30 @@ kdoprnt(void (*put)(int), const char *fmt, va_list ap)
                        put(ch);
                }
                lflag = 0;
-reswitch:      switch (ch = *fmt++) {
+               zeropad = 0;
+               width = 0;
+rflag:         ch = *fmt++;
+reswitch:      switch (ch) {
+               case '0':
+                       /*
+                        * ``Note that 0 is taken as a flag, not as the
+                        * beginning of a field width.''
+                        *      -- ANSI X3J11
+                        */
+                       zeropad = 1;
+                       goto rflag;
+               case '1': case '2': case '3': case '4':
+               case '5': case '6': case '7': case '8': case '9':
+                       n = 0;
+                       do {
+                               n = 10 * n + to_digit(ch);
+                               ch = *fmt++;
+                       } while (is_digit(ch));
+                       width = n;
+                       goto reswitch;
                case 'l':
                        lflag++;
-                       goto reswitch;
+                       goto rflag;
 #ifndef        STRIPPED
                case 'b':
                {
@@ -112,7 +139,7 @@ reswitch:   switch (ch = *fmt++) {
 
                        ul = va_arg(ap, int);
                        p = va_arg(ap, char *);
-                       kprintn(put, ul, *p++);
+                       kprintn(put, ul, *p++, width);
 
                        if (!ul)
                                break;
@@ -149,7 +176,7 @@ reswitch:   switch (ch = *fmt++) {
                                        put('-');
                                        ull = -(int64_t)ull;
                                }
-                               kprintn64(put, ull, 10);
+                               kprintn64(put, ull, 10, width);
                                break;
                        } 
 #endif
@@ -159,31 +186,31 @@ reswitch: switch (ch = *fmt++) {
                                put('-');
                                ul = -(long)ul;
                        }
-                       kprintn(put, ul, 10);
+                       kprintn(put, ul, 10, width);
                        break;
                case 'o':
 #ifdef LIBSA_LONGLONG_PRINTF
                        if (lflag > 1) {
                                ull = va_arg(ap, u_int64_t);
-                               kprintn64(put, ull, 8);
+                               kprintn64(put, ull, 8, width);
                                break;
                        } 
 #endif
                        ul = lflag ?
                            va_arg(ap, u_long) : va_arg(ap, u_int);
-                       kprintn(put, ul, 8);
+                       kprintn(put, ul, 8, width);
                        break;
                case 'u':
 #ifdef LIBSA_LONGLONG_PRINTF
                        if (lflag > 1) {
                                ull = va_arg(ap, u_int64_t);
-                               kprintn64(put, ull, 10);
+                               kprintn64(put, ull, 10, width);
                                break;
                        } 
 #endif
                        ul = lflag ?
                            va_arg(ap, u_long) : va_arg(ap, u_int);
-                       kprintn(put, ul, 10);
+                       kprintn(put, ul, 10, width);
                        break;
                case 'p':
                        put('0');
@@ -193,7 +220,7 @@ reswitch:   switch (ch = *fmt++) {
 #ifdef LIBSA_LONGLONG_PRINTF
                        if (lflag > 1) {
                                ull = va_arg(ap, u_int64_t);
-                               kprintn64(put, ull, 16);
+                               kprintn64(put, ull, 16, width);
                                break;
                        }
 #else
@@ -207,6 +234,10 @@ reswitch:  switch (ch = *fmt++) {
                                do {
                                        *p++ = hexdig[ull & 15];
                                } while (ull >>= 4);
+                               while ((p - buf) < width &&
+                                   (p - buf) < sizeof(buf)) {
+                                       *p++ = '0';
+                               }
                                do {
                                        put(*--p);
                                } while (p > buf);
@@ -215,7 +246,7 @@ reswitch:   switch (ch = *fmt++) {
 #endif
                        ul = lflag ?
                            va_arg(ap, u_long) : va_arg(ap, u_int);
-                       kprintn(put, ul, 16);
+                       kprintn(put, ul, 16, width);
                        break;
                default:
                        put('%');
@@ -231,7 +262,7 @@ reswitch:   switch (ch = *fmt++) {
 }
 
 void
-kprintn(void (*put)(int), unsigned long ul, int base)
+kprintn(void (*put)(int), unsigned long ul, int base, int width)
 {
        /* hold a long in base 8 */
        char *p, buf[(sizeof(long) * NBBY / 3) + 1];
@@ -240,6 +271,9 @@ kprintn(void (*put)(int), unsigned long ul, int base)
        do {
                *p++ = hexdig[ul % base];
        } while (ul /= base);
+       while ((p - buf) < width && (p - buf) < sizeof(buf)) {
+               *p++ = '0';
+       }
        do {
                put(*--p);
        } while (p > buf);
@@ -247,7 +281,7 @@ kprintn(void (*put)(int), unsigned long ul, int base)
 
 #ifdef LIBSA_LONGLONG_PRINTF
 void
-kprintn64(void (*put)(int), u_int64_t ull, int base)
+kprintn64(void (*put)(int), u_int64_t ull, int base, int width)
 {
        /* hold an int64_t in base 8 */
        char *p, buf[(sizeof(u_int64_t) * NBBY / 3) + 1];
@@ -256,6 +290,9 @@ kprintn64(void (*put)(int), u_int64_t ull, int base)
        do {
                *p++ = hexdig[ull % base];
        } while (ull /= base);
+       while ((p - buf) < width && (p - buf) < sizeof(buf)) {
+               *p++ = '0';
+       }
        do {
                put(*--p);
        } while (p > buf);

Reply via email to