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