]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/subr_prf.c
xnu-517.tar.gz
[apple/xnu.git] / bsd / kern / subr_prf.c
index 814ac7056e526f1fddd44ad76d679084e202a020..1a4051963931e6e833a3d1815025e40c5982653e 100644 (file)
@@ -3,19 +3,22 @@
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
- * The contents of this file constitute Original Code as defined in and
- * are subject to the Apple Public Source License Version 1.1 (the
- * "License").  You may not use this file except in compliance with the
- * License.  Please obtain a copy of the License at
- * http://www.apple.com/publicsource and read it before using this file.
+ * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
  * 
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
- * License for the specific language governing rights and limitations
- * under the License.
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
@@ -90,7 +93,6 @@
 #include <stdarg.h>
 #include <sys/malloc.h>
 #include <sys/lock.h>
-#include <kern/parallel.h>
 #include <sys/subr_prf.h>
 
 #include <kern/cpu_number.h>   /* for cpu_number() */
@@ -115,6 +117,11 @@ int        (*v_putc)() = cnputc;           /* routine to putc on virtual console */
 
 extern struct tty cons;                /* standard console tty */
 extern struct  tty *constty;           /* pointer to console "window" tty */
+extern int  __doprnt(const char *fmt,
+                                        va_list    *argp,
+                                        void       (*putc)(int, void *arg),
+                                        void       *arg,
+                                        int        radix);
 
 /*
  *     Record cpu that panic'd and lock around panic data
@@ -132,11 +139,16 @@ boolean_t new_printf_cpu_number;  /* do we need to output who we are */
 extern void logwakeup();
 extern void halt_cpu();
 extern boot();
-int    putchar();
+
 
 static void
 snprintf_func(int ch, void *arg);
 
+struct putchar_args {
+       int flags;
+       struct tty *tty;
+};
+static void putchar(int c, void *arg);
 
 
 /*
@@ -148,28 +160,27 @@ void
 uprintf(const char *fmt, ...)
 {
        register struct proc *p = current_proc();
+       struct putchar_args pca;
        va_list ap;
+       
+       pca.flags = TOTTY;
+       pca.tty   = (struct tty *)p->p_session->s_ttyp;
 
-       unix_master();          /* sessions, sigh */
        if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) {
                va_start(ap, fmt);
-               prf(fmt, ap, TOTTY, (struct tty *)p->p_session->s_ttyvp);
+               __doprnt(fmt, &ap, putchar, &pca, 10);
                va_end(ap);
        }
-       unix_release();
 }
 
 tpr_t
 tprintf_open(p)
        register struct proc *p;
 {
-       unix_master();          /* sessions, sigh */
        if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) {
                SESSHOLD(p->p_session);
-               unix_release();
                return ((tpr_t) p->p_session);
        }
-       unix_release();
        return ((tpr_t) NULL);
 }
 
@@ -177,10 +188,8 @@ void
 tprintf_close(sess)
        tpr_t sess;
 {
-       unix_master();          /* sessions, sigh */
        if (sess)
                SESSRELE((struct session *) sess);
-       unix_release();
 }
 
 /*
@@ -194,19 +203,20 @@ tprintf(tpr_t tpr, const char *fmt, ...)
        struct tty *tp = NULL;
        int flags = TOLOG;
        va_list ap;
+       struct putchar_args pca;
 
        logpri(LOG_INFO);
-       unix_master();          /* sessions, sigh */
        if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) {
                flags |= TOTTY;
                tp = sess->s_ttyp;
        }
-       if (tp != NULL) {
-               va_start(ap, fmt);
-               prf(fmt, ap, TOTTY, tp);
-               va_end(ap);
-       }
-       unix_release();
+       
+       pca.flags = flags;
+       pca.tty   = tp;
+       va_start(ap, fmt);
+       __doprnt(fmt, &ap, putchar, &pca, 10);
+       va_end(ap);
+
        logwakeup();
 }
 
@@ -221,8 +231,12 @@ ttyprintf(struct tty *tp, const char *fmt, ...)
        va_list ap;
 
        if (tp != NULL) {
+               struct putchar_args pca;
+               pca.flags = TOTTY;
+               pca.tty   = tp;
+               
                va_start(ap, fmt);
-               prf(fmt, ap, TOTTY, tp);
+               __doprnt(fmt, &ap, putchar, &pca, 10);
                va_end(ap);
        }
 }
@@ -234,10 +248,13 @@ void
 logpri(level)
        int level;
 {
-
-       putchar('<', TOLOG, (struct tty *)0);
+       struct putchar_args pca;
+       pca.flags = TOLOG;
+       pca.tty   = NULL;
+       
+       putchar('<', &pca);
        printn((u_long)level, 10, TOLOG, (struct tty *)0, 0, 0);
-       putchar('>', TOLOG, (struct tty *)0);
+       putchar('>', &pca);
 }
 
 void
@@ -245,256 +262,82 @@ addlog(const char *fmt, ...)
 {
        register s = splhigh();
        va_list ap;
+       struct putchar_args pca;
+
+       pca.flags = TOLOG;
+       pca.tty   = NULL;
 
        va_start(ap, fmt);
-       prf(fmt, ap, TOLOG, (struct tty *)0);
+       __doprnt(fmt, &ap, putchar, &pca, 10);
+       
        splx(s);
-       if (!log_open)
-               prf(fmt, ap, TOCONS, (struct tty *)0);
+       if (!log_open) {
+               pca.flags = TOCONS;
+               __doprnt(fmt, &ap, putchar, &pca, 10);
+       }
        va_end(ap);
        logwakeup();
 }
 void _printf(int flags, struct tty *ttyp, const char *format, ...)
 {
        va_list ap;
+       struct putchar_args pca;
+
+       pca.flags = flags;
+       pca.tty   = ttyp;
        
        va_start(ap, format);
-       prf(format, ap, flags, ttyp);
+       __doprnt(format, &ap, putchar, &pca, 10);
        va_end(ap);
 }
 
 int prf(const char *fmt, va_list ap, int flags, struct tty *ttyp)
 {
-       register int b, c, i;
-       char *s;
-       int any;
-       int zf = 0, fld_size;
-       
-#if    NCPUS > 1
-       int cpun = cpu_number();
+       struct putchar_args pca;
 
-       if(ttyp == 0) {
-               simple_lock(&printf_lock);
+       pca.flags = flags;
+       pca.tty   = ttyp;
+
+#if    NCPUS > 1
+    int cpun = cpu_number();
+
+    if(ttyp == 0) {
+           simple_lock(&printf_lock);
        } else
                TTY_LOCK(ttyp);
-               
+
        if (cpun != master_cpu)
-               new_printf_cpu_number = TRUE;
+           new_printf_cpu_number = TRUE;
 
        if (new_printf_cpu_number) {
                putchar('{', flags, ttyp);
                printn((u_long)cpun, 10, flags, ttyp, 0, 0);
                putchar('}', flags, ttyp);
        }
-#endif /* NCPUS > 1 */ 
-loop:
-       while ((c = *fmt++) != '%') {
-               if (c == '\0') {
-#if    NCPUS > 1
-                       if(ttyp == 0) {
-                               simple_unlock(&printf_lock);
-                       } else
-                               TTY_UNLOCK(ttyp);
-#endif
-                       return 0;
-               }
-               putchar(c, flags, ttyp);
-       }
-again:
-       zf = 0;
-       fld_size = 0;
-       c = *fmt++;
-       if (c == '0')
-               zf = '0';
-       fld_size = 0;
-       for (;c <= '9' && c >= '0'; c = *fmt++)
-               fld_size = fld_size * 10 + c - '0';
-       
-       /* THIS CODE IS VAX DEPENDENT IN HANDLING %l? AND %c */
-       switch (c) {
-
-       case 'l':
-               goto again;
-       case 'x': case 'X':
-               b = 16;
-               goto number;
-       case 'd': case 'D':
-       case 'u':               /* what a joke */
-               b = 10;
-               goto number;
-       case 'o': case 'O':
-               b = 8;
-number:
-               printn(va_arg(ap, unsigned), b, flags, ttyp, zf, fld_size);
-               break;
-       case 'c':
-               b = va_arg(ap, unsigned);
-#if BYTE_ORDER == LITTLE_ENDIAN
-               for (i = 24; i >= 0; i -= 8)
-                       if (c = (b >> i) & 0x7f)
-                               putchar(c, flags, ttyp);
-#endif
-#if BYTE_ORDER == BIG_ENDIAN
-               if ((c = (b & 0x7f)))
-                       putchar(c, flags, ttyp);
-#endif
-               break;
-       case 'b':
-               b = va_arg(ap, unsigned);
-               s = va_arg(ap, char *);
-               printn((u_long)b, *s++, flags, ttyp, 0, 0);
-               any = 0;
-               if (b) {
-                       while ((i = *s++)) {
-                               if (*s <= 32) {
-                                       register int j;
-
-                                       if (any++)
-                                               putchar(',', flags, ttyp);
-                                       j = *s++ ;
-                                       for (; (c = *s) > 32 ; s++)
-                                               putchar(c, flags, ttyp);
-                                       printn( (u_long)( (b >> (j-1)) &
-                                                        ( (2 << (i-j)) -1)),
-                                                8, flags, ttyp, 0, 0);
-                               } else if (b & (1 << (i-1))) {
-                                       putchar(any? ',' : '<', flags, ttyp);
-                                       any = 1;
-                                       for (; (c = *s) > 32; s++)
-                                               putchar(c, flags, ttyp);
-                               } else
-                                       for (; *s > 32; s++)
-                                               ;
-                       }
-                       putchar('>', flags, ttyp);
-               }
-               break;
-
-       case 's':
-               s = va_arg(ap, char *);
-#ifdef DEBUG
-               if (fld_size) {
-                       while (fld_size-- > 0)
-                               putchar((c = *s++)? c : '_', flags, ttyp);
-               } else {
-                       while ((c = *s++))
-                               putchar(c, flags, ttyp);
-               }
-#else  
-               while (c = *s++)
-                       putchar(c, flags, ttyp);
-#endif
-               break;
-
-       case '%':
-               putchar('%', flags, ttyp);
-               goto loop;
-       case 'C':
-               b = va_arg(ap, unsigned);
-#if BYTE_ORDER == LITTLE_ENDIAN
-               for (i = 24; i >= 0; i -= 8)
-                       if (c = (b >> i) & 0x7f)
-                               putchar(c, flags, ttyp);
-#endif
-#if BYTE_ORDER == BIG_ENDIAN
-               if ((c = (b & 0x7f)))
-                       putchar(c, flags, ttyp);
-#endif
+#endif /* NCPUS > 1 */
+         
+       __doprnt(fmt, &ap, putchar, &pca, 10);
 
-       case 'r':
-       case 'R':
-               b = va_arg(ap, unsigned);
-               s = va_arg(ap, char *);
-               if (c == 'R') {
-                       puts("0x", flags, ttyp);
-                       printn((u_long)b, 16, flags, ttyp, 0, 0);
-               }
-               any = 0;
-               if (c == 'r' || b) {
-                       register struct reg_desc *rd;
-                       register struct reg_values *rv;
-                       unsigned field;
-
-                       putchar('<', flags, ttyp);
-                       for (rd = (struct reg_desc *)s; rd->rd_mask; rd++) {
-                               field = b & rd->rd_mask;
-                               field = (rd->rd_shift > 0)
-                                   ? field << rd->rd_shift
-                                   : field >> -rd->rd_shift;
-                               if (any &&
-                                     (rd->rd_format || rd->rd_values
-                                        || (rd->rd_name && field)
-                                     )
-                               )
-                                       putchar(',', flags, ttyp);
-                               if (rd->rd_name) {
-                                       if (rd->rd_format || rd->rd_values
-                                           || field) {
-                                               puts(rd->rd_name, flags, ttyp);
-                                               any = 1;
-                                       }
-                                       if (rd->rd_format || rd->rd_values) {
-                                               putchar('=', flags, ttyp);
-                                               any = 1;
-                                       }
-                               }
-                               if (rd->rd_format) {
-                                       _printf(flags, ttyp, rd->rd_format,
-                                         field);
-                                       any = 1;
-                                       if (rd->rd_values)
-                                               putchar(':', flags, ttyp);
-                               }
-                               if (rd->rd_values) {
-                                       any = 1;
-                                       for (rv = rd->rd_values;
-                                           rv->rv_name;
-                                           rv++) {
-                                               if (field == rv->rv_value) {
-                                                       puts(rv->rv_name, flags,
-                                                           ttyp);
-                                                       break;
-                                               }
-                                       }
-                                       if (rv->rv_name == NULL)
-                                               puts("???", flags, ttyp);
-                               }
-                       }
-                       putchar('>', flags, ttyp);
-               }
-               break;
-
-       case 'n':
-       case 'N':
-               {
-                       register struct reg_values *rv;
-
-                       b = va_arg(ap, unsigned);
-                       s = va_arg(ap,char *);
-                       for (rv = (struct reg_values *)s; rv->rv_name; rv++) {
-                               if (b == rv->rv_value) {
-                                       puts(rv->rv_name, flags, ttyp);
-                                       break;
-                               }
-                       }
-                       if (rv->rv_name == NULL)
-                               puts("???", flags, ttyp);
-                       if (c == 'N' || rv->rv_name == NULL) {
-                               putchar(':', flags, ttyp);
-                               printn((u_long)b, 10, flags, ttyp, 0, 0);
-                       }
-               }
-               break;
-       }
-       goto loop;
+#if    NCPUS > 1
+       if(ttyp == 0) {
+               simple_unlock(&printf_lock);
+       } else
+               TTY_UNLOCK(ttyp);
+#endif
+       return 0;
 }
 
 static void puts(const char *s, int flags, struct tty *ttyp)
 {
        register char c;
+       struct putchar_args pca;
+
+       pca.flags = flags;
+       pca.tty   = ttyp;
 
        while ((c = *s++))
-               putchar(c, flags, ttyp);
+               putchar(c, &pca);
 }
 
 /*
@@ -505,9 +348,13 @@ static void printn(u_long n, int b, int flags, struct tty *ttyp, int zf, int fld
 {
        char prbuf[11];
        register char *cp;
+       struct putchar_args pca;
+
+       pca.flags = flags;
+       pca.tty   = ttyp;
 
        if (b == 10 && (int)n < 0) {
-               putchar('-', flags, ttyp);
+               putchar('-', &pca);
                n = (unsigned)(-(int)n);
        }
        cp = prbuf;
@@ -518,12 +365,12 @@ static void printn(u_long n, int b, int flags, struct tty *ttyp, int zf, int fld
        if (fld_size) {
                for (fld_size -= cp - prbuf; fld_size > 0; fld_size--)
                        if (zf)
-                               putchar('0', flags, ttyp);
+                               putchar('0', &pca);
                        else
-                               putchar(' ', flags, ttyp);
+                               putchar(' ', &pca);
        }
        do
-               putchar(*--cp, flags, ttyp);
+               putchar(*--cp, &pca);
        while (cp > prbuf);
 }
 
@@ -543,32 +390,30 @@ void tablefull(const char *tab)
  * are saved in msgbuf for inspection later.
  */
 /*ARGSUSED*/
-int
-putchar(c, flags, tp)
-       register int c;
-       struct tty *tp;
+void
+putchar(int c, void *arg)
 {
+       struct putchar_args *pca = arg;
        register struct msgbuf *mbp;
-       char **sp = (char**) tp;
+       char **sp = (char**) pca->tty;
 
        if (panicstr)
                constty = 0;
-       if ((flags & TOCONS) && tp == NULL && constty) {
-               tp = constty;
-               flags |= TOTTY;
+       if ((pca->flags & TOCONS) && pca->tty == NULL && constty) {
+               pca->tty = constty;
+               pca->flags |= TOTTY;
        }
-       if ((flags & TOTTY) && tp && tputchar(c, tp) < 0 &&
-           (flags & TOCONS) && tp == constty)
+       if ((pca->flags & TOTTY) && pca->tty && tputchar(c, pca->tty) < 0 &&
+           (pca->flags & TOCONS) && pca->tty == constty)
                constty = 0;
-       if ((flags & TOLOG) && c != '\0' && c != '\r' && c != 0177)
+       if ((pca->flags & TOLOG) && c != '\0' && c != '\r' && c != 0177)
                log_putc(c);
-       if ((flags & TOCONS) && constty == 0 && c != '\0')
+       if ((pca->flags & TOCONS) && constty == 0 && c != '\0')
                (*v_putc)(c);
-       if (flags & TOSTR) {
+       if (pca->flags & TOSTR) {
                **sp = c;
                (*sp)++;
        }
-       return 0;
 }
 
 
@@ -580,10 +425,16 @@ int
 vsprintf(char *buf, const char *cfmt, va_list ap)
 {
        int retval;
+       struct snprintf_arg info;
 
-       retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap);
-       buf[retval] = '\0';
-       return retval;
+       info.str = buf;
+       info.remain = 999999;
+
+       retval = __doprnt(cfmt, &ap, snprintf_func, &info, 10);
+       if (info.remain >= 1) {
+               *info.str++ = '\0';
+       }
+       return 0;
 }
 
 /*
@@ -612,7 +463,7 @@ vsnprintf(char *str, size_t size, const char *format, va_list ap)
 
        info.str = str;
        info.remain = size;
-       retval = kvprintf(format, snprintf_func, &info, 10, ap);
+       retval = __doprnt(format, &ap, snprintf_func, &info, 10);
        if (info.remain >= 1)
                *info.str++ = '\0';
        return retval;
@@ -629,274 +480,10 @@ snprintf_func(int ch, void *arg)
        }
 }
 
-/*
- * Put a number (base <= 16) in a buffer in reverse order; return an
- * optional length and a pointer to the NULL terminated (preceded?)
- * buffer.
- */
-static char *
-ksprintn(ul, base, lenp)
-       register u_long ul;
-       register int base, *lenp;
-{                                      /* A long in base 8, plus NULL. */
-       static char buf[sizeof(long) * NBBY / 3 + 2];
-       register char *p;
-
-       p = buf;
-       do {
-               *++p = hex2ascii(ul % base);
-       } while (ul /= base);
-       if (lenp)
-               *lenp = p - buf;
-       return (p);
-}
-
-/*
- * Scaled down version of printf(3).
- *
- * Two additional formats:
- *
- * The format %b is supported to decode error registers.
- * Its usage is:
- *
- *     printf("reg=%b\n", regval, "<base><arg>*");
- *
- * where <base> is the output base expressed as a control character, e.g.
- * \10 gives octal; \20 gives hex.  Each arg is a sequence of characters,
- * the first of which gives the bit number to be inspected (origin 1), and
- * the next characters (up to a control character, i.e. a character <= 32),
- * give the name of the register.  Thus:
- *
- *     kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
- *
- * would produce output:
- *
- *     reg=3<BITTWO,BITONE>
- *
- * XXX:  %D  -- Hexdump, takes pointer and separator string:
- *             ("%6D", ptr, ":")   -> XX:XX:XX:XX:XX:XX
- *             ("%*D", len, ptr, " " -> XX XX XX XX ...
- */
 int
 kvprintf(char const *fmt, void (*func)(int, void*), void *arg, int radix, va_list ap)
 {
-#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
+       __doprnt(fmt, &ap, func, arg, radix);
+       return 0;
 }
+