148987Sbostic /*- 248987Sbostic * Copyright (c) 1991 The Regents of the University of California. 348987Sbostic * All rights reserved. 448987Sbostic * 548987Sbostic * %sccs.include.redist.c% 648987Sbostic * 7*49168Swilliam * @(#)printf.c 5.5 (Berkeley) 05/05/91 848987Sbostic */ 948987Sbostic 1048987Sbostic /* 1148988Sbostic * Scaled down version of printf(3). 1248987Sbostic * 1349118Sbostic * One additional format: 1448987Sbostic * 1549118Sbostic * 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 3349118Sbostic #include <sys/cdefs.h> 34*49168Swilliam #include <sys/types.h> 3548987Sbostic 3649118Sbostic /* 3749118Sbostic * Note that stdarg.h and the ANSI style va_start macro is used for both 3849118Sbostic * ANSI and traditional C compilers. 3949118Sbostic */ 4049118Sbostic #define KERNEL 4149118Sbostic #include <machine/stdarg.h> 4249118Sbostic #undef KERNEL 4348987Sbostic 4449118Sbostic static void kprintn __P((u_long, int)); 4549118Sbostic 4648987Sbostic void 4748987Sbostic #if __STDC__ 4848987Sbostic printf(const char *fmt, ...) 4948987Sbostic #else 5049118Sbostic printf(fmt /* , va_alist */) 5148987Sbostic char *fmt; 5248987Sbostic #endif 5348987Sbostic { 5448987Sbostic register char *p; 5548987Sbostic register int ch, n; 5648989Sbostic unsigned long ul; 5748987Sbostic int lflag, set; 5849118Sbostic va_list ap; 5948987Sbostic 6048987Sbostic va_start(ap, fmt); 6148987Sbostic for (;;) { 6248987Sbostic while ((ch = *fmt++) != '%') { 6348987Sbostic if (ch == '\0') 6448987Sbostic return; 6548987Sbostic putchar(ch); 6648987Sbostic } 6748987Sbostic lflag = 0; 6848987Sbostic reswitch: switch (ch = *fmt++) { 6948987Sbostic case 'l': 7048987Sbostic lflag = 1; 7148987Sbostic goto reswitch; 7248987Sbostic case 'b': 7348989Sbostic ul = va_arg(ap, int); 7448987Sbostic p = va_arg(ap, char *); 7549118Sbostic kprintn(ul, *p++); 7648987Sbostic 7748989Sbostic if (!ul) 7848987Sbostic break; 7948987Sbostic 8048987Sbostic for (set = 0; n = *p++;) { 8148989Sbostic if (ul & (1 << (n - 1))) { 8248987Sbostic putchar(set ? ',' : '<'); 8348987Sbostic for (; (n = *p) > ' '; ++p) 8448987Sbostic putchar(n); 8548987Sbostic set = 1; 8648987Sbostic } else 8748987Sbostic for (; *p > ' '; ++p); 8848987Sbostic } 8948987Sbostic if (set) 9048987Sbostic putchar('>'); 9148987Sbostic break; 9248987Sbostic case 'c': 9348987Sbostic ch = va_arg(ap, int); 9448987Sbostic putchar(ch & 0x7f); 9548987Sbostic break; 9648987Sbostic case 's': 9748987Sbostic p = va_arg(ap, char *); 9848987Sbostic while (ch = *p++) 9948987Sbostic putchar(ch); 10048987Sbostic break; 10149118Sbostic case 'D': 10249118Sbostic lflag = 1; 10349118Sbostic /* FALLTHROUGH */ 10448987Sbostic case 'd': 10548989Sbostic ul = lflag ? 10648987Sbostic va_arg(ap, long) : va_arg(ap, int); 10748989Sbostic if ((long)ul < 0) { 10848987Sbostic putchar('-'); 10948989Sbostic ul = -(long)ul; 11048987Sbostic } 11149118Sbostic kprintn(ul, 10); 11248987Sbostic break; 11349118Sbostic case 'O': 11449118Sbostic lflag = 1; 11549118Sbostic /* FALLTHROUGH */ 11648987Sbostic case 'o': 11748989Sbostic ul = lflag ? 11849118Sbostic va_arg(ap, u_long) : va_arg(ap, u_int); 11949118Sbostic kprintn(ul, 8); 12048987Sbostic break; 12149118Sbostic case 'U': 12249118Sbostic lflag = 1; 12349118Sbostic /* FALLTHROUGH */ 12448987Sbostic case 'u': 12548989Sbostic ul = lflag ? 12649118Sbostic va_arg(ap, u_long) : va_arg(ap, u_int); 12749118Sbostic kprintn(ul, 10); 12848987Sbostic break; 12949118Sbostic case 'X': 13049118Sbostic lflag = 1; 13149118Sbostic /* FALLTHROUGH */ 13248987Sbostic case 'x': 13348989Sbostic ul = lflag ? 13449118Sbostic va_arg(ap, u_long) : va_arg(ap, u_int); 13549118Sbostic kprintn(ul, 16); 13648987Sbostic break; 13748987Sbostic default: 13848987Sbostic putchar('%'); 13948987Sbostic if (lflag) 14048987Sbostic putchar('l'); 14148987Sbostic putchar(ch); 14248987Sbostic } 14348987Sbostic } 14448987Sbostic va_end(ap); 14548987Sbostic } 14648987Sbostic 14748987Sbostic static void 14849118Sbostic kprintn(ul, base) 14948989Sbostic unsigned long ul; 15048987Sbostic int base; 15148987Sbostic { 152*49168Swilliam /* hold a long in base 8 */ 153*49168Swilliam char *p, buf[(sizeof(long) * NBBY / 3) + 1]; 15448987Sbostic 15548987Sbostic p = buf; 15648987Sbostic do { 15748989Sbostic *p++ = "0123456789abcdef"[ul % base]; 15848989Sbostic } while (ul /= base); 15948987Sbostic do { 16048987Sbostic putchar(*--p); 16148987Sbostic } while (p > buf); 16248987Sbostic } 163