diff --git a/lib/libstand/printf.c b/lib/libstand/printf.c index 5f1bedc03d7c..e877a537418c 100644 --- a/lib/libstand/printf.c +++ b/lib/libstand/printf.c @@ -46,6 +46,8 @@ __FBSDID("$FreeBSD$"); */ #include +#include +#include #include #include #include "stand.h" @@ -56,7 +58,9 @@ __FBSDID("$FreeBSD$"); */ #include -static char *ksprintn (u_long num, int base, int *len); +#define MAXNBUF (sizeof(intmax_t) * CHAR_BIT + 1) + +static char *ksprintn (char *buf, uintmax_t num, int base, int *len); static int kvprintf(char const *fmt, void (*func)(int), void *arg, int radix, va_list ap); int @@ -101,24 +105,23 @@ vsprintf(char *buf, const char *cfmt, va_list ap) } /* - * Put a number (base <= 16) in a buffer in reverse order; return an - * optional length and a pointer to the NULL terminated (preceded?) - * buffer. + * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse + * order; return an optional length and a pointer to the last character + * written in the buffer (i.e., the first character of the string). + * The buffer pointed to by `nbuf' must have length >= MAXNBUF. */ static char * -ksprintn(ul, base, lenp) - u_long ul; - int base, *lenp; -{ /* A long in base 8, plus NULL. */ - static char buf[sizeof(long) * CHAR_BIT / 3 + 2]; +ksprintn(char *nbuf, uintmax_t num, int base, int *lenp) +{ char *p; - p = buf; + p = nbuf; + *p = '\0'; do { - *++p = hex2ascii(ul % base); - } while (ul /= base); + *++p = hex2ascii(num % base); + } while (num /= base); if (lenp) - *lenp = p - buf; + *lenp = p - nbuf; return (p); } @@ -152,15 +155,19 @@ static int kvprintf(char const *fmt, void (*func)(int), void *arg, int radix, va_list ap) { #define PCHAR(c) {int cc=(c); if (func) (*func)(cc); else *d++ = cc; retval++; } - char *p, *q, *d; + char nbuf[MAXNBUF]; + char *d; + const char *p, *percent, *q; u_char *up; int ch, n; - u_long ul; - int base, lflag, tmp, width, ladjust, sharpflag, neg, sign, dot; + uintmax_t num; + int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot; + int jflag, tflag, zflag; int dwidth; char padc; int retval = 0; + num = 0; if (!func) d = (char *) arg; else @@ -176,12 +183,14 @@ kvprintf(char const *fmt, void (*func)(int), void *arg, int radix, va_list ap) padc = ' '; width = 0; while ((ch = (u_char)*fmt++) != '%') { - if (ch == '\0') - return retval; + if (ch == '\0') + return (retval); PCHAR(ch); } - lflag = 0; ladjust = 0; sharpflag = 0; neg = 0; + percent = fmt - 1; + qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0; sign = 0; dot = 0; dwidth = 0; + jflag = 0; tflag = 0; zflag = 0; reswitch: switch (ch = (u_char)*fmt++) { case '.': dot = 1; @@ -228,17 +237,17 @@ reswitch: switch (ch = (u_char)*fmt++) { width = n; goto reswitch; case 'b': - ul = va_arg(ap, int); + num = va_arg(ap, int); p = va_arg(ap, char *); - for (q = ksprintn(ul, *p++, NULL); *q;) + for (q = ksprintn(nbuf, num, *p++, NULL); *q;) PCHAR(*q--); - if (!ul) + if (num == 0) break; for (tmp = 0; *p;) { n = *p++; - if (ul & (1 << (n - 1))) { + if (num & (1 << (n - 1))) { PCHAR(tmp ? ',' : '<'); for (; (n = *p) > ' '; ++p) PCHAR(n); @@ -268,26 +277,49 @@ reswitch: switch (ch = (u_char)*fmt++) { } break; case 'd': - ul = lflag ? va_arg(ap, long) : va_arg(ap, int); - sign = 1; + case 'i': base = 10; - goto number; + sign = 1; + goto handle_sign; + case 'j': + jflag = 1; + goto reswitch; case 'l': - lflag = 1; + if (lflag) { + lflag = 0; + qflag = 1; + } else + lflag = 1; goto reswitch; case 'n': - ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); - base = radix; - goto number; + if (jflag) + *(va_arg(ap, intmax_t *)) = retval; + else if (qflag) + *(va_arg(ap, quad_t *)) = retval; + else if (lflag) + *(va_arg(ap, long *)) = retval; + else if (zflag) + *(va_arg(ap, size_t *)) = retval; + else + *(va_arg(ap, int *)) = retval; + break; case 'o': - ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); base = 8; - goto number; + goto handle_nosign; case 'p': - ul = (u_long)va_arg(ap, void *); base = 16; - sharpflag = 1; + sharpflag = (width == 0); + sign = 0; + num = (uintptr_t)va_arg(ap, void *); goto number; + case 'q': + qflag = 1; + goto reswitch; + case 'r': + base = radix; + if (sign) + goto handle_sign; + goto handle_nosign; case 's': p = va_arg(ap, char *); if (p == NULL) @@ -309,19 +341,58 @@ reswitch: switch (ch = (u_char)*fmt++) { while (width--) PCHAR(padc); break; + case 't': + tflag = 1; + goto reswitch; case 'u': - ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); base = 10; - goto number; + goto handle_nosign; case 'x': - ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); + case 'X': base = 16; -number: if (sign && (long)ul < 0L) { + goto handle_nosign; + case 'y': + base = 16; + sign = 1; + goto handle_sign; + case 'z': + zflag = 1; + goto reswitch; +handle_nosign: + sign = 0; + if (jflag) + num = va_arg(ap, uintmax_t); + else if (qflag) + num = va_arg(ap, u_quad_t); + else if (tflag) + num = va_arg(ap, ptrdiff_t); + else if (lflag) + num = va_arg(ap, u_long); + else if (zflag) + num = va_arg(ap, size_t); + else + num = va_arg(ap, u_int); + goto number; +handle_sign: + if (jflag) + num = va_arg(ap, intmax_t); + else if (qflag) + num = va_arg(ap, quad_t); + else if (tflag) + num = va_arg(ap, ptrdiff_t); + else if (lflag) + num = va_arg(ap, long); + else if (zflag) + num = va_arg(ap, size_t); + else + num = va_arg(ap, int); +number: + if (sign && (intmax_t)num < 0) { neg = 1; - ul = -(long)ul; + num = -(intmax_t)num; } - p = ksprintn(ul, base, &tmp); - if (sharpflag && ul != 0) { + p = ksprintn(nbuf, num, base, &tmp); + if (sharpflag && num != 0) { if (base == 8) tmp++; else if (base == 16) @@ -335,7 +406,7 @@ number: if (sign && (long)ul < 0L) { PCHAR(padc); if (neg) PCHAR('-'); - if (sharpflag && ul != 0) { + if (sharpflag && num != 0) { if (base == 8) { PCHAR('0'); } else if (base == 16) { @@ -353,13 +424,10 @@ number: if (sign && (long)ul < 0L) { break; default: - PCHAR('%'); - if (lflag) - PCHAR('l'); - PCHAR(ch); + while (percent < fmt) + PCHAR(*percent++); break; } } #undef PCHAR } -