]> git.saurik.com Git - apple/xnu.git/blob - osfmk/ddb/db_output.c
xnu-344.49.tar.gz
[apple/xnu.git] / osfmk / ddb / db_output.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 /*
26 * @OSF_COPYRIGHT@
27 */
28 /*
29 * Mach Operating System
30 * Copyright (c) 1991,1990 Carnegie Mellon University
31 * All Rights Reserved.
32 *
33 * Permission to use, copy, modify and distribute this software and its
34 * documentation is hereby granted, provided that both the copyright
35 * notice and this permission notice appear in all copies of the
36 * software, derivative works or modified versions, and any portions
37 * thereof, and that both notices appear in supporting documentation.
38 *
39 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
40 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
41 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
42 *
43 * Carnegie Mellon requests users of this software to return to
44 *
45 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
46 * School of Computer Science
47 * Carnegie Mellon University
48 * Pittsburgh PA 15213-3890
49 *
50 * any improvements or extensions that they make and grant Carnegie Mellon
51 * the rights to redistribute these changes.
52 */
53 /*
54 */
55 /*
56 * Author: David B. Golub, Carnegie Mellon University
57 * Date: 7/90
58 */
59
60 /*
61 * Printf and character output for debugger.
62 */
63
64 #include <mach/boolean.h>
65 #include <kern/misc_protos.h>
66 #include <stdarg.h>
67 #include <machine/db_machdep.h>
68 #include <ddb/db_command.h>
69 #include <ddb/db_lex.h>
70 #include <ddb/db_input.h>
71 #include <ddb/db_output.h>
72 #include <ddb/db_task_thread.h>
73
74 /*
75 * Character output - tracks position in line.
76 * To do this correctly, we should know how wide
77 * the output device is - then we could zero
78 * the line position when the output device wraps
79 * around to the start of the next line.
80 *
81 * Instead, we count the number of spaces printed
82 * since the last printing character so that we
83 * don't print trailing spaces. This avoids most
84 * of the wraparounds.
85 */
86
87 #ifndef DB_MAX_LINE
88 #define DB_MAX_LINE 24 /* maximum line */
89 #define DB_MAX_WIDTH 132 /* maximum width */
90 #endif /* DB_MAX_LINE */
91
92 #define DB_MIN_MAX_WIDTH 20 /* minimum max width */
93 #define DB_MIN_MAX_LINE 3 /* minimum max line */
94 #define CTRL(c) ((c) & 0xff)
95
96 int db_output_position = 0; /* output column */
97 int db_output_line = 0; /* output line number */
98 int db_last_non_space = 0; /* last non-space character */
99 int db_last_gen_return = 0; /* last character generated return */
100 int db_auto_wrap = 1; /* auto wrap at end of line ? */
101 int db_tab_stop_width = 8; /* how wide are tab stops? */
102 #define NEXT_TAB(i) \
103 ((((i) + db_tab_stop_width) / db_tab_stop_width) * db_tab_stop_width)
104 int db_max_line = DB_MAX_LINE; /* output max lines */
105 int db_max_width = DB_MAX_WIDTH; /* output line width */
106
107
108 /* Prototypes for functions local to this file. XXX -- should be static!
109 */
110 static void db_more(void);
111 void db_advance_output_position(int new_output_position,
112 int blank);
113
114
115 /*
116 * Force pending whitespace.
117 */
118 void
119 db_force_whitespace(void)
120 {
121 register int last_print, next_tab;
122
123 last_print = db_last_non_space;
124 while (last_print < db_output_position) {
125 next_tab = NEXT_TAB(last_print);
126 if (next_tab <= db_output_position) {
127 cnputc('\t');
128 last_print = next_tab;
129 }
130 else {
131 cnputc(' ');
132 last_print++;
133 }
134 }
135 db_last_non_space = db_output_position;
136 }
137
138 void
139 db_reset_more()
140 {
141 db_output_line = 0;
142 }
143
144 static void
145 db_more(void)
146 {
147 register char *p;
148 boolean_t quit_output = FALSE;
149
150 #if defined(__alpha)
151 extern boolean_t kdebug_mode;
152 if (kdebug_mode) return;
153 #endif /* defined(__alpha) */
154 for (p = "--db_more--"; *p; p++)
155 cnputc(*p);
156 switch(cngetc()) {
157 case ' ':
158 db_output_line = 0;
159 break;
160 case 'q':
161 case CTRL('c'):
162 db_output_line = 0;
163 quit_output = TRUE;
164 break;
165 default:
166 db_output_line--;
167 break;
168 }
169 p = "\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b";
170 while (*p)
171 cnputc(*p++);
172 if (quit_output) {
173 db_error((char *) 0);
174 /* NOTREACHED */
175 }
176 }
177
178 void
179 db_advance_output_position(int new_output_position,
180 int blank)
181 {
182 if (db_max_width >= DB_MIN_MAX_WIDTH
183 && new_output_position >= db_max_width) {
184 /* auto new line */
185 if (!db_auto_wrap || blank)
186 cnputc('\n');
187 db_output_position = 0;
188 db_last_non_space = 0;
189 db_last_gen_return = 1;
190 db_output_line++;
191 } else {
192 db_output_position = new_output_position;
193 }
194 }
195
196 boolean_t
197 db_reserve_output_position(int increment)
198 {
199 if (db_max_width >= DB_MIN_MAX_WIDTH
200 && db_output_position + increment >= db_max_width) {
201 /* auto new line */
202 if (!db_auto_wrap || db_last_non_space != db_output_position)
203 cnputc('\n');
204 db_output_position = 0;
205 db_last_non_space = 0;
206 db_last_gen_return = 1;
207 db_output_line++;
208 return TRUE;
209 }
210 return FALSE;
211 }
212
213 /*
214 * Output character. Buffer whitespace.
215 */
216 void
217 db_putchar(char c)
218 {
219 if (db_max_line >= DB_MIN_MAX_LINE && db_output_line >= db_max_line-1)
220 db_more();
221 if (c > ' ' && c <= '~') {
222 /*
223 * Printing character.
224 * If we have spaces to print, print them first.
225 * Use tabs if possible.
226 */
227 db_force_whitespace();
228 cnputc(c);
229 db_last_gen_return = 0;
230 db_advance_output_position(db_output_position+1, 0);
231 db_last_non_space = db_output_position;
232 }
233 else if (c == '\n') {
234 /* Return */
235 if (db_last_gen_return) {
236 db_last_gen_return = 0;
237 } else {
238 cnputc(c);
239 db_output_position = 0;
240 db_last_non_space = 0;
241 db_output_line++;
242 db_check_interrupt();
243 }
244 }
245 else if (c == '\t') {
246 /* assume tabs every 8 positions */
247 db_advance_output_position(NEXT_TAB(db_output_position), 1);
248 }
249 else if (c == ' ') {
250 /* space */
251 db_advance_output_position(db_output_position+1, 1);
252 }
253 else if (c == '\007') {
254 /* bell */
255 cnputc(c);
256 }
257 /* other characters are assumed non-printing */
258 }
259
260 /*
261 * Return output position
262 */
263 int
264 db_print_position(void)
265 {
266 return (db_output_position);
267 }
268
269 /*
270 * End line if too long.
271 */
272 void
273 db_end_line(void)
274 {
275 if (db_output_position >= db_max_width-1) {
276 /* auto new line */
277 if (!db_auto_wrap)
278 cnputc('\n');
279 db_output_position = 0;
280 db_last_non_space = 0;
281 db_last_gen_return = 1;
282 db_output_line++;
283 }
284 }
285
286 /*
287 * Printing
288 */
289
290 void
291 db_printf(char *fmt, ...)
292 {
293 va_list listp;
294
295 #ifdef luna88k
296 db_printing();
297 #endif
298 va_start(listp, fmt);
299 _doprnt(fmt, &listp, db_putchar, db_radix);
300 va_end(listp);
301 }
302
303 /* alternate name */
304
305 void
306 kdbprintf(char *fmt, ...)
307 {
308 va_list listp;
309
310 va_start(listp, fmt);
311 _doprnt(fmt, &listp, db_putchar, db_radix);
312 va_end(listp);
313 }
314
315 int db_indent = 0;
316
317 /*
318 * Printing (to console) with indentation.
319 */
320 void
321 iprintf(char *fmt, ...)
322 {
323 va_list listp;
324 register int i;
325
326 for (i = db_indent; i > 0; ){
327 if (i >= 8) {
328 kdbprintf("\t");
329 i -= 8;
330 }
331 else {
332 kdbprintf(" ");
333 i--;
334 }
335 }
336
337 va_start(listp, fmt);
338 _doprnt(fmt, &listp, db_putchar, db_radix);
339 va_end(listp);
340 }
341
342 void
343 db_output_prompt(void)
344 {
345 db_printf("db%s", (db_default_act) ? "t": "");
346 #if NCPUS > 1
347 db_printf("{%d}", cpu_number());
348 #endif
349 db_printf("> ");
350 }
351