1 /*- 2 * Copyright (c) 1991 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)printf.c 5.4 (Berkeley) 05/04/91 8 */ 9 10 /* 11 * Scaled down version of printf(3). 12 * 13 * One additional format: 14 * 15 * The format %b is supported to decode error registers. 16 * Its usage is: 17 * 18 * printf("reg=%b\n", regval, "<base><arg>*"); 19 * 20 * where <base> is the output base expressed as a control character, e.g. 21 * \10 gives octal; \20 gives hex. Each arg is a sequence of characters, 22 * the first of which gives the bit number to be inspected (origin 1), and 23 * the next characters (up to a control character, i.e. a character <= 32), 24 * give the name of the register. Thus: 25 * 26 * printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); 27 * 28 * would produce output: 29 * 30 * reg=3<BITTWO,BITONE> 31 */ 32 33 #include <sys/cdefs.h> 34 35 /* 36 * Note that stdarg.h and the ANSI style va_start macro is used for both 37 * ANSI and traditional C compilers. 38 */ 39 #define KERNEL 40 #include <machine/stdarg.h> 41 #undef KERNEL 42 43 static void kprintn __P((u_long, int)); 44 45 void 46 #if __STDC__ 47 printf(const char *fmt, ...) 48 #else 49 printf(fmt /* , va_alist */) 50 char *fmt; 51 #endif 52 { 53 register char *p; 54 register int ch, n; 55 unsigned long ul; 56 int lflag, set; 57 va_list ap; 58 59 va_start(ap, fmt); 60 for (;;) { 61 while ((ch = *fmt++) != '%') { 62 if (ch == '\0') 63 return; 64 putchar(ch); 65 } 66 lflag = 0; 67 reswitch: switch (ch = *fmt++) { 68 case 'l': 69 lflag = 1; 70 goto reswitch; 71 case 'b': 72 ul = va_arg(ap, int); 73 p = va_arg(ap, char *); 74 kprintn(ul, *p++); 75 76 if (!ul) 77 break; 78 79 for (set = 0; n = *p++;) { 80 if (ul & (1 << (n - 1))) { 81 putchar(set ? ',' : '<'); 82 for (; (n = *p) > ' '; ++p) 83 putchar(n); 84 set = 1; 85 } else 86 for (; *p > ' '; ++p); 87 } 88 if (set) 89 putchar('>'); 90 break; 91 case 'c': 92 ch = va_arg(ap, int); 93 putchar(ch & 0x7f); 94 break; 95 case 's': 96 p = va_arg(ap, char *); 97 while (ch = *p++) 98 putchar(ch); 99 break; 100 case 'D': 101 lflag = 1; 102 /* FALLTHROUGH */ 103 case 'd': 104 ul = lflag ? 105 va_arg(ap, long) : va_arg(ap, int); 106 if ((long)ul < 0) { 107 putchar('-'); 108 ul = -(long)ul; 109 } 110 kprintn(ul, 10); 111 break; 112 case 'O': 113 lflag = 1; 114 /* FALLTHROUGH */ 115 case 'o': 116 ul = lflag ? 117 va_arg(ap, u_long) : va_arg(ap, u_int); 118 kprintn(ul, 8); 119 break; 120 case 'U': 121 lflag = 1; 122 /* FALLTHROUGH */ 123 case 'u': 124 ul = lflag ? 125 va_arg(ap, u_long) : va_arg(ap, u_int); 126 kprintn(ul, 10); 127 break; 128 case 'X': 129 lflag = 1; 130 /* FALLTHROUGH */ 131 case 'x': 132 ul = lflag ? 133 va_arg(ap, u_long) : va_arg(ap, u_int); 134 kprintn(ul, 16); 135 break; 136 default: 137 putchar('%'); 138 if (lflag) 139 putchar('l'); 140 putchar(ch); 141 } 142 } 143 va_end(ap); 144 } 145 146 static void 147 kprintn(ul, base) 148 unsigned long ul; 149 int base; 150 { 151 char *p, buf[11]; /* hold 2^32 in base 8 */ 152 153 p = buf; 154 do { 155 *p++ = "0123456789abcdef"[ul % base]; 156 } while (ul /= base); 157 do { 158 putchar(*--p); 159 } while (p > buf); 160 } 161