Annotation of funnyos/libkern/printf.c, Revision 1.2
1.2 ! nbrk 1: /* $Id: printf.c,v 1.1.1.1 2007/10/16 08:41:04 init Exp $ */
1.1 init 2: /* $OpenBSD: printf.c,v 1.24 2006/09/18 21:11:50 mpf Exp $ */
3: /* $NetBSD: printf.c,v 1.10 1996/11/30 04:19:21 gwr Exp $ */
4:
5: /*-
6: * Copyright (c) 1993
7: * The Regents of the University of California. All rights reserved.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in the
16: * documentation and/or other materials provided with the distribution.
17: * 3. Neither the name of the University nor the names of its contributors
18: * may be used to endorse or promote products derived from this software
19: * without specific prior written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31: * SUCH DAMAGE.
32: *
33: * @(#)printf.c 8.1 (Berkeley) 6/11/93
34: */
35:
36: /*
37: * Scaled down version of printf(3).
38: *
39: * One additional format:
40: *
41: * The format %b is supported to decode error registers.
42: * Its usage is:
43: *
44: * printf("reg=%b\n", regval, "<base><arg>*");
45: *
46: * where <base> is the output base expressed as a control character, e.g.
47: * \10 gives octal; \20 gives hex. Each arg is a sequence of characters,
48: * the first of which gives the bit number to be inspected (origin 1), and
49: * the next characters (up to a control character, i.e. a character <= 32),
50: * give the name of the register. Thus:
51: *
52: * printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
53: *
54: * would produce output:
55: *
56: * reg=3<BITTWO,BITONE>
57: */
58:
59: #include <sys/types.h>
60: #include <sys/stdarg.h>
1.2 ! nbrk 61:
! 62: #include <dev/cpuvar.h> /* __cpu_disable_irq() for kpanic() */
1.1 init 63: #include <libkern/printf.h>
64:
65:
66: void kdoprnt(void (*)(char), const char *, va_list);
67: void kprintn(void (*put)(char), unsigned long ul, int base);
68:
69: const char hexdig[] = "0123456789abcdef";
70:
71: /*
72: * putchar function; usually gets xxx_early_putc at startup and then gets fcons_putc after fcons attachment.
73: */
74: void (*putchar)(char);
75:
76:
77: void
78: kpanic(const char *fmt, ...)
79: {
80: /*
1.2 ! nbrk 81: * System panic. Just disables interrupts, prints alarm message and spins off forever.
1.1 init 82: */
83: va_list ap;
84:
1.2 ! nbrk 85: __cpu_disable_irq();
1.1 init 86:
87: putchar('\n');
88: putchar('S');
89: putchar('Y');
90: putchar('S');
91: putchar('T');
92: putchar('E');
93: putchar('M');
94: putchar(' ');
95: putchar('P');
96: putchar('A');
97: putchar('N');
98: putchar('I');
99: putchar('C');
100: putchar(' ');
101: putchar(':');
102: putchar(' ');
103:
104: va_start(ap, fmt);
105: kdoprnt(putchar, fmt, ap);
106: va_end(ap);
107:
108: while(1)
109: ;
110: /* NOTREACHED */
111: }
112:
113:
114: void
115: printf(const char *fmt, ...)
116: {
117: va_list ap;
118:
119: va_start(ap, fmt);
120: kdoprnt(putchar, fmt, ap);
121: va_end(ap);
122: }
123:
124: void
125: kdoprnt(void (*put)(char), const char *fmt, va_list ap)
126: {
127: #ifdef LIBSA_LONGLONG_PRINTF
128: u_int64_t ull;
129: #endif
130: unsigned long ul;
131: int ch, lflag;
132: char *p;
133:
134: for (;;) {
135: while ((ch = *fmt++) != '%') {
136: if (ch == '\0')
137: return;
138: put(ch);
139: }
140: lflag = 0;
141: reswitch: switch (ch = *fmt++) {
142: case 'l':
143: lflag++;
144: goto reswitch;
145: #ifndef STRIPPED
146: case 'b':
147: {
148: int set, n;
149:
150: ul = va_arg(ap, int);
151: p = va_arg(ap, char *);
152: kprintn(put, ul, *p++);
153:
154: if (!ul)
155: break;
156:
157: for (set = 0; (n = *p++);) {
158: if (ul & (1 << (n - 1))) {
159: put(set ? ',' : '<');
160: for (; (n = *p) > ' '; ++p)
161: put(n);
162: set = 1;
163: } else
164: for (; *p > ' '; ++p)
165: ;
166: }
167: if (set)
168: put('>');
169: }
170: break;
171: #endif
172: case 'c':
173: ch = va_arg(ap, int);
174: put(ch & 0x7f);
175: break;
176: case 's':
177: p = va_arg(ap, char *);
178: while ((ch = *p++))
179: put(ch);
180: break;
181: case 'd':
182: #ifdef LIBSA_LONGLONG_PRINTF
183: if (lflag > 1) {
184: ull = va_arg(ap, int64_t);
185: if ((int64_t)ull < 0) {
186: put('-');
187: ull = -(int64_t)ull;
188: }
189: kprintn64(put, ull, 10);
190: break;
191: }
192: #endif
193: ul = lflag ?
194: va_arg(ap, long) : va_arg(ap, int);
195: if ((long)ul < 0) {
196: put('-');
197: ul = -(long)ul;
198: }
199: kprintn(put, ul, 10);
200: break;
201: case 'o':
202: #ifdef LIBSA_LONGLONG_PRINTF
203: if (lflag > 1) {
204: ull = va_arg(ap, u_int64_t);
205: kprintn64(put, ull, 8);
206: break;
207: }
208: #endif
209: ul = lflag ?
210: va_arg(ap, u_long) : va_arg(ap, u_int);
211: kprintn(put, ul, 8);
212: break;
213: case 'u':
214: #ifdef LIBSA_LONGLONG_PRINTF
215: if (lflag > 1) {
216: ull = va_arg(ap, u_int64_t);
217: kprintn64(put, ull, 10);
218: break;
219: }
220: #endif
221: ul = lflag ?
222: va_arg(ap, u_long) : va_arg(ap, u_int);
223: kprintn(put, ul, 10);
224: break;
225: case 'p':
226: put('0');
227: put('x');
228: lflag += sizeof(void *)==sizeof(u_long)? 1 : 0;
229: case 'x':
230: #ifdef LIBSA_LONGLONG_PRINTF
231: if (lflag > 1) {
232: ull = va_arg(ap, u_int64_t);
233: kprintn64(put, ull, 16);
234: break;
235: }
236: #else
237: if (lflag > 1) {
238: /* hold an int64_t in base 16 */
239: char *p, buf[(sizeof(u_int64_t) * 8 / 4) + 1];
240: u_int64_t ull;
241:
242: ull = va_arg(ap, u_int64_t);
243: p = buf;
244: do {
245: *p++ = hexdig[ull & 15];
246: } while (ull >>= 4);
247: do {
248: put(*--p);
249: } while (p > buf);
250: break;
251: }
252: #endif
253: ul = lflag ?
254: va_arg(ap, u_long) : va_arg(ap, u_int);
255: kprintn(put, ul, 16);
256: break;
257: default:
258: put('%');
259: #ifdef LIBSA_LONGLONG_PRINTF
260: while (--lflag)
261: #else
262: if (lflag)
263: #endif
264: put('l');
265: put(ch);
266: }
267: }
268: va_end(ap);
269: }
270:
271:
272: void
273: kprintn(void (*put)(char), unsigned long ul, int base)
274: {
275: /* hold a long in base 8 */
276: char *p, buf[(sizeof(long) * 8 / 3) + 1];
277:
278: p = buf;
279: do {
280: *p++ = hexdig[ul % base];
281: } while (ul /= base);
282: do {
283: put(*--p);
284: } while (p > buf);
285: }
286:
CVSweb