xref: /netbsd/sys/ddb/db_output.c (revision bf9ec67e)
1 /*	$NetBSD: db_output.c,v 1.27 2002/02/15 07:33:51 simonb 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.27 2002/02/15 07:33:51 simonb 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_line = 0;			/* output line number */
76 int	db_tab_stop_width = 8;			/* how wide are tab stops? */
77 int	db_max_line = DB_MAX_LINE;		/* output max lines */
78 int	db_max_width = DB_MAX_WIDTH;		/* output line width */
79 
80 static int	db_output_position = 0;		/* output column */
81 static int	db_last_non_space = 0;		/* last non-space character */
82 
83 static void db_more(void);
84 
85 /*
86  * Force pending whitespace.
87  */
88 void
89 db_force_whitespace(void)
90 {
91 	int last_print, next_tab;
92 
93 	last_print = db_last_non_space;
94 	while (last_print < db_output_position) {
95 		next_tab = DB_NEXT_TAB(last_print);
96 		if (next_tab <= db_output_position) {
97 			while (last_print < next_tab) { /* DON'T send a tab!! */
98 				cnputc(' ');
99 				last_print++;
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(void)
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(int c)
144 {
145 	if (db_max_line >= DB_MIN_MAX_LINE && db_output_line >= db_max_line-1)
146 		db_more();
147 	if (c > ' ' && c <= '~') {
148 		/*
149 		 * Printing character.
150 		 * If we have spaces to print, print them first.
151 		 * Use tabs if possible.
152 		 */
153 		db_force_whitespace();
154 		cnputc(c);
155 		db_output_position++;
156 		if (db_max_width >= DB_MIN_MAX_WIDTH
157 		    && db_output_position >= db_max_width) {
158 			/* auto new line */
159 			cnputc('\n');
160 			db_output_position = 0;
161 			db_last_non_space = 0;
162 			db_output_line++;
163 		}
164 		db_last_non_space = db_output_position;
165 	} else if (c == '\n') {
166 		/* Return */
167 		cnputc(c);
168 		db_output_position = 0;
169 		db_last_non_space = 0;
170 		db_output_line++;
171 		db_check_interrupt();
172 	} else if (c == '\t') {
173 		/* assume tabs every 8 positions */
174 		db_output_position = DB_NEXT_TAB(db_output_position);
175 	} else if (c == ' ') {
176 		/* space */
177 		db_output_position++;
178 	} else if (c == '\007') {
179 		/* bell */
180 		cnputc(c);
181 	}
182 	/* other characters are assumed non-printing */
183 }
184 
185 /*
186  * Return output position
187  */
188 int
189 db_print_position(void)
190 {
191 
192 	return (db_output_position);
193 }
194 
195 /*
196  * End line if too long.
197  */
198 void
199 db_end_line(void)
200 {
201 
202 	if (db_output_position >= db_max_width)
203 		db_printf("\n");
204 }
205 
206 /*
207  * Replacement for old '%r' kprintf format.
208  */
209 void
210 db_format_radix(char *buf, size_t bufsiz, quad_t val, int altflag)
211 {
212 	const char *fmt;
213 
214 	if (db_radix == 16) {
215 		db_format_hex(buf, bufsiz, val, altflag);
216 		return;
217 	}
218 
219 	if (db_radix == 8)
220 		fmt = altflag ? "-%#qo" : "-%qo";
221 	else
222 		fmt = altflag ? "-%#qu" : "-%qu";
223 
224 	if (val < 0)
225 		val = -val;
226 	else
227 		++fmt;
228 
229 	snprintf(buf, bufsiz, fmt, val);
230 }
231 
232 /*
233  * Replacement for old '%z' kprintf format.
234  */
235 void
236 db_format_hex(char *buf, size_t bufsiz, quad_t val, int altflag)
237 {
238 	/* Only use alternate form if val is nonzero. */
239 	const char *fmt = (altflag && val) ? "-%#qx" : "-%qx";
240 
241 	if (val < 0)
242 		val = -val;
243 	else
244 		++fmt;
245 
246 	snprintf(buf, bufsiz, fmt, val);
247 }
248