-#define PCHAR(c) {int cc=(c); if (func) (*func)(cc,arg); else *d++ = cc; retval++; }
- char *p, *q, *d;
- u_char *up;
- int ch, n;
- u_long ul;
- int base, lflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
- int dwidth;
- char padc;
- int retval = 0;
-
- if (!func)
- d = (char *) arg;
- else
- d = NULL;
-
- if (fmt == NULL)
- fmt = "(fmt null)\n";
-
- if (radix < 2 || radix > 36)
- radix = 10;
-
- for (;;) {
- padc = ' ';
- width = 0;
- while ((ch = (u_char)*fmt++) != '%') {
- if (ch == '\0')
- return retval;
- PCHAR(ch);
- }
- lflag = 0; ladjust = 0; sharpflag = 0; neg = 0;
- sign = 0; dot = 0; dwidth = 0;
-reswitch: switch (ch = (u_char)*fmt++) {
- case '.':
- dot = 1;
- goto reswitch;
- case '#':
- sharpflag = 1;
- goto reswitch;
- case '+':
- sign = 1;
- goto reswitch;
- case '-':
- ladjust = 1;
- goto reswitch;
- case '%':
- PCHAR(ch);
- break;
- case '*':
- if (!dot) {
- width = va_arg(ap, int);
- if (width < 0) {
- ladjust = !ladjust;
- width = -width;
- }
- } else {
- dwidth = va_arg(ap, int);
- }
- goto reswitch;
- case '0':
- if (!dot) {
- padc = '0';
- goto reswitch;
- }
- case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- for (n = 0;; ++fmt) {
- n = n * 10 + ch - '0';
- ch = *fmt;
- if (ch < '0' || ch > '9')
- break;
- }
- if (dot)
- dwidth = n;
- else
- width = n;
- goto reswitch;
- case 'b':
- ul = va_arg(ap, int);
- p = va_arg(ap, char *);
- for (q = ksprintn(ul, *p++, NULL); *q;)
- PCHAR(*q--);
-
- if (!ul)
- break;
-
- for (tmp = 0; *p;) {
- n = *p++;
- if (ul & (1 << (n - 1))) {
- PCHAR(tmp ? ',' : '<');
- for (; (n = *p) > ' '; ++p)
- PCHAR(n);
- tmp = 1;
- } else
- for (; *p > ' '; ++p)
- continue;
- }
- if (tmp)
- PCHAR('>');
- break;
- case 'c':
- PCHAR(va_arg(ap, int));
- break;
- case 'D':
- up = va_arg(ap, u_char *);
- p = va_arg(ap, char *);
- if (!width)
- width = 16;
- while(width--) {
- PCHAR(hex2ascii(*up >> 4));
- PCHAR(hex2ascii(*up & 0x0f));
- up++;
- if (width)
- for (q=p;*q;q++)
- PCHAR(*q);
- }
- break;
- case 'd':
- ul = lflag ? va_arg(ap, long) : va_arg(ap, int);
- sign = 1;
- base = 10;
- goto number;
- case 'l':
- lflag = 1;
- goto reswitch;
- case 'o':
- ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
- base = 8;
- goto nosign;
- case 'p':
- ul = (uintptr_t)va_arg(ap, void *);
- base = 16;
- sharpflag = (width == 0);
- goto nosign;
- case 'n':
- case 'r':
- ul = lflag ? va_arg(ap, u_long) :
- sign ? (u_long)va_arg(ap, int) : va_arg(ap, u_int);
- base = radix;
- goto number;
- case 's':
- p = va_arg(ap, char *);
- if (p == NULL)
- p = "(null)";
- if (!dot)
- n = strlen (p);
- else
- for (n = 0; n < dwidth && p[n]; n++)
- continue;
-
- width -= n;
-
- if (!ladjust && width > 0)
- while (width--)
- PCHAR(padc);
- while (n--)
- PCHAR(*p++);
- if (ladjust && width > 0)
- while (width--)
- PCHAR(padc);
- break;
- case 'u':
- ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
- base = 10;
- goto nosign;
- case 'x':
- ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
- base = 16;
- goto nosign;
- case 'z':
- ul = lflag ? va_arg(ap, u_long) :
- sign ? (u_long)va_arg(ap, int) : va_arg(ap, u_int);
- base = 16;
- goto number;
-nosign: sign = 0;
-number: if (sign && (long)ul < 0L) {
- neg = 1;
- ul = -(long)ul;
- }
- p = ksprintn(ul, base, &tmp);
- if (sharpflag && ul != 0) {
- if (base == 8)
- tmp++;
- else if (base == 16)
- tmp += 2;
- }
- if (neg)
- tmp++;
-
- if (!ladjust && width && (width -= tmp) > 0)
- while (width--)
- PCHAR(padc);
- if (neg)
- PCHAR('-');
- if (sharpflag && ul != 0) {
- if (base == 8) {
- PCHAR('0');
- } else if (base == 16) {
- PCHAR('0');
- PCHAR('x');
- }
- }
-
- while (*p)
- PCHAR(*p--);
-
- if (ladjust && width && (width -= tmp) > 0)
- while (width--)
- PCHAR(padc);
-
- break;
- default:
- PCHAR('%');
- if (lflag)
- PCHAR('l');
- PCHAR(ch);
- break;
- }
- }
-#undef PCHAR