db_output.c revision 1.25 1 /* $NetBSD: db_output.c,v 1.25 2001/07/01 12:16:25 mrg 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 (at) 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 #include <sys/param.h>
33 #include <sys/systm.h>
34
35 #include <machine/stdarg.h>
36
37 #include <dev/cons.h>
38
39 #include <machine/db_machdep.h>
40
41 #include <ddb/db_command.h>
42 #include <ddb/db_output.h>
43 #include <ddb/db_interface.h>
44 #include <ddb/db_sym.h>
45 #include <ddb/db_extern.h>
46
47 /*
48 * Character output - tracks position in line.
49 * To do this correctly, we should know how wide
50 * the output device is - then we could zero
51 * the line position when the output device wraps
52 * around to the start of the next line.
53 *
54 * Instead, we count the number of spaces printed
55 * since the last printing character so that we
56 * don't print trailing spaces. This avoids most
57 * of the wraparounds.
58 */
59
60 #ifndef DB_MAX_LINE
61 #define DB_MAX_LINE 24 /* maximum line */
62 #endif /* DB_MAX_LINE */
63 #ifndef DB_MAX_WIDTH
64 #define DB_MAX_WIDTH 80 /* maximum width */
65 #endif /* DB_MAX_WIDTH */
66
67 #define DB_MIN_MAX_WIDTH 20 /* minimum max width */
68 #define DB_MIN_MAX_LINE 3 /* minimum max line */
69 #define CTRL(c) ((c) & 0xff)
70
71 int db_output_position = 0; /* output column */
72 int db_output_line = 0; /* output line number */
73 int db_last_non_space = 0; /* last non-space character */
74 int db_tab_stop_width = 8; /* how wide are tab stops? */
75 int db_max_line = DB_MAX_LINE; /* output max lines */
76 int db_max_width = DB_MAX_WIDTH; /* output line width */
77
78 static void db_more __P((void));
79
80 /*
81 * Force pending whitespace.
82 */
83 void
84 db_force_whitespace()
85 {
86 int last_print, next_tab;
87
88 last_print = db_last_non_space;
89 while (last_print < db_output_position) {
90 next_tab = DB_NEXT_TAB(last_print);
91 if (next_tab <= db_output_position) {
92 while (last_print < next_tab) { /* DON'T send a tab!!! */
93 cnputc(' ');
94 last_print++;
95 }
96 }
97 else {
98 cnputc(' ');
99 last_print++;
100 }
101 }
102 db_last_non_space = db_output_position;
103 }
104
105 static void
106 db_more()
107 {
108 char *p;
109 int quit_output = 0;
110
111 for (p = "--db_more--"; *p; p++)
112 cnputc(*p);
113 switch(cngetc()) {
114 case ' ':
115 db_output_line = 0;
116 break;
117 case 'q':
118 case CTRL('c'):
119 db_output_line = 0;
120 quit_output = 1;
121 break;
122 default:
123 db_output_line--;
124 break;
125 }
126 p = "\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b";
127 while (*p)
128 cnputc(*p++);
129 if (quit_output) {
130 db_error(0);
131 /* NOTREACHED */
132 }
133 }
134
135 /*
136 * Output character. Buffer whitespace.
137 */
138 void
139 db_putchar(c)
140 int c; /* character to output */
141 {
142 if (db_max_line >= DB_MIN_MAX_LINE && db_output_line >= db_max_line-1)
143 db_more();
144 if (c > ' ' && c <= '~') {
145 /*
146 * Printing character.
147 * If we have spaces to print, print them first.
148 * Use tabs if possible.
149 */
150 db_force_whitespace();
151 cnputc(c);
152 db_output_position++;
153 if (db_max_width >= DB_MIN_MAX_WIDTH
154 && db_output_position >= db_max_width) {
155 /* auto new line */
156 cnputc('\n');
157 db_output_position = 0;
158 db_last_non_space = 0;
159 db_output_line++;
160 }
161 db_last_non_space = db_output_position;
162 }
163 else if (c == '\n') {
164 /* Return */
165 cnputc(c);
166 db_output_position = 0;
167 db_last_non_space = 0;
168 db_output_line++;
169 db_check_interrupt();
170 }
171 else if (c == '\t') {
172 /* assume tabs every 8 positions */
173 db_output_position = DB_NEXT_TAB(db_output_position);
174 }
175 else if (c == ' ') {
176 /* space */
177 db_output_position++;
178 }
179 else if (c == '\007') {
180 /* bell */
181 cnputc(c);
182 }
183 /* other characters are assumed non-printing */
184 }
185
186 /*
187 * Return output position
188 */
189 int
190 db_print_position()
191 {
192 return (db_output_position);
193 }
194
195 /*
196 * End line if too long.
197 */
198 void
199 db_end_line()
200 {
201 if (db_output_position >= db_max_width)
202 db_printf("\n");
203 }
204
205 /*
206 * Replacement for old '%r' kprintf format.
207 */
208 void
209 db_format_radix(buf, bufsiz, val, altflag)
210 char *buf;
211 size_t bufsiz;
212 quad_t val;
213 int altflag;
214 {
215 const char *fmt;
216
217 if (db_radix == 16) {
218 db_format_hex(buf, bufsiz, val, altflag);
219 return;
220 }
221
222 if (db_radix == 8)
223 fmt = altflag ? "-%#qo" : "-%qo";
224 else
225 fmt = altflag ? "-%#qu" : "-%qu";
226
227 if (val < 0)
228 val = -val;
229 else
230 ++fmt;
231
232 snprintf(buf, bufsiz, fmt, val);
233 }
234
235 /*
236 * Replacement for old '%z' kprintf format.
237 */
238 void
239 db_format_hex(buf, bufsiz, val, altflag)
240 char *buf;
241 size_t bufsiz;
242 quad_t val;
243 int altflag;
244 {
245 /* Only use alternate form if val is nonzero. */
246 const char *fmt = (altflag && val) ? "-%#qx" : "-%qx";
247
248 if (val < 0)
249 val = -val;
250 else
251 ++fmt;
252
253 snprintf(buf, bufsiz, fmt, val);
254 }
255