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