[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.124.2.1

1.124.2.1! skrll       1: /*     $NetBSD: subr_prf.c,v 1.129 2009/01/02 22:03:00 pooka 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.124.2.1! skrll      40: __KERNEL_RCSID(0, "$NetBSD: subr_prf.c,v 1.129 2009/01/02 22:03:00 pooka 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.90      atatat     45: #include "opt_dump.h"
1.12      cgd        46:
                     47: #include <sys/param.h>
1.78      kleink     48: #include <sys/stdint.h>
1.12      cgd        49: #include <sys/systm.h>
                     50: #include <sys/buf.h>
1.109     he         51: #include <sys/device.h>
1.12      cgd        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.87      thorpej    62: #include <sys/kprintf.h>
1.115     ad         63: #include <sys/atomic.h>
1.124.2.1! skrll      64: #include <sys/kernel.h>
1.116     dogcow     65: #include <sys/cpu.h>
1.12      cgd        66:
1.20      christos   67: #include <dev/cons.h>
                     68:
1.108     joerg      69: #include <net/if.h>
                     70:
1.49      jonathan   71: #ifdef DDB
                     72: #include <ddb/ddbvar.h>
1.72      jhawk      73: #include <machine/db_machdep.h>
                     74: #include <ddb/db_command.h>
                     75: #include <ddb/db_interface.h>
1.49      jonathan   76: #endif
                     77:
1.67      ws         78: #ifdef IPKDB
                     79: #include <ipkdb/ipkdb.h>
                     80: #endif
                     81:
1.124.2.1! skrll      82: static kmutex_t kprintf_mtx;
        !            83: static bool kprintf_inited = false;
1.49      jonathan   84:
1.12      cgd        85: /*
1.45      chuck      86:  * note that stdarg.h and the ansi style va_start macro is used for both
                     87:  * ansi and traditional c complers.
                     88:  * XXX: this requires that stdarg.h define: va_alist and va_dcl
1.12      cgd        89:  */
                     90: #include <machine/stdarg.h>
                     91:
1.28      ws         92:
1.22      christos   93: #ifdef KGDB
1.42      thorpej    94: #include <sys/kgdb.h>
1.12      cgd        95: #endif
1.45      chuck      96: #ifdef DDB
                     97: #include <ddb/db_output.h>     /* db_printf, db_putchar prototypes */
                     98: #endif
                     99:
                    100:
                    101: /*
                    102:  * defines
                    103:  */
                    104:
                    105:
                    106: /*
                    107:  * local prototypes
                    108:  */
                    109:
1.94      junyoung  110: static void     putchar(int, int, struct tty *);
1.20      christos  111:
1.12      cgd       112:
1.37      thorpej   113: /*
1.45      chuck     114:  * globals
1.37      thorpej   115:  */
                    116:
1.77      tsutsui   117: extern struct tty *constty;    /* pointer to console "window" tty */
1.45      chuck     118: extern int log_open;   /* subr_log: is /dev/klog open? */
                    119: const  char *panicstr; /* arg to first call to panic (used as a flag
                    120:                           to indicate that panic has already been called). */
1.115     ad        121: struct cpu_info *paniccpu;     /* cpu that first paniced */
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.124.2.1! skrll     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.124.2.1! skrll     150:  * Locking is inited fairly early in MI bootstrap.  Before that
        !           151:  * prints are done unlocked.  But that doesn't really matter,
        !           152:  * since nothing can preempt us before interrupts are enabled.
        !           153:  */
        !           154: void
        !           155: kprintf_init()
        !           156: {
        !           157:
        !           158:        KASSERT(!kprintf_inited && cold); /* not foolproof, but ... */
        !           159:        mutex_init(&kprintf_mtx, MUTEX_DEFAULT, IPL_HIGH);
        !           160:        kprintf_inited = true;
        !           161: }
        !           162:
        !           163: void
        !           164: kprintf_lock()
        !           165: {
        !           166:
        !           167:        if (__predict_true(kprintf_inited))
        !           168:                mutex_enter(&kprintf_mtx);
        !           169: }
        !           170:
        !           171: void
        !           172: kprintf_unlock()
        !           173: {
        !           174:
        !           175:        if (__predict_true(kprintf_inited)) {
        !           176:                /* assert kprintf wasn't somehow inited while we were in */
        !           177:                KASSERT(mutex_owned(&kprintf_mtx));
        !           178:                mutex_exit(&kprintf_mtx);
        !           179:        }
        !           180: }
        !           181:
        !           182: /*
1.89      thorpej   183:  * twiddle: spin a little propellor on the console.
                    184:  */
                    185:
                    186: void
                    187: twiddle(void)
                    188: {
                    189:        static const char twiddle_chars[] = "|/-\\";
                    190:        static int pos;
                    191:
1.124.2.1! skrll     192:        kprintf_lock();
1.89      thorpej   193:
                    194:        putchar(twiddle_chars[pos++ & 3], TOCONS, NULL);
                    195:        putchar('\b', TOCONS, NULL);
                    196:
1.124.2.1! skrll     197:        kprintf_unlock();
1.89      thorpej   198: }
                    199:
                    200: /*
1.45      chuck     201:  * panic: handle an unresolvable fatal error
                    202:  *
                    203:  * prints "panic: <message>" and reboots.   if called twice (i.e. recursive
1.96      perry     204:  * call) we avoid trying to sync the disk and just reboot (to avoid
1.45      chuck     205:  * recursive panics).
1.12      cgd       206:  */
1.45      chuck     207:
1.14      cgd       208: void
1.12      cgd       209: panic(const char *fmt, ...)
                    210: {
1.115     ad        211:        CPU_INFO_ITERATOR cii;
                    212:        struct cpu_info *ci, *oci;
1.14      cgd       213:        int bootopt;
1.12      cgd       214:        va_list ap;
                    215:
1.115     ad        216:        /*
                    217:         * Disable preemption.  If already panicing on another CPU, sit
                    218:         * here and spin until the system is rebooted.  Allow the CPU that
                    219:         * first paniced to panic again.
                    220:         */
1.120     ad        221:        kpreempt_disable();
1.115     ad        222:        ci = curcpu();
                    223:        oci = atomic_cas_ptr((void *)&paniccpu, NULL, ci);
                    224:        if (oci != NULL && oci != ci) {
                    225:                /* Give interrupts a chance to try and prevent deadlock. */
                    226:                for (;;) {
1.124.2.1! skrll     227: #ifndef _RUMPKERNEL /* XXXpooka: temporary build fix */
1.115     ad        228:                        DELAY(10);
1.124.2.1! skrll     229: #endif /* _RUMPKERNEL */
1.115     ad        230:                }
                    231:        }
                    232:
                    233:        /*
                    234:         * Convert the current thread to a bound thread and prevent all
                    235:         * CPUs from scheduling unbound jobs.  Do so without taking any
                    236:         * locks.
                    237:         */
1.117     ad        238:        curlwp->l_pflag |= LP_BOUND;
1.115     ad        239:        for (CPU_INFO_FOREACH(cii, ci)) {
                    240:                ci->ci_schedstate.spc_flags |= SPCF_OFFLINE;
                    241:        }
                    242:
1.124.2.1! skrll     243:        bootopt = RB_AUTOBOOT | RB_NOSYNC;
1.90      atatat    244:        if (dumponpanic)
                    245:                bootopt |= RB_DUMP;
1.74      sommerfe  246:        if (!panicstr)
1.12      cgd       247:                panicstr = fmt;
1.74      sommerfe  248:        doing_shutdown = 1;
1.79      simonb    249:
1.81      fvdl      250:        if (msgbufenabled && msgbufp->msg_magic == MSG_MAGIC)
1.79      simonb    251:                panicstart = msgbufp->msg_bufx;
1.96      perry     252:
1.12      cgd       253:        va_start(ap, fmt);
1.45      chuck     254:        printf("panic: ");
                    255:        vprintf(fmt, ap);
                    256:        printf("\n");
1.12      cgd       257:        va_end(ap);
1.79      simonb    258:
1.81      fvdl      259:        if (msgbufenabled && msgbufp->msg_magic == MSG_MAGIC)
1.79      simonb    260:                panicend = msgbufp->msg_bufx;
1.12      cgd       261:
1.67      ws        262: #ifdef IPKDB
1.32      ws        263:        ipkdb_panic();
1.28      ws        264: #endif
1.12      cgd       265: #ifdef KGDB
                    266:        kgdb_panic();
                    267: #endif
                    268: #ifdef KADB
1.14      cgd       269:        if (boothowto & RB_KDB)
                    270:                kdbpanic();
1.12      cgd       271: #endif
                    272: #ifdef DDB
1.101     darrenr   273:        if (db_onpanic == 1)
1.38      thorpej   274:                Debugger();
1.102     darrenr   275:        else if (db_onpanic >= 0) {
1.73      jhawk     276:                static int intrace = 0;
                    277:
1.101     darrenr   278:                if (intrace == 0) {
                    279:                        intrace = 1;
1.73      jhawk     280:                        printf("Begin traceback...\n");
                    281:                        db_stack_trace_print(
1.85      scw       282:                            (db_expr_t)(intptr_t)__builtin_frame_address(0),
1.105     thorpej   283:                            true, 65535, "", printf);
1.73      jhawk     284:                        printf("End traceback...\n");
1.101     darrenr   285:                        intrace = 0;
1.73      jhawk     286:                } else
                    287:                        printf("Faulted in mid-traceback; aborting...");
1.101     darrenr   288:                if (db_onpanic == 2)
                    289:                        Debugger();
1.72      jhawk     290:        }
1.12      cgd       291: #endif
1.39      gwr       292:        cpu_reboot(bootopt, NULL);
1.12      cgd       293: }
                    294:
                    295: /*
1.45      chuck     296:  * kernel logging functions: log, logpri, addlog
                    297:  */
                    298:
                    299: /*
                    300:  * log: write to the log buffer
                    301:  *
                    302:  * => will not sleep [so safe to call from interrupt]
                    303:  * => will log to console if /dev/klog isn't open
                    304:  */
                    305:
                    306: void
                    307: log(int level, const char *fmt, ...)
                    308: {
                    309:        va_list ap;
                    310:
1.124.2.1! skrll     311:        kprintf_lock();
1.54      thorpej   312:
                    313:        klogpri(level);         /* log the level first */
1.45      chuck     314:        va_start(ap, fmt);
                    315:        kprintf(fmt, TOLOG, NULL, NULL, ap);
                    316:        va_end(ap);
                    317:        if (!log_open) {
                    318:                va_start(ap, fmt);
                    319:                kprintf(fmt, TOCONS, NULL, NULL, ap);
                    320:                va_end(ap);
                    321:        }
1.64      thorpej   322:
1.124.2.1! skrll     323:        kprintf_unlock();
1.64      thorpej   324:
                    325:        logwakeup();            /* wake up anyone waiting for log msgs */
                    326: }
                    327:
                    328: /*
                    329:  * vlog: write to the log buffer [already have va_alist]
                    330:  */
                    331:
                    332: void
1.99      thorpej   333: vlog(int level, const char *fmt, va_list ap)
1.64      thorpej   334: {
                    335:
1.124.2.1! skrll     336:        kprintf_lock();
1.64      thorpej   337:
                    338:        klogpri(level);         /* log the level first */
                    339:        kprintf(fmt, TOLOG, NULL, NULL, ap);
                    340:        if (!log_open)
                    341:                kprintf(fmt, TOCONS, NULL, NULL, ap);
1.54      thorpej   342:
1.124.2.1! skrll     343:        kprintf_unlock();
1.54      thorpej   344:
1.45      chuck     345:        logwakeup();            /* wake up anyone waiting for log msgs */
                    346: }
                    347:
                    348: /*
                    349:  * logpri: log the priority level to the klog
                    350:  */
                    351:
1.54      thorpej   352: void
1.99      thorpej   353: logpri(int level)
1.45      chuck     354: {
1.54      thorpej   355:
1.124.2.1! skrll     356:        kprintf_lock();
1.54      thorpej   357:        klogpri(level);
1.124.2.1! skrll     358:        kprintf_unlock();
1.54      thorpej   359: }
                    360:
                    361: /*
                    362:  * Note: we must be in the mutex here!
                    363:  */
1.87      thorpej   364: void
1.99      thorpej   365: klogpri(int level)
1.54      thorpej   366: {
1.45      chuck     367:        char *p;
                    368:        char snbuf[KPRINTF_BUFSIZE];
                    369:
                    370:        putchar('<', TOLOG, NULL);
1.76      tv        371:        snprintf(snbuf, sizeof(snbuf), "%d", level);
1.45      chuck     372:        for (p = snbuf ; *p ; p++)
                    373:                putchar(*p, TOLOG, NULL);
                    374:        putchar('>', TOLOG, NULL);
                    375: }
                    376:
                    377: /*
                    378:  * addlog: add info to previous log message
1.12      cgd       379:  */
1.45      chuck     380:
1.12      cgd       381: void
1.45      chuck     382: addlog(const char *fmt, ...)
                    383: {
                    384:        va_list ap;
                    385:
1.124.2.1! skrll     386:        kprintf_lock();
1.54      thorpej   387:
1.45      chuck     388:        va_start(ap, fmt);
                    389:        kprintf(fmt, TOLOG, NULL, NULL, ap);
                    390:        va_end(ap);
                    391:        if (!log_open) {
                    392:                va_start(ap, fmt);
                    393:                kprintf(fmt, TOCONS, NULL, NULL, ap);
                    394:                va_end(ap);
                    395:        }
1.54      thorpej   396:
1.124.2.1! skrll     397:        kprintf_unlock();
1.54      thorpej   398:
1.45      chuck     399:        logwakeup();
                    400: }
                    401:
                    402:
                    403: /*
                    404:  * putchar: print a single character on console or user terminal.
                    405:  *
                    406:  * => if console, then the last MSGBUFS chars are saved in msgbuf
                    407:  *     for inspection later (e.g. dmesg/syslog)
1.54      thorpej   408:  * => we must already be in the mutex!
1.45      chuck     409:  */
                    410: static void
1.99      thorpej   411: putchar(int c, int flags, struct tty *tp)
1.12      cgd       412: {
                    413:
1.45      chuck     414:        if (panicstr)
                    415:                constty = NULL;
                    416:        if ((flags & TOCONS) && tp == NULL && constty) {
                    417:                tp = constty;
                    418:                flags |= TOTTY;
                    419:        }
1.91      christos  420:        if ((flags & TOTTY) && tp &&
                    421:            tputchar(c, flags, tp) < 0 &&
1.45      chuck     422:            (flags & TOCONS) && tp == constty)
                    423:                constty = NULL;
                    424:        if ((flags & TOLOG) &&
1.111     ad        425:            c != '\0' && c != '\r' && c != 0177)
                    426:                logputchar(c);
1.45      chuck     427:        if ((flags & TOCONS) && constty == NULL && c != '\0')
                    428:                (*v_putc)(c);
                    429: #ifdef DDB
                    430:        if (flags & TODDB)
                    431:                db_putchar(c);
                    432: #endif
1.12      cgd       433: }
                    434:
1.124.2.1! skrll     435: /*
        !           436:  * tablefull: warn that a system table is full
        !           437:  */
        !           438:
        !           439: void
        !           440: tablefull(const char *tab, const char *hint)
        !           441: {
        !           442:        if (hint)
        !           443:                log(LOG_ERR, "%s: table is full - %s\n", tab, hint);
        !           444:        else
        !           445:                log(LOG_ERR, "%s: table is full\n", tab);
        !           446: }
        !           447:
1.45      chuck     448:
1.12      cgd       449: /*
1.45      chuck     450:  * uprintf: print to the controlling tty of the current process
                    451:  *
                    452:  * => we may block if the tty queue is full
                    453:  * => no message is printed if the queue doesn't clear in a reasonable
                    454:  *     time
1.12      cgd       455:  */
1.45      chuck     456:
1.12      cgd       457: void
                    458: uprintf(const char *fmt, ...)
                    459: {
1.69      augustss  460:        struct proc *p = curproc;
1.12      cgd       461:        va_list ap;
                    462:
1.119     ad        463:        /* mutex_enter(proc_lock); XXXSMP */
1.104     ad        464:
                    465:        if (p->p_lflag & PL_CONTROLT && p->p_session->s_ttyvp) {
                    466:                /* No mutex needed; going to process TTY. */
                    467:                va_start(ap, fmt);
                    468:                kprintf(fmt, TOTTY, p->p_session->s_ttyp, NULL, ap);
                    469:                va_end(ap);
                    470:        }
                    471:
1.119     ad        472:        /* mutex_exit(proc_lock); XXXSMP */
1.104     ad        473: }
                    474:
                    475: void
                    476: uprintf_locked(const char *fmt, ...)
                    477: {
                    478:        struct proc *p = curproc;
                    479:        va_list ap;
                    480:
                    481:        if (p->p_lflag & PL_CONTROLT && p->p_session->s_ttyvp) {
1.54      thorpej   482:                /* No mutex needed; going to process TTY. */
1.12      cgd       483:                va_start(ap, fmt);
1.45      chuck     484:                kprintf(fmt, TOTTY, p->p_session->s_ttyp, NULL, ap);
1.12      cgd       485:                va_end(ap);
                    486:        }
                    487: }
                    488:
1.45      chuck     489: /*
                    490:  * tprintf functions: used to send messages to a specific process
                    491:  *
                    492:  * usage:
                    493:  *   get a tpr_t handle on a process "p" by using "tprintf_open(p)"
                    494:  *   use the handle when calling "tprintf"
                    495:  *   when done, do a "tprintf_close" to drop the handle
                    496:  */
                    497:
                    498: /*
                    499:  * tprintf_open: get a tprintf handle on a process "p"
                    500:  *
                    501:  * => returns NULL if process can't be printed to
                    502:  */
                    503:
1.12      cgd       504: tpr_t
1.99      thorpej   505: tprintf_open(struct proc *p)
1.12      cgd       506: {
1.104     ad        507:        tpr_t cookie;
1.12      cgd       508:
1.104     ad        509:        cookie = NULL;
                    510:
1.119     ad        511:        mutex_enter(proc_lock);
1.104     ad        512:        if (p->p_lflag & PL_CONTROLT && p->p_session->s_ttyvp) {
1.12      cgd       513:                SESSHOLD(p->p_session);
1.104     ad        514:                cookie = (tpr_t)p->p_session;
1.12      cgd       515:        }
1.119     ad        516:        mutex_exit(proc_lock);
1.104     ad        517:
                    518:        return cookie;
1.12      cgd       519: }
                    520:
1.45      chuck     521: /*
                    522:  * tprintf_close: dispose of a tprintf handle obtained with tprintf_open
                    523:  */
                    524:
1.12      cgd       525: void
1.99      thorpej   526: tprintf_close(tpr_t sess)
1.12      cgd       527: {
                    528:
1.118     yamt      529:        if (sess) {
1.119     ad        530:                mutex_enter(proc_lock);
1.12      cgd       531:                SESSRELE((struct session *) sess);
1.119     ad        532:                mutex_exit(proc_lock);
1.118     yamt      533:        }
1.12      cgd       534: }
                    535:
                    536: /*
1.96      perry     537:  * tprintf: given tprintf handle to a process [obtained with tprintf_open],
1.45      chuck     538:  * send a message to the controlling tty for that process.
                    539:  *
                    540:  * => also sends message to /dev/klog
1.12      cgd       541:  */
                    542: void
                    543: tprintf(tpr_t tpr, const char *fmt, ...)
                    544: {
1.69      augustss  545:        struct session *sess = (struct session *)tpr;
1.12      cgd       546:        struct tty *tp = NULL;
1.124.2.1! skrll     547:        int flags = TOLOG;
1.12      cgd       548:        va_list ap;
                    549:
1.119     ad        550:        /* mutex_enter(proc_lock); XXXSMP */
1.12      cgd       551:        if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) {
                    552:                flags |= TOTTY;
                    553:                tp = sess->s_ttyp;
                    554:        }
1.54      thorpej   555:
1.124.2.1! skrll     556:        kprintf_lock();
1.54      thorpej   557:
                    558:        klogpri(LOG_INFO);
1.12      cgd       559:        va_start(ap, fmt);
1.45      chuck     560:        kprintf(fmt, flags, tp, NULL, ap);
1.12      cgd       561:        va_end(ap);
1.54      thorpej   562:
1.124.2.1! skrll     563:        kprintf_unlock();
1.119     ad        564:        /* mutex_exit(proc_lock);       XXXSMP */
1.54      thorpej   565:
1.12      cgd       566:        logwakeup();
                    567: }
                    568:
1.45      chuck     569:
1.12      cgd       570: /*
1.45      chuck     571:  * ttyprintf: send a message to a specific tty
                    572:  *
                    573:  * => should be used only by tty driver or anything that knows the
1.52      mrg       574:  *    underlying tty will not be revoked(2)'d away.  [otherwise,
                    575:  *    use tprintf]
1.12      cgd       576:  */
                    577: void
                    578: ttyprintf(struct tty *tp, const char *fmt, ...)
                    579: {
                    580:        va_list ap;
                    581:
1.54      thorpej   582:        /* No mutex needed; going to process TTY. */
1.12      cgd       583:        va_start(ap, fmt);
1.45      chuck     584:        kprintf(fmt, TOTTY, tp, NULL, ap);
1.12      cgd       585:        va_end(ap);
                    586: }
                    587:
1.45      chuck     588: #ifdef DDB
1.12      cgd       589:
                    590: /*
1.45      chuck     591:  * db_printf: printf for DDB (via db_putchar)
1.12      cgd       592:  */
1.45      chuck     593:
1.12      cgd       594: void
1.45      chuck     595: db_printf(const char *fmt, ...)
1.12      cgd       596: {
                    597:        va_list ap;
                    598:
1.54      thorpej   599:        /* No mutex needed; DDB pauses all processors. */
1.12      cgd       600:        va_start(ap, fmt);
1.45      chuck     601:        kprintf(fmt, TODDB, NULL, NULL, ap);
1.12      cgd       602:        va_end(ap);
1.95      reinoud   603:
                    604:        if (db_tee_msgbuf) {
                    605:                va_start(ap, fmt);
                    606:                kprintf(fmt, TOLOG, NULL, NULL, ap);
                    607:                va_end(ap);
                    608:        };
1.84      drochner  609: }
                    610:
                    611: void
1.99      thorpej   612: db_vprintf(const char *fmt, va_list ap)
1.84      drochner  613: {
                    614:
                    615:        /* No mutex needed; DDB pauses all processors. */
                    616:        kprintf(fmt, TODDB, NULL, NULL, ap);
1.95      reinoud   617:        if (db_tee_msgbuf)
                    618:                kprintf(fmt, TOLOG, NULL, NULL, ap);
1.12      cgd       619: }
                    620:
1.45      chuck     621: #endif /* DDB */
1.12      cgd       622:
1.108     joerg     623: static void
                    624: kprintf_internal(const char *fmt, int oflags, void *vp, char *sbuf, ...)
                    625: {
                    626:        va_list ap;
                    627:
                    628:        va_start(ap, sbuf);
                    629:        (void)kprintf(fmt, oflags, vp, sbuf, ap);
                    630:        va_end(ap);
                    631: }
                    632:
1.88      thorpej   633: /*
                    634:  * Device autoconfiguration printf routines.  These change their
                    635:  * behavior based on the AB_* flags in boothowto.  If AB_SILENT
                    636:  * is set, messages never go to the console (but they still always
                    637:  * go to the log).  AB_VERBOSE overrides AB_SILENT.
                    638:  */
                    639:
                    640: /*
                    641:  * aprint_normal: Send to console unless AB_QUIET.  Always goes
                    642:  * to the log.
                    643:  */
1.108     joerg     644: static void
                    645: aprint_normal_internal(const char *prefix, const char *fmt, va_list ap)
1.88      thorpej   646: {
1.124.2.1! skrll     647:        int flags = TOLOG;
1.88      thorpej   648:
                    649:        if ((boothowto & (AB_SILENT|AB_QUIET)) == 0 ||
                    650:            (boothowto & AB_VERBOSE) != 0)
                    651:                flags |= TOCONS;
1.96      perry     652:
1.124.2.1! skrll     653:        kprintf_lock();
1.88      thorpej   654:
1.108     joerg     655:        if (prefix)
                    656:                kprintf_internal("%s: ", flags, NULL, NULL, prefix);
1.88      thorpej   657:        kprintf(fmt, flags, NULL, NULL, ap);
                    658:
1.124.2.1! skrll     659:        kprintf_unlock();
1.96      perry     660:
1.88      thorpej   661:        if (!panicstr)
                    662:                logwakeup();
                    663: }
                    664:
1.108     joerg     665: void
                    666: aprint_normal(const char *fmt, ...)
                    667: {
                    668:        va_list ap;
                    669:
                    670:        va_start(ap, fmt);
                    671:        aprint_normal_internal(NULL, fmt, ap);
                    672:        va_end(ap);
                    673: }
                    674:
                    675: void
                    676: aprint_normal_dev(device_t dv, const char *fmt, ...)
                    677: {
                    678:        va_list ap;
                    679:
                    680:        va_start(ap, fmt);
                    681:        aprint_normal_internal(device_xname(dv), fmt, ap);
                    682:        va_end(ap);
                    683: }
                    684:
                    685: void
                    686: aprint_normal_ifnet(struct ifnet *ifp, const char *fmt, ...)
                    687: {
                    688:        va_list ap;
                    689:
                    690:        va_start(ap, fmt);
                    691:        aprint_normal_internal(ifp->if_xname, fmt, ap);
                    692:        va_end(ap);
                    693: }
                    694:
1.88      thorpej   695: /*
1.89      thorpej   696:  * aprint_error: Send to console unless AB_QUIET.  Always goes
                    697:  * to the log.  Also counts the number of times called so other
                    698:  * parts of the kernel can report the number of errors during a
                    699:  * given phase of system startup.
                    700:  */
                    701: static int aprint_error_count;
                    702:
                    703: int
                    704: aprint_get_error_count(void)
                    705: {
1.124.2.1! skrll     706:        int count;
1.89      thorpej   707:
1.124.2.1! skrll     708:        kprintf_lock();
1.89      thorpej   709:
                    710:        count = aprint_error_count;
                    711:        aprint_error_count = 0;
                    712:
1.124.2.1! skrll     713:        kprintf_unlock();
1.89      thorpej   714:
                    715:        return (count);
                    716: }
                    717:
1.108     joerg     718: static void
                    719: aprint_error_internal(const char *prefix, const char *fmt, va_list ap)
1.89      thorpej   720: {
1.124.2.1! skrll     721:        int flags = TOLOG;
1.89      thorpej   722:
                    723:        if ((boothowto & (AB_SILENT|AB_QUIET)) == 0 ||
                    724:            (boothowto & AB_VERBOSE) != 0)
                    725:                flags |= TOCONS;
1.96      perry     726:
1.124.2.1! skrll     727:        kprintf_lock();
1.89      thorpej   728:
                    729:        aprint_error_count++;
                    730:
1.108     joerg     731:        if (prefix)
                    732:                kprintf_internal("%s: ", flags, NULL, NULL, prefix);
1.89      thorpej   733:        kprintf(fmt, flags, NULL, NULL, ap);
                    734:
1.124.2.1! skrll     735:        kprintf_unlock();
1.96      perry     736:
1.89      thorpej   737:        if (!panicstr)
                    738:                logwakeup();
                    739: }
                    740:
1.108     joerg     741: void
                    742: aprint_error(const char *fmt, ...)
                    743: {
                    744:        va_list ap;
                    745:
                    746:        va_start(ap, fmt);
                    747:        aprint_error_internal(NULL, fmt, ap);
                    748:        va_end(ap);
                    749: }
                    750:
                    751: void
                    752: aprint_error_dev(device_t dv, const char *fmt, ...)
                    753: {
                    754:        va_list ap;
                    755:
                    756:        va_start(ap, fmt);
                    757:        aprint_error_internal(device_xname(dv), fmt, ap);
                    758:        va_end(ap);
                    759: }
                    760:
                    761: void
                    762: aprint_error_ifnet(struct ifnet *ifp, const char *fmt, ...)
                    763: {
                    764:        va_list ap;
                    765:
                    766:        va_start(ap, fmt);
                    767:        aprint_error_internal(ifp->if_xname, fmt, ap);
                    768:        va_end(ap);
                    769: }
                    770:
1.89      thorpej   771: /*
1.88      thorpej   772:  * aprint_naive: Send to console only if AB_QUIET.  Never goes
                    773:  * to the log.
                    774:  */
1.108     joerg     775: static void
                    776: aprint_naive_internal(const char *prefix, const char *fmt, va_list ap)
                    777: {
                    778:
                    779:        if ((boothowto & (AB_QUIET|AB_SILENT|AB_VERBOSE)) != AB_QUIET)
                    780:                return;
                    781:
1.124.2.1! skrll     782:        kprintf_lock();
1.108     joerg     783:
                    784:        if (prefix)
                    785:                kprintf_internal("%s: ", TOCONS, NULL, NULL, prefix);
                    786:        kprintf(fmt, TOCONS, NULL, NULL, ap);
                    787:
1.124.2.1! skrll     788:        kprintf_unlock();
1.108     joerg     789: }
                    790:
1.88      thorpej   791: void
                    792: aprint_naive(const char *fmt, ...)
                    793: {
                    794:        va_list ap;
                    795:
1.108     joerg     796:        va_start(ap, fmt);
                    797:        aprint_naive_internal(NULL, fmt, ap);
                    798:        va_end(ap);
                    799: }
                    800:
                    801: void
                    802: aprint_naive_dev(device_t dv, const char *fmt, ...)
                    803: {
                    804:        va_list ap;
                    805:
                    806:        va_start(ap, fmt);
                    807:        aprint_naive_internal(device_xname(dv), fmt, ap);
                    808:        va_end(ap);
                    809: }
1.88      thorpej   810:
1.108     joerg     811: void
                    812: aprint_naive_ifnet(struct ifnet *ifp, const char *fmt, ...)
                    813: {
                    814:        va_list ap;
1.88      thorpej   815:
1.108     joerg     816:        va_start(ap, fmt);
                    817:        aprint_naive_internal(ifp->if_xname, fmt, ap);
                    818:        va_end(ap);
1.88      thorpej   819: }
                    820:
                    821: /*
                    822:  * aprint_verbose: Send to console only if AB_VERBOSE.  Always
                    823:  * goes to the log.
                    824:  */
1.108     joerg     825: static void
                    826: aprint_verbose_internal(const char *prefix, const char *fmt, va_list ap)
1.88      thorpej   827: {
1.124.2.1! skrll     828:        int flags = TOLOG;
1.88      thorpej   829:
                    830:        if (boothowto & AB_VERBOSE)
                    831:                flags |= TOCONS;
1.96      perry     832:
1.124.2.1! skrll     833:        kprintf_lock();
1.88      thorpej   834:
1.108     joerg     835:        if (prefix)
                    836:                kprintf_internal("%s: ", flags, NULL, NULL, prefix);
1.88      thorpej   837:        kprintf(fmt, flags, NULL, NULL, ap);
                    838:
1.124.2.1! skrll     839:        kprintf_unlock();
1.96      perry     840:
1.88      thorpej   841:        if (!panicstr)
                    842:                logwakeup();
                    843: }
                    844:
1.108     joerg     845: void
                    846: aprint_verbose(const char *fmt, ...)
                    847: {
                    848:        va_list ap;
                    849:
                    850:        va_start(ap, fmt);
                    851:        aprint_verbose_internal(NULL, fmt, ap);
                    852:        va_end(ap);
                    853: }
                    854:
                    855: void
                    856: aprint_verbose_dev(device_t dv, const char *fmt, ...)
                    857: {
                    858:        va_list ap;
                    859:
                    860:        va_start(ap, fmt);
                    861:        aprint_verbose_internal(device_xname(dv), fmt, ap);
                    862:        va_end(ap);
                    863: }
                    864:
                    865: void
                    866: aprint_verbose_ifnet(struct ifnet *ifp, const char *fmt, ...)
                    867: {
                    868:        va_list ap;
                    869:
                    870:        va_start(ap, fmt);
                    871:        aprint_verbose_internal(ifp->if_xname, fmt, ap);
                    872:        va_end(ap);
                    873: }
                    874:
1.88      thorpej   875: /*
                    876:  * aprint_debug: Send to console and log only if AB_DEBUG.
                    877:  */
1.108     joerg     878: static void
                    879: aprint_debug_internal(const char *prefix, const char *fmt, va_list ap)
                    880: {
                    881:
                    882:        if ((boothowto & AB_DEBUG) == 0)
                    883:                return;
                    884:
1.124.2.1! skrll     885:        kprintf_lock();
1.108     joerg     886:
                    887:        if (prefix)
                    888:                kprintf_internal("%s: ", TOCONS | TOLOG, NULL, NULL, prefix);
                    889:        kprintf(fmt, TOCONS | TOLOG, NULL, NULL, ap);
                    890:
1.124.2.1! skrll     891:        kprintf_unlock();
1.108     joerg     892: }
                    893:
1.88      thorpej   894: void
                    895: aprint_debug(const char *fmt, ...)
                    896: {
                    897:        va_list ap;
                    898:
1.108     joerg     899:        va_start(ap, fmt);
                    900:        aprint_debug_internal(NULL, fmt, ap);
                    901:        va_end(ap);
                    902: }
                    903:
                    904: void
                    905: aprint_debug_dev(device_t dv, const char *fmt, ...)
                    906: {
                    907:        va_list ap;
                    908:
                    909:        va_start(ap, fmt);
                    910:        aprint_debug_internal(device_xname(dv), fmt, ap);
                    911:        va_end(ap);
                    912: }
1.88      thorpej   913:
1.108     joerg     914: void
                    915: aprint_debug_ifnet(struct ifnet *ifp, const char *fmt, ...)
                    916: {
                    917:        va_list ap;
1.88      thorpej   918:
1.108     joerg     919:        va_start(ap, fmt);
                    920:        aprint_debug_internal(ifp->if_xname, fmt, ap);
                    921:        va_end(ap);
1.89      thorpej   922: }
                    923:
1.123     dyoung    924: void
                    925: printf_tolog(const char *fmt, ...)
                    926: {
                    927:        va_list ap;
                    928:
1.124.2.1! skrll     929:        kprintf_lock();
1.123     dyoung    930:
                    931:        va_start(ap, fmt);
                    932:        (void)kprintf(fmt, TOLOG, NULL, NULL, ap);
                    933:        va_end(ap);
                    934:
1.124.2.1! skrll     935:        kprintf_unlock();
1.123     dyoung    936: }
                    937:
1.89      thorpej   938: /*
                    939:  * printf_nolog: Like printf(), but does not send message to the log.
                    940:  */
                    941:
                    942: void
                    943: printf_nolog(const char *fmt, ...)
                    944: {
                    945:        va_list ap;
                    946:
1.124.2.1! skrll     947:        kprintf_lock();
1.89      thorpej   948:
                    949:        va_start(ap, fmt);
                    950:        kprintf(fmt, TOCONS, NULL, NULL, ap);
                    951:        va_end(ap);
                    952:
1.124.2.1! skrll     953:        kprintf_unlock();
1.88      thorpej   954: }
1.12      cgd       955:
1.45      chuck     956: /*
1.76      tv        957:  * normal kernel printf functions: printf, vprintf, snprintf, vsnprintf
1.45      chuck     958:  */
1.12      cgd       959:
1.45      chuck     960: /*
                    961:  * printf: print a message to the console and the log
                    962:  */
1.12      cgd       963: void
1.30      christos  964: printf(const char *fmt, ...)
1.12      cgd       965: {
                    966:        va_list ap;
1.54      thorpej   967:
1.124.2.1! skrll     968:        kprintf_lock();
1.12      cgd       969:
                    970:        va_start(ap, fmt);
1.45      chuck     971:        kprintf(fmt, TOCONS | TOLOG, NULL, NULL, ap);
1.12      cgd       972:        va_end(ap);
1.54      thorpej   973:
1.124.2.1! skrll     974:        kprintf_unlock();
1.54      thorpej   975:
1.12      cgd       976:        if (!panicstr)
                    977:                logwakeup();
                    978: }
                    979:
1.45      chuck     980: /*
                    981:  * vprintf: print a message to the console and the log [already have
                    982:  *     va_alist]
                    983:  */
                    984:
1.40      thorpej   985: void
1.99      thorpej   986: vprintf(const char *fmt, va_list ap)
1.40      thorpej   987: {
1.54      thorpej   988:
1.124.2.1! skrll     989:        kprintf_lock();
1.40      thorpej   990:
1.45      chuck     991:        kprintf(fmt, TOCONS | TOLOG, NULL, NULL, ap);
1.54      thorpej   992:
1.124.2.1! skrll     993:        kprintf_unlock();
1.54      thorpej   994:
1.40      thorpej   995:        if (!panicstr)
                    996:                logwakeup();
                    997: }
                    998:
1.12      cgd       999: /*
1.45      chuck    1000:  * sprintf: print a message to a buffer
1.12      cgd      1001:  */
1.45      chuck    1002: int
1.98      christos 1003: sprintf(char *bf, const char *fmt, ...)
1.45      chuck    1004: {
                   1005:        int retval;
1.12      cgd      1006:        va_list ap;
                   1007:
1.45      chuck    1008:        va_start(ap, fmt);
1.98      christos 1009:        retval = kprintf(fmt, TOBUFONLY, NULL, bf, ap);
1.12      cgd      1010:        va_end(ap);
1.98      christos 1011:        *(bf + retval) = 0;     /* null terminate */
1.45      chuck    1012:        return(retval);
1.55      thorpej  1013: }
                   1014:
                   1015: /*
                   1016:  * vsprintf: print a message to a buffer [already have va_alist]
                   1017:  */
                   1018:
                   1019: int
1.99      thorpej  1020: vsprintf(char *bf, const char *fmt, va_list ap)
1.55      thorpej  1021: {
                   1022:        int retval;
                   1023:
1.98      christos 1024:        retval = kprintf(fmt, TOBUFONLY, NULL, bf, ap);
                   1025:        *(bf + retval) = 0;     /* null terminate */
1.55      thorpej  1026:        return (retval);
1.12      cgd      1027: }
                   1028:
                   1029: /*
1.58      msaitoh  1030:  * snprintf: print a message to a buffer
                   1031:  */
                   1032: int
1.98      christos 1033: snprintf(char *bf, size_t size, const char *fmt, ...)
1.58      msaitoh  1034: {
                   1035:        int retval;
                   1036:        va_list ap;
                   1037:        char *p;
                   1038:
                   1039:        if (size < 1)
                   1040:                return (-1);
1.98      christos 1041:        p = bf + size - 1;
1.58      msaitoh  1042:        va_start(ap, fmt);
1.98      christos 1043:        retval = kprintf(fmt, TOBUFONLY, &p, bf, ap);
1.58      msaitoh  1044:        va_end(ap);
                   1045:        *(p) = 0;       /* null terminate */
                   1046:        return(retval);
                   1047: }
                   1048:
                   1049: /*
                   1050:  * vsnprintf: print a message to a buffer [already have va_alist]
                   1051:  */
                   1052: int
1.99      thorpej  1053: vsnprintf(char *bf, size_t size, const char *fmt, va_list ap)
1.58      msaitoh  1054: {
                   1055:        int retval;
                   1056:        char *p;
                   1057:
                   1058:        if (size < 1)
                   1059:                return (-1);
1.98      christos 1060:        p = bf + size - 1;
                   1061:        retval = kprintf(fmt, TOBUFONLY, &p, bf, ap);
1.58      msaitoh  1062:        *(p) = 0;       /* null terminate */
                   1063:        return(retval);
                   1064: }
                   1065:
                   1066: /*
1.45      chuck    1067:  * kprintf: scaled down version of printf(3).
                   1068:  *
1.96      perry    1069:  * this version based on vfprintf() from libc which was derived from
1.45      chuck    1070:  * software contributed to Berkeley by Chris Torek.
                   1071:  *
1.76      tv       1072:  * NOTE: The kprintf mutex must be held if we're going TOBUF or TOCONS!
1.45      chuck    1073:  */
                   1074:
                   1075: /*
                   1076:  * macros for converting digits to letters and vice versa
                   1077:  */
                   1078: #define        to_digit(c)     ((c) - '0')
                   1079: #define is_digit(c)    ((unsigned)to_digit(c) <= 9)
                   1080: #define        to_char(n)      ((n) + '0')
                   1081:
                   1082: /*
                   1083:  * flags used during conversion.
                   1084:  */
                   1085: #define        ALT             0x001           /* alternate form */
                   1086: #define        HEXPREFIX       0x002           /* add 0x or 0X prefix */
                   1087: #define        LADJUST         0x004           /* left adjustment */
                   1088: #define        LONGDBL         0x008           /* long double; unimplemented */
                   1089: #define        LONGINT         0x010           /* long integer */
                   1090: #define        QUADINT         0x020           /* quad integer */
                   1091: #define        SHORTINT        0x040           /* short integer */
1.78      kleink   1092: #define        MAXINT          0x080           /* intmax_t */
                   1093: #define        PTRINT          0x100           /* intptr_t */
                   1094: #define        SIZEINT         0x200           /* size_t */
                   1095: #define        ZEROPAD         0x400           /* zero (as opposed to blank) pad */
                   1096: #define FPT            0x800           /* Floating point number */
1.45      chuck    1097:
                   1098:        /*
                   1099:         * To extend shorts properly, we need both signed and unsigned
                   1100:         * argument extraction methods.
                   1101:         */
                   1102: #define        SARG() \
1.78      kleink   1103:        (flags&MAXINT ? va_arg(ap, intmax_t) : \
                   1104:            flags&PTRINT ? va_arg(ap, intptr_t) : \
                   1105:            flags&SIZEINT ? va_arg(ap, ssize_t) : /* XXX */ \
                   1106:            flags&QUADINT ? va_arg(ap, quad_t) : \
1.45      chuck    1107:            flags&LONGINT ? va_arg(ap, long) : \
                   1108:            flags&SHORTINT ? (long)(short)va_arg(ap, int) : \
                   1109:            (long)va_arg(ap, int))
                   1110: #define        UARG() \
1.78      kleink   1111:        (flags&MAXINT ? va_arg(ap, uintmax_t) : \
                   1112:            flags&PTRINT ? va_arg(ap, uintptr_t) : \
                   1113:            flags&SIZEINT ? va_arg(ap, size_t) : \
                   1114:            flags&QUADINT ? va_arg(ap, u_quad_t) : \
1.45      chuck    1115:            flags&LONGINT ? va_arg(ap, u_long) : \
                   1116:            flags&SHORTINT ? (u_long)(u_short)va_arg(ap, int) : \
                   1117:            (u_long)va_arg(ap, u_int))
                   1118:
1.60      explorer 1119: #define KPRINTF_PUTCHAR(C) {                                           \
                   1120:        if (oflags == TOBUFONLY) {                                      \
                   1121:                if ((vp != NULL) && (sbuf == tailp)) {                  \
                   1122:                        ret += 1;               /* indicate error */    \
                   1123:                        goto overflow;                                  \
                   1124:                }                                                       \
                   1125:                *sbuf++ = (C);                                          \
                   1126:        } else {                                                        \
                   1127:                putchar((C), oflags, (struct tty *)vp);                 \
                   1128:        }                                                               \
1.58      msaitoh  1129: }
1.45      chuck    1130:
1.54      thorpej  1131: /*
                   1132:  * Guts of kernel printf.  Note, we already expect to be in a mutex!
                   1133:  */
1.87      thorpej  1134: int
1.99      thorpej  1135: kprintf(const char *fmt0, int oflags, void *vp, char *sbuf, va_list ap)
1.45      chuck    1136: {
1.98      christos 1137:        const char *fmt;        /* format string */
1.45      chuck    1138:        int ch;                 /* character from fmt */
                   1139:        int n;                  /* handy integer (short term usage) */
                   1140:        char *cp;               /* handy char pointer (short term usage) */
                   1141:        int flags;              /* flags as above */
                   1142:        int ret;                /* return value accumulator */
                   1143:        int width;              /* width from format (%8d), or 0 */
                   1144:        int prec;               /* precision from format (%.3d), or -1 */
                   1145:        char sign;              /* sign prefix (' ', '+', '-', or \0) */
                   1146:
                   1147:        u_quad_t _uquad;        /* integer arguments %[diouxX] */
                   1148:        enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */
                   1149:        int dprec;              /* a copy of prec if [diouxX], 0 otherwise */
                   1150:        int realsz;             /* field size expanded by dprec */
                   1151:        int size;               /* size of converted field or string */
1.97      christos 1152:        const char *xdigs;      /* digits for [xX] conversion */
1.98      christos 1153:        char bf[KPRINTF_BUFSIZE]; /* space for %c, %[diouxX] */
1.61      explorer 1154:        char *tailp;            /* tail pointer for snprintf */
1.58      msaitoh  1155:
1.61      explorer 1156:        tailp = NULL;   /* XXX: shutup gcc */
1.60      explorer 1157:        if (oflags == TOBUFONLY && (vp != NULL))
                   1158:                tailp = *(char **)vp;
1.45      chuck    1159:
                   1160:        cp = NULL;      /* XXX: shutup gcc */
                   1161:        size = 0;       /* XXX: shutup gcc */
                   1162:
1.98      christos 1163:        fmt = fmt0;
1.45      chuck    1164:        ret = 0;
                   1165:
                   1166:        xdigs = NULL;           /* XXX: shut up gcc warning */
                   1167:
                   1168:        /*
                   1169:         * Scan the format for conversions (`%' character).
                   1170:         */
                   1171:        for (;;) {
                   1172:                while (*fmt != '%' && *fmt) {
1.58      msaitoh  1173:                        ret++;
1.45      chuck    1174:                        KPRINTF_PUTCHAR(*fmt++);
                   1175:                }
                   1176:                if (*fmt == 0)
                   1177:                        goto done;
                   1178:
                   1179:                fmt++;          /* skip over '%' */
                   1180:
                   1181:                flags = 0;
                   1182:                dprec = 0;
                   1183:                width = 0;
                   1184:                prec = -1;
                   1185:                sign = '\0';
                   1186:
                   1187: rflag:         ch = *fmt++;
                   1188: reswitch:      switch (ch) {
                   1189:                case ' ':
                   1190:                        /*
                   1191:                         * ``If the space and + flags both appear, the space
                   1192:                         * flag will be ignored.''
                   1193:                         *      -- ANSI X3J11
                   1194:                         */
                   1195:                        if (!sign)
                   1196:                                sign = ' ';
                   1197:                        goto rflag;
                   1198:                case '#':
                   1199:                        flags |= ALT;
                   1200:                        goto rflag;
                   1201:                case '*':
                   1202:                        /*
                   1203:                         * ``A negative field width argument is taken as a
                   1204:                         * - flag followed by a positive field width.''
                   1205:                         *      -- ANSI X3J11
                   1206:                         * They don't exclude field widths read from args.
                   1207:                         */
                   1208:                        if ((width = va_arg(ap, int)) >= 0)
                   1209:                                goto rflag;
                   1210:                        width = -width;
                   1211:                        /* FALLTHROUGH */
                   1212:                case '-':
                   1213:                        flags |= LADJUST;
                   1214:                        goto rflag;
                   1215:                case '+':
                   1216:                        sign = '+';
                   1217:                        goto rflag;
                   1218:                case '.':
                   1219:                        if ((ch = *fmt++) == '*') {
                   1220:                                n = va_arg(ap, int);
                   1221:                                prec = n < 0 ? -1 : n;
                   1222:                                goto rflag;
                   1223:                        }
                   1224:                        n = 0;
                   1225:                        while (is_digit(ch)) {
                   1226:                                n = 10 * n + to_digit(ch);
                   1227:                                ch = *fmt++;
                   1228:                        }
                   1229:                        prec = n < 0 ? -1 : n;
                   1230:                        goto reswitch;
                   1231:                case '0':
                   1232:                        /*
                   1233:                         * ``Note that 0 is taken as a flag, not as the
                   1234:                         * beginning of a field width.''
                   1235:                         *      -- ANSI X3J11
                   1236:                         */
                   1237:                        flags |= ZEROPAD;
                   1238:                        goto rflag;
                   1239:                case '1': case '2': case '3': case '4':
                   1240:                case '5': case '6': case '7': case '8': case '9':
                   1241:                        n = 0;
                   1242:                        do {
                   1243:                                n = 10 * n + to_digit(ch);
                   1244:                                ch = *fmt++;
                   1245:                        } while (is_digit(ch));
                   1246:                        width = n;
                   1247:                        goto reswitch;
                   1248:                case 'h':
                   1249:                        flags |= SHORTINT;
                   1250:                        goto rflag;
1.78      kleink   1251:                case 'j':
                   1252:                        flags |= MAXINT;
                   1253:                        goto rflag;
1.45      chuck    1254:                case 'l':
                   1255:                        if (*fmt == 'l') {
                   1256:                                fmt++;
                   1257:                                flags |= QUADINT;
                   1258:                        } else {
                   1259:                                flags |= LONGINT;
                   1260:                        }
                   1261:                        goto rflag;
                   1262:                case 'q':
                   1263:                        flags |= QUADINT;
                   1264:                        goto rflag;
1.78      kleink   1265:                case 't':
                   1266:                        flags |= PTRINT;
                   1267:                        goto rflag;
                   1268:                case 'z':
                   1269:                        flags |= SIZEINT;
                   1270:                        goto rflag;
1.45      chuck    1271:                case 'c':
1.98      christos 1272:                        *(cp = bf) = va_arg(ap, int);
1.45      chuck    1273:                        size = 1;
                   1274:                        sign = '\0';
                   1275:                        break;
                   1276:                case 'D':
                   1277:                        flags |= LONGINT;
                   1278:                        /*FALLTHROUGH*/
                   1279:                case 'd':
                   1280:                case 'i':
                   1281:                        _uquad = SARG();
                   1282:                        if ((quad_t)_uquad < 0) {
                   1283:                                _uquad = -_uquad;
                   1284:                                sign = '-';
                   1285:                        }
                   1286:                        base = DEC;
                   1287:                        goto number;
                   1288:                case 'n':
1.78      kleink   1289:                        if (flags & MAXINT)
                   1290:                                *va_arg(ap, intmax_t *) = ret;
                   1291:                        else if (flags & PTRINT)
                   1292:                                *va_arg(ap, intptr_t *) = ret;
                   1293:                        else if (flags & SIZEINT)
                   1294:                                *va_arg(ap, ssize_t *) = ret;
                   1295:                        else if (flags & QUADINT)
1.45      chuck    1296:                                *va_arg(ap, quad_t *) = ret;
                   1297:                        else if (flags & LONGINT)
                   1298:                                *va_arg(ap, long *) = ret;
                   1299:                        else if (flags & SHORTINT)
                   1300:                                *va_arg(ap, short *) = ret;
                   1301:                        else
                   1302:                                *va_arg(ap, int *) = ret;
                   1303:                        continue;       /* no output */
                   1304:                case 'O':
                   1305:                        flags |= LONGINT;
                   1306:                        /*FALLTHROUGH*/
                   1307:                case 'o':
                   1308:                        _uquad = UARG();
                   1309:                        base = OCT;
                   1310:                        goto nosign;
                   1311:                case 'p':
                   1312:                        /*
                   1313:                         * ``The argument shall be a pointer to void.  The
                   1314:                         * value of the pointer is converted to a sequence
                   1315:                         * of printable characters, in an implementation-
                   1316:                         * defined manner.''
                   1317:                         *      -- ANSI X3J11
                   1318:                         */
                   1319:                        /* NOSTRICT */
                   1320:                        _uquad = (u_long)va_arg(ap, void *);
                   1321:                        base = HEX;
1.97      christos 1322:                        xdigs = hexdigits;
1.45      chuck    1323:                        flags |= HEXPREFIX;
                   1324:                        ch = 'x';
                   1325:                        goto nosign;
                   1326:                case 's':
                   1327:                        if ((cp = va_arg(ap, char *)) == NULL)
1.98      christos 1328:                                /*XXXUNCONST*/
                   1329:                                cp = __UNCONST("(null)");
1.45      chuck    1330:                        if (prec >= 0) {
                   1331:                                /*
                   1332:                                 * can't use strlen; can only look for the
                   1333:                                 * NUL in the first `prec' characters, and
                   1334:                                 * strlen() will go further.
                   1335:                                 */
                   1336:                                char *p = memchr(cp, 0, prec);
                   1337:
                   1338:                                if (p != NULL) {
                   1339:                                        size = p - cp;
                   1340:                                        if (size > prec)
                   1341:                                                size = prec;
                   1342:                                } else
                   1343:                                        size = prec;
                   1344:                        } else
                   1345:                                size = strlen(cp);
                   1346:                        sign = '\0';
                   1347:                        break;
                   1348:                case 'U':
                   1349:                        flags |= LONGINT;
                   1350:                        /*FALLTHROUGH*/
                   1351:                case 'u':
                   1352:                        _uquad = UARG();
                   1353:                        base = DEC;
                   1354:                        goto nosign;
                   1355:                case 'X':
1.103     martin   1356:                        xdigs = HEXDIGITS;
1.45      chuck    1357:                        goto hex;
                   1358:                case 'x':
1.97      christos 1359:                        xdigs = hexdigits;
1.45      chuck    1360: hex:                   _uquad = UARG();
                   1361:                        base = HEX;
                   1362:                        /* leading 0x/X only if non-zero */
                   1363:                        if (flags & ALT && _uquad != 0)
                   1364:                                flags |= HEXPREFIX;
                   1365:
                   1366:                        /* unsigned conversions */
                   1367: nosign:                        sign = '\0';
                   1368:                        /*
                   1369:                         * ``... diouXx conversions ... if a precision is
                   1370:                         * specified, the 0 flag will be ignored.''
                   1371:                         *      -- ANSI X3J11
                   1372:                         */
                   1373: number:                        if ((dprec = prec) >= 0)
                   1374:                                flags &= ~ZEROPAD;
                   1375:
                   1376:                        /*
                   1377:                         * ``The result of converting a zero value with an
                   1378:                         * explicit precision of zero is no characters.''
                   1379:                         *      -- ANSI X3J11
                   1380:                         */
1.98      christos 1381:                        cp = bf + KPRINTF_BUFSIZE;
1.45      chuck    1382:                        if (_uquad != 0 || prec != 0) {
                   1383:                                /*
                   1384:                                 * Unsigned mod is hard, and unsigned mod
                   1385:                                 * by a constant is easier than that by
                   1386:                                 * a variable; hence this switch.
                   1387:                                 */
                   1388:                                switch (base) {
                   1389:                                case OCT:
                   1390:                                        do {
                   1391:                                                *--cp = to_char(_uquad & 7);
                   1392:                                                _uquad >>= 3;
                   1393:                                        } while (_uquad);
                   1394:                                        /* handle octal leading 0 */
                   1395:                                        if (flags & ALT && *cp != '0')
                   1396:                                                *--cp = '0';
                   1397:                                        break;
                   1398:
                   1399:                                case DEC:
                   1400:                                        /* many numbers are 1 digit */
                   1401:                                        while (_uquad >= 10) {
                   1402:                                                *--cp = to_char(_uquad % 10);
                   1403:                                                _uquad /= 10;
                   1404:                                        }
                   1405:                                        *--cp = to_char(_uquad);
                   1406:                                        break;
                   1407:
                   1408:                                case HEX:
                   1409:                                        do {
                   1410:                                                *--cp = xdigs[_uquad & 15];
                   1411:                                                _uquad >>= 4;
                   1412:                                        } while (_uquad);
                   1413:                                        break;
                   1414:
                   1415:                                default:
1.98      christos 1416:                                        /*XXXUNCONST*/
                   1417:                                        cp = __UNCONST("bug in kprintf: bad base");
1.45      chuck    1418:                                        size = strlen(cp);
                   1419:                                        goto skipsize;
                   1420:                                }
                   1421:                        }
1.98      christos 1422:                        size = bf + KPRINTF_BUFSIZE - cp;
1.45      chuck    1423:                skipsize:
                   1424:                        break;
                   1425:                default:        /* "%?" prints ?, unless ? is NUL */
                   1426:                        if (ch == '\0')
                   1427:                                goto done;
                   1428:                        /* pretend it was %c with argument ch */
1.98      christos 1429:                        cp = bf;
1.45      chuck    1430:                        *cp = ch;
                   1431:                        size = 1;
                   1432:                        sign = '\0';
                   1433:                        break;
                   1434:                }
                   1435:
                   1436:                /*
                   1437:                 * All reasonable formats wind up here.  At this point, `cp'
                   1438:                 * points to a string which (if not flags&LADJUST) should be
                   1439:                 * padded out to `width' places.  If flags&ZEROPAD, it should
                   1440:                 * first be prefixed by any sign or other prefix; otherwise,
                   1441:                 * it should be blank padded before the prefix is emitted.
                   1442:                 * After any left-hand padding and prefixing, emit zeroes
                   1443:                 * required by a decimal [diouxX] precision, then print the
                   1444:                 * string proper, then emit zeroes required by any leftover
                   1445:                 * floating precision; finally, if LADJUST, pad with blanks.
                   1446:                 *
                   1447:                 * Compute actual size, so we know how much to pad.
                   1448:                 * size excludes decimal prec; realsz includes it.
                   1449:                 */
                   1450:                realsz = dprec > size ? dprec : size;
                   1451:                if (sign)
                   1452:                        realsz++;
                   1453:                else if (flags & HEXPREFIX)
                   1454:                        realsz+= 2;
                   1455:
1.58      msaitoh  1456:                /* adjust ret */
                   1457:                ret += width > realsz ? width : realsz;
                   1458:
1.45      chuck    1459:                /* right-adjusting blank padding */
                   1460:                if ((flags & (LADJUST|ZEROPAD)) == 0) {
                   1461:                        n = width - realsz;
                   1462:                        while (n-- > 0)
                   1463:                                KPRINTF_PUTCHAR(' ');
                   1464:                }
                   1465:
                   1466:                /* prefix */
                   1467:                if (sign) {
                   1468:                        KPRINTF_PUTCHAR(sign);
                   1469:                } else if (flags & HEXPREFIX) {
                   1470:                        KPRINTF_PUTCHAR('0');
                   1471:                        KPRINTF_PUTCHAR(ch);
                   1472:                }
                   1473:
                   1474:                /* right-adjusting zero padding */
                   1475:                if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD) {
                   1476:                        n = width - realsz;
                   1477:                        while (n-- > 0)
                   1478:                                KPRINTF_PUTCHAR('0');
                   1479:                }
                   1480:
                   1481:                /* leading zeroes from decimal precision */
                   1482:                n = dprec - size;
                   1483:                while (n-- > 0)
                   1484:                        KPRINTF_PUTCHAR('0');
                   1485:
                   1486:                /* the string or number proper */
                   1487:                while (size--)
                   1488:                        KPRINTF_PUTCHAR(*cp++);
                   1489:                /* left-adjusting padding (always blank) */
                   1490:                if (flags & LADJUST) {
                   1491:                        n = width - realsz;
                   1492:                        while (n-- > 0)
                   1493:                                KPRINTF_PUTCHAR(' ');
                   1494:                }
1.58      msaitoh  1495:        }
1.45      chuck    1496:
                   1497: done:
1.58      msaitoh  1498:        if ((oflags == TOBUFONLY) && (vp != NULL))
                   1499:                *(char **)vp = sbuf;
1.92      matt     1500:        (*v_flush)();
1.58      msaitoh  1501: overflow:
1.45      chuck    1502:        return (ret);
                   1503:        /* NOTREACHED */
1.12      cgd      1504: }

CVSweb <webmaster@jp.NetBSD.org>