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