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