148987Sbostic /*- 248987Sbostic * Copyright (c) 1991 The Regents of the University of California. 348987Sbostic * All rights reserved. 448987Sbostic * 548987Sbostic * %sccs.include.redist.c% 648987Sbostic * 7*49118Sbostic * @(#)printf.c 5.4 (Berkeley) 05/04/91 848987Sbostic */ 948987Sbostic 1048987Sbostic /* 1148988Sbostic * Scaled down version of printf(3). 1248987Sbostic * 13*49118Sbostic * One additional format: 1448987Sbostic * 15*49118Sbostic * The format %b is supported to decode error registers. 1648987Sbostic * Its usage is: 1748987Sbostic * 1848987Sbostic * printf("reg=%b\n", regval, "<base><arg>*"); 1948987Sbostic * 2048987Sbostic * where <base> is the output base expressed as a control character, e.g. 2148987Sbostic * \10 gives octal; \20 gives hex. Each arg is a sequence of characters, 2248987Sbostic * the first of which gives the bit number to be inspected (origin 1), and 2348987Sbostic * the next characters (up to a control character, i.e. a character <= 32), 2448987Sbostic * give the name of the register. Thus: 2548987Sbostic * 2648987Sbostic * printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); 2748987Sbostic * 2848987Sbostic * would produce output: 2948987Sbostic * 3048987Sbostic * reg=3<BITTWO,BITONE> 3148987Sbostic */ 3248987Sbostic 33*49118Sbostic #include <sys/cdefs.h> 3448987Sbostic 35*49118Sbostic /* 36*49118Sbostic * Note that stdarg.h and the ANSI style va_start macro is used for both 37*49118Sbostic * ANSI and traditional C compilers. 38*49118Sbostic */ 39*49118Sbostic #define KERNEL 40*49118Sbostic #include <machine/stdarg.h> 41*49118Sbostic #undef KERNEL 4248987Sbostic 43*49118Sbostic static void kprintn __P((u_long, int)); 44*49118Sbostic 4548987Sbostic void 4648987Sbostic #if __STDC__ 4748987Sbostic printf(const char *fmt, ...) 4848987Sbostic #else 49*49118Sbostic printf(fmt /* , va_alist */) 5048987Sbostic char *fmt; 5148987Sbostic #endif 5248987Sbostic { 5348987Sbostic register char *p; 5448987Sbostic register int ch, n; 5548989Sbostic unsigned long ul; 5648987Sbostic int lflag, set; 57*49118Sbostic va_list ap; 5848987Sbostic 5948987Sbostic va_start(ap, fmt); 6048987Sbostic for (;;) { 6148987Sbostic while ((ch = *fmt++) != '%') { 6248987Sbostic if (ch == '\0') 6348987Sbostic return; 6448987Sbostic putchar(ch); 6548987Sbostic } 6648987Sbostic lflag = 0; 6748987Sbostic reswitch: switch (ch = *fmt++) { 6848987Sbostic case 'l': 6948987Sbostic lflag = 1; 7048987Sbostic goto reswitch; 7148987Sbostic case 'b': 7248989Sbostic ul = va_arg(ap, int); 7348987Sbostic p = va_arg(ap, char *); 74*49118Sbostic kprintn(ul, *p++); 7548987Sbostic 7648989Sbostic if (!ul) 7748987Sbostic break; 7848987Sbostic 7948987Sbostic for (set = 0; n = *p++;) { 8048989Sbostic if (ul & (1 << (n - 1))) { 8148987Sbostic putchar(set ? ',' : '<'); 8248987Sbostic for (; (n = *p) > ' '; ++p) 8348987Sbostic putchar(n); 8448987Sbostic set = 1; 8548987Sbostic } else 8648987Sbostic for (; *p > ' '; ++p); 8748987Sbostic } 8848987Sbostic if (set) 8948987Sbostic putchar('>'); 9048987Sbostic break; 9148987Sbostic case 'c': 9248987Sbostic ch = va_arg(ap, int); 9348987Sbostic putchar(ch & 0x7f); 9448987Sbostic break; 9548987Sbostic case 's': 9648987Sbostic p = va_arg(ap, char *); 9748987Sbostic while (ch = *p++) 9848987Sbostic putchar(ch); 9948987Sbostic break; 100*49118Sbostic case 'D': 101*49118Sbostic lflag = 1; 102*49118Sbostic /* FALLTHROUGH */ 10348987Sbostic case 'd': 10448989Sbostic ul = lflag ? 10548987Sbostic va_arg(ap, long) : va_arg(ap, int); 10648989Sbostic if ((long)ul < 0) { 10748987Sbostic putchar('-'); 10848989Sbostic ul = -(long)ul; 10948987Sbostic } 110*49118Sbostic kprintn(ul, 10); 11148987Sbostic break; 112*49118Sbostic case 'O': 113*49118Sbostic lflag = 1; 114*49118Sbostic /* FALLTHROUGH */ 11548987Sbostic case 'o': 11648989Sbostic ul = lflag ? 117*49118Sbostic va_arg(ap, u_long) : va_arg(ap, u_int); 118*49118Sbostic kprintn(ul, 8); 11948987Sbostic break; 120*49118Sbostic case 'U': 121*49118Sbostic lflag = 1; 122*49118Sbostic /* FALLTHROUGH */ 12348987Sbostic case 'u': 12448989Sbostic ul = lflag ? 125*49118Sbostic va_arg(ap, u_long) : va_arg(ap, u_int); 126*49118Sbostic kprintn(ul, 10); 12748987Sbostic break; 128*49118Sbostic case 'X': 129*49118Sbostic lflag = 1; 130*49118Sbostic /* FALLTHROUGH */ 13148987Sbostic case 'x': 13248989Sbostic ul = lflag ? 133*49118Sbostic va_arg(ap, u_long) : va_arg(ap, u_int); 134*49118Sbostic kprintn(ul, 16); 13548987Sbostic break; 13648987Sbostic default: 13748987Sbostic putchar('%'); 13848987Sbostic if (lflag) 13948987Sbostic putchar('l'); 14048987Sbostic putchar(ch); 14148987Sbostic } 14248987Sbostic } 14348987Sbostic va_end(ap); 14448987Sbostic } 14548987Sbostic 14648987Sbostic static void 147*49118Sbostic kprintn(ul, base) 14848989Sbostic unsigned long ul; 14948987Sbostic int base; 15048987Sbostic { 15148987Sbostic char *p, buf[11]; /* hold 2^32 in base 8 */ 15248987Sbostic 15348987Sbostic p = buf; 15448987Sbostic do { 15548989Sbostic *p++ = "0123456789abcdef"[ul % base]; 15648989Sbostic } while (ul /= base); 15748987Sbostic do { 15848987Sbostic putchar(*--p); 15948987Sbostic } while (p > buf); 16048987Sbostic } 161