1 /*- 2 * Copyright (c) 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * from: @(#)printf.c 8.1 (Berkeley) 6/11/93 34 * $Id: printf.c,v 1.1 1994/01/26 02:03:53 brezak Exp $ 35 */ 36 37 /* 38 * Scaled down version of printf(3). 39 * 40 * One additional format: 41 * 42 * The format %b is supported to decode error registers. 43 * Its usage is: 44 * 45 * printf("reg=%b\n", regval, "<base><arg>*"); 46 * 47 * where <base> is the output base expressed as a control character, e.g. 48 * \10 gives octal; \20 gives hex. Each arg is a sequence of characters, 49 * the first of which gives the bit number to be inspected (origin 1), and 50 * the next characters (up to a control character, i.e. a character <= 32), 51 * give the name of the register. Thus: 52 * 53 * printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); 54 * 55 * would produce output: 56 * 57 * reg=3<BITTWO,BITONE> 58 */ 59 60 #include <sys/cdefs.h> 61 #include <sys/types.h> 62 63 /* 64 * Note that stdarg.h and the ANSI style va_start macro is used for both 65 * ANSI and traditional C compilers. 66 */ 67 #define KERNEL 68 #include <machine/stdarg.h> 69 #undef KERNEL 70 71 static void kprintn __P((u_long, int)); 72 73 void 74 #if __STDC__ 75 printf(const char *fmt, ...) 76 #else 77 printf(fmt /* , va_alist */) 78 char *fmt; 79 #endif 80 { 81 register char *p; 82 register int ch, n; 83 unsigned long ul; 84 int lflag, set; 85 va_list ap; 86 87 va_start(ap, fmt); 88 for (;;) { 89 while ((ch = *fmt++) != '%') { 90 if (ch == '\0') 91 return; 92 putchar(ch); 93 } 94 lflag = 0; 95 reswitch: switch (ch = *fmt++) { 96 case 'l': 97 lflag = 1; 98 goto reswitch; 99 case 'b': 100 ul = va_arg(ap, int); 101 p = va_arg(ap, char *); 102 kprintn(ul, *p++); 103 104 if (!ul) 105 break; 106 107 for (set = 0; n = *p++;) { 108 if (ul & (1 << (n - 1))) { 109 putchar(set ? ',' : '<'); 110 for (; (n = *p) > ' '; ++p) 111 putchar(n); 112 set = 1; 113 } else 114 for (; *p > ' '; ++p); 115 } 116 if (set) 117 putchar('>'); 118 break; 119 case 'c': 120 ch = va_arg(ap, int); 121 putchar(ch & 0x7f); 122 break; 123 case 's': 124 p = va_arg(ap, char *); 125 while (ch = *p++) 126 putchar(ch); 127 break; 128 case 'd': 129 ul = lflag ? 130 va_arg(ap, long) : va_arg(ap, int); 131 if ((long)ul < 0) { 132 putchar('-'); 133 ul = -(long)ul; 134 } 135 kprintn(ul, 10); 136 break; 137 case 'o': 138 ul = lflag ? 139 va_arg(ap, u_long) : va_arg(ap, u_int); 140 kprintn(ul, 8); 141 break; 142 case 'u': 143 ul = lflag ? 144 va_arg(ap, u_long) : va_arg(ap, u_int); 145 kprintn(ul, 10); 146 break; 147 case 'x': 148 ul = lflag ? 149 va_arg(ap, u_long) : va_arg(ap, u_int); 150 kprintn(ul, 16); 151 break; 152 default: 153 putchar('%'); 154 if (lflag) 155 putchar('l'); 156 putchar(ch); 157 } 158 } 159 va_end(ap); 160 } 161 162 static void 163 kprintn(ul, base) 164 unsigned long ul; 165 int base; 166 { 167 /* hold a long in base 8 */ 168 char *p, buf[(sizeof(long) * NBBY / 3) + 1]; 169 170 p = buf; 171 do { 172 *p++ = "0123456789abcdef"[ul % base]; 173 } while (ul /= base); 174 do { 175 putchar(*--p); 176 } while (p > buf); 177 } 178