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.5 (Berkeley) 05/05/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 #include <sys/types.h> 35 36 /* 37 * Note that stdarg.h and the ANSI style va_start macro is used for both 38 * ANSI and traditional C compilers. 39 */ 40 #define KERNEL 41 #include <machine/stdarg.h> 42 #undef KERNEL 43 44 static void kprintn __P((u_long, int)); 45 46 void 47 #if __STDC__ 48 printf(const char *fmt, ...) 49 #else 50 printf(fmt /* , va_alist */) 51 char *fmt; 52 #endif 53 { 54 register char *p; 55 register int ch, n; 56 unsigned long ul; 57 int lflag, set; 58 va_list ap; 59 60 va_start(ap, fmt); 61 for (;;) { 62 while ((ch = *fmt++) != '%') { 63 if (ch == '\0') 64 return; 65 putchar(ch); 66 } 67 lflag = 0; 68 reswitch: switch (ch = *fmt++) { 69 case 'l': 70 lflag = 1; 71 goto reswitch; 72 case 'b': 73 ul = va_arg(ap, int); 74 p = va_arg(ap, char *); 75 kprintn(ul, *p++); 76 77 if (!ul) 78 break; 79 80 for (set = 0; n = *p++;) { 81 if (ul & (1 << (n - 1))) { 82 putchar(set ? ',' : '<'); 83 for (; (n = *p) > ' '; ++p) 84 putchar(n); 85 set = 1; 86 } else 87 for (; *p > ' '; ++p); 88 } 89 if (set) 90 putchar('>'); 91 break; 92 case 'c': 93 ch = va_arg(ap, int); 94 putchar(ch & 0x7f); 95 break; 96 case 's': 97 p = va_arg(ap, char *); 98 while (ch = *p++) 99 putchar(ch); 100 break; 101 case 'D': 102 lflag = 1; 103 /* FALLTHROUGH */ 104 case 'd': 105 ul = lflag ? 106 va_arg(ap, long) : va_arg(ap, int); 107 if ((long)ul < 0) { 108 putchar('-'); 109 ul = -(long)ul; 110 } 111 kprintn(ul, 10); 112 break; 113 case 'O': 114 lflag = 1; 115 /* FALLTHROUGH */ 116 case 'o': 117 ul = lflag ? 118 va_arg(ap, u_long) : va_arg(ap, u_int); 119 kprintn(ul, 8); 120 break; 121 case 'U': 122 lflag = 1; 123 /* FALLTHROUGH */ 124 case 'u': 125 ul = lflag ? 126 va_arg(ap, u_long) : va_arg(ap, u_int); 127 kprintn(ul, 10); 128 break; 129 case 'X': 130 lflag = 1; 131 /* FALLTHROUGH */ 132 case 'x': 133 ul = lflag ? 134 va_arg(ap, u_long) : va_arg(ap, u_int); 135 kprintn(ul, 16); 136 break; 137 default: 138 putchar('%'); 139 if (lflag) 140 putchar('l'); 141 putchar(ch); 142 } 143 } 144 va_end(ap); 145 } 146 147 static void 148 kprintn(ul, base) 149 unsigned long ul; 150 int base; 151 { 152 /* hold a long in base 8 */ 153 char *p, buf[(sizeof(long) * NBBY / 3) + 1]; 154 155 p = buf; 156 do { 157 *p++ = "0123456789abcdef"[ul % base]; 158 } while (ul /= base); 159 do { 160 putchar(*--p); 161 } while (p > buf); 162 } 163