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