xref: /netbsd-src/sys/ddb/db_output.c (revision ce63d6c20fc4ec8ddc95c84bb229e3c4ecf82b69)
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  * $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