xref: /386bsd/usr/src/kernel/ddb/db_output.c (revision a2142627)
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 /*
27  * HISTORY
28  * $Log: db_output.c,v $
29  * Revision 1.1  1992/03/25  21:45:18  pace
30  * Initial revision
31  *
32  * Revision 2.3  91/02/05  17:06:45  mrt
33  * 	Changed to new Mach copyright
34  * 	[91/01/31  16:18:41  mrt]
35  *
36  * Revision 2.2  90/08/27  21:51:25  dbg
37  * 	Put extra features of db_doprnt in _doprnt.
38  * 	[90/08/20            dbg]
39  * 	Reduce lint.
40  * 	[90/08/07            dbg]
41  * 	Created.
42  * 	[90/07/25            dbg]
43  *
44  */
45 /*
46  * 	Author: David B. Golub, Carnegie Mellon University
47  *	Date:	7/90
48  */
49 
50 /*
51  * Printf and character output for debugger.
52  */
53 
54 #include "sys/param.h"
55 #include "machine/stdarg.h"
56 
57 /*
58  *	Character output - tracks position in line.
59  *	To do this correctly, we should know how wide
60  *	the output device is - then we could zero
61  *	the line position when the output device wraps
62  *	around to the start of the next line.
63  *
64  *	Instead, we count the number of spaces printed
65  *	since the last printing character so that we
66  *	don't print trailing spaces.  This avoids most
67  *	of the wraparounds.
68  */
69 int	db_output_position = 0;		/* output column */
70 int	db_last_non_space = 0;		/* last non-space character */
71 int	db_tab_stop_width = 8;		/* how wide are tab stops? */
72 #define	NEXT_TAB(i) \
73 	((((i) + db_tab_stop_width) / db_tab_stop_width) * db_tab_stop_width)
74 int	db_max_width = 79;		/* output line width */
75 
76 extern void	db_check_interrupt();
77 
78 /*
79  * Force pending whitespace.
80  */
81 void
db_force_whitespace()82 db_force_whitespace()
83 {
84 	register int last_print, next_tab;
85 
86 	last_print = db_last_non_space;
87 	while (last_print < db_output_position) {
88 	    next_tab = NEXT_TAB(last_print);
89 	    /*if (next_tab <= db_output_position) {
90 		console_putchar('\t');
91 		last_print = next_tab;
92 	    }
93 	    else { */
94 		console_putchar(' ');
95 		last_print++;
96 	    /* }*/
97 	}
98 	db_last_non_space = db_output_position;
99 }
100 
101 /*
102  * Output character.  Buffer whitespace.
103  */
db_putchar(c)104 db_putchar(c)
105 	int	c;		/* character to output */
106 {
107 	if (c > ' ' && c <= '~') {
108 	    /*
109 	     * Printing character.
110 	     * If we have spaces to print, print them first.
111 	     * Use tabs if possible.
112 	     */
113 	    db_force_whitespace();
114 	    console_putchar(c);
115 	    /*cnputc(c);*/
116 	    db_output_position++;
117 	    db_last_non_space = db_output_position;
118 	}
119 	else if (c == '\n' || c == '\r') {
120 	    /* Return */
121 	    console_putchar(c);
122 	    db_output_position = 0;
123 	    db_last_non_space = 0;
124 	    db_check_interrupt();
125 	}
126 	else if (c == '\t') {
127 	    /* assume tabs every 8 positions */
128 	    db_output_position = NEXT_TAB(db_output_position);
129 	}
130 	else if (c == ' ') {
131 	    /* space */
132 	    db_output_position++;
133 	}
134 	else if (c == '\007') {
135 	    /* bell */
136 	    console_putchar(c);
137 	    /*cnputc(c);*/
138 	}
139 	/* other characters are assumed non-printing */
140 }
141 
142 /*
143  * Return output position
144  */
145 int
db_print_position()146 db_print_position()
147 {
148 	return (db_output_position);
149 }
150 
151 /*
152  * End line if too long.
153  */
154 void
db_end_line(int n)155 db_end_line(int n)
156 {
157 	if (db_output_position + n >= db_max_width)
158 	    db_putchar('\n');
159 	    /*db_printf("\n");*/
160 }
161 
162 /*
163  * Printing
164  */
165 extern int	db_radix;
166 
167 /*VARARGS1*/
db_printf(char * fmt,...)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*/
kdbprintf(char * fmt,...)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 *
db_ksprintn(ul,base,lenp)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 
db_printf_guts(fmt,ap)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