1 /* 2 * Copyright (c) 1992 OMRON Corporation. 3 * Copyright (c) 1992, 1993 4 * The Regents of the University of California. All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * OMRON Corporation. 8 * 9 * %sccs.include.redist.c% 10 * 11 * @(#)dbgprf.c 8.1 (Berkeley) 06/10/93 12 */ 13 14 /* 15 * dbgprf.c -- batched printf for device driver debugging 16 * by A.Fujita, May-3-1992 17 */ 18 19 #ifdef DEBUGPRINT 20 21 #include <sys/param.h> 22 #include <sys/systm.h> 23 24 #include <machine/stdarg.h> 25 26 static char *sprintn __P((u_long num, int base, int *len)); 27 28 #define DBG_LINES 80 29 #define DBG_BUFS 300 30 31 struct dbgprf { 32 struct dbgprf *dbg_forw; 33 struct dbgprf *dbg_back; 34 char dbg_buf[DBG_LINES]; 35 }; 36 37 struct dbgprf dbgprf[DBG_BUFS]; 38 39 struct dbgprf dbgroot = { 40 &dbgroot, 41 &dbgroot, 42 }; 43 44 int dbg_used = 0; 45 46 void 47 dbgprintall() 48 { 49 register struct dbgprf *dbgp; 50 51 for (dbgp = dbgroot.dbg_forw; dbgp != &dbgroot; dbgp = dbgp->dbg_forw) { 52 printf("%s", dbgp->dbg_buf); 53 } 54 } 55 56 void 57 #ifdef __STDC__ 58 dbgprintf(const char *cfmt, ...) 59 #else 60 dbgprintf(cfmt /*, va_alist */) 61 char *cfmt; 62 #endif 63 { 64 register struct dbgprf *dbgp; 65 register const char *fmt = cfmt; 66 register char *p, *bp; 67 register int ch, base; 68 u_long ul; 69 int lflag; 70 va_list ap; 71 72 if (dbg_used < DBG_BUFS) { 73 dbgp = &dbgprf[dbg_used++]; 74 } else { 75 dbgp = dbgroot.dbg_forw; 76 remque(dbgp); 77 } 78 79 va_start(ap, cfmt); 80 for (bp = dbgp->dbg_buf; ; ) { 81 while ((ch = *(u_char *)fmt++) != '%') 82 if ((*bp++ = ch) == '\0') 83 goto done; 84 85 lflag = 0; 86 reswitch: switch (ch = *(u_char *)fmt++) { 87 case 'l': 88 lflag = 1; 89 goto reswitch; 90 case 'c': 91 *bp++ = va_arg(ap, int); 92 break; 93 case 's': 94 p = va_arg(ap, char *); 95 while (*bp++ = *p++) 96 ; 97 --bp; 98 break; 99 case 'd': 100 ul = lflag ? va_arg(ap, long) : va_arg(ap, int); 101 if ((long)ul < 0) { 102 *bp++ = '-'; 103 ul = -(long)ul; 104 } 105 base = 10; 106 goto number; 107 break; 108 case 'o': 109 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 110 base = 8; 111 goto number; 112 break; 113 case 'u': 114 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 115 base = 10; 116 goto number; 117 break; 118 case 'x': 119 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 120 base = 16; 121 number: for (p = sprintn(ul, base, NULL); ch = *p--;) 122 *bp++ = ch; 123 break; 124 default: 125 *bp++ = '%'; 126 if (lflag) 127 *bp++ = 'l'; 128 /* FALLTHROUGH */ 129 case '%': 130 *bp++ = ch; 131 } 132 } 133 va_end(ap); 134 135 done: 136 insque(dbgp, dbgroot.dbg_back); 137 138 /* printf("%s", dbgp->dbg_buf); */ 139 } 140 141 /* 142 * Put a number (base <= 16) in a buffer in reverse order; return an 143 * optional length and a pointer to the NULL terminated (preceded?) 144 * buffer. 145 */ 146 static char * 147 sprintn(ul, base, lenp) 148 register u_long ul; 149 register int base, *lenp; 150 { /* A long in base 8, plus NULL. */ 151 static char buf[sizeof(long) * NBBY / 3 + 2]; 152 register char *p; 153 154 p = buf; 155 do { 156 *++p = "0123456789abcdef"[ul % base]; 157 } while (ul /= base); 158 if (lenp) 159 *lenp = p - buf; 160 return (p); 161 } 162 #endif 163