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