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