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