FreeBSD/Linux Kernel Cross Reference
sys/ddb/db_output.c
1 /*
2 * Mach Operating System
3 * Copyright (c) 1991,1990 Carnegie Mellon University
4 * All Rights Reserved.
5 *
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
11 *
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15 *
16 * Carnegie Mellon requests users of this software to return to
17 *
18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
22 *
23 * any improvements or extensions that they make and grant Carnegie the
24 * rights to redistribute these changes.
25 */
26 /*
27 * Author: David B. Golub, Carnegie Mellon University
28 * Date: 7/90
29 */
30
31 /*
32 * Printf and character output for debugger.
33 */
34
35 #include <sys/cdefs.h>
36 __FBSDID("$FreeBSD: releng/5.3/sys/ddb/db_output.c 131952 2004-07-10 23:47:20Z marcel $");
37
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/cons.h>
41 #include <sys/kdb.h>
42 #include <sys/kernel.h>
43 #include <sys/sysctl.h>
44
45 #include <machine/stdarg.h>
46
47 #include <ddb/ddb.h>
48 #include <ddb/db_output.h>
49
50 /*
51 * Character output - tracks position in line.
52 * To do this correctly, we should know how wide
53 * the output device is - then we could zero
54 * the line position when the output device wraps
55 * around to the start of the next line.
56 *
57 * Instead, we count the number of spaces printed
58 * since the last printing character so that we
59 * don't print trailing spaces. This avoids most
60 * of the wraparounds.
61 */
62 static int db_output_position = 0; /* output column */
63 static int db_last_non_space = 0; /* last non-space character */
64 db_expr_t db_tab_stop_width = 8; /* how wide are tab stops? */
65 #define NEXT_TAB(i) \
66 ((((i) + db_tab_stop_width) / db_tab_stop_width) * db_tab_stop_width)
67 db_expr_t db_max_width = 79; /* output line width */
68 static int db_newlines; /* # lines this page */
69 static int db_maxlines = -1; /* max lines per page */
70 static db_page_calloutfcn_t *db_page_callout = NULL;
71 static void *db_page_callout_arg = NULL;
72 static int ddb_use_printf = 0;
73 SYSCTL_INT(_debug, OID_AUTO, ddb_use_printf, CTLFLAG_RW, &ddb_use_printf, 0,
74 "use printf for all ddb output");
75
76 static void db_putchar(int c, void *arg);
77
78 /*
79 * Force pending whitespace.
80 */
81 void
82 db_force_whitespace()
83 {
84 register int last_print, next_tab;
85
86 last_print = db_last_non_space;
87 while (last_print < db_output_position) {
88 next_tab = NEXT_TAB(last_print);
89 if (next_tab <= db_output_position) {
90 while (last_print < next_tab) { /* DON'T send a tab!!! */
91 cnputc(' ');
92 last_print++;
93 }
94 }
95 else {
96 cnputc(' ');
97 last_print++;
98 }
99 }
100 db_last_non_space = db_output_position;
101 }
102
103 /*
104 * Output character. Buffer whitespace.
105 */
106 static void
107 db_putchar(c, arg)
108 int c; /* character to output */
109 void * arg;
110 {
111
112 /*
113 * If not in the debugger or the user requests it, output data to
114 * both the console and the message buffer.
115 */
116 if (!kdb_active || ddb_use_printf) {
117 printf("%c", c);
118 if (!kdb_active)
119 return;
120 if (c == '\r' || c == '\n')
121 db_check_interrupt();
122 if (c == '\n' && db_maxlines > 0 && db_page_callout != NULL) {
123 db_newlines++;
124 if (db_newlines >= db_maxlines) {
125 db_maxlines = -1;
126 db_page_callout(db_page_callout_arg);
127 }
128 }
129 return;
130 }
131
132 /* Otherwise, output data directly to the console. */
133 if (c > ' ' && c <= '~') {
134 /*
135 * Printing character.
136 * If we have spaces to print, print them first.
137 * Use tabs if possible.
138 */
139 db_force_whitespace();
140 cnputc(c);
141 db_output_position++;
142 db_last_non_space = db_output_position;
143 }
144 else if (c == '\n') {
145 /* Newline */
146 cnputc(c);
147 db_output_position = 0;
148 db_last_non_space = 0;
149 db_check_interrupt();
150 if (db_maxlines > 0 && db_page_callout != NULL) {
151 db_newlines++;
152 if (db_newlines >= db_maxlines) {
153 db_maxlines = -1;
154 db_page_callout(db_page_callout_arg);
155 }
156 }
157 }
158 else if (c == '\r') {
159 /* Return */
160 cnputc(c);
161 db_output_position = 0;
162 db_last_non_space = 0;
163 db_check_interrupt();
164 }
165 else if (c == '\t') {
166 /* assume tabs every 8 positions */
167 db_output_position = NEXT_TAB(db_output_position);
168 }
169 else if (c == ' ') {
170 /* space */
171 db_output_position++;
172 }
173 else if (c == '\007') {
174 /* bell */
175 cnputc(c);
176 }
177 /* other characters are assumed non-printing */
178 }
179
180 /*
181 * Register callout for providing a pager for output.
182 */
183 void
184 db_setup_paging(db_page_calloutfcn_t *callout, void *arg, int maxlines)
185 {
186
187 db_page_callout = callout;
188 db_page_callout_arg = arg;
189 db_maxlines = maxlines;
190 db_newlines = 0;
191 }
192
193 /*
194 * A simple paging callout function. If the argument is not null, it
195 * points to an integer that will be set to 1 if the user asks to quit.
196 */
197 void
198 db_simple_pager(void *arg)
199 {
200 int c;
201
202 db_printf("--More--\r");
203 for (;;) {
204 c = cngetc();
205 switch (c) {
206 case '\n':
207 /* Just one more line. */
208 db_setup_paging(db_simple_pager, arg, 1);
209 return;
210 case ' ':
211 /* Another page. */
212 db_setup_paging(db_simple_pager, arg,
213 DB_LINES_PER_PAGE);
214 return;
215 case 'q':
216 case 'Q':
217 case 'x':
218 case 'X':
219 /* Quit */
220 if (arg != NULL) {
221 *(int *)arg = 1;
222 db_printf("\n");
223 return;
224 }
225 #if 0
226 /* FALLTHROUGH */
227 default:
228 cnputc('\007');
229 #endif
230 }
231 }
232 }
233
234 /*
235 * Return output position
236 */
237 int
238 db_print_position()
239 {
240 return (db_output_position);
241 }
242
243 /*
244 * Printing
245 */
246 void
247 #if __STDC__
248 db_printf(const char *fmt, ...)
249 #else
250 db_printf(fmt)
251 const char *fmt;
252 #endif
253 {
254 va_list listp;
255
256 va_start(listp, fmt);
257 kvprintf (fmt, db_putchar, NULL, db_radix, listp);
258 va_end(listp);
259 }
260
261 int db_indent;
262
263 void
264 #if __STDC__
265 db_iprintf(const char *fmt,...)
266 #else
267 db_iprintf(fmt)
268 const char *fmt;
269 #endif
270 {
271 register int i;
272 va_list listp;
273
274 for (i = db_indent; i >= 8; i -= 8)
275 db_printf("\t");
276 while (--i >= 0)
277 db_printf(" ");
278 va_start(listp, fmt);
279 kvprintf (fmt, db_putchar, NULL, db_radix, listp);
280 va_end(listp);
281 }
282
283 /*
284 * End line if too long.
285 */
286 void
287 db_end_line()
288 {
289 if (db_output_position >= db_max_width)
290 db_printf("\n");
291 }
Cache object: a5850c9f86cf8f57f103bd9cee6f6705
|