Annotation of sys/kern/subr_prf.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: subr_prf.c,v 1.70 2007/04/26 20:28:25 deraadt Exp $ */
2: /* $NetBSD: subr_prf.c,v 1.45 1997/10/24 18:14:25 chuck Exp $ */
3:
4: /*-
5: * Copyright (c) 1986, 1988, 1991, 1993
6: * The Regents of the University of California. All rights reserved.
7: * (c) UNIX System Laboratories, Inc.
8: * All or some portions of this file are derived from material licensed
9: * to the University of California by American Telephone and Telegraph
10: * Co. or Unix System Laboratories, Inc. and are reproduced herein with
11: * the permission of UNIX System Laboratories, Inc.
12: *
13: * Redistribution and use in source and binary forms, with or without
14: * modification, are permitted provided that the following conditions
15: * are met:
16: * 1. Redistributions of source code must retain the above copyright
17: * notice, this list of conditions and the following disclaimer.
18: * 2. Redistributions in binary form must reproduce the above copyright
19: * notice, this list of conditions and the following disclaimer in the
20: * documentation and/or other materials provided with the distribution.
21: * 3. Neither the name of the University nor the names of its contributors
22: * may be used to endorse or promote products derived from this software
23: * without specific prior written permission.
24: *
25: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35: * SUCH DAMAGE.
36: *
37: * @(#)subr_prf.c 8.3 (Berkeley) 1/21/94
38: */
39:
40: #include <sys/param.h>
41: #include <sys/systm.h>
42: #include <sys/buf.h>
43: #include <sys/conf.h>
44: #include <sys/reboot.h>
45: #include <sys/msgbuf.h>
46: #include <sys/proc.h>
47: #include <sys/ioctl.h>
48: #include <sys/vnode.h>
49: #include <sys/file.h>
50: #include <sys/tty.h>
51: #include <sys/tprintf.h>
52: #include <sys/syslog.h>
53: #include <sys/malloc.h>
54: #include <sys/pool.h>
55: #include <sys/mutex.h>
56:
57: #include <dev/cons.h>
58:
59: /*
60: * note that stdarg.h and the ansi style va_start macro is used for both
61: * ansi and traditional c compilers.
62: */
63: #include <sys/stdarg.h>
64:
65: #ifdef KGDB
66: #include <sys/kgdb.h>
67: #include <machine/cpu.h>
68: #endif
69: #ifdef DDB
70: #include <ddb/db_output.h> /* db_printf, db_putchar prototypes */
71: #include <ddb/db_var.h> /* db_log, db_radix */
72: #endif
73: #if defined(UVM_SWAP_ENCRYPT)
74: extern int uvm_doswapencrypt;
75: #endif
76:
77:
78: /*
79: * defines
80: */
81:
82: /* flags for kprintf */
83: #define TOCONS 0x01 /* to the console */
84: #define TOTTY 0x02 /* to the process' tty */
85: #define TOLOG 0x04 /* to the kernel message buffer */
86: #define TOBUFONLY 0x08 /* to the buffer (only) [for snprintf] */
87: #define TODDB 0x10 /* to ddb console */
88: #define TOCOUNT 0x20 /* act like [v]snprintf */
89:
90: /* max size buffer kprintf needs to print quad_t [size in base 8 + \0] */
91: #define KPRINTF_BUFSIZE (sizeof(quad_t) * NBBY / 3 + 2)
92:
93:
94: /*
95: * local prototypes
96: */
97:
98: int kprintf(const char *, int, void *, char *, va_list);
99: void kputchar(int, int, struct tty *);
100:
101: struct mutex kprintf_mutex = MUTEX_INITIALIZER(IPL_HIGH);
102:
103: /*
104: * globals
105: */
106:
107: extern struct tty *constty; /* pointer to console "window" tty */
108: int consintr = 1; /* ok to handle console interrupts? */
109: extern int log_open; /* subr_log: is /dev/klog open? */
110: const char *panicstr; /* arg to first call to panic (used as a flag
111: to indicate that panic has already been called). */
112: #ifdef DDB
113: /*
114: * Enter ddb on panic.
115: */
116: int db_panic = 1;
117:
118: /*
119: * db_console controls if we can be able to enter ddb by a special key
120: * combination (machine dependent).
121: * If DDB_SAFE_CONSOLE is defined in the kernel configuration it allows
122: * to break into console during boot. It's _really_ useful when debugging
123: * some things in the kernel that can cause init(8) to crash.
124: */
125: #ifdef DDB_SAFE_CONSOLE
126: int db_console = 1;
127: #else
128: int db_console = 0;
129: #endif
130: #endif
131:
132: /*
133: * panic on spl assertion failure?
134: */
135: int splassert_ctl = 1;
136:
137: /*
138: * v_putc: routine to putc on virtual console
139: *
140: * the v_putc pointer can be used to redirect the console cnputc elsewhere
141: * [e.g. to a "virtual console"].
142: */
143:
144: void (*v_putc)(int) = cnputc; /* start with cnputc (normal cons) */
145:
146:
147: /*
148: * functions
149: */
150:
151: /*
152: * Partial support (the failure case) of the assertion facility
153: * commonly found in userland.
154: */
155: void
156: __assert(const char *t, const char *f, int l, const char *e)
157: {
158:
159: panic("kernel %sassertion \"%s\" failed: file \"%s\", line %d",
160: t, e, f, l);
161: }
162:
163: /*
164: * tablefull: warn that a system table is full
165: */
166:
167: void
168: tablefull(const char *tab)
169: {
170: log(LOG_ERR, "%s: table is full\n", tab);
171: }
172:
173: /*
174: * panic: handle an unresolvable fatal error
175: *
176: * prints "panic: <message>" and reboots. if called twice (i.e. recursive
177: * call) we avoid trying to sync the disk and just reboot (to avoid
178: * recursive panics).
179: */
180:
181: void
182: panic(const char *fmt, ...)
183: {
184: static char panicbuf[512];
185: int bootopt;
186: va_list ap;
187:
188: bootopt = RB_AUTOBOOT | RB_DUMP;
189: #if defined(UVM_SWAP_ENCRYPT)
190: if (uvm_doswapencrypt)
191: bootopt &= ~RB_DUMP;
192: #endif
193: va_start(ap, fmt);
194: if (panicstr)
195: bootopt |= RB_NOSYNC;
196: else {
197: vsnprintf(panicbuf, sizeof panicbuf, fmt, ap);
198: panicstr = panicbuf;
199: }
200: va_end(ap);
201:
202: printf("panic: ");
203: va_start(ap, fmt);
204: vprintf(fmt, ap);
205: printf("\n");
206: va_end(ap);
207:
208: #ifdef KGDB
209: kgdb_panic();
210: #endif
211: #ifdef KADB
212: if (boothowto & RB_KDB)
213: kdbpanic();
214: #endif
215: #ifdef DDB
216: if (db_panic)
217: Debugger();
218: else
219: db_stack_dump();
220: #endif
221: boot(bootopt);
222: }
223:
224: /*
225: * We print only the function name. The file name is usually very long and
226: * would eat tons of space in the kernel.
227: */
228: void
229: splassert_fail(int wantipl, int haveipl, const char *func)
230: {
231:
232: printf("splassert: %s: want %d have %d\n", func, wantipl, haveipl);
233: switch (splassert_ctl) {
234: case 1:
235: break;
236: case 2:
237: #ifdef DDB
238: db_stack_dump();
239: #endif
240: break;
241: case 3:
242: #ifdef DDB
243: db_stack_dump();
244: Debugger();
245: #endif
246: break;
247: default:
248: panic("spl assertion failure in %s", func);
249: }
250: }
251:
252: /*
253: * kernel logging functions: log, logpri, addlog
254: */
255:
256: /*
257: * log: write to the log buffer
258: *
259: * => will not sleep [so safe to call from interrupt]
260: * => will log to console if /dev/klog isn't open
261: */
262:
263: void
264: log(int level, const char *fmt, ...)
265: {
266: int s;
267: va_list ap;
268:
269: s = splhigh();
270: logpri(level); /* log the level first */
271: va_start(ap, fmt);
272: kprintf(fmt, TOLOG, NULL, NULL, ap);
273: va_end(ap);
274: splx(s);
275: if (!log_open) {
276: va_start(ap, fmt);
277: kprintf(fmt, TOCONS, NULL, NULL, ap);
278: va_end(ap);
279: }
280: logwakeup(); /* wake up anyone waiting for log msgs */
281: }
282:
283: /*
284: * logpri: log the priority level to the klog
285: */
286:
287: void
288: logpri(int level)
289: {
290: char *p;
291: char snbuf[KPRINTF_BUFSIZE];
292:
293: kputchar('<', TOLOG, NULL);
294: snprintf(snbuf, sizeof snbuf, "%d", level);
295: for (p = snbuf ; *p ; p++)
296: kputchar(*p, TOLOG, NULL);
297: kputchar('>', TOLOG, NULL);
298: }
299:
300: /*
301: * addlog: add info to previous log message
302: */
303:
304: int
305: addlog(const char *fmt, ...)
306: {
307: int s;
308: va_list ap;
309:
310: s = splhigh();
311: va_start(ap, fmt);
312: kprintf(fmt, TOLOG, NULL, NULL, ap);
313: va_end(ap);
314: splx(s);
315: if (!log_open) {
316: va_start(ap, fmt);
317: kprintf(fmt, TOCONS, NULL, NULL, ap);
318: va_end(ap);
319: }
320: logwakeup();
321: return(0);
322: }
323:
324:
325: /*
326: * kputchar: print a single character on console or user terminal.
327: *
328: * => if console, then the last MSGBUFS chars are saved in msgbuf
329: * for inspection later (e.g. dmesg/syslog)
330: */
331: void
332: kputchar(int c, int flags, struct tty *tp)
333: {
334: extern int msgbufmapped;
335:
336: if (panicstr)
337: constty = NULL;
338: if ((flags & TOCONS) && tp == NULL && constty) {
339: tp = constty;
340: flags |= TOTTY;
341: }
342: if ((flags & TOTTY) && tp && tputchar(c, tp) < 0 &&
343: (flags & TOCONS) && tp == constty)
344: constty = NULL;
345: if ((flags & TOLOG) &&
346: c != '\0' && c != '\r' && c != 0177 && msgbufmapped)
347: msgbuf_putchar(c);
348: if ((flags & TOCONS) && constty == NULL && c != '\0')
349: (*v_putc)(c);
350: #ifdef DDB
351: if (flags & TODDB)
352: db_putchar(c);
353: #endif
354: }
355:
356:
357: /*
358: * uprintf: print to the controlling tty of the current process
359: *
360: * => we may block if the tty queue is full
361: * => no message is printed if the queue doesn't clear in a reasonable
362: * time
363: */
364:
365: void
366: uprintf(const char *fmt, ...)
367: {
368: struct proc *p = curproc;
369: va_list ap;
370:
371: if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) {
372: va_start(ap, fmt);
373: kprintf(fmt, TOTTY, p->p_session->s_ttyp, NULL, ap);
374: va_end(ap);
375: }
376: }
377:
378: #if defined(NFSSERVER) || defined(NFSCLIENT)
379:
380: /*
381: * tprintf functions: used to send messages to a specific process
382: *
383: * usage:
384: * get a tpr_t handle on a process "p" by using "tprintf_open(p)"
385: * use the handle when calling "tprintf"
386: * when done, do a "tprintf_close" to drop the handle
387: */
388:
389: /*
390: * tprintf_open: get a tprintf handle on a process "p"
391: *
392: * => returns NULL if process can't be printed to
393: */
394:
395: tpr_t
396: tprintf_open(struct proc *p)
397: {
398:
399: if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) {
400: SESSHOLD(p->p_session);
401: return ((tpr_t) p->p_session);
402: }
403: return ((tpr_t) NULL);
404: }
405:
406: /*
407: * tprintf_close: dispose of a tprintf handle obtained with tprintf_open
408: */
409:
410: void
411: tprintf_close(tpr_t sess)
412: {
413:
414: if (sess)
415: SESSRELE((struct session *) sess);
416: }
417:
418: /*
419: * tprintf: given tprintf handle to a process [obtained with tprintf_open],
420: * send a message to the controlling tty for that process.
421: *
422: * => also sends message to /dev/klog
423: */
424: void
425: tprintf(tpr_t tpr, const char *fmt, ...)
426: {
427: struct session *sess = (struct session *)tpr;
428: struct tty *tp = NULL;
429: int flags = TOLOG;
430: va_list ap;
431:
432: logpri(LOG_INFO);
433: if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) {
434: flags |= TOTTY;
435: tp = sess->s_ttyp;
436: }
437: va_start(ap, fmt);
438: kprintf(fmt, flags, tp, NULL, ap);
439: va_end(ap);
440: logwakeup();
441: }
442:
443: #endif /* NFSSERVER || NFSCLIENT */
444:
445:
446: /*
447: * ttyprintf: send a message to a specific tty
448: *
449: * => should be used only by tty driver or anything that knows the
450: * underlying tty will not be revoked(2)'d away. [otherwise,
451: * use tprintf]
452: */
453: void
454: ttyprintf(struct tty *tp, const char *fmt, ...)
455: {
456: va_list ap;
457:
458: va_start(ap, fmt);
459: kprintf(fmt, TOTTY, tp, NULL, ap);
460: va_end(ap);
461: }
462:
463: #ifdef DDB
464:
465: /*
466: * db_printf: printf for DDB (via db_putchar)
467: */
468:
469: int
470: db_printf(const char *fmt, ...)
471: {
472: va_list ap;
473: int flags, retval;
474:
475: flags = TODDB;
476: if (db_log)
477: flags |= TOLOG;
478: va_start(ap, fmt);
479: retval = kprintf(fmt, flags, NULL, NULL, ap);
480: va_end(ap);
481: return(retval);
482: }
483:
484: #endif /* DDB */
485:
486:
487: /*
488: * normal kernel printf functions: printf, vprintf, snprintf
489: */
490:
491: /*
492: * printf: print a message to the console and the log
493: */
494: int
495: printf(const char *fmt, ...)
496: {
497: va_list ap;
498: int savintr, retval;
499:
500: mtx_enter(&kprintf_mutex);
501:
502: savintr = consintr; /* disable interrupts */
503: consintr = 0;
504: va_start(ap, fmt);
505: retval = kprintf(fmt, TOCONS | TOLOG, NULL, NULL, ap);
506: va_end(ap);
507: if (!panicstr)
508: logwakeup();
509: consintr = savintr; /* reenable interrupts */
510:
511: mtx_leave(&kprintf_mutex);
512:
513: return(retval);
514: }
515:
516: /*
517: * vprintf: print a message to the console and the log [already have a
518: * va_list]
519: */
520:
521: int
522: vprintf(const char *fmt, va_list ap)
523: {
524: int savintr, retval;
525:
526: mtx_enter(&kprintf_mutex);
527:
528: savintr = consintr; /* disable interrupts */
529: consintr = 0;
530: retval = kprintf(fmt, TOCONS | TOLOG, NULL, NULL, ap);
531: if (!panicstr)
532: logwakeup();
533: consintr = savintr; /* reenable interrupts */
534:
535: mtx_leave(&kprintf_mutex);
536:
537: return (retval);
538: }
539:
540: /*
541: * snprintf: print a message to a buffer
542: */
543: int
544: snprintf(char *buf, size_t size, const char *fmt, ...)
545: {
546: int retval;
547: va_list ap;
548: char *p;
549:
550: p = buf + size - 1;
551: if (size < 1)
552: p = buf;
553: va_start(ap, fmt);
554: retval = kprintf(fmt, TOBUFONLY | TOCOUNT, &p, buf, ap);
555: va_end(ap);
556: if (size > 0)
557: *(p) = 0; /* null terminate */
558: return(retval);
559: }
560:
561: /*
562: * vsnprintf: print a message to a buffer [already have va_alist]
563: */
564: int
565: vsnprintf(char *buf, size_t size, const char *fmt, va_list ap)
566: {
567: int retval;
568: char *p;
569:
570: p = buf + size - 1;
571: if (size < 1)
572: p = buf;
573: retval = kprintf(fmt, TOBUFONLY | TOCOUNT, &p, buf, ap);
574: if (size > 0)
575: *(p) = 0; /* null terminate */
576: return(retval);
577: }
578:
579: /*
580: * kprintf: scaled down version of printf(3).
581: *
582: * this version based on vfprintf() from libc which was derived from
583: * software contributed to Berkeley by Chris Torek.
584: *
585: * Two additional formats:
586: *
587: * The format %b is supported to decode error registers.
588: * Its usage is:
589: *
590: * printf("reg=%b\n", regval, "<base><arg>*");
591: *
592: * where <base> is the output base expressed as a control character, e.g.
593: * \10 gives octal; \20 gives hex. Each arg is a sequence of characters,
594: * the first of which gives the bit number to be inspected (origin 1), and
595: * the next characters (up to a control character, i.e. a character <= 32),
596: * give the name of the register. Thus:
597: *
598: * kprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
599: *
600: * would produce output:
601: *
602: * reg=3<BITTWO,BITONE>
603: *
604: * To support larger integers (> 32 bits), %b formatting will also accept
605: * control characters in the region 0x80 - 0xff. 0x80 refers to bit 0,
606: * 0x81 refers to bit 1, and so on. The equivalent string to the above is:
607: *
608: * kprintf("reg=%b\n", 3, "\10\201BITTWO\200BITONE\n");
609: *
610: * and would produce the same output.
611: *
612: * Like the rest of printf, %b can be prefixed to handle various size
613: * modifiers, eg. %b is for "int", %lb is for "long", and %llb supports
614: * "long long".
615: *
616: * This code is large and complicated...
617: */
618:
619: /*
620: * macros for converting digits to letters and vice versa
621: */
622: #define to_digit(c) ((c) - '0')
623: #define is_digit(c) ((unsigned)to_digit(c) <= 9)
624: #define to_char(n) ((n) + '0')
625:
626: /*
627: * flags used during conversion.
628: */
629: #define ALT 0x001 /* alternate form */
630: #define HEXPREFIX 0x002 /* add 0x or 0X prefix */
631: #define LADJUST 0x004 /* left adjustment */
632: #define LONGDBL 0x008 /* long double; unimplemented */
633: #define LONGINT 0x010 /* long integer */
634: #define QUADINT 0x020 /* quad integer */
635: #define SHORTINT 0x040 /* short integer */
636: #define ZEROPAD 0x080 /* zero (as opposed to blank) pad */
637: #define FPT 0x100 /* Floating point number */
638:
639: /*
640: * To extend shorts properly, we need both signed and unsigned
641: * argument extraction methods.
642: */
643: #define SARG() \
644: (flags&QUADINT ? va_arg(ap, quad_t) : \
645: flags&LONGINT ? va_arg(ap, long) : \
646: flags&SHORTINT ? (long)(short)va_arg(ap, int) : \
647: (long)va_arg(ap, int))
648: #define UARG() \
649: (flags&QUADINT ? va_arg(ap, u_quad_t) : \
650: flags&LONGINT ? va_arg(ap, u_long) : \
651: flags&SHORTINT ? (u_long)(u_short)va_arg(ap, int) : \
652: (u_long)va_arg(ap, u_int))
653:
654: #define KPRINTF_PUTCHAR(C) do { \
655: int chr = (C); \
656: ret += 1; \
657: if (oflags & TOBUFONLY) { \
658: if ((vp != NULL) && (sbuf == tailp)) { \
659: if (!(oflags & TOCOUNT)) \
660: goto overflow; \
661: } else \
662: *sbuf++ = chr; \
663: } else { \
664: kputchar(chr, oflags, (struct tty *)vp); \
665: } \
666: } while(0)
667:
668: int
669: kprintf(const char *fmt0, int oflags, void *vp, char *sbuf, va_list ap)
670: {
671: char *fmt; /* format string */
672: int ch; /* character from fmt */
673: int n; /* handy integer (short term usage) */
674: char *cp = NULL; /* handy char pointer (short term usage) */
675: int flags; /* flags as above */
676: int ret; /* return value accumulator */
677: int width; /* width from format (%8d), or 0 */
678: int prec; /* precision from format (%.3d), or -1 */
679: char sign; /* sign prefix (' ', '+', '-', or \0) */
680:
681: u_quad_t _uquad; /* integer arguments %[diouxX] */
682: enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */
683: int dprec; /* a copy of prec if [diouxX], 0 otherwise */
684: int realsz; /* field size expanded by dprec */
685: int size = 0; /* size of converted field or string */
686: char *xdigs = NULL; /* digits for [xX] conversion */
687: char buf[KPRINTF_BUFSIZE]; /* space for %c, %[diouxX] */
688: char *tailp = NULL; /* tail pointer for snprintf */
689:
690: if ((oflags & TOBUFONLY) && (vp != NULL))
691: tailp = *(char **)vp;
692:
693: fmt = (char *)fmt0;
694: ret = 0;
695:
696: /*
697: * Scan the format for conversions (`%' character).
698: */
699: for (;;) {
700: while (*fmt != '%' && *fmt) {
701: KPRINTF_PUTCHAR(*fmt++);
702: }
703: if (*fmt == 0)
704: goto done;
705:
706: fmt++; /* skip over '%' */
707:
708: flags = 0;
709: dprec = 0;
710: width = 0;
711: prec = -1;
712: sign = '\0';
713:
714: rflag: ch = *fmt++;
715: reswitch: switch (ch) {
716: /* XXX: non-standard '%b' format */
717: case 'b': {
718: char *b, *z;
719: int tmp;
720: _uquad = UARG();
721: b = va_arg(ap, char *);
722: if (*b == 8)
723: snprintf(buf, sizeof buf, "%llo", _uquad);
724: else if (*b == 10)
725: snprintf(buf, sizeof buf, "%lld", _uquad);
726: else if (*b == 16)
727: snprintf(buf, sizeof buf, "%llx", _uquad);
728: else
729: break;
730: b++;
731:
732: z = buf;
733: while (*z) {
734: KPRINTF_PUTCHAR(*z++);
735: }
736:
737: if (_uquad) {
738: tmp = 0;
739: while ((n = *b++) != 0) {
740: if (n & 0x80)
741: n &= 0x7f;
742: else if (n <= ' ')
743: n = n - 1;
744: if (_uquad & (1LL << n)) {
745: KPRINTF_PUTCHAR(tmp ? ',':'<');
746: while (*b > ' ' &&
747: (*b & 0x80) == 0) {
748: KPRINTF_PUTCHAR(*b);
749: b++;
750: }
751: tmp = 1;
752: } else {
753: while (*b > ' ' &&
754: (*b & 0x80) == 0)
755: b++;
756: }
757: }
758: if (tmp) {
759: KPRINTF_PUTCHAR('>');
760: }
761: }
762: continue; /* no output */
763: }
764:
765: #ifdef DDB
766: /* XXX: non-standard '%r' format (print int in db_radix) */
767: case 'r':
768: if ((oflags & TODDB) == 0)
769: goto default_case;
770:
771: if (db_radix == 16)
772: goto case_z; /* signed hex */
773: _uquad = SARG();
774: if ((quad_t)_uquad < 0) {
775: _uquad = -_uquad;
776: sign = '-';
777: }
778: base = (db_radix == 8) ? OCT : DEC;
779: goto number;
780:
781:
782: /* XXX: non-standard '%z' format ("signed hex", a "hex %i")*/
783: case 'z':
784: case_z:
785: if ((oflags & TODDB) == 0)
786: goto default_case;
787:
788: xdigs = "0123456789abcdef";
789: ch = 'x'; /* the 'x' in '0x' (below) */
790: _uquad = SARG();
791: base = HEX;
792: /* leading 0x/X only if non-zero */
793: if (flags & ALT && _uquad != 0)
794: flags |= HEXPREFIX;
795: if ((quad_t)_uquad < 0) {
796: _uquad = -_uquad;
797: sign = '-';
798: }
799: goto number;
800: #endif
801:
802: case ' ':
803: /*
804: * ``If the space and + flags both appear, the space
805: * flag will be ignored.''
806: * -- ANSI X3J11
807: */
808: if (!sign)
809: sign = ' ';
810: goto rflag;
811: case '#':
812: flags |= ALT;
813: goto rflag;
814: case '*':
815: /*
816: * ``A negative field width argument is taken as a
817: * - flag followed by a positive field width.''
818: * -- ANSI X3J11
819: * They don't exclude field widths read from args.
820: */
821: if ((width = va_arg(ap, int)) >= 0)
822: goto rflag;
823: width = -width;
824: /* FALLTHROUGH */
825: case '-':
826: flags |= LADJUST;
827: goto rflag;
828: case '+':
829: sign = '+';
830: goto rflag;
831: case '.':
832: if ((ch = *fmt++) == '*') {
833: n = va_arg(ap, int);
834: prec = n < 0 ? -1 : n;
835: goto rflag;
836: }
837: n = 0;
838: while (is_digit(ch)) {
839: n = 10 * n + to_digit(ch);
840: ch = *fmt++;
841: }
842: prec = n < 0 ? -1 : n;
843: goto reswitch;
844: case '0':
845: /*
846: * ``Note that 0 is taken as a flag, not as the
847: * beginning of a field width.''
848: * -- ANSI X3J11
849: */
850: flags |= ZEROPAD;
851: goto rflag;
852: case '1': case '2': case '3': case '4':
853: case '5': case '6': case '7': case '8': case '9':
854: n = 0;
855: do {
856: n = 10 * n + to_digit(ch);
857: ch = *fmt++;
858: } while (is_digit(ch));
859: width = n;
860: goto reswitch;
861: case 'h':
862: flags |= SHORTINT;
863: goto rflag;
864: case 'l':
865: if (*fmt == 'l') {
866: fmt++;
867: flags |= QUADINT;
868: } else {
869: flags |= LONGINT;
870: }
871: goto rflag;
872: case 'q':
873: flags |= QUADINT;
874: goto rflag;
875: case 'c':
876: *(cp = buf) = va_arg(ap, int);
877: size = 1;
878: sign = '\0';
879: break;
880: case 'D':
881: flags |= LONGINT;
882: /*FALLTHROUGH*/
883: case 'd':
884: case 'i':
885: _uquad = SARG();
886: if ((quad_t)_uquad < 0) {
887: _uquad = -_uquad;
888: sign = '-';
889: }
890: base = DEC;
891: goto number;
892: case 'n':
893: #ifdef DDB
894: /* XXX: non-standard '%n' format */
895: /*
896: * XXX: HACK! DDB wants '%n' to be a '%u' printed
897: * in db_radix format. this should die since '%n'
898: * is already defined in standard printf to write
899: * the number of chars printed so far to the arg (which
900: * should be a pointer.
901: */
902: if (oflags & TODDB) {
903: if (db_radix == 16)
904: ch = 'x'; /* convert to %x */
905: else if (db_radix == 8)
906: ch = 'o'; /* convert to %o */
907: else
908: ch = 'u'; /* convert to %u */
909:
910: /* ... and start again */
911: goto reswitch;
912: }
913:
914: #endif
915: if (flags & QUADINT)
916: *va_arg(ap, quad_t *) = ret;
917: else if (flags & LONGINT)
918: *va_arg(ap, long *) = ret;
919: else if (flags & SHORTINT)
920: *va_arg(ap, short *) = ret;
921: else
922: *va_arg(ap, int *) = ret;
923: continue; /* no output */
924: case 'O':
925: flags |= LONGINT;
926: /*FALLTHROUGH*/
927: case 'o':
928: _uquad = UARG();
929: base = OCT;
930: goto nosign;
931: case 'p':
932: /*
933: * ``The argument shall be a pointer to void. The
934: * value of the pointer is converted to a sequence
935: * of printable characters, in an implementation-
936: * defined manner.''
937: * -- ANSI X3J11
938: */
939: /* NOSTRICT */
940: _uquad = (u_long)va_arg(ap, void *);
941: base = HEX;
942: xdigs = "0123456789abcdef";
943: flags |= HEXPREFIX;
944: ch = 'x';
945: goto nosign;
946: case 's':
947: if ((cp = va_arg(ap, char *)) == NULL)
948: cp = "(null)";
949: if (prec >= 0) {
950: /*
951: * can't use strlen; can only look for the
952: * NUL in the first `prec' characters, and
953: * strlen() will go further.
954: */
955: char *p = memchr(cp, 0, prec);
956:
957: if (p != NULL) {
958: size = p - cp;
959: if (size > prec)
960: size = prec;
961: } else
962: size = prec;
963: } else
964: size = strlen(cp);
965: sign = '\0';
966: break;
967: case 'U':
968: flags |= LONGINT;
969: /*FALLTHROUGH*/
970: case 'u':
971: _uquad = UARG();
972: base = DEC;
973: goto nosign;
974: case 'X':
975: xdigs = "0123456789ABCDEF";
976: goto hex;
977: case 'x':
978: xdigs = "0123456789abcdef";
979: hex: _uquad = UARG();
980: base = HEX;
981: /* leading 0x/X only if non-zero */
982: if (flags & ALT && _uquad != 0)
983: flags |= HEXPREFIX;
984:
985: /* unsigned conversions */
986: nosign: sign = '\0';
987: /*
988: * ``... diouXx conversions ... if a precision is
989: * specified, the 0 flag will be ignored.''
990: * -- ANSI X3J11
991: */
992: number: if ((dprec = prec) >= 0)
993: flags &= ~ZEROPAD;
994:
995: /*
996: * ``The result of converting a zero value with an
997: * explicit precision of zero is no characters.''
998: * -- ANSI X3J11
999: */
1000: cp = buf + KPRINTF_BUFSIZE;
1001: if (_uquad != 0 || prec != 0) {
1002: /*
1003: * Unsigned mod is hard, and unsigned mod
1004: * by a constant is easier than that by
1005: * a variable; hence this switch.
1006: */
1007: switch (base) {
1008: case OCT:
1009: do {
1010: *--cp = to_char(_uquad & 7);
1011: _uquad >>= 3;
1012: } while (_uquad);
1013: /* handle octal leading 0 */
1014: if (flags & ALT && *cp != '0')
1015: *--cp = '0';
1016: break;
1017:
1018: case DEC:
1019: /* many numbers are 1 digit */
1020: while (_uquad >= 10) {
1021: *--cp = to_char(_uquad % 10);
1022: _uquad /= 10;
1023: }
1024: *--cp = to_char(_uquad);
1025: break;
1026:
1027: case HEX:
1028: do {
1029: *--cp = xdigs[_uquad & 15];
1030: _uquad >>= 4;
1031: } while (_uquad);
1032: break;
1033:
1034: default:
1035: cp = "bug in kprintf: bad base";
1036: size = strlen(cp);
1037: goto skipsize;
1038: }
1039: }
1040: size = buf + KPRINTF_BUFSIZE - cp;
1041: skipsize:
1042: break;
1043: default: /* "%?" prints ?, unless ? is NUL */
1044: #ifdef DDB
1045: default_case: /* DDB */
1046: #endif
1047: if (ch == '\0')
1048: goto done;
1049: /* pretend it was %c with argument ch */
1050: cp = buf;
1051: *cp = ch;
1052: size = 1;
1053: sign = '\0';
1054: break;
1055: }
1056:
1057: /*
1058: * All reasonable formats wind up here. At this point, `cp'
1059: * points to a string which (if not flags&LADJUST) should be
1060: * padded out to `width' places. If flags&ZEROPAD, it should
1061: * first be prefixed by any sign or other prefix; otherwise,
1062: * it should be blank padded before the prefix is emitted.
1063: * After any left-hand padding and prefixing, emit zeroes
1064: * required by a decimal [diouxX] precision, then print the
1065: * string proper, then emit zeroes required by any leftover
1066: * floating precision; finally, if LADJUST, pad with blanks.
1067: *
1068: * Compute actual size, so we know how much to pad.
1069: * size excludes decimal prec; realsz includes it.
1070: */
1071: realsz = dprec > size ? dprec : size;
1072: if (sign)
1073: realsz++;
1074: else if (flags & HEXPREFIX)
1075: realsz+= 2;
1076:
1077: /* right-adjusting blank padding */
1078: if ((flags & (LADJUST|ZEROPAD)) == 0) {
1079: n = width - realsz;
1080: while (n-- > 0)
1081: KPRINTF_PUTCHAR(' ');
1082: }
1083:
1084: /* prefix */
1085: if (sign) {
1086: KPRINTF_PUTCHAR(sign);
1087: } else if (flags & HEXPREFIX) {
1088: KPRINTF_PUTCHAR('0');
1089: KPRINTF_PUTCHAR(ch);
1090: }
1091:
1092: /* right-adjusting zero padding */
1093: if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD) {
1094: n = width - realsz;
1095: while (n-- > 0)
1096: KPRINTF_PUTCHAR('0');
1097: }
1098:
1099: /* leading zeroes from decimal precision */
1100: n = dprec - size;
1101: while (n-- > 0)
1102: KPRINTF_PUTCHAR('0');
1103:
1104: /* the string or number proper */
1105: while (size--)
1106: KPRINTF_PUTCHAR(*cp++);
1107: /* left-adjusting padding (always blank) */
1108: if (flags & LADJUST) {
1109: n = width - realsz;
1110: while (n-- > 0)
1111: KPRINTF_PUTCHAR(' ');
1112: }
1113: }
1114:
1115: done:
1116: if ((oflags & TOBUFONLY) && (vp != NULL))
1117: *(char **)vp = sbuf;
1118: overflow:
1119: return (ret);
1120: /* NOTREACHED */
1121: }
1122:
1123: #if __GNUC_PREREQ__(2,96)
1124: /*
1125: * XXX - these functions shouldn't be in the kernel, but gcc 3.X feels like
1126: * translating some printf calls to puts and since it doesn't seem
1127: * possible to just turn off parts of those optimizations (some of
1128: * them are really useful), we have to provide a dummy puts and putchar
1129: * that are wrappers around printf.
1130: */
1131: int puts(const char *);
1132: int putchar(int c);
1133:
1134: int
1135: puts(const char *str)
1136: {
1137: printf("%s\n", str);
1138:
1139: return (0);
1140: }
1141:
1142: int
1143: putchar(int c)
1144: {
1145: printf("%c", c);
1146:
1147: return (c);
1148: }
1149:
1150:
1151: #endif
CVSweb