xref: /netbsd-src/sys/ddb/db_output.c (revision 1ca5c1b28139779176bd5c13ad7c5f25c0bcd5f8)
1 /*	$NetBSD: db_output.c,v 1.26 2001/11/12 22:54:05 lukem Exp $	*/
2 
3 /*
4  * Mach Operating System
5  * Copyright (c) 1991,1990 Carnegie Mellon University
6  * All Rights Reserved.
7  *
8  * Permission to use, copy, modify and distribute this software and its
9  * documentation is hereby granted, provided that both the copyright
10  * notice and this permission notice appear in all copies of the
11  * software, derivative works or modified versions, and any portions
12  * thereof, and that both notices appear in supporting documentation.
13  *
14  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
15  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
16  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
17  *
18  * Carnegie Mellon requests users of this software to return to
19  *
20  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
21  *  School of Computer Science
22  *  Carnegie Mellon University
23  *  Pittsburgh PA 15213-3890
24  *
25  * any improvements or extensions that they make and grant Carnegie the
26  * rights to redistribute these changes.
27  */
28 
29 /*
30  * Printf and character output for debugger.
31  */
32 
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: db_output.c,v 1.26 2001/11/12 22:54:05 lukem Exp $");
35 
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 
39 #include <machine/stdarg.h>
40 
41 #include <dev/cons.h>
42 
43 #include <machine/db_machdep.h>
44 
45 #include <ddb/db_command.h>
46 #include <ddb/db_output.h>
47 #include <ddb/db_interface.h>
48 #include <ddb/db_sym.h>
49 #include <ddb/db_extern.h>
50 
51 /*
52  *	Character output - tracks position in line.
53  *	To do this correctly, we should know how wide
54  *	the output device is - then we could zero
55  *	the line position when the output device wraps
56  *	around to the start of the next line.
57  *
58  *	Instead, we count the number of spaces printed
59  *	since the last printing character so that we
60  *	don't print trailing spaces.  This avoids most
61  *	of the wraparounds.
62  */
63 
64 #ifndef	DB_MAX_LINE
65 #define	DB_MAX_LINE		24	/* maximum line */
66 #endif	/* DB_MAX_LINE */
67 #ifndef	DB_MAX_WIDTH
68 #define DB_MAX_WIDTH		80	/* maximum width */
69 #endif	/* DB_MAX_WIDTH */
70 
71 #define DB_MIN_MAX_WIDTH	20	/* minimum max width */
72 #define DB_MIN_MAX_LINE		3	/* minimum max line */
73 #define CTRL(c)			((c) & 0xff)
74 
75 int	db_output_position = 0;		/* output column */
76 int	db_output_line = 0;		/* output line number */
77 int	db_last_non_space = 0;		/* last non-space character */
78 int	db_tab_stop_width = 8;		/* how wide are tab stops? */
79 int	db_max_line = DB_MAX_LINE;	/* output max lines */
80 int	db_max_width = DB_MAX_WIDTH;	/* output line width */
81 
82 static void db_more __P((void));
83 
84 /*
85  * Force pending whitespace.
86  */
87 void
88 db_force_whitespace()
89 {
90 	int last_print, next_tab;
91 
92 	last_print = db_last_non_space;
93 	while (last_print < db_output_position) {
94 	    next_tab = DB_NEXT_TAB(last_print);
95 	    if (next_tab <= db_output_position) {
96 		while (last_print < next_tab) { /* DON'T send a tab!!! */
97 			cnputc(' ');
98 			last_print++;
99 		}
100 	    }
101 	    else {
102 		cnputc(' ');
103 		last_print++;
104 	    }
105 	}
106 	db_last_non_space = db_output_position;
107 }
108 
109 static void
110 db_more()
111 {
112 	char *p;
113 	int quit_output = 0;
114 
115 	for (p = "--db_more--"; *p; p++)
116 	    cnputc(*p);
117 	switch(cngetc()) {
118 	case ' ':
119 	    db_output_line = 0;
120 	    break;
121 	case 'q':
122 	case CTRL('c'):
123 	    db_output_line = 0;
124 	    quit_output = 1;
125 	    break;
126 	default:
127 	    db_output_line--;
128 	    break;
129 	}
130 	p = "\b\b\b\b\b\b\b\b\b\b\b           \b\b\b\b\b\b\b\b\b\b\b";
131 	while (*p)
132 	    cnputc(*p++);
133 	if (quit_output) {
134 	    db_error(0);
135 	    /* NOTREACHED */
136 	}
137 }
138 
139 /*
140  * Output character.  Buffer whitespace.
141  */
142 void
143 db_putchar(c)
144 	int	c;		/* character to output */
145 {
146 	if (db_max_line >= DB_MIN_MAX_LINE && db_output_line >= db_max_line-1)
147 	    db_more();
148 	if (c > ' ' && c <= '~') {
149 	    /*
150 	     * Printing character.
151 	     * If we have spaces to print, print them first.
152 	     * Use tabs if possible.
153 	     */
154 	    db_force_whitespace();
155 	    cnputc(c);
156 	    db_output_position++;
157 	    if (db_max_width >= DB_MIN_MAX_WIDTH
158 		&& db_output_position >= db_max_width) {
159 		/* auto new line */
160 		cnputc('\n');
161 		db_output_position = 0;
162 		db_last_non_space = 0;
163 		db_output_line++;
164 	    }
165 	    db_last_non_space = db_output_position;
166 	}
167 	else if (c == '\n') {
168 	    /* Return */
169 	    cnputc(c);
170 	    db_output_position = 0;
171 	    db_last_non_space = 0;
172 	    db_output_line++;
173 	    db_check_interrupt();
174 	}
175 	else if (c == '\t') {
176 	    /* assume tabs every 8 positions */
177 	    db_output_position = DB_NEXT_TAB(db_output_position);
178 	}
179 	else if (c == ' ') {
180 	    /* space */
181 	    db_output_position++;
182 	}
183 	else if (c == '\007') {
184 	    /* bell */
185 	    cnputc(c);
186 	}
187 	/* other characters are assumed non-printing */
188 }
189 
190 /*
191  * Return output position
192  */
193 int
194 db_print_position()
195 {
196 	return (db_output_position);
197 }
198 
199 /*
200  * End line if too long.
201  */
202 void
203 db_end_line()
204 {
205 	if (db_output_position >= db_max_width)
206 	    db_printf("\n");
207 }
208 
209 /*
210  * Replacement for old '%r' kprintf format.
211  */
212 void
213 db_format_radix(buf, bufsiz, val, altflag)
214 	char *buf;
215 	size_t bufsiz;
216 	quad_t val;
217 	int altflag;
218 {
219 	const char *fmt;
220 
221 	if (db_radix == 16) {
222 		db_format_hex(buf, bufsiz, val, altflag);
223 		return;
224 	}
225 
226 	if (db_radix == 8)
227 		fmt = altflag ? "-%#qo" : "-%qo";
228 	else
229 		fmt = altflag ? "-%#qu" : "-%qu";
230 
231 	if (val < 0)
232 		val = -val;
233 	else
234 		++fmt;
235 
236 	snprintf(buf, bufsiz, fmt, val);
237 }
238 
239 /*
240  * Replacement for old '%z' kprintf format.
241  */
242 void
243 db_format_hex(buf, bufsiz, val, altflag)
244 	char *buf;
245 	size_t bufsiz;
246 	quad_t val;
247 	int altflag;
248 {
249 	/* Only use alternate form if val is nonzero. */
250 	const char *fmt = (altflag && val) ? "-%#qx" : "-%qx";
251 
252 	if (val < 0)
253 		val = -val;
254 	else
255 		++fmt;
256 
257 	snprintf(buf, bufsiz, fmt, val);
258 }
259