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