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