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