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