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