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
dbgprintall()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__
dbgprintf(const char * cfmt,...)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 *
sprintn(ul,base,lenp)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