db_output.c revision 1.1.1.1 1 /*
2 * Mach Operating System
3 * Copyright (c) 1991,1990 Carnegie Mellon University
4 * All Rights Reserved.
5 *
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
11 *
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15 *
16 * Carnegie Mellon requests users of this software to return to
17 *
18 * Software Distribution Coordinator or Software.Distribution (at) CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
22 *
23 * any improvements or extensions that they make and grant Carnegie the
24 * rights to redistribute these changes.
25 */
26 /*
27 * HISTORY
28 * $Log: db_output.c,v $
29 * Revision 1.1.1.1 1993/03/21 09:45:37 cgd
30 * initial import of 386bsd-0.1 sources
31 *
32 * Revision 1.1 1992/03/25 21:45:18 pace
33 * Initial revision
34 *
35 * Revision 2.3 91/02/05 17:06:45 mrt
36 * Changed to new Mach copyright
37 * [91/01/31 16:18:41 mrt]
38 *
39 * Revision 2.2 90/08/27 21:51:25 dbg
40 * Put extra features of db_doprnt in _doprnt.
41 * [90/08/20 dbg]
42 * Reduce lint.
43 * [90/08/07 dbg]
44 * Created.
45 * [90/07/25 dbg]
46 *
47 */
48 /*
49 * Author: David B. Golub, Carnegie Mellon University
50 * Date: 7/90
51 */
52
53 /*
54 * Printf and character output for debugger.
55 */
56
57 #include "param.h"
58 #include <machine/stdarg.h>
59
60 /*
61 * Character output - tracks position in line.
62 * To do this correctly, we should know how wide
63 * the output device is - then we could zero
64 * the line position when the output device wraps
65 * around to the start of the next line.
66 *
67 * Instead, we count the number of spaces printed
68 * since the last printing character so that we
69 * don't print trailing spaces. This avoids most
70 * of the wraparounds.
71 */
72 int db_output_position = 0; /* output column */
73 int db_last_non_space = 0; /* last non-space character */
74 int db_tab_stop_width = 8; /* how wide are tab stops? */
75 #define NEXT_TAB(i) \
76 ((((i) + db_tab_stop_width) / db_tab_stop_width) * db_tab_stop_width)
77 int db_max_width = 80; /* output line width */
78
79 extern void db_check_interrupt();
80
81 /*
82 * Force pending whitespace.
83 */
84 void
85 db_force_whitespace()
86 {
87 register int last_print, next_tab;
88
89 last_print = db_last_non_space;
90 while (last_print < db_output_position) {
91 next_tab = NEXT_TAB(last_print);
92 if (next_tab <= db_output_position) {
93 cnputc('\t');
94 last_print = next_tab;
95 }
96 else {
97 cnputc(' ');
98 last_print++;
99 }
100 }
101 db_last_non_space = db_output_position;
102 }
103
104 /*
105 * Output character. Buffer whitespace.
106 */
107 db_putchar(c)
108 int c; /* character to output */
109 {
110 if (c > ' ' && c <= '~') {
111 /*
112 * Printing character.
113 * If we have spaces to print, print them first.
114 * Use tabs if possible.
115 */
116 db_force_whitespace();
117 cnputc(c);
118 db_output_position++;
119 db_last_non_space = db_output_position;
120 }
121 else if (c == '\n') {
122 /* Return */
123 cnputc(c);
124 db_output_position = 0;
125 db_last_non_space = 0;
126 db_check_interrupt();
127 }
128 else if (c == '\t') {
129 /* assume tabs every 8 positions */
130 db_output_position = NEXT_TAB(db_output_position);
131 }
132 else if (c == ' ') {
133 /* space */
134 db_output_position++;
135 }
136 else if (c == '\007') {
137 /* bell */
138 cnputc(c);
139 }
140 /* other characters are assumed non-printing */
141 }
142
143 /*
144 * Return output position
145 */
146 int
147 db_print_position()
148 {
149 return (db_output_position);
150 }
151
152 /*
153 * End line if too long.
154 */
155 void
156 db_end_line()
157 {
158 if (db_output_position >= db_max_width)
159 db_printf("\n");
160 }
161
162 /*
163 * Printing
164 */
165 extern int db_radix;
166
167 /*VARARGS1*/
168 db_printf(char *fmt, ...)
169 {
170 va_list listp;
171 va_start(listp, fmt);
172 db_printf_guts (fmt, listp);
173 va_end(listp);
174 }
175
176 /* alternate name */
177
178 /*VARARGS1*/
179 kdbprintf(char *fmt, ...)
180 {
181 va_list listp;
182 va_start(listp, fmt);
183 db_printf_guts (fmt, listp);
184 va_end(listp);
185 }
186
187 /*
188 * Put a number (base <= 16) in a buffer in reverse order; return an
189 * optional length and a pointer to the NULL terminated (preceded?)
190 * buffer.
191 */
192 static char *
193 db_ksprintn(ul, base, lenp)
194 register u_long ul;
195 register int base, *lenp;
196 { /* A long in base 8, plus NULL. */
197 static char buf[sizeof(long) * NBBY / 3 + 2];
198 register char *p;
199
200 p = buf;
201 do {
202 *++p = "0123456789abcdef"[ul % base];
203 } while (ul /= base);
204 if (lenp)
205 *lenp = p - buf;
206 return (p);
207 }
208
209 db_printf_guts(fmt, ap)
210 register const char *fmt;
211 va_list ap;
212 {
213 register char *p;
214 register int ch, n;
215 u_long ul;
216 int base, lflag, tmp, width;
217 char padc;
218 int ladjust;
219 int sharpflag;
220 int neg;
221
222 for (;;) {
223 padc = ' ';
224 width = 0;
225 while ((ch = *(u_char *)fmt++) != '%') {
226 if (ch == '\0')
227 return;
228 db_putchar(ch);
229 }
230 lflag = 0;
231 ladjust = 0;
232 sharpflag = 0;
233 neg = 0;
234 reswitch: switch (ch = *(u_char *)fmt++) {
235 case '0':
236 padc = '0';
237 goto reswitch;
238 case '1': case '2': case '3': case '4':
239 case '5': case '6': case '7': case '8': case '9':
240 for (width = 0;; ++fmt) {
241 width = width * 10 + ch - '0';
242 ch = *fmt;
243 if (ch < '0' || ch > '9')
244 break;
245 }
246 goto reswitch;
247 case 'l':
248 lflag = 1;
249 goto reswitch;
250 case '-':
251 ladjust = 1;
252 goto reswitch;
253 case '#':
254 sharpflag = 1;
255 goto reswitch;
256 case 'b':
257 ul = va_arg(ap, int);
258 p = va_arg(ap, char *);
259 for (p = db_ksprintn(ul, *p++, NULL); ch = *p--;)
260 db_putchar(ch);
261
262 if (!ul)
263 break;
264
265 for (tmp = 0; n = *p++;) {
266 if (ul & (1 << (n - 1))) {
267 db_putchar(tmp ? ',' : '<');
268 for (; (n = *p) > ' '; ++p)
269 db_putchar(n);
270 tmp = 1;
271 } else
272 for (; *p > ' '; ++p);
273 }
274 if (tmp)
275 db_putchar('>');
276 break;
277 case '*':
278 width = va_arg (ap, int);
279 if (width < 0) {
280 ladjust = !ladjust;
281 width = -width;
282 }
283 goto reswitch;
284 case 'c':
285 db_putchar(va_arg(ap, int));
286 break;
287 case 's':
288 p = va_arg(ap, char *);
289 width -= strlen (p);
290 if (!ladjust && width > 0)
291 while (width--)
292 db_putchar (padc);
293 while (ch = *p++)
294 db_putchar(ch);
295 if (ladjust && width > 0)
296 while (width--)
297 db_putchar (padc);
298 break;
299 case 'r':
300 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
301 if ((long)ul < 0) {
302 neg = 1;
303 ul = -(long)ul;
304 }
305 base = db_radix;
306 if (base < 8 || base > 16)
307 base = 10;
308 goto number;
309 case 'n':
310 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
311 base = db_radix;
312 if (base < 8 || base > 16)
313 base = 10;
314 goto number;
315 case 'd':
316 ul = lflag ? va_arg(ap, long) : va_arg(ap, int);
317 if ((long)ul < 0) {
318 neg = 1;
319 ul = -(long)ul;
320 }
321 base = 10;
322 goto number;
323 case 'o':
324 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
325 base = 8;
326 goto number;
327 case 'u':
328 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
329 base = 10;
330 goto number;
331 case 'z':
332 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
333 if ((long)ul < 0) {
334 neg = 1;
335 ul = -(long)ul;
336 }
337 base = 16;
338 goto number;
339 case 'x':
340 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
341 base = 16;
342 number: p = (char *)db_ksprintn(ul, base, &tmp);
343 if (sharpflag && ul != 0) {
344 if (base == 8)
345 tmp++;
346 else if (base == 16)
347 tmp += 2;
348 }
349 if (neg)
350 tmp++;
351
352 if (!ladjust && width && (width -= tmp) > 0)
353 while (width--)
354 db_putchar(padc);
355 if (neg)
356 db_putchar ('-');
357 if (sharpflag && ul != 0) {
358 if (base == 8) {
359 db_putchar ('0');
360 } else if (base == 16) {
361 db_putchar ('0');
362 db_putchar ('x');
363 }
364 }
365 if (ladjust && width && (width -= tmp) > 0)
366 while (width--)
367 db_putchar(padc);
368
369 while (ch = *p--)
370 db_putchar(ch);
371 break;
372 default:
373 db_putchar('%');
374 if (lflag)
375 db_putchar('l');
376 /* FALLTHROUGH */
377 case '%':
378 db_putchar(ch);
379 }
380 }
381 }
382
383