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