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.3 (Berkeley) 05/03/91 8 */ 9 10 /* 11 * Scaled down version of printf(3). 12 * 13 * Used to print diagnostic information directly on the console tty. Since 14 * it is not interrupt driven, all system activities are suspended. Printf 15 * should not be used for chit-chat. 16 * 17 * One additional format: %b is supported to decode error registers. 18 * Its usage is: 19 * 20 * printf("reg=%b\n", regval, "<base><arg>*"); 21 * 22 * where <base> is the output base expressed as a control character, e.g. 23 * \10 gives octal; \20 gives hex. Each arg is a sequence of characters, 24 * the first of which gives the bit number to be inspected (origin 1), and 25 * the next characters (up to a control character, i.e. a character <= 32), 26 * give the name of the register. Thus: 27 * 28 * printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); 29 * 30 * would produce output: 31 * 32 * reg=3<BITTWO,BITONE> 33 */ 34 35 #if __STDC__ 36 #include <stdarg.h> 37 #else 38 #include <varargs.h> 39 #endif 40 41 static void abort(){} /* Needed by stdarg macros. */ 42 static void number(); 43 44 void 45 #if __STDC__ 46 printf(const char *fmt, ...) 47 #else 48 printf(fmt, va_alist) 49 char *fmt; 50 va_dcl 51 #endif 52 { 53 register char *p; 54 register int ch, n; 55 unsigned long ul; 56 int lflag, set; 57 58 va_list ap; 59 #if __STDC__ 60 va_start(ap, fmt); 61 #else 62 va_start(ap); 63 #endif 64 for (;;) { 65 while ((ch = *fmt++) != '%') { 66 if (ch == '\0') 67 return; 68 putchar(ch); 69 } 70 lflag = 0; 71 reswitch: switch (ch = *fmt++) { 72 case 'l': 73 lflag = 1; 74 goto reswitch; 75 case 'b': 76 ul = va_arg(ap, int); 77 p = va_arg(ap, char *); 78 number(ul, *p++); 79 80 if (!ul) 81 break; 82 83 for (set = 0; n = *p++;) { 84 if (ul & (1 << (n - 1))) { 85 putchar(set ? ',' : '<'); 86 for (; (n = *p) > ' '; ++p) 87 putchar(n); 88 set = 1; 89 } else 90 for (; *p > ' '; ++p); 91 } 92 if (set) 93 putchar('>'); 94 break; 95 case 'c': 96 ch = va_arg(ap, int); 97 putchar(ch & 0x7f); 98 break; 99 case 's': 100 p = va_arg(ap, char *); 101 while (ch = *p++) 102 putchar(ch); 103 break; 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 number(ul, 10); 112 break; 113 case 'o': 114 ul = lflag ? 115 va_arg(ap, long) : va_arg(ap, unsigned int); 116 number(ul, 8); 117 break; 118 case 'u': 119 ul = lflag ? 120 va_arg(ap, long) : va_arg(ap, unsigned int); 121 number(ul, 10); 122 break; 123 case 'x': 124 ul = lflag ? 125 va_arg(ap, long) : va_arg(ap, unsigned int); 126 number(ul, 16); 127 break; 128 default: 129 putchar('%'); 130 if (lflag) 131 putchar('l'); 132 putchar(ch); 133 } 134 } 135 va_end(ap); 136 } 137 138 static void 139 number(ul, base) 140 unsigned long ul; 141 int base; 142 { 143 char *p, buf[11]; /* hold 2^32 in base 8 */ 144 145 p = buf; 146 do { 147 *p++ = "0123456789abcdef"[ul % base]; 148 } while (ul /= base); 149 do { 150 putchar(*--p); 151 } while (p > buf); 152 } 153