Annotation of funnyos/libkern/printf.c, Revision 1.1.1.1
1.1 init 1: /* $Id: printf.c,v 1.1.1.1 2007/10/12 08:40:38 init Exp $ */
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>
61: #include <libkern/printf.h>
62:
63:
64: void kdoprnt(void (*)(char), const char *, va_list);
65: void kprintn(void (*put)(char), unsigned long ul, int base);
66:
67: const char hexdig[] = "0123456789abcdef";
68:
69: /*
70: * putchar function; usually gets xxx_early_putc at startup and then gets fcons_putc after fcons attachment.
71: */
72: void (*putchar)(char);
73:
74:
75: void
76: kpanic(const char *fmt, ...)
77: {
78: /*
79: * System panic. Just disables interrupts, kills sheduler, prints alarm message and spins off forever.
80: */
81: va_list ap;
82:
83: /* XXX disable intrs & sched */
84:
85: putchar('\n');
86: putchar('S');
87: putchar('Y');
88: putchar('S');
89: putchar('T');
90: putchar('E');
91: putchar('M');
92: putchar(' ');
93: putchar('P');
94: putchar('A');
95: putchar('N');
96: putchar('I');
97: putchar('C');
98: putchar(' ');
99: putchar(':');
100: putchar(' ');
101:
102: va_start(ap, fmt);
103: kdoprnt(putchar, fmt, ap);
104: va_end(ap);
105:
106: while(1)
107: ;
108: /* NOTREACHED */
109: }
110:
111:
112: void
113: printf(const char *fmt, ...)
114: {
115: va_list ap;
116:
117: va_start(ap, fmt);
118: kdoprnt(putchar, fmt, ap);
119: va_end(ap);
120: }
121:
122: void
123: kdoprnt(void (*put)(char), const char *fmt, va_list ap)
124: {
125: #ifdef LIBSA_LONGLONG_PRINTF
126: u_int64_t ull;
127: #endif
128: unsigned long ul;
129: int ch, lflag;
130: char *p;
131:
132: for (;;) {
133: while ((ch = *fmt++) != '%') {
134: if (ch == '\0')
135: return;
136: put(ch);
137: }
138: lflag = 0;
139: reswitch: switch (ch = *fmt++) {
140: case 'l':
141: lflag++;
142: goto reswitch;
143: #ifndef STRIPPED
144: case 'b':
145: {
146: int set, n;
147:
148: ul = va_arg(ap, int);
149: p = va_arg(ap, char *);
150: kprintn(put, ul, *p++);
151:
152: if (!ul)
153: break;
154:
155: for (set = 0; (n = *p++);) {
156: if (ul & (1 << (n - 1))) {
157: put(set ? ',' : '<');
158: for (; (n = *p) > ' '; ++p)
159: put(n);
160: set = 1;
161: } else
162: for (; *p > ' '; ++p)
163: ;
164: }
165: if (set)
166: put('>');
167: }
168: break;
169: #endif
170: case 'c':
171: ch = va_arg(ap, int);
172: put(ch & 0x7f);
173: break;
174: case 's':
175: p = va_arg(ap, char *);
176: while ((ch = *p++))
177: put(ch);
178: break;
179: case 'd':
180: #ifdef LIBSA_LONGLONG_PRINTF
181: if (lflag > 1) {
182: ull = va_arg(ap, int64_t);
183: if ((int64_t)ull < 0) {
184: put('-');
185: ull = -(int64_t)ull;
186: }
187: kprintn64(put, ull, 10);
188: break;
189: }
190: #endif
191: ul = lflag ?
192: va_arg(ap, long) : va_arg(ap, int);
193: if ((long)ul < 0) {
194: put('-');
195: ul = -(long)ul;
196: }
197: kprintn(put, ul, 10);
198: break;
199: case 'o':
200: #ifdef LIBSA_LONGLONG_PRINTF
201: if (lflag > 1) {
202: ull = va_arg(ap, u_int64_t);
203: kprintn64(put, ull, 8);
204: break;
205: }
206: #endif
207: ul = lflag ?
208: va_arg(ap, u_long) : va_arg(ap, u_int);
209: kprintn(put, ul, 8);
210: break;
211: case 'u':
212: #ifdef LIBSA_LONGLONG_PRINTF
213: if (lflag > 1) {
214: ull = va_arg(ap, u_int64_t);
215: kprintn64(put, ull, 10);
216: break;
217: }
218: #endif
219: ul = lflag ?
220: va_arg(ap, u_long) : va_arg(ap, u_int);
221: kprintn(put, ul, 10);
222: break;
223: case 'p':
224: put('0');
225: put('x');
226: lflag += sizeof(void *)==sizeof(u_long)? 1 : 0;
227: case 'x':
228: #ifdef LIBSA_LONGLONG_PRINTF
229: if (lflag > 1) {
230: ull = va_arg(ap, u_int64_t);
231: kprintn64(put, ull, 16);
232: break;
233: }
234: #else
235: if (lflag > 1) {
236: /* hold an int64_t in base 16 */
237: char *p, buf[(sizeof(u_int64_t) * 8 / 4) + 1];
238: u_int64_t ull;
239:
240: ull = va_arg(ap, u_int64_t);
241: p = buf;
242: do {
243: *p++ = hexdig[ull & 15];
244: } while (ull >>= 4);
245: do {
246: put(*--p);
247: } while (p > buf);
248: break;
249: }
250: #endif
251: ul = lflag ?
252: va_arg(ap, u_long) : va_arg(ap, u_int);
253: kprintn(put, ul, 16);
254: break;
255: default:
256: put('%');
257: #ifdef LIBSA_LONGLONG_PRINTF
258: while (--lflag)
259: #else
260: if (lflag)
261: #endif
262: put('l');
263: put(ch);
264: }
265: }
266: va_end(ap);
267: }
268:
269:
270: void
271: kprintn(void (*put)(char), unsigned long ul, int base)
272: {
273: /* hold a long in base 8 */
274: char *p, buf[(sizeof(long) * 8 / 3) + 1];
275:
276: p = buf;
277: do {
278: *p++ = hexdig[ul % base];
279: } while (ul /= base);
280: do {
281: put(*--p);
282: } while (p > buf);
283: }
284:
CVSweb