xref: /csrg-svn/sys/stand/printf.c (revision 63277)
1*63277Smckusick /*-
2*63277Smckusick  * Copyright (c) 1993 The Regents of the University of California.
3*63277Smckusick  * All rights reserved.
4*63277Smckusick  *
5*63277Smckusick  * %sccs.include.redist.c%
6*63277Smckusick  *
7*63277Smckusick  *	@(#)printf.c	7.1 (Berkeley) 06/11/93
8*63277Smckusick  */
9*63277Smckusick 
10*63277Smckusick /*
11*63277Smckusick  * Scaled down version of printf(3).
12*63277Smckusick  *
13*63277Smckusick  * One additional format:
14*63277Smckusick  *
15*63277Smckusick  * The format %b is supported to decode error registers.
16*63277Smckusick  * Its usage is:
17*63277Smckusick  *
18*63277Smckusick  *	printf("reg=%b\n", regval, "<base><arg>*");
19*63277Smckusick  *
20*63277Smckusick  * where <base> is the output base expressed as a control character, e.g.
21*63277Smckusick  * \10 gives octal; \20 gives hex.  Each arg is a sequence of characters,
22*63277Smckusick  * the first of which gives the bit number to be inspected (origin 1), and
23*63277Smckusick  * the next characters (up to a control character, i.e. a character <= 32),
24*63277Smckusick  * give the name of the register.  Thus:
25*63277Smckusick  *
26*63277Smckusick  *	printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
27*63277Smckusick  *
28*63277Smckusick  * would produce output:
29*63277Smckusick  *
30*63277Smckusick  *	reg=3<BITTWO,BITONE>
31*63277Smckusick  */
32*63277Smckusick 
33*63277Smckusick #include <sys/cdefs.h>
34*63277Smckusick #include <sys/types.h>
35*63277Smckusick 
36*63277Smckusick /*
37*63277Smckusick  * Note that stdarg.h and the ANSI style va_start macro is used for both
38*63277Smckusick  * ANSI and traditional C compilers.
39*63277Smckusick  */
40*63277Smckusick #define KERNEL
41*63277Smckusick #include <machine/stdarg.h>
42*63277Smckusick #undef KERNEL
43*63277Smckusick 
44*63277Smckusick static void kprintn __P((u_long, int));
45*63277Smckusick 
46*63277Smckusick void
47*63277Smckusick #if __STDC__
48*63277Smckusick printf(const char *fmt, ...)
49*63277Smckusick #else
50*63277Smckusick printf(fmt /* , va_alist */)
51*63277Smckusick 	char *fmt;
52*63277Smckusick #endif
53*63277Smckusick {
54*63277Smckusick 	register char *p;
55*63277Smckusick 	register int ch, n;
56*63277Smckusick 	unsigned long ul;
57*63277Smckusick 	int lflag, set;
58*63277Smckusick 	va_list ap;
59*63277Smckusick 
60*63277Smckusick 	va_start(ap, fmt);
61*63277Smckusick 	for (;;) {
62*63277Smckusick 		while ((ch = *fmt++) != '%') {
63*63277Smckusick 			if (ch == '\0')
64*63277Smckusick 				return;
65*63277Smckusick 			putchar(ch);
66*63277Smckusick 		}
67*63277Smckusick 		lflag = 0;
68*63277Smckusick reswitch:	switch (ch = *fmt++) {
69*63277Smckusick 		case 'l':
70*63277Smckusick 			lflag = 1;
71*63277Smckusick 			goto reswitch;
72*63277Smckusick 		case 'b':
73*63277Smckusick 			ul = va_arg(ap, int);
74*63277Smckusick 			p = va_arg(ap, char *);
75*63277Smckusick 			kprintn(ul, *p++);
76*63277Smckusick 
77*63277Smckusick 			if (!ul)
78*63277Smckusick 				break;
79*63277Smckusick 
80*63277Smckusick 			for (set = 0; n = *p++;) {
81*63277Smckusick 				if (ul & (1 << (n - 1))) {
82*63277Smckusick 					putchar(set ? ',' : '<');
83*63277Smckusick 					for (; (n = *p) > ' '; ++p)
84*63277Smckusick 						putchar(n);
85*63277Smckusick 					set = 1;
86*63277Smckusick 				} else
87*63277Smckusick 					for (; *p > ' '; ++p);
88*63277Smckusick 			}
89*63277Smckusick 			if (set)
90*63277Smckusick 				putchar('>');
91*63277Smckusick 			break;
92*63277Smckusick 		case 'c':
93*63277Smckusick 			ch = va_arg(ap, int);
94*63277Smckusick 				putchar(ch & 0x7f);
95*63277Smckusick 			break;
96*63277Smckusick 		case 's':
97*63277Smckusick 			p = va_arg(ap, char *);
98*63277Smckusick 			while (ch = *p++)
99*63277Smckusick 				putchar(ch);
100*63277Smckusick 			break;
101*63277Smckusick 		case 'd':
102*63277Smckusick 			ul = lflag ?
103*63277Smckusick 			    va_arg(ap, long) : va_arg(ap, int);
104*63277Smckusick 			if ((long)ul < 0) {
105*63277Smckusick 				putchar('-');
106*63277Smckusick 				ul = -(long)ul;
107*63277Smckusick 			}
108*63277Smckusick 			kprintn(ul, 10);
109*63277Smckusick 			break;
110*63277Smckusick 		case 'o':
111*63277Smckusick 			ul = lflag ?
112*63277Smckusick 			    va_arg(ap, u_long) : va_arg(ap, u_int);
113*63277Smckusick 			kprintn(ul, 8);
114*63277Smckusick 			break;
115*63277Smckusick 		case 'u':
116*63277Smckusick 			ul = lflag ?
117*63277Smckusick 			    va_arg(ap, u_long) : va_arg(ap, u_int);
118*63277Smckusick 			kprintn(ul, 10);
119*63277Smckusick 			break;
120*63277Smckusick 		case 'x':
121*63277Smckusick 			ul = lflag ?
122*63277Smckusick 			    va_arg(ap, u_long) : va_arg(ap, u_int);
123*63277Smckusick 			kprintn(ul, 16);
124*63277Smckusick 			break;
125*63277Smckusick 		default:
126*63277Smckusick 			putchar('%');
127*63277Smckusick 			if (lflag)
128*63277Smckusick 				putchar('l');
129*63277Smckusick 			putchar(ch);
130*63277Smckusick 		}
131*63277Smckusick 	}
132*63277Smckusick 	va_end(ap);
133*63277Smckusick }
134*63277Smckusick 
135*63277Smckusick static void
136*63277Smckusick kprintn(ul, base)
137*63277Smckusick 	unsigned long ul;
138*63277Smckusick 	int base;
139*63277Smckusick {
140*63277Smckusick 					/* hold a long in base 8 */
141*63277Smckusick 	char *p, buf[(sizeof(long) * NBBY / 3) + 1];
142*63277Smckusick 
143*63277Smckusick 	p = buf;
144*63277Smckusick 	do {
145*63277Smckusick 		*p++ = "0123456789abcdef"[ul % base];
146*63277Smckusick 	} while (ul /= base);
147*63277Smckusick 	do {
148*63277Smckusick 		putchar(*--p);
149*63277Smckusick 	} while (p > buf);
150*63277Smckusick }
151