[BACK]Return to subr_prf.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / kern

Annotation of src/sys/kern/subr_prf.c, Revision 1.101

1.101   ! darrenr     1: /*     $NetBSD: subr_prf.c,v 1.100 2005/12/11 12:24:30 christos Exp $  */
1.15      cgd         2:
1.12      cgd         3: /*-
                      4:  * Copyright (c) 1986, 1988, 1991, 1993
                      5:  *     The Regents of the University of California.  All rights reserved.
                      6:  * (c) UNIX System Laboratories, Inc.
                      7:  * All or some portions of this file are derived from material licensed
                      8:  * to the University of California by American Telephone and Telegraph
                      9:  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
                     10:  * the permission of UNIX System Laboratories, Inc.
                     11:  *
                     12:  * Redistribution and use in source and binary forms, with or without
                     13:  * modification, are permitted provided that the following conditions
                     14:  * are met:
                     15:  * 1. Redistributions of source code must retain the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer.
                     17:  * 2. Redistributions in binary form must reproduce the above copyright
                     18:  *    notice, this list of conditions and the following disclaimer in the
                     19:  *    documentation and/or other materials provided with the distribution.
1.93      agc        20:  * 3. Neither the name of the University nor the names of its contributors
1.12      cgd        21:  *    may be used to endorse or promote products derived from this software
                     22:  *    without specific prior written permission.
                     23:  *
                     24:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     25:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     26:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     27:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     28:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     29:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     30:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     31:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     32:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     33:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     34:  * SUCH DAMAGE.
                     35:  *
1.48      fvdl       36:  *     @(#)subr_prf.c  8.4 (Berkeley) 5/4/95
1.12      cgd        37:  */
1.82      lukem      38:
                     39: #include <sys/cdefs.h>
1.101   ! darrenr    40: __KERNEL_RCSID(0, "$NetBSD: subr_prf.c,v 1.100 2005/12/11 12:24:30 christos Exp $");
1.54      thorpej    41:
1.49      jonathan   42: #include "opt_ddb.h"
1.67      ws         43: #include "opt_ipkdb.h"
1.80      lukem      44: #include "opt_kgdb.h"
1.54      thorpej    45: #include "opt_multiprocessor.h"
1.90      atatat     46: #include "opt_dump.h"
1.12      cgd        47:
                     48: #include <sys/param.h>
1.78      kleink     49: #include <sys/stdint.h>
1.12      cgd        50: #include <sys/systm.h>
                     51: #include <sys/buf.h>
                     52: #include <sys/reboot.h>
                     53: #include <sys/msgbuf.h>
                     54: #include <sys/proc.h>
                     55: #include <sys/ioctl.h>
                     56: #include <sys/vnode.h>
                     57: #include <sys/file.h>
                     58: #include <sys/tty.h>
                     59: #include <sys/tprintf.h>
                     60: #include <sys/syslog.h>
                     61: #include <sys/malloc.h>
1.54      thorpej    62: #include <sys/lock.h>
1.87      thorpej    63: #include <sys/kprintf.h>
1.12      cgd        64:
1.20      christos   65: #include <dev/cons.h>
                     66:
1.49      jonathan   67: #ifdef DDB
                     68: #include <ddb/ddbvar.h>
1.72      jhawk      69: #include <machine/db_machdep.h>
                     70: #include <ddb/db_command.h>
                     71: #include <ddb/db_interface.h>
1.49      jonathan   72: #endif
                     73:
1.67      ws         74: #ifdef IPKDB
                     75: #include <ipkdb/ipkdb.h>
                     76: #endif
                     77:
1.54      thorpej    78: #if defined(MULTIPROCESSOR)
1.63      thorpej    79: struct simplelock kprintf_slock = SIMPLELOCK_INITIALIZER;
1.55      thorpej    80: #endif /* MULTIPROCESSOR */
1.49      jonathan   81:
1.12      cgd        82: /*
1.45      chuck      83:  * note that stdarg.h and the ansi style va_start macro is used for both
                     84:  * ansi and traditional c complers.
                     85:  * XXX: this requires that stdarg.h define: va_alist and va_dcl
1.12      cgd        86:  */
                     87: #include <machine/stdarg.h>
                     88:
1.28      ws         89:
1.22      christos   90: #ifdef KGDB
1.42      thorpej    91: #include <sys/kgdb.h>
1.22      christos   92: #include <machine/cpu.h>
1.12      cgd        93: #endif
1.45      chuck      94: #ifdef DDB
                     95: #include <ddb/db_output.h>     /* db_printf, db_putchar prototypes */
                     96: #endif
                     97:
                     98:
                     99: /*
                    100:  * defines
                    101:  */
                    102:
                    103: /* max size buffer kprintf needs to print quad_t [size in base 8 + \0] */
                    104: #define KPRINTF_BUFSIZE                (sizeof(quad_t) * NBBY / 3 + 2)
                    105:
                    106:
                    107: /*
                    108:  * local prototypes
                    109:  */
                    110:
1.94      junyoung  111: static void     putchar(int, int, struct tty *);
1.20      christos  112:
1.12      cgd       113:
1.37      thorpej   114: /*
1.45      chuck     115:  * globals
1.37      thorpej   116:  */
                    117:
1.77      tsutsui   118: extern struct tty *constty;    /* pointer to console "window" tty */
1.45      chuck     119: extern int log_open;   /* subr_log: is /dev/klog open? */
                    120: const  char *panicstr; /* arg to first call to panic (used as a flag
                    121:                           to indicate that panic has already been called). */
1.79      simonb    122: long   panicstart, panicend;   /* position in the msgbuf of the start and
                    123:                                   end of the formatted panicstr. */
1.74      sommerfe  124: int    doing_shutdown; /* set to indicate shutdown in progress */
1.45      chuck     125:
1.90      atatat    126: #ifndef        DUMP_ON_PANIC
                    127: #define        DUMP_ON_PANIC   1
                    128: #endif
                    129: int    dumponpanic = DUMP_ON_PANIC;
                    130:
1.45      chuck     131: /*
                    132:  * v_putc: routine to putc on virtual console
                    133:  *
                    134:  * the v_putc pointer can be used to redirect the console cnputc elsewhere
                    135:  * [e.g. to a "virtual console"].
                    136:  */
1.12      cgd       137:
1.94      junyoung  138: void (*v_putc)(int) = cnputc;  /* start with cnputc (normal cons) */
                    139: void (*v_flush)(void) = cnflush;       /* start with cnflush (normal cons) */
1.12      cgd       140:
1.97      christos  141: const char hexdigits[] = "0123456789abcdef";
                    142: const char HEXDIGITS[] = "0123456789ABCDEF";
                    143:
1.12      cgd       144:
1.45      chuck     145: /*
                    146:  * functions
                    147:  */
1.12      cgd       148:
                    149: /*
1.45      chuck     150:  * tablefull: warn that a system table is full
1.12      cgd       151:  */
1.45      chuck     152:
                    153: void
1.99      thorpej   154: tablefull(const char *tab, const char *hint)
1.45      chuck     155: {
1.75      jdolecek  156:        if (hint)
                    157:                log(LOG_ERR, "%s: table is full - %s\n", tab, hint);
                    158:        else
                    159:                log(LOG_ERR, "%s: table is full\n", tab);
1.45      chuck     160: }
1.12      cgd       161:
                    162: /*
1.89      thorpej   163:  * twiddle: spin a little propellor on the console.
                    164:  */
                    165:
                    166: void
                    167: twiddle(void)
                    168: {
                    169:        static const char twiddle_chars[] = "|/-\\";
                    170:        static int pos;
                    171:        int s;
                    172:
                    173:        KPRINTF_MUTEX_ENTER(s);
                    174:
                    175:        putchar(twiddle_chars[pos++ & 3], TOCONS, NULL);
                    176:        putchar('\b', TOCONS, NULL);
                    177:
                    178:        KPRINTF_MUTEX_EXIT(s);
                    179: }
                    180:
                    181: /*
1.45      chuck     182:  * panic: handle an unresolvable fatal error
                    183:  *
                    184:  * prints "panic: <message>" and reboots.   if called twice (i.e. recursive
1.96      perry     185:  * call) we avoid trying to sync the disk and just reboot (to avoid
1.45      chuck     186:  * recursive panics).
1.12      cgd       187:  */
1.45      chuck     188:
1.14      cgd       189: void
1.12      cgd       190: panic(const char *fmt, ...)
                    191: {
1.14      cgd       192:        int bootopt;
1.12      cgd       193:        va_list ap;
                    194:
1.90      atatat    195:        bootopt = RB_AUTOBOOT;
                    196:        if (dumponpanic)
                    197:                bootopt |= RB_DUMP;
1.74      sommerfe  198:        if (doing_shutdown)
1.12      cgd       199:                bootopt |= RB_NOSYNC;
1.74      sommerfe  200:        if (!panicstr)
1.12      cgd       201:                panicstr = fmt;
1.74      sommerfe  202:        doing_shutdown = 1;
1.79      simonb    203:
1.81      fvdl      204:        if (msgbufenabled && msgbufp->msg_magic == MSG_MAGIC)
1.79      simonb    205:                panicstart = msgbufp->msg_bufx;
1.96      perry     206:
1.12      cgd       207:        va_start(ap, fmt);
1.45      chuck     208:        printf("panic: ");
                    209:        vprintf(fmt, ap);
                    210:        printf("\n");
1.12      cgd       211:        va_end(ap);
1.79      simonb    212:
1.81      fvdl      213:        if (msgbufenabled && msgbufp->msg_magic == MSG_MAGIC)
1.79      simonb    214:                panicend = msgbufp->msg_bufx;
1.12      cgd       215:
1.67      ws        216: #ifdef IPKDB
1.32      ws        217:        ipkdb_panic();
1.28      ws        218: #endif
1.12      cgd       219: #ifdef KGDB
                    220:        kgdb_panic();
                    221: #endif
                    222: #ifdef KADB
1.14      cgd       223:        if (boothowto & RB_KDB)
                    224:                kdbpanic();
1.12      cgd       225: #endif
                    226: #ifdef DDB
1.101   ! darrenr   227:        if (db_onpanic == 1)
1.38      thorpej   228:                Debugger();
1.72      jhawk     229:        else {
1.73      jhawk     230:                static int intrace = 0;
                    231:
1.101   ! darrenr   232:                if (intrace == 0) {
        !           233:                        intrace = 1;
1.73      jhawk     234:                        printf("Begin traceback...\n");
                    235:                        db_stack_trace_print(
1.85      scw       236:                            (db_expr_t)(intptr_t)__builtin_frame_address(0),
1.73      jhawk     237:                            TRUE, 65535, "", printf);
                    238:                        printf("End traceback...\n");
1.101   ! darrenr   239:                        intrace = 0;
1.73      jhawk     240:                } else
                    241:                        printf("Faulted in mid-traceback; aborting...");
1.101   ! darrenr   242:                if (db_onpanic == 2)
        !           243:                        Debugger();
1.72      jhawk     244:        }
1.12      cgd       245: #endif
1.39      gwr       246:        cpu_reboot(bootopt, NULL);
1.12      cgd       247: }
                    248:
                    249: /*
1.45      chuck     250:  * kernel logging functions: log, logpri, addlog
                    251:  */
                    252:
                    253: /*
                    254:  * log: write to the log buffer
                    255:  *
                    256:  * => will not sleep [so safe to call from interrupt]
                    257:  * => will log to console if /dev/klog isn't open
                    258:  */
                    259:
                    260: void
                    261: log(int level, const char *fmt, ...)
                    262: {
1.54      thorpej   263:        int s;
1.45      chuck     264:        va_list ap;
                    265:
1.54      thorpej   266:        KPRINTF_MUTEX_ENTER(s);
                    267:
                    268:        klogpri(level);         /* log the level first */
1.45      chuck     269:        va_start(ap, fmt);
                    270:        kprintf(fmt, TOLOG, NULL, NULL, ap);
                    271:        va_end(ap);
                    272:        if (!log_open) {
                    273:                va_start(ap, fmt);
                    274:                kprintf(fmt, TOCONS, NULL, NULL, ap);
                    275:                va_end(ap);
                    276:        }
1.64      thorpej   277:
                    278:        KPRINTF_MUTEX_EXIT(s);
                    279:
                    280:        logwakeup();            /* wake up anyone waiting for log msgs */
                    281: }
                    282:
                    283: /*
                    284:  * vlog: write to the log buffer [already have va_alist]
                    285:  */
                    286:
                    287: void
1.99      thorpej   288: vlog(int level, const char *fmt, va_list ap)
1.64      thorpej   289: {
                    290:        int s;
                    291:
                    292:        KPRINTF_MUTEX_ENTER(s);
                    293:
                    294:        klogpri(level);         /* log the level first */
                    295:        kprintf(fmt, TOLOG, NULL, NULL, ap);
                    296:        if (!log_open)
                    297:                kprintf(fmt, TOCONS, NULL, NULL, ap);
1.54      thorpej   298:
                    299:        KPRINTF_MUTEX_EXIT(s);
                    300:
1.45      chuck     301:        logwakeup();            /* wake up anyone waiting for log msgs */
                    302: }
                    303:
                    304: /*
                    305:  * logpri: log the priority level to the klog
                    306:  */
                    307:
1.54      thorpej   308: void
1.99      thorpej   309: logpri(int level)
1.45      chuck     310: {
1.54      thorpej   311:        int s;
                    312:
                    313:        KPRINTF_MUTEX_ENTER(s);
                    314:        klogpri(level);
                    315:        KPRINTF_MUTEX_EXIT(s);
                    316: }
                    317:
                    318: /*
                    319:  * Note: we must be in the mutex here!
                    320:  */
1.87      thorpej   321: void
1.99      thorpej   322: klogpri(int level)
1.54      thorpej   323: {
1.45      chuck     324:        char *p;
                    325:        char snbuf[KPRINTF_BUFSIZE];
                    326:
                    327:        putchar('<', TOLOG, NULL);
1.76      tv        328:        snprintf(snbuf, sizeof(snbuf), "%d", level);
1.45      chuck     329:        for (p = snbuf ; *p ; p++)
                    330:                putchar(*p, TOLOG, NULL);
                    331:        putchar('>', TOLOG, NULL);
                    332: }
                    333:
                    334: /*
                    335:  * addlog: add info to previous log message
1.12      cgd       336:  */
1.45      chuck     337:
1.12      cgd       338: void
1.45      chuck     339: addlog(const char *fmt, ...)
                    340: {
1.54      thorpej   341:        int s;
1.45      chuck     342:        va_list ap;
                    343:
1.54      thorpej   344:        KPRINTF_MUTEX_ENTER(s);
                    345:
1.45      chuck     346:        va_start(ap, fmt);
                    347:        kprintf(fmt, TOLOG, NULL, NULL, ap);
                    348:        va_end(ap);
                    349:        if (!log_open) {
                    350:                va_start(ap, fmt);
                    351:                kprintf(fmt, TOCONS, NULL, NULL, ap);
                    352:                va_end(ap);
                    353:        }
1.54      thorpej   354:
                    355:        KPRINTF_MUTEX_EXIT(s);
                    356:
1.45      chuck     357:        logwakeup();
                    358: }
                    359:
                    360:
                    361: /*
                    362:  * putchar: print a single character on console or user terminal.
                    363:  *
                    364:  * => if console, then the last MSGBUFS chars are saved in msgbuf
                    365:  *     for inspection later (e.g. dmesg/syslog)
1.54      thorpej   366:  * => we must already be in the mutex!
1.45      chuck     367:  */
                    368: static void
1.99      thorpej   369: putchar(int c, int flags, struct tty *tp)
1.12      cgd       370: {
1.69      augustss  371:        struct kern_msgbuf *mbp;
1.12      cgd       372:
1.45      chuck     373:        if (panicstr)
                    374:                constty = NULL;
                    375:        if ((flags & TOCONS) && tp == NULL && constty) {
                    376:                tp = constty;
                    377:                flags |= TOTTY;
                    378:        }
1.91      christos  379:        if ((flags & TOTTY) && tp &&
                    380:            tputchar(c, flags, tp) < 0 &&
1.45      chuck     381:            (flags & TOCONS) && tp == constty)
                    382:                constty = NULL;
                    383:        if ((flags & TOLOG) &&
                    384:            c != '\0' && c != '\r' && c != 0177 && msgbufenabled) {
                    385:                mbp = msgbufp;
                    386:                if (mbp->msg_magic != MSG_MAGIC) {
                    387:                        /*
                    388:                         * Arguably should panic or somehow notify the
                    389:                         * user...  but how?  Panic may be too drastic,
                    390:                         * and would obliterate the message being kicked
                    391:                         * out (maybe a panic itself), and printf
                    392:                         * would invoke us recursively.  Silently punt
                    393:                         * for now.  If syslog is running, it should
                    394:                         * notice.
                    395:                         */
                    396:                        msgbufenabled = 0;
                    397:                } else {
                    398:                        mbp->msg_bufc[mbp->msg_bufx++] = c;
                    399:                        if (mbp->msg_bufx < 0 || mbp->msg_bufx >= mbp->msg_bufs)
                    400:                                mbp->msg_bufx = 0;
1.48      fvdl      401:                        /* If the buffer is full, keep the most recent data. */
                    402:                        if (mbp->msg_bufr == mbp->msg_bufx) {
                    403:                                 if (++mbp->msg_bufr >= mbp->msg_bufs)
                    404:                                        mbp->msg_bufr = 0;
                    405:                        }
1.45      chuck     406:                }
                    407:        }
                    408:        if ((flags & TOCONS) && constty == NULL && c != '\0')
                    409:                (*v_putc)(c);
                    410: #ifdef DDB
                    411:        if (flags & TODDB)
                    412:                db_putchar(c);
                    413: #endif
1.12      cgd       414: }
                    415:
1.45      chuck     416:
1.12      cgd       417: /*
1.45      chuck     418:  * uprintf: print to the controlling tty of the current process
                    419:  *
                    420:  * => we may block if the tty queue is full
                    421:  * => no message is printed if the queue doesn't clear in a reasonable
                    422:  *     time
1.12      cgd       423:  */
1.45      chuck     424:
1.12      cgd       425: void
                    426: uprintf(const char *fmt, ...)
                    427: {
1.69      augustss  428:        struct proc *p = curproc;
1.12      cgd       429:        va_list ap;
                    430:
                    431:        if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) {
1.54      thorpej   432:                /* No mutex needed; going to process TTY. */
1.12      cgd       433:                va_start(ap, fmt);
1.45      chuck     434:                kprintf(fmt, TOTTY, p->p_session->s_ttyp, NULL, ap);
1.12      cgd       435:                va_end(ap);
                    436:        }
                    437: }
                    438:
1.45      chuck     439: /*
                    440:  * tprintf functions: used to send messages to a specific process
                    441:  *
                    442:  * usage:
                    443:  *   get a tpr_t handle on a process "p" by using "tprintf_open(p)"
                    444:  *   use the handle when calling "tprintf"
                    445:  *   when done, do a "tprintf_close" to drop the handle
                    446:  */
                    447:
                    448: /*
                    449:  * tprintf_open: get a tprintf handle on a process "p"
                    450:  *
                    451:  * => returns NULL if process can't be printed to
                    452:  */
                    453:
1.12      cgd       454: tpr_t
1.99      thorpej   455: tprintf_open(struct proc *p)
1.12      cgd       456: {
                    457:
                    458:        if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) {
                    459:                SESSHOLD(p->p_session);
                    460:                return ((tpr_t) p->p_session);
                    461:        }
                    462:        return ((tpr_t) NULL);
                    463: }
                    464:
1.45      chuck     465: /*
                    466:  * tprintf_close: dispose of a tprintf handle obtained with tprintf_open
                    467:  */
                    468:
1.12      cgd       469: void
1.99      thorpej   470: tprintf_close(tpr_t sess)
1.12      cgd       471: {
                    472:
                    473:        if (sess)
                    474:                SESSRELE((struct session *) sess);
                    475: }
                    476:
                    477: /*
1.96      perry     478:  * tprintf: given tprintf handle to a process [obtained with tprintf_open],
1.45      chuck     479:  * send a message to the controlling tty for that process.
                    480:  *
                    481:  * => also sends message to /dev/klog
1.12      cgd       482:  */
                    483: void
                    484: tprintf(tpr_t tpr, const char *fmt, ...)
                    485: {
1.69      augustss  486:        struct session *sess = (struct session *)tpr;
1.12      cgd       487:        struct tty *tp = NULL;
1.54      thorpej   488:        int s, flags = TOLOG;
1.12      cgd       489:        va_list ap;
                    490:
                    491:        if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) {
                    492:                flags |= TOTTY;
                    493:                tp = sess->s_ttyp;
                    494:        }
1.54      thorpej   495:
                    496:        KPRINTF_MUTEX_ENTER(s);
                    497:
                    498:        klogpri(LOG_INFO);
1.12      cgd       499:        va_start(ap, fmt);
1.45      chuck     500:        kprintf(fmt, flags, tp, NULL, ap);
1.12      cgd       501:        va_end(ap);
1.54      thorpej   502:
                    503:        KPRINTF_MUTEX_EXIT(s);
                    504:
1.12      cgd       505:        logwakeup();
                    506: }
                    507:
1.45      chuck     508:
1.12      cgd       509: /*
1.45      chuck     510:  * ttyprintf: send a message to a specific tty
                    511:  *
                    512:  * => should be used only by tty driver or anything that knows the
1.52      mrg       513:  *    underlying tty will not be revoked(2)'d away.  [otherwise,
                    514:  *    use tprintf]
1.12      cgd       515:  */
                    516: void
                    517: ttyprintf(struct tty *tp, const char *fmt, ...)
                    518: {
                    519:        va_list ap;
                    520:
1.54      thorpej   521:        /* No mutex needed; going to process TTY. */
1.12      cgd       522:        va_start(ap, fmt);
1.45      chuck     523:        kprintf(fmt, TOTTY, tp, NULL, ap);
1.12      cgd       524:        va_end(ap);
                    525: }
                    526:
1.45      chuck     527: #ifdef DDB
1.12      cgd       528:
                    529: /*
1.45      chuck     530:  * db_printf: printf for DDB (via db_putchar)
1.12      cgd       531:  */
1.45      chuck     532:
1.12      cgd       533: void
1.45      chuck     534: db_printf(const char *fmt, ...)
1.12      cgd       535: {
                    536:        va_list ap;
                    537:
1.54      thorpej   538:        /* No mutex needed; DDB pauses all processors. */
1.12      cgd       539:        va_start(ap, fmt);
1.45      chuck     540:        kprintf(fmt, TODDB, NULL, NULL, ap);
1.12      cgd       541:        va_end(ap);
1.95      reinoud   542:
                    543:        if (db_tee_msgbuf) {
                    544:                va_start(ap, fmt);
                    545:                kprintf(fmt, TOLOG, NULL, NULL, ap);
                    546:                va_end(ap);
                    547:        };
1.84      drochner  548: }
                    549:
                    550: void
1.99      thorpej   551: db_vprintf(const char *fmt, va_list ap)
1.84      drochner  552: {
                    553:
                    554:        /* No mutex needed; DDB pauses all processors. */
                    555:        kprintf(fmt, TODDB, NULL, NULL, ap);
1.95      reinoud   556:        if (db_tee_msgbuf)
                    557:                kprintf(fmt, TOLOG, NULL, NULL, ap);
1.12      cgd       558: }
                    559:
1.45      chuck     560: #endif /* DDB */
1.12      cgd       561:
1.88      thorpej   562: /*
                    563:  * Device autoconfiguration printf routines.  These change their
                    564:  * behavior based on the AB_* flags in boothowto.  If AB_SILENT
                    565:  * is set, messages never go to the console (but they still always
                    566:  * go to the log).  AB_VERBOSE overrides AB_SILENT.
                    567:  */
                    568:
                    569: /*
                    570:  * aprint_normal: Send to console unless AB_QUIET.  Always goes
                    571:  * to the log.
                    572:  */
                    573: void
                    574: aprint_normal(const char *fmt, ...)
                    575: {
                    576:        va_list ap;
                    577:        int s, flags = TOLOG;
                    578:
                    579:        if ((boothowto & (AB_SILENT|AB_QUIET)) == 0 ||
                    580:            (boothowto & AB_VERBOSE) != 0)
                    581:                flags |= TOCONS;
1.96      perry     582:
1.88      thorpej   583:        KPRINTF_MUTEX_ENTER(s);
                    584:
                    585:        va_start(ap, fmt);
                    586:        kprintf(fmt, flags, NULL, NULL, ap);
                    587:        va_end(ap);
                    588:
                    589:        KPRINTF_MUTEX_EXIT(s);
1.96      perry     590:
1.88      thorpej   591:        if (!panicstr)
                    592:                logwakeup();
                    593: }
                    594:
                    595: /*
1.89      thorpej   596:  * aprint_error: Send to console unless AB_QUIET.  Always goes
                    597:  * to the log.  Also counts the number of times called so other
                    598:  * parts of the kernel can report the number of errors during a
                    599:  * given phase of system startup.
                    600:  */
                    601: static int aprint_error_count;
                    602:
                    603: int
                    604: aprint_get_error_count(void)
                    605: {
                    606:        int count, s;
                    607:
                    608:        KPRINTF_MUTEX_ENTER(s);
                    609:
                    610:        count = aprint_error_count;
                    611:        aprint_error_count = 0;
                    612:
                    613:        KPRINTF_MUTEX_EXIT(s);
                    614:
                    615:        return (count);
                    616: }
                    617:
                    618: void
                    619: aprint_error(const char *fmt, ...)
                    620: {
                    621:        va_list ap;
                    622:        int s, flags = TOLOG;
                    623:
                    624:        if ((boothowto & (AB_SILENT|AB_QUIET)) == 0 ||
                    625:            (boothowto & AB_VERBOSE) != 0)
                    626:                flags |= TOCONS;
1.96      perry     627:
1.89      thorpej   628:        KPRINTF_MUTEX_ENTER(s);
                    629:
                    630:        aprint_error_count++;
                    631:
                    632:        va_start(ap, fmt);
                    633:        kprintf(fmt, flags, NULL, NULL, ap);
                    634:        va_end(ap);
                    635:
                    636:        KPRINTF_MUTEX_EXIT(s);
1.96      perry     637:
1.89      thorpej   638:        if (!panicstr)
                    639:                logwakeup();
                    640: }
                    641:
                    642: /*
1.88      thorpej   643:  * aprint_naive: Send to console only if AB_QUIET.  Never goes
                    644:  * to the log.
                    645:  */
                    646: void
                    647: aprint_naive(const char *fmt, ...)
                    648: {
                    649:        va_list ap;
                    650:        int s;
                    651:
                    652:        if ((boothowto & (AB_QUIET|AB_SILENT|AB_VERBOSE)) == AB_QUIET) {
                    653:                KPRINTF_MUTEX_ENTER(s);
                    654:
                    655:                va_start(ap, fmt);
                    656:                kprintf(fmt, TOCONS, NULL, NULL, ap);
                    657:                va_end(ap);
                    658:
                    659:                KPRINTF_MUTEX_EXIT(s);
                    660:        }
                    661: }
                    662:
                    663: /*
                    664:  * aprint_verbose: Send to console only if AB_VERBOSE.  Always
                    665:  * goes to the log.
                    666:  */
                    667: void
                    668: aprint_verbose(const char *fmt, ...)
                    669: {
                    670:        va_list ap;
                    671:        int s, flags = TOLOG;
                    672:
                    673:        if (boothowto & AB_VERBOSE)
                    674:                flags |= TOCONS;
1.96      perry     675:
1.88      thorpej   676:        KPRINTF_MUTEX_ENTER(s);
                    677:
                    678:        va_start(ap, fmt);
                    679:        kprintf(fmt, flags, NULL, NULL, ap);
                    680:        va_end(ap);
                    681:
                    682:        KPRINTF_MUTEX_EXIT(s);
1.96      perry     683:
1.88      thorpej   684:        if (!panicstr)
                    685:                logwakeup();
                    686: }
                    687:
                    688: /*
                    689:  * aprint_debug: Send to console and log only if AB_DEBUG.
                    690:  */
                    691: void
                    692: aprint_debug(const char *fmt, ...)
                    693: {
                    694:        va_list ap;
                    695:        int s;
                    696:
                    697:        if (boothowto & AB_DEBUG) {
                    698:                KPRINTF_MUTEX_ENTER(s);
                    699:
                    700:                va_start(ap, fmt);
                    701:                kprintf(fmt, TOCONS | TOLOG, NULL, NULL, ap);
                    702:                va_end(ap);
                    703:
                    704:                KPRINTF_MUTEX_EXIT(s);
                    705:        }
1.89      thorpej   706: }
                    707:
                    708: /*
                    709:  * printf_nolog: Like printf(), but does not send message to the log.
                    710:  */
                    711:
                    712: void
                    713: printf_nolog(const char *fmt, ...)
                    714: {
                    715:        va_list ap;
                    716:        int s;
                    717:
                    718:        KPRINTF_MUTEX_ENTER(s);
                    719:
                    720:        va_start(ap, fmt);
                    721:        kprintf(fmt, TOCONS, NULL, NULL, ap);
                    722:        va_end(ap);
                    723:
                    724:        KPRINTF_MUTEX_EXIT(s);
1.88      thorpej   725: }
1.12      cgd       726:
1.45      chuck     727: /*
1.76      tv        728:  * normal kernel printf functions: printf, vprintf, snprintf, vsnprintf
1.45      chuck     729:  */
1.12      cgd       730:
1.45      chuck     731: /*
                    732:  * printf: print a message to the console and the log
                    733:  */
1.12      cgd       734: void
1.30      christos  735: printf(const char *fmt, ...)
1.12      cgd       736: {
                    737:        va_list ap;
1.66      thorpej   738:        int s;
1.54      thorpej   739:
                    740:        KPRINTF_MUTEX_ENTER(s);
1.12      cgd       741:
                    742:        va_start(ap, fmt);
1.45      chuck     743:        kprintf(fmt, TOCONS | TOLOG, NULL, NULL, ap);
1.12      cgd       744:        va_end(ap);
1.54      thorpej   745:
                    746:        KPRINTF_MUTEX_EXIT(s);
                    747:
1.12      cgd       748:        if (!panicstr)
                    749:                logwakeup();
                    750: }
                    751:
1.45      chuck     752: /*
                    753:  * vprintf: print a message to the console and the log [already have
                    754:  *     va_alist]
                    755:  */
                    756:
1.40      thorpej   757: void
1.99      thorpej   758: vprintf(const char *fmt, va_list ap)
1.40      thorpej   759: {
1.66      thorpej   760:        int s;
1.54      thorpej   761:
                    762:        KPRINTF_MUTEX_ENTER(s);
1.40      thorpej   763:
1.45      chuck     764:        kprintf(fmt, TOCONS | TOLOG, NULL, NULL, ap);
1.54      thorpej   765:
                    766:        KPRINTF_MUTEX_EXIT(s);
                    767:
1.40      thorpej   768:        if (!panicstr)
                    769:                logwakeup();
                    770: }
                    771:
1.12      cgd       772: /*
1.45      chuck     773:  * sprintf: print a message to a buffer
1.12      cgd       774:  */
1.45      chuck     775: int
1.98      christos  776: sprintf(char *bf, const char *fmt, ...)
1.45      chuck     777: {
                    778:        int retval;
1.12      cgd       779:        va_list ap;
                    780:
1.45      chuck     781:        va_start(ap, fmt);
1.98      christos  782:        retval = kprintf(fmt, TOBUFONLY, NULL, bf, ap);
1.12      cgd       783:        va_end(ap);
1.98      christos  784:        *(bf + retval) = 0;     /* null terminate */
1.45      chuck     785:        return(retval);
1.55      thorpej   786: }
                    787:
                    788: /*
                    789:  * vsprintf: print a message to a buffer [already have va_alist]
                    790:  */
                    791:
                    792: int
1.99      thorpej   793: vsprintf(char *bf, const char *fmt, va_list ap)
1.55      thorpej   794: {
                    795:        int retval;
                    796:
1.98      christos  797:        retval = kprintf(fmt, TOBUFONLY, NULL, bf, ap);
                    798:        *(bf + retval) = 0;     /* null terminate */
1.55      thorpej   799:        return (retval);
1.12      cgd       800: }
                    801:
                    802: /*
1.58      msaitoh   803:  * snprintf: print a message to a buffer
                    804:  */
                    805: int
1.98      christos  806: snprintf(char *bf, size_t size, const char *fmt, ...)
1.58      msaitoh   807: {
                    808:        int retval;
                    809:        va_list ap;
                    810:        char *p;
                    811:
                    812:        if (size < 1)
                    813:                return (-1);
1.98      christos  814:        p = bf + size - 1;
1.58      msaitoh   815:        va_start(ap, fmt);
1.98      christos  816:        retval = kprintf(fmt, TOBUFONLY, &p, bf, ap);
1.58      msaitoh   817:        va_end(ap);
                    818:        *(p) = 0;       /* null terminate */
                    819:        return(retval);
                    820: }
                    821:
                    822: /*
                    823:  * vsnprintf: print a message to a buffer [already have va_alist]
                    824:  */
                    825: int
1.99      thorpej   826: vsnprintf(char *bf, size_t size, const char *fmt, va_list ap)
1.58      msaitoh   827: {
                    828:        int retval;
                    829:        char *p;
                    830:
                    831:        if (size < 1)
                    832:                return (-1);
1.98      christos  833:        p = bf + size - 1;
                    834:        retval = kprintf(fmt, TOBUFONLY, &p, bf, ap);
1.58      msaitoh   835:        *(p) = 0;       /* null terminate */
                    836:        return(retval);
                    837: }
                    838:
                    839: /*
1.76      tv        840:  * bitmask_snprintf: print an interpreted bitmask to a buffer
1.45      chuck     841:  *
                    842:  * => returns pointer to the buffer
1.37      thorpej   843:  */
                    844: char *
1.99      thorpej   845: bitmask_snprintf(u_quad_t val, const char *p, char *bf, size_t buflen)
1.37      thorpej   846: {
                    847:        char *bp, *q;
                    848:        size_t left;
1.98      christos  849:        const char *sbase;
                    850:        char snbuf[KPRINTF_BUFSIZE];
1.51      pk        851:        int base, bit, ch, len, sep;
                    852:        u_quad_t field;
1.37      thorpej   853:
1.98      christos  854:        bp = bf;
                    855:        memset(bf, 0, buflen);
1.37      thorpej   856:
                    857:        /*
                    858:         * Always leave room for the trailing NULL.
                    859:         */
                    860:        left = buflen - 1;
                    861:
                    862:        /*
                    863:         * Print the value into the buffer.  Abort if there's not
                    864:         * enough room.
                    865:         */
1.45      chuck     866:        if (buflen < KPRINTF_BUFSIZE)
1.98      christos  867:                return (bf);
1.37      thorpej   868:
1.51      pk        869:        ch = *p++;
                    870:        base = ch != '\177' ? ch : *p++;
                    871:        sbase = base == 8 ? "%qo" : base == 10 ? "%qd" : base == 16 ? "%qx" : 0;
                    872:        if (sbase == 0)
1.98      christos  873:                return (bf);    /* punt if not oct, dec, or hex */
1.45      chuck     874:
1.76      tv        875:        snprintf(snbuf, sizeof(snbuf), sbase, val);
1.45      chuck     876:        for (q = snbuf ; *q ; q++) {
                    877:                *bp++ = *q;
1.37      thorpej   878:                left--;
                    879:        }
                    880:
                    881:        /*
1.65      sommerfe  882:         * If the value we printed was 0 and we're using the old-style format,
                    883:         * or if we don't have room for "<x>", we're done.
1.37      thorpej   884:         */
1.65      sommerfe  885:        if (((val == 0) && (ch != '\177')) || left < 3)
1.98      christos  886:                return (bf);
1.37      thorpej   887:
1.83      enami     888: #define PUTBYTE(b, c, l) do {  \
1.37      thorpej   889:        *(b)++ = (c);           \
                    890:        if (--(l) == 0)         \
1.83      enami     891:                goto out;       \
1.86      perry     892: } while (/*CONSTCOND*/ 0)
1.51      pk        893: #define PUTSTR(b, p, l) do {           \
                    894:        int c;                          \
                    895:        while ((c = *(p)++) != 0) {     \
                    896:                *(b)++ = c;             \
                    897:                if (--(l) == 0)         \
                    898:                        goto out;       \
                    899:        }                               \
1.86      perry     900: } while (/*CONSTCOND*/ 0)
1.37      thorpej   901:
1.51      pk        902:        /*
1.76      tv        903:         * Chris Torek's new bitmask format is identified by a leading \177
1.51      pk        904:         */
                    905:        sep = '<';
                    906:        if (ch != '\177') {
1.76      tv        907:                /* old (standard) format. */
1.51      pk        908:                for (;(bit = *p++) != 0;) {
                    909:                        if (val & (1 << (bit - 1))) {
                    910:                                PUTBYTE(bp, sep, left);
                    911:                                for (; (ch = *p) > ' '; ++p) {
                    912:                                        PUTBYTE(bp, ch, left);
1.37      thorpej   913:                                }
1.51      pk        914:                                sep = ',';
                    915:                        } else
                    916:                                for (; *p > ' '; ++p)
                    917:                                        continue;
                    918:                }
                    919:        } else {
1.76      tv        920:                /* new quad-capable format; also does fields. */
1.51      pk        921:                field = val;
                    922:                while ((ch = *p++) != '\0') {
                    923:                        bit = *p++;     /* now 0-origin */
                    924:                        switch (ch) {
                    925:                        case 'b':
                    926:                                if (((u_int)(val >> bit) & 1) == 0)
                    927:                                        goto skip;
                    928:                                PUTBYTE(bp, sep, left);
                    929:                                PUTSTR(bp, p, left);
                    930:                                sep = ',';
                    931:                                break;
                    932:                        case 'f':
                    933:                        case 'F':
                    934:                                len = *p++;     /* field length */
                    935:                                field = (val >> bit) & ((1ULL << len) - 1);
                    936:                                if (ch == 'F')  /* just extract */
                    937:                                        break;
                    938:                                PUTBYTE(bp, sep, left);
                    939:                                sep = ',';
                    940:                                PUTSTR(bp, p, left);
                    941:                                PUTBYTE(bp, '=', left);
                    942:                                sprintf(snbuf, sbase, field);
                    943:                                q = snbuf; PUTSTR(bp, q, left);
                    944:                                break;
                    945:                        case '=':
                    946:                        case ':':
                    947:                                /*
                    948:                                 * Here "bit" is actually a value instead,
                    949:                                 * to be compared against the last field.
                    950:                                 * This only works for values in [0..255],
                    951:                                 * of course.
                    952:                                 */
                    953:                                if ((int)field != bit)
                    954:                                        goto skip;
                    955:                                if (ch == '=')
                    956:                                        PUTBYTE(bp, '=', left);
                    957:                                PUTSTR(bp, p, left);
                    958:                                break;
                    959:                        default:
                    960:                        skip:
                    961:                                while (*p++ != '\0')
                    962:                                        continue;
                    963:                                break;
                    964:                        }
                    965:                }
1.37      thorpej   966:        }
1.51      pk        967:        if (sep != '<')
                    968:                PUTBYTE(bp, '>', left);
                    969:
                    970: out:
1.98      christos  971:        return (bf);
1.37      thorpej   972:
                    973: #undef PUTBYTE
1.51      pk        974: #undef PUTSTR
1.45      chuck     975: }
                    976:
                    977: /*
                    978:  * kprintf: scaled down version of printf(3).
                    979:  *
1.96      perry     980:  * this version based on vfprintf() from libc which was derived from
1.45      chuck     981:  * software contributed to Berkeley by Chris Torek.
                    982:  *
1.76      tv        983:  * NOTE: The kprintf mutex must be held if we're going TOBUF or TOCONS!
1.45      chuck     984:  */
                    985:
                    986: /*
                    987:  * macros for converting digits to letters and vice versa
                    988:  */
                    989: #define        to_digit(c)     ((c) - '0')
                    990: #define is_digit(c)    ((unsigned)to_digit(c) <= 9)
                    991: #define        to_char(n)      ((n) + '0')
                    992:
                    993: /*
                    994:  * flags used during conversion.
                    995:  */
                    996: #define        ALT             0x001           /* alternate form */
                    997: #define        HEXPREFIX       0x002           /* add 0x or 0X prefix */
                    998: #define        LADJUST         0x004           /* left adjustment */
                    999: #define        LONGDBL         0x008           /* long double; unimplemented */
                   1000: #define        LONGINT         0x010           /* long integer */
                   1001: #define        QUADINT         0x020           /* quad integer */
                   1002: #define        SHORTINT        0x040           /* short integer */
1.78      kleink   1003: #define        MAXINT          0x080           /* intmax_t */
                   1004: #define        PTRINT          0x100           /* intptr_t */
                   1005: #define        SIZEINT         0x200           /* size_t */
                   1006: #define        ZEROPAD         0x400           /* zero (as opposed to blank) pad */
                   1007: #define FPT            0x800           /* Floating point number */
1.45      chuck    1008:
                   1009:        /*
                   1010:         * To extend shorts properly, we need both signed and unsigned
                   1011:         * argument extraction methods.
                   1012:         */
                   1013: #define        SARG() \
1.78      kleink   1014:        (flags&MAXINT ? va_arg(ap, intmax_t) : \
                   1015:            flags&PTRINT ? va_arg(ap, intptr_t) : \
                   1016:            flags&SIZEINT ? va_arg(ap, ssize_t) : /* XXX */ \
                   1017:            flags&QUADINT ? va_arg(ap, quad_t) : \
1.45      chuck    1018:            flags&LONGINT ? va_arg(ap, long) : \
                   1019:            flags&SHORTINT ? (long)(short)va_arg(ap, int) : \
                   1020:            (long)va_arg(ap, int))
                   1021: #define        UARG() \
1.78      kleink   1022:        (flags&MAXINT ? va_arg(ap, uintmax_t) : \
                   1023:            flags&PTRINT ? va_arg(ap, uintptr_t) : \
                   1024:            flags&SIZEINT ? va_arg(ap, size_t) : \
                   1025:            flags&QUADINT ? va_arg(ap, u_quad_t) : \
1.45      chuck    1026:            flags&LONGINT ? va_arg(ap, u_long) : \
                   1027:            flags&SHORTINT ? (u_long)(u_short)va_arg(ap, int) : \
                   1028:            (u_long)va_arg(ap, u_int))
                   1029:
1.60      explorer 1030: #define KPRINTF_PUTCHAR(C) {                                           \
                   1031:        if (oflags == TOBUFONLY) {                                      \
                   1032:                if ((vp != NULL) && (sbuf == tailp)) {                  \
                   1033:                        ret += 1;               /* indicate error */    \
                   1034:                        goto overflow;                                  \
                   1035:                }                                                       \
                   1036:                *sbuf++ = (C);                                          \
                   1037:        } else {                                                        \
                   1038:                putchar((C), oflags, (struct tty *)vp);                 \
                   1039:        }                                                               \
1.58      msaitoh  1040: }
1.45      chuck    1041:
1.54      thorpej  1042: /*
                   1043:  * Guts of kernel printf.  Note, we already expect to be in a mutex!
                   1044:  */
1.87      thorpej  1045: int
1.99      thorpej  1046: kprintf(const char *fmt0, int oflags, void *vp, char *sbuf, va_list ap)
1.45      chuck    1047: {
1.98      christos 1048:        const char *fmt;        /* format string */
1.45      chuck    1049:        int ch;                 /* character from fmt */
                   1050:        int n;                  /* handy integer (short term usage) */
                   1051:        char *cp;               /* handy char pointer (short term usage) */
                   1052:        int flags;              /* flags as above */
                   1053:        int ret;                /* return value accumulator */
                   1054:        int width;              /* width from format (%8d), or 0 */
                   1055:        int prec;               /* precision from format (%.3d), or -1 */
                   1056:        char sign;              /* sign prefix (' ', '+', '-', or \0) */
                   1057:
                   1058:        u_quad_t _uquad;        /* integer arguments %[diouxX] */
                   1059:        enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */
                   1060:        int dprec;              /* a copy of prec if [diouxX], 0 otherwise */
                   1061:        int realsz;             /* field size expanded by dprec */
                   1062:        int size;               /* size of converted field or string */
1.97      christos 1063:        const char *xdigs;      /* digits for [xX] conversion */
1.98      christos 1064:        char bf[KPRINTF_BUFSIZE]; /* space for %c, %[diouxX] */
1.61      explorer 1065:        char *tailp;            /* tail pointer for snprintf */
1.58      msaitoh  1066:
1.61      explorer 1067:        tailp = NULL;   /* XXX: shutup gcc */
1.60      explorer 1068:        if (oflags == TOBUFONLY && (vp != NULL))
                   1069:                tailp = *(char **)vp;
1.45      chuck    1070:
                   1071:        cp = NULL;      /* XXX: shutup gcc */
                   1072:        size = 0;       /* XXX: shutup gcc */
                   1073:
1.98      christos 1074:        fmt = fmt0;
1.45      chuck    1075:        ret = 0;
                   1076:
                   1077:        xdigs = NULL;           /* XXX: shut up gcc warning */
                   1078:
                   1079:        /*
                   1080:         * Scan the format for conversions (`%' character).
                   1081:         */
                   1082:        for (;;) {
                   1083:                while (*fmt != '%' && *fmt) {
1.58      msaitoh  1084:                        ret++;
1.45      chuck    1085:                        KPRINTF_PUTCHAR(*fmt++);
                   1086:                }
                   1087:                if (*fmt == 0)
                   1088:                        goto done;
                   1089:
                   1090:                fmt++;          /* skip over '%' */
                   1091:
                   1092:                flags = 0;
                   1093:                dprec = 0;
                   1094:                width = 0;
                   1095:                prec = -1;
                   1096:                sign = '\0';
                   1097:
                   1098: rflag:         ch = *fmt++;
                   1099: reswitch:      switch (ch) {
                   1100:                case ' ':
                   1101:                        /*
                   1102:                         * ``If the space and + flags both appear, the space
                   1103:                         * flag will be ignored.''
                   1104:                         *      -- ANSI X3J11
                   1105:                         */
                   1106:                        if (!sign)
                   1107:                                sign = ' ';
                   1108:                        goto rflag;
                   1109:                case '#':
                   1110:                        flags |= ALT;
                   1111:                        goto rflag;
                   1112:                case '*':
                   1113:                        /*
                   1114:                         * ``A negative field width argument is taken as a
                   1115:                         * - flag followed by a positive field width.''
                   1116:                         *      -- ANSI X3J11
                   1117:                         * They don't exclude field widths read from args.
                   1118:                         */
                   1119:                        if ((width = va_arg(ap, int)) >= 0)
                   1120:                                goto rflag;
                   1121:                        width = -width;
                   1122:                        /* FALLTHROUGH */
                   1123:                case '-':
                   1124:                        flags |= LADJUST;
                   1125:                        goto rflag;
                   1126:                case '+':
                   1127:                        sign = '+';
                   1128:                        goto rflag;
                   1129:                case '.':
                   1130:                        if ((ch = *fmt++) == '*') {
                   1131:                                n = va_arg(ap, int);
                   1132:                                prec = n < 0 ? -1 : n;
                   1133:                                goto rflag;
                   1134:                        }
                   1135:                        n = 0;
                   1136:                        while (is_digit(ch)) {
                   1137:                                n = 10 * n + to_digit(ch);
                   1138:                                ch = *fmt++;
                   1139:                        }
                   1140:                        prec = n < 0 ? -1 : n;
                   1141:                        goto reswitch;
                   1142:                case '0':
                   1143:                        /*
                   1144:                         * ``Note that 0 is taken as a flag, not as the
                   1145:                         * beginning of a field width.''
                   1146:                         *      -- ANSI X3J11
                   1147:                         */
                   1148:                        flags |= ZEROPAD;
                   1149:                        goto rflag;
                   1150:                case '1': case '2': case '3': case '4':
                   1151:                case '5': case '6': case '7': case '8': case '9':
                   1152:                        n = 0;
                   1153:                        do {
                   1154:                                n = 10 * n + to_digit(ch);
                   1155:                                ch = *fmt++;
                   1156:                        } while (is_digit(ch));
                   1157:                        width = n;
                   1158:                        goto reswitch;
                   1159:                case 'h':
                   1160:                        flags |= SHORTINT;
                   1161:                        goto rflag;
1.78      kleink   1162:                case 'j':
                   1163:                        flags |= MAXINT;
                   1164:                        goto rflag;
1.45      chuck    1165:                case 'l':
                   1166:                        if (*fmt == 'l') {
                   1167:                                fmt++;
                   1168:                                flags |= QUADINT;
                   1169:                        } else {
                   1170:                                flags |= LONGINT;
                   1171:                        }
                   1172:                        goto rflag;
                   1173:                case 'q':
                   1174:                        flags |= QUADINT;
                   1175:                        goto rflag;
1.78      kleink   1176:                case 't':
                   1177:                        flags |= PTRINT;
                   1178:                        goto rflag;
                   1179:                case 'z':
                   1180:                        flags |= SIZEINT;
                   1181:                        goto rflag;
1.45      chuck    1182:                case 'c':
1.98      christos 1183:                        *(cp = bf) = va_arg(ap, int);
1.45      chuck    1184:                        size = 1;
                   1185:                        sign = '\0';
                   1186:                        break;
                   1187:                case 'D':
                   1188:                        flags |= LONGINT;
                   1189:                        /*FALLTHROUGH*/
                   1190:                case 'd':
                   1191:                case 'i':
                   1192:                        _uquad = SARG();
                   1193:                        if ((quad_t)_uquad < 0) {
                   1194:                                _uquad = -_uquad;
                   1195:                                sign = '-';
                   1196:                        }
                   1197:                        base = DEC;
                   1198:                        goto number;
                   1199:                case 'n':
1.78      kleink   1200:                        if (flags & MAXINT)
                   1201:                                *va_arg(ap, intmax_t *) = ret;
                   1202:                        else if (flags & PTRINT)
                   1203:                                *va_arg(ap, intptr_t *) = ret;
                   1204:                        else if (flags & SIZEINT)
                   1205:                                *va_arg(ap, ssize_t *) = ret;
                   1206:                        else if (flags & QUADINT)
1.45      chuck    1207:                                *va_arg(ap, quad_t *) = ret;
                   1208:                        else if (flags & LONGINT)
                   1209:                                *va_arg(ap, long *) = ret;
                   1210:                        else if (flags & SHORTINT)
                   1211:                                *va_arg(ap, short *) = ret;
                   1212:                        else
                   1213:                                *va_arg(ap, int *) = ret;
                   1214:                        continue;       /* no output */
                   1215:                case 'O':
                   1216:                        flags |= LONGINT;
                   1217:                        /*FALLTHROUGH*/
                   1218:                case 'o':
                   1219:                        _uquad = UARG();
                   1220:                        base = OCT;
                   1221:                        goto nosign;
                   1222:                case 'p':
                   1223:                        /*
                   1224:                         * ``The argument shall be a pointer to void.  The
                   1225:                         * value of the pointer is converted to a sequence
                   1226:                         * of printable characters, in an implementation-
                   1227:                         * defined manner.''
                   1228:                         *      -- ANSI X3J11
                   1229:                         */
                   1230:                        /* NOSTRICT */
                   1231:                        _uquad = (u_long)va_arg(ap, void *);
                   1232:                        base = HEX;
1.97      christos 1233:                        xdigs = hexdigits;
1.45      chuck    1234:                        flags |= HEXPREFIX;
                   1235:                        ch = 'x';
                   1236:                        goto nosign;
                   1237:                case 's':
                   1238:                        if ((cp = va_arg(ap, char *)) == NULL)
1.98      christos 1239:                                /*XXXUNCONST*/
                   1240:                                cp = __UNCONST("(null)");
1.45      chuck    1241:                        if (prec >= 0) {
                   1242:                                /*
                   1243:                                 * can't use strlen; can only look for the
                   1244:                                 * NUL in the first `prec' characters, and
                   1245:                                 * strlen() will go further.
                   1246:                                 */
                   1247:                                char *p = memchr(cp, 0, prec);
                   1248:
                   1249:                                if (p != NULL) {
                   1250:                                        size = p - cp;
                   1251:                                        if (size > prec)
                   1252:                                                size = prec;
                   1253:                                } else
                   1254:                                        size = prec;
                   1255:                        } else
                   1256:                                size = strlen(cp);
                   1257:                        sign = '\0';
                   1258:                        break;
                   1259:                case 'U':
                   1260:                        flags |= LONGINT;
                   1261:                        /*FALLTHROUGH*/
                   1262:                case 'u':
                   1263:                        _uquad = UARG();
                   1264:                        base = DEC;
                   1265:                        goto nosign;
                   1266:                case 'X':
1.97      christos 1267:                        xdigs = hexdigits;
1.45      chuck    1268:                        goto hex;
                   1269:                case 'x':
1.97      christos 1270:                        xdigs = hexdigits;
1.45      chuck    1271: hex:                   _uquad = UARG();
                   1272:                        base = HEX;
                   1273:                        /* leading 0x/X only if non-zero */
                   1274:                        if (flags & ALT && _uquad != 0)
                   1275:                                flags |= HEXPREFIX;
                   1276:
                   1277:                        /* unsigned conversions */
                   1278: nosign:                        sign = '\0';
                   1279:                        /*
                   1280:                         * ``... diouXx conversions ... if a precision is
                   1281:                         * specified, the 0 flag will be ignored.''
                   1282:                         *      -- ANSI X3J11
                   1283:                         */
                   1284: number:                        if ((dprec = prec) >= 0)
                   1285:                                flags &= ~ZEROPAD;
                   1286:
                   1287:                        /*
                   1288:                         * ``The result of converting a zero value with an
                   1289:                         * explicit precision of zero is no characters.''
                   1290:                         *      -- ANSI X3J11
                   1291:                         */
1.98      christos 1292:                        cp = bf + KPRINTF_BUFSIZE;
1.45      chuck    1293:                        if (_uquad != 0 || prec != 0) {
                   1294:                                /*
                   1295:                                 * Unsigned mod is hard, and unsigned mod
                   1296:                                 * by a constant is easier than that by
                   1297:                                 * a variable; hence this switch.
                   1298:                                 */
                   1299:                                switch (base) {
                   1300:                                case OCT:
                   1301:                                        do {
                   1302:                                                *--cp = to_char(_uquad & 7);
                   1303:                                                _uquad >>= 3;
                   1304:                                        } while (_uquad);
                   1305:                                        /* handle octal leading 0 */
                   1306:                                        if (flags & ALT && *cp != '0')
                   1307:                                                *--cp = '0';
                   1308:                                        break;
                   1309:
                   1310:                                case DEC:
                   1311:                                        /* many numbers are 1 digit */
                   1312:                                        while (_uquad >= 10) {
                   1313:                                                *--cp = to_char(_uquad % 10);
                   1314:                                                _uquad /= 10;
                   1315:                                        }
                   1316:                                        *--cp = to_char(_uquad);
                   1317:                                        break;
                   1318:
                   1319:                                case HEX:
                   1320:                                        do {
                   1321:                                                *--cp = xdigs[_uquad & 15];
                   1322:                                                _uquad >>= 4;
                   1323:                                        } while (_uquad);
                   1324:                                        break;
                   1325:
                   1326:                                default:
1.98      christos 1327:                                        /*XXXUNCONST*/
                   1328:                                        cp = __UNCONST("bug in kprintf: bad base");
1.45      chuck    1329:                                        size = strlen(cp);
                   1330:                                        goto skipsize;
                   1331:                                }
                   1332:                        }
1.98      christos 1333:                        size = bf + KPRINTF_BUFSIZE - cp;
1.45      chuck    1334:                skipsize:
                   1335:                        break;
                   1336:                default:        /* "%?" prints ?, unless ? is NUL */
                   1337:                        if (ch == '\0')
                   1338:                                goto done;
                   1339:                        /* pretend it was %c with argument ch */
1.98      christos 1340:                        cp = bf;
1.45      chuck    1341:                        *cp = ch;
                   1342:                        size = 1;
                   1343:                        sign = '\0';
                   1344:                        break;
                   1345:                }
                   1346:
                   1347:                /*
                   1348:                 * All reasonable formats wind up here.  At this point, `cp'
                   1349:                 * points to a string which (if not flags&LADJUST) should be
                   1350:                 * padded out to `width' places.  If flags&ZEROPAD, it should
                   1351:                 * first be prefixed by any sign or other prefix; otherwise,
                   1352:                 * it should be blank padded before the prefix is emitted.
                   1353:                 * After any left-hand padding and prefixing, emit zeroes
                   1354:                 * required by a decimal [diouxX] precision, then print the
                   1355:                 * string proper, then emit zeroes required by any leftover
                   1356:                 * floating precision; finally, if LADJUST, pad with blanks.
                   1357:                 *
                   1358:                 * Compute actual size, so we know how much to pad.
                   1359:                 * size excludes decimal prec; realsz includes it.
                   1360:                 */
                   1361:                realsz = dprec > size ? dprec : size;
                   1362:                if (sign)
                   1363:                        realsz++;
                   1364:                else if (flags & HEXPREFIX)
                   1365:                        realsz+= 2;
                   1366:
1.58      msaitoh  1367:                /* adjust ret */
                   1368:                ret += width > realsz ? width : realsz;
                   1369:
1.45      chuck    1370:                /* right-adjusting blank padding */
                   1371:                if ((flags & (LADJUST|ZEROPAD)) == 0) {
                   1372:                        n = width - realsz;
                   1373:                        while (n-- > 0)
                   1374:                                KPRINTF_PUTCHAR(' ');
                   1375:                }
                   1376:
                   1377:                /* prefix */
                   1378:                if (sign) {
                   1379:                        KPRINTF_PUTCHAR(sign);
                   1380:                } else if (flags & HEXPREFIX) {
                   1381:                        KPRINTF_PUTCHAR('0');
                   1382:                        KPRINTF_PUTCHAR(ch);
                   1383:                }
                   1384:
                   1385:                /* right-adjusting zero padding */
                   1386:                if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD) {
                   1387:                        n = width - realsz;
                   1388:                        while (n-- > 0)
                   1389:                                KPRINTF_PUTCHAR('0');
                   1390:                }
                   1391:
                   1392:                /* leading zeroes from decimal precision */
                   1393:                n = dprec - size;
                   1394:                while (n-- > 0)
                   1395:                        KPRINTF_PUTCHAR('0');
                   1396:
                   1397:                /* the string or number proper */
                   1398:                while (size--)
                   1399:                        KPRINTF_PUTCHAR(*cp++);
                   1400:                /* left-adjusting padding (always blank) */
                   1401:                if (flags & LADJUST) {
                   1402:                        n = width - realsz;
                   1403:                        while (n-- > 0)
                   1404:                                KPRINTF_PUTCHAR(' ');
                   1405:                }
1.58      msaitoh  1406:        }
1.45      chuck    1407:
                   1408: done:
1.58      msaitoh  1409:        if ((oflags == TOBUFONLY) && (vp != NULL))
                   1410:                *(char **)vp = sbuf;
1.92      matt     1411:        (*v_flush)();
1.58      msaitoh  1412: overflow:
1.45      chuck    1413:        return (ret);
                   1414:        /* NOTREACHED */
1.12      cgd      1415: }

CVSweb <webmaster@jp.NetBSD.org>