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.7 (Berkeley) 10/11/92 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 ul = lflag ? 103 va_arg(ap, long) : va_arg(ap, int); 104 if ((long)ul < 0) { 105 putchar('-'); 106 ul = -(long)ul; 107 } 108 kprintn(ul, 10); 109 break; 110 case 'o': 111 ul = lflag ? 112 va_arg(ap, u_long) : va_arg(ap, u_int); 113 kprintn(ul, 8); 114 break; 115 case 'u': 116 ul = lflag ? 117 va_arg(ap, u_long) : va_arg(ap, u_int); 118 kprintn(ul, 10); 119 break; 120 case 'x': 121 ul = lflag ? 122 va_arg(ap, u_long) : va_arg(ap, u_int); 123 kprintn(ul, 16); 124 break; 125 default: 126 putchar('%'); 127 if (lflag) 128 putchar('l'); 129 putchar(ch); 130 } 131 } 132 va_end(ap); 133 } 134 135 static void 136 kprintn(ul, base) 137 unsigned long ul; 138 int base; 139 { 140 /* hold a long in base 8 */ 141 char *p, buf[(sizeof(long) * NBBY / 3) + 1]; 142 143 p = buf; 144 do { 145 *p++ = "0123456789abcdef"[ul % base]; 146 } while (ul /= base); 147 do { 148 putchar(*--p); 149 } while (p > buf); 150 } 151