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>