db_output.c revision 3140
1211201Stakawata/*
2211201Stakawata * Mach Operating System
3211201Stakawata * Copyright (c) 1991,1990 Carnegie Mellon University
4211201Stakawata * All Rights Reserved.
5211201Stakawata *
6211201Stakawata * Permission to use, copy, modify and distribute this software and its
7211201Stakawata * documentation is hereby granted, provided that both the copyright
8211201Stakawata * notice and this permission notice appear in all copies of the
9211201Stakawata * software, derivative works or modified versions, and any portions
10211201Stakawata * thereof, and that both notices appear in supporting documentation.
11211201Stakawata *
12211201Stakawata * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
13211201Stakawata * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14211201Stakawata * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15211201Stakawata *
16211201Stakawata * Carnegie Mellon requests users of this software to return to
17211201Stakawata *
18211201Stakawata *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
19211201Stakawata *  School of Computer Science
20211201Stakawata *  Carnegie Mellon University
21211201Stakawata *  Pittsburgh PA 15213-3890
22211201Stakawata *
23211201Stakawata * any improvements or extensions that they make and grant Carnegie the
24211201Stakawata * rights to redistribute these changes.
25211201Stakawata *
26211201Stakawata *	$Id: db_output.c,v 1.8 1994/08/27 16:14:09 davidg Exp $
27211201Stakawata */
28211201Stakawata
29211201Stakawata/*
30211201Stakawata * 	Author: David B. Golub, Carnegie Mellon University
31211201Stakawata *	Date:	7/90
32211201Stakawata */
33211201Stakawata
34211201Stakawata/*
35211201Stakawata * Printf and character output for debugger.
36211201Stakawata */
37211201Stakawata
38211201Stakawata#include <sys/param.h>
39211201Stakawata#include <sys/systm.h>
40211201Stakawata#include <machine/stdarg.h>
41211201Stakawata#include <ddb/ddb.h>
42211201Stakawata#include <machine/cons.h>
43211201Stakawata
44211201Stakawata/*
45211201Stakawata *	Character output - tracks position in line.
46211201Stakawata *	To do this correctly, we should know how wide
47211201Stakawata *	the output device is - then we could zero
48211201Stakawata *	the line position when the output device wraps
49211201Stakawata *	around to the start of the next line.
50211201Stakawata *
51211201Stakawata *	Instead, we count the number of spaces printed
52211201Stakawata *	since the last printing character so that we
53211201Stakawata *	don't print trailing spaces.  This avoids most
54211201Stakawata *	of the wraparounds.
55211201Stakawata */
56211201Stakawataint	db_output_position = 0;		/* output column */
57211201Stakawataint	db_last_non_space = 0;		/* last non-space character */
58211201Stakawataint	db_tab_stop_width = 8;		/* how wide are tab stops? */
59211201Stakawata#define	NEXT_TAB(i) \
60211201Stakawata	((((i) + db_tab_stop_width) / db_tab_stop_width) * db_tab_stop_width)
61211201Stakawataint	db_max_width = 80;		/* output line width */
62211201Stakawata
63211201Stakawata
64211201Stakawatastatic void db_printf_guts(const char *, va_list);
65211201Stakawata
66211201Stakawata/*
67211201Stakawata * Force pending whitespace.
68211201Stakawata */
69211201Stakawatavoid
70211201Stakawatadb_force_whitespace()
71211201Stakawata{
72211201Stakawata	register int last_print, next_tab;
73211201Stakawata
74211201Stakawata	last_print = db_last_non_space;
75211201Stakawata	while (last_print < db_output_position) {
76211201Stakawata	    next_tab = NEXT_TAB(last_print);
77211201Stakawata	    if (next_tab <= db_output_position) {
78211201Stakawata		while (last_print < next_tab) { /* DON'T send a tab!!! */
79211201Stakawata			cnputc(' ');
80211201Stakawata			last_print++;
81211201Stakawata		}
82211201Stakawata	    }
83211201Stakawata	    else {
84211201Stakawata		cnputc(' ');
85211201Stakawata		last_print++;
86211201Stakawata	    }
87211201Stakawata	}
88211201Stakawata	db_last_non_space = db_output_position;
89211201Stakawata}
90211201Stakawata
91211201Stakawata/*
92211201Stakawata * Output character.  Buffer whitespace.
93211201Stakawata */
94211201Stakawatavoid
95211201Stakawatadb_putchar(c)
96211201Stakawata	int	c;		/* character to output */
97211201Stakawata{
98211201Stakawata	if (c > ' ' && c <= '~') {
99211201Stakawata	    /*
100211201Stakawata	     * Printing character.
101211201Stakawata	     * If we have spaces to print, print them first.
102211201Stakawata	     * Use tabs if possible.
103211201Stakawata	     */
104211201Stakawata	    db_force_whitespace();
105211201Stakawata	    cnputc(c);
106211201Stakawata	    db_output_position++;
107211201Stakawata	    db_last_non_space = db_output_position;
108211201Stakawata	}
109211201Stakawata	else if (c == '\n') {
110211201Stakawata	    /* Newline */
111211201Stakawata	    cnputc(c);
112211201Stakawata	    db_output_position = 0;
113211201Stakawata	    db_last_non_space = 0;
114211201Stakawata	    db_check_interrupt();
115211201Stakawata	}
116211201Stakawata	else if (c == '\r') {
117211201Stakawata	    /* Return */
118211201Stakawata	    cnputc(c);
119211201Stakawata	    db_output_position = 0;
120211201Stakawata	    db_last_non_space = 0;
121211201Stakawata	    db_check_interrupt();
122211201Stakawata	}
123211201Stakawata	else if (c == '\t') {
124211201Stakawata	    /* assume tabs every 8 positions */
125211201Stakawata	    db_output_position = NEXT_TAB(db_output_position);
126211201Stakawata	}
127211201Stakawata	else if (c == ' ') {
128211201Stakawata	    /* space */
129211201Stakawata	    db_output_position++;
130211201Stakawata	}
131211201Stakawata	else if (c == '\007') {
132211201Stakawata	    /* bell */
133211201Stakawata	    cnputc(c);
134211201Stakawata	}
135211201Stakawata	/* other characters are assumed non-printing */
136211201Stakawata}
137211201Stakawata
138211201Stakawata/*
139211201Stakawata * Return output position
140211201Stakawata */
141211201Stakawataint
142211201Stakawatadb_print_position()
143211201Stakawata{
144211201Stakawata	return (db_output_position);
145211201Stakawata}
146211201Stakawata
147211201Stakawata/*
148211201Stakawata * Printing
149211201Stakawata */
150211201Stakawatavoid
151211201Stakawatadb_printf(const char *fmt, ...)
152211201Stakawata{
153211201Stakawata	va_list	listp;
154211201Stakawata	va_start(listp, fmt);
155211201Stakawata	db_printf_guts (fmt, listp);
156211201Stakawata	va_end(listp);
157211201Stakawata}
158211201Stakawata
159211201Stakawata/* alternate name */
160211201Stakawata
161211201Stakawata/*VARARGS1*/
162211201Stakawatavoid
163211201Stakawatakdbprintf(char *fmt, ...)
164211201Stakawata{
165211201Stakawata	va_list	listp;
166211201Stakawata	va_start(listp, fmt);
167211201Stakawata	db_printf_guts (fmt, listp);
168211201Stakawata	va_end(listp);
169211201Stakawata}
170211201Stakawata
171211201Stakawata/*
172211201Stakawata * End line if too long.
173211201Stakawata */
174211201Stakawatavoid
175211201Stakawatadb_end_line()
176211201Stakawata{
177211201Stakawata	if (db_output_position >= db_max_width)
178211201Stakawata	    db_printf("\n");
179211201Stakawata}
180211201Stakawata
181211201Stakawata/*
182211201Stakawata * Put a number (base <= 16) in a buffer in reverse order; return an
183211201Stakawata * optional length and a pointer to the NULL terminated (preceded?)
184211201Stakawata * buffer.
185211201Stakawata */
186211201Stakawatastatic char *
187211201Stakawatadb_ksprintn(ul, base, lenp)
188211201Stakawata	register u_long ul;
189211201Stakawata	register int base, *lenp;
190211201Stakawata{					/* A long in base 8, plus NULL. */
191211201Stakawata	static char buf[sizeof(long) * NBBY / 3 + 2];
192211201Stakawata	register char *p;
193211201Stakawata
194211201Stakawata	p = buf;
195211201Stakawata	do {
196211201Stakawata		*++p = "0123456789abcdef"[ul % base];
197211201Stakawata	} while (ul /= base);
198211201Stakawata	if (lenp)
199211201Stakawata		*lenp = p - buf;
200211201Stakawata	return (p);
201211201Stakawata}
202211201Stakawata
203211201Stakawatastatic void
204211201Stakawatadb_printf_guts(fmt, ap)
205211201Stakawata	register const char *fmt;
206211201Stakawata	va_list ap;
207211201Stakawata{
208211201Stakawata	register char *p;
209211201Stakawata	register int ch, n;
210211201Stakawata	u_long ul;
211211201Stakawata	int base, lflag, tmp, width;
212211201Stakawata	char padc;
213211201Stakawata	int ladjust;
214211201Stakawata	int sharpflag;
215211201Stakawata	int neg;
216211201Stakawata
217211201Stakawata	for (;;) {
218211201Stakawata		padc = ' ';
219211201Stakawata		width = 0;
220211201Stakawata		while ((ch = *(u_char *)fmt++) != '%') {
221211201Stakawata			if (ch == '\0')
222211201Stakawata				return;
223211201Stakawata			db_putchar(ch);
224211201Stakawata		}
225211201Stakawata		lflag = 0;
226211201Stakawata		ladjust = 0;
227211201Stakawata		sharpflag = 0;
228211201Stakawata		neg = 0;
229211201Stakawatareswitch:	switch (ch = *(u_char *)fmt++) {
230211201Stakawata		case '0':
231211201Stakawata			padc = '0';
232211201Stakawata			goto reswitch;
233211201Stakawata		case '1': case '2': case '3': case '4':
234211201Stakawata		case '5': case '6': case '7': case '8': case '9':
235211201Stakawata			for (width = 0;; ++fmt) {
236211201Stakawata				width = width * 10 + ch - '0';
237211201Stakawata				ch = *fmt;
238211201Stakawata				if (ch < '0' || ch > '9')
239211201Stakawata					break;
240211201Stakawata			}
241211201Stakawata			goto reswitch;
242211201Stakawata		case 'l':
243211201Stakawata			lflag = 1;
244211201Stakawata			goto reswitch;
245211201Stakawata		case '-':
246211201Stakawata			ladjust = 1;
247211201Stakawata			goto reswitch;
248211201Stakawata		case '#':
249211201Stakawata			sharpflag = 1;
250211201Stakawata			goto reswitch;
251211201Stakawata		case 'b':
252211201Stakawata			ul = va_arg(ap, int);
253211201Stakawata			p = va_arg(ap, char *);
254211201Stakawata			for (p = db_ksprintn(ul, *p++, NULL); *p;p--)
255211201Stakawata				db_putchar(*p);
256211201Stakawata
257211201Stakawata			if (!ul)
258211201Stakawata				break;
259211201Stakawata
260211201Stakawata			for (tmp = 0; *p;) {
261211201Stakawata				n = *p++;
262211201Stakawata				if (ul & (1 << (n - 1))) {
263211201Stakawata					db_putchar(tmp ? ',' : '<');
264211201Stakawata					for (; (n = *p) > ' '; ++p)
265211201Stakawata						db_putchar(n);
266211201Stakawata					tmp = 1;
267211201Stakawata				} else
268211201Stakawata					for (; *p > ' '; ++p);
269211201Stakawata			}
270211201Stakawata			if (tmp)
271211201Stakawata				db_putchar('>');
272211201Stakawata			break;
273211201Stakawata		case '*':
274211201Stakawata			width = va_arg (ap, int);
275211201Stakawata			if (width < 0) {
276211201Stakawata				ladjust = !ladjust;
277211201Stakawata				width = -width;
278211201Stakawata			}
279211201Stakawata			goto reswitch;
280211201Stakawata		case 'c':
281211201Stakawata			db_putchar(va_arg(ap, int));
282211201Stakawata			break;
283211201Stakawata		case 's':
284211201Stakawata			p = va_arg(ap, char *);
285211201Stakawata			width -= strlen (p);
286211201Stakawata			if (!ladjust && width > 0)
287211201Stakawata				while (width--)
288211201Stakawata					db_putchar (padc);
289211201Stakawata			for (;*p;p++)
290211201Stakawata				db_putchar(*p);
291211201Stakawata			if (ladjust && width > 0)
292211201Stakawata				while (width--)
293211201Stakawata					db_putchar (padc);
294211201Stakawata			break;
295211201Stakawata		case 'r':
296211201Stakawata			ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
297211201Stakawata			if ((long)ul < 0) {
298211201Stakawata				neg = 1;
299211201Stakawata				ul = -(long)ul;
300211201Stakawata			}
301211201Stakawata			base = db_radix;
302211201Stakawata			if (base < 8 || base > 16)
303211201Stakawata				base = 10;
304211201Stakawata			goto number;
305211201Stakawata		case 'n':
306211201Stakawata			ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
307211201Stakawata			base = db_radix;
308211201Stakawata			if (base < 8 || base > 16)
309211201Stakawata				base = 10;
310211201Stakawata			goto number;
311211201Stakawata		case 'd':
312211201Stakawata			ul = lflag ? va_arg(ap, long) : va_arg(ap, int);
313211201Stakawata			if ((long)ul < 0) {
314211201Stakawata				neg = 1;
315211201Stakawata				ul = -(long)ul;
316211201Stakawata			}
317211201Stakawata			base = 10;
318211201Stakawata			goto number;
319211201Stakawata		case 'o':
320211201Stakawata			ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
321211201Stakawata			base = 8;
322211201Stakawata			goto number;
323211201Stakawata		case 'u':
324211201Stakawata			ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
325211201Stakawata			base = 10;
326211201Stakawata			goto number;
327211201Stakawata		case 'z':
328211201Stakawata			ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
329211201Stakawata			if ((long)ul < 0) {
330211201Stakawata				neg = 1;
331211201Stakawata				ul = -(long)ul;
332211201Stakawata			}
333211201Stakawata			base = 16;
334211201Stakawata			goto number;
335211201Stakawata		case 'x':
336211201Stakawata			ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
337211201Stakawata			base = 16;
338211201Stakawatanumber:			p = (char *)db_ksprintn(ul, base, &tmp);
339211201Stakawata			if (sharpflag && ul != 0) {
340211201Stakawata				if (base == 8)
341211201Stakawata					tmp++;
342211201Stakawata				else if (base == 16)
343211201Stakawata					tmp += 2;
344211201Stakawata			}
345211201Stakawata			if (neg)
346211201Stakawata				tmp++;
347211201Stakawata
348211201Stakawata			if (!ladjust && width && (width -= tmp) > 0)
349211201Stakawata				while (width--)
350211201Stakawata					db_putchar(padc);
351211201Stakawata			if (neg)
352211201Stakawata				db_putchar ('-');
353211201Stakawata			if (sharpflag && ul != 0) {
354211201Stakawata				if (base == 8) {
355211201Stakawata					db_putchar ('0');
356211201Stakawata				} else if (base == 16) {
357211201Stakawata					db_putchar ('0');
358211201Stakawata					db_putchar ('x');
359211201Stakawata				}
360211201Stakawata			}
361211201Stakawata			if (ladjust && width && (width -= tmp) > 0)
362211201Stakawata				while (width--)
363211201Stakawata					db_putchar(padc);
364211201Stakawata
365211201Stakawata			for (;*p;p--)
366211201Stakawata				db_putchar(*p);
367211201Stakawata			break;
368211201Stakawata		default:
369211201Stakawata			db_putchar('%');
370211201Stakawata			if (lflag)
371211201Stakawata				db_putchar('l');
372211201Stakawata			/* FALLTHROUGH */
373211201Stakawata		case '%':
374211201Stakawata			db_putchar(ch);
375211201Stakawata		}
376211201Stakawata	}
377211201Stakawata}
378211201Stakawata
379211201Stakawata