diff options
Diffstat (limited to 'lib/vsprintf.c')
| -rw-r--r-- | lib/vsprintf.c | 90 |
1 files changed, 43 insertions, 47 deletions
diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 4188308..d2b4d48 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -1,14 +1,16 @@ #include <stdarg.h> -#include <stdbool.h> #include <stdint.h> +#include <sys/types.h> enum TYPE { TYPE_INT = 1, TYPE_UINT = 2, - TYPE_HEX = 3, - TYPE_CHAR = 4, - TYPE_STRING = 5, - TYPE_PERCENT = 6 + TYPE_DEC = 3, + TYPE_OCT = 4, + TYPE_HEX = 5, + TYPE_CHAR = 6, + TYPE_STRING = 7, + TYPE_PERCENT = 8 }; enum FLAGS { @@ -17,60 +19,40 @@ enum FLAGS { FL_UPPER = 4 /* uppercase */ }; -static void hex(char **str, char flags, int fwidth, int size, int x) { - bool seen; - int i, y, len; +static void num(char **str, char flags, int base, int fwidth, int x) { + int i, y, len = 0; char c; - char *prefl = "0x"; - char *prefu = "0X"; + char *s = NULL; /* print the prefix, if the alt flag is set */ - if(flags & FL_ALT) { - if(flags & FL_UPPER) { - while(*prefu) - *(*str)++ = *prefu++; - } else { - while(*prefl) - *(*str)++ = *prefl++; - } - } + if(x && (flags & FL_ALT) && base == 8) + s = "0"; + if(x && (flags & FL_ALT) && base == 16) + s = (flags & FL_UPPER) ? "0X" : "0x"; + while(s && *s) + *(*str)++ = *s++; /* calculate the number of digits */ - len = 0; y = x; - seen = false; - for(i = 0; i < sizeof(y) << 1; i++) { - c = ((unsigned int) y >> 28); - if(c) - seen = true; - if(c || seen) - len++; - y = y << 4; + while(y) { + y /= base; + len++; } /* print the padding characters (if any) */ - c = ' '; - if(flags & FL_ZERO) - c = '0'; for(i = 0; i < fwidth - len; i++) - *(*str)++ = c; + *((*str)++) = (flags & FL_ZERO) ? '0' : ' '; - /* actually print the digits */ - seen = false; - for(i = 0; i < sizeof(x) << 1; i++) { - c = ((unsigned int) x >> 28) + '0'; - if(c > '9') { - c += 0x27; - if(flags & FL_UPPER) - c -= 0x20; - } + *str += len; + s = *str; + while(len--) { + c = (x % base) + '0'; + if(c > '9') + c += (flags & FL_UPPER) ? 7 : 39; - if(c != '0') - seen = true; - if(c != '0' || seen) - *(*str)++ = c; + *(--s) = c; - x = x << 4; + x /= base; } } @@ -103,6 +85,12 @@ int vsprintf(char *str, char *fmt, va_list ap) { case 'c': type = TYPE_CHAR; goto done; + case 'd': + type = TYPE_DEC; + goto done; + case 'o': + type = TYPE_OCT; + goto done; case 's': type = TYPE_STRING; goto done; @@ -144,9 +132,17 @@ done: case TYPE_CHAR: *str++ = va_arg(ap, char); break; + case TYPE_DEC: + x = va_arg(ap, int); + num(&str, flags, 10, fwidth, x); + break; + case TYPE_OCT: + x = va_arg(ap, int); + num(&str, flags, 8, fwidth, x); + break; case TYPE_HEX: x = va_arg(ap, int); - hex(&str, flags, fwidth, 4, x); + num(&str, flags, 16, fwidth, x); break; case TYPE_PERCENT: *str++ = '%'; |
