xref: /openbsd-src/sys/ddb/db_output.c (revision a28daedfc357b214be5c701aa8ba8adb29a7f1c2)
1 /*	$OpenBSD: db_output.c,v 1.25 2006/07/06 18:14:14 miod Exp $	*/
2 /*	$NetBSD: db_output.c,v 1.13 1996/04/01 17:27:14 christos Exp $	*/
3 
4 /*
5  * Mach Operating System
6  * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University
7  * All Rights Reserved.
8  *
9  * Permission to use, copy, modify and distribute this software and its
10  * documentation is hereby granted, provided that both the copyright
11  * notice and this permission notice appear in all copies of the
12  * software, derivative works or modified versions, and any portions
13  * thereof, and that both notices appear in supporting documentation.
14  *
15  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
16  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
17  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
18  *
19  * Carnegie Mellon requests users of this software to return to
20  *
21  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
22  *  School of Computer Science
23  *  Carnegie Mellon University
24  *  Pittsburgh PA 15213-3890
25  *
26  * any improvements or extensions that they make and grant Carnegie Mellon
27  * the rights to redistribute these changes.
28  */
29 
30 /*
31  * Printf and character output for debugger.
32  */
33 #include <sys/param.h>
34 #include <sys/proc.h>
35 #include <sys/stdarg.h>
36 #include <sys/systm.h>
37 
38 #include <dev/cons.h>
39 
40 #include <uvm/uvm_extern.h>
41 
42 #include <machine/db_machdep.h>
43 
44 #include <ddb/db_command.h>
45 #include <ddb/db_output.h>
46 #include <ddb/db_interface.h>
47 #include <ddb/db_sym.h>
48 #include <ddb/db_var.h>
49 #include <ddb/db_extern.h>
50 
51 /*
52  *	Character output - tracks position in line.
53  *	To do this correctly, we should know how wide
54  *	the output device is - then we could zero
55  *	the line position when the output device wraps
56  *	around to the start of the next line.
57  *
58  *	Instead, we count the number of spaces printed
59  *	since the last printing character so that we
60  *	don't print trailing spaces.  This avoids most
61  *	of the wraparounds.
62  */
63 
64 #ifndef	DB_MAX_LINE
65 #define	DB_MAX_LINE		24	/* maximum line */
66 #define DB_MAX_WIDTH		80	/* maximum width */
67 #endif	/* DB_MAX_LINE */
68 
69 #define DB_MIN_MAX_WIDTH	20	/* minimum max width */
70 #define DB_MIN_MAX_LINE		3	/* minimum max line */
71 #define CTRL(c)			((c) & 0xff)
72 
73 int	db_output_position = 0;		/* output column */
74 int	db_output_line = 0;		/* output line number */
75 int	db_last_non_space = 0;		/* last non-space character */
76 int	db_tab_stop_width = 8;		/* how wide are tab stops? */
77 #define	NEXT_TAB(i) \
78 	((((i) + db_tab_stop_width) / db_tab_stop_width) * db_tab_stop_width)
79 int	db_max_line = DB_MAX_LINE;	/* output max lines */
80 int	db_max_width = DB_MAX_WIDTH;	/* output line width */
81 int	db_radix = 16;			/* output numbers radix */
82 
83 static void db_more(void);
84 
85 /*
86  * Force pending whitespace.
87  */
88 void
89 db_force_whitespace(void)
90 {
91 	int last_print, next_tab;
92 
93 	last_print = db_last_non_space;
94 	while (last_print < db_output_position) {
95 	    next_tab = NEXT_TAB(last_print);
96 	    if (next_tab <= db_output_position) {
97 		while (last_print < next_tab) { /* DON'T send a tab!!! */
98 			cnputc(' ');
99 			last_print++;
100 		}
101 	    }
102 	    else {
103 		cnputc(' ');
104 		last_print++;
105 	    }
106 	}
107 	db_last_non_space = db_output_position;
108 }
109 
110 static void
111 db_more(void)
112 {
113 	char *p;
114 	int quit_output = 0;
115 
116 	for (p = "--db_more--"; *p; p++)
117 	    cnputc(*p);
118 	switch(cngetc()) {
119 	case ' ':
120 	    db_output_line = 0;
121 	    break;
122 	case 'q':
123 	case CTRL('c'):
124 	    db_output_line = 0;
125 	    quit_output = 1;
126 	    break;
127 	default:
128 	    db_output_line--;
129 	    break;
130 	}
131 	p = "\b\b\b\b\b\b\b\b\b\b\b           \b\b\b\b\b\b\b\b\b\b\b";
132 	while (*p)
133 	    cnputc(*p++);
134 	if (quit_output) {
135 	    db_error(0);
136 	    /* NOTREACHED */
137 	}
138 }
139 
140 /*
141  * Output character.  Buffer whitespace.
142  */
143 void
144 db_putchar(int c)
145 {
146 	if (db_max_line >= DB_MIN_MAX_LINE && db_output_line >= db_max_line-1)
147 	    db_more();
148 
149 	if (c > ' ' && c <= '~') {
150 	    /*
151 	     * Printing character.
152 	     * If we have spaces to print, print them first.
153 	     * Use tabs if possible.
154 	     */
155 	    db_force_whitespace();
156 	    cnputc(c);
157 	    db_output_position++;
158 	    if (db_max_width >= DB_MIN_MAX_WIDTH
159 		&& db_output_position >= db_max_width-1) {
160 		/* auto new line */
161 		cnputc('\n');
162 		db_output_position = 0;
163 		db_last_non_space = 0;
164 		db_output_line++;
165 	    }
166 	    db_last_non_space = db_output_position;
167 	}
168 	else if (c == '\n') {
169 	    /* Return */
170 	    cnputc(c);
171 	    db_output_position = 0;
172 	    db_last_non_space = 0;
173 	    db_output_line++;
174 	}
175 	else if (c == '\t') {
176 	    /* assume tabs every 8 positions */
177 	    db_output_position = NEXT_TAB(db_output_position);
178 	}
179 	else if (c == ' ') {
180 	    /* space */
181 	    db_output_position++;
182 	}
183 	else if (c == '\007') {
184 	    /* bell */
185 	    cnputc(c);
186 	}
187 	/* other characters are assumed non-printing */
188 }
189 
190 /*
191  * Return output position
192  */
193 int
194 db_print_position(void)
195 {
196 	return (db_output_position);
197 }
198 
199 /*
200  * End line if too long.
201  */
202 void
203 db_end_line(int space)
204 {
205 	if (db_output_position >= db_max_width - space)
206 	    db_printf("\n");
207 }
208 
209 char *
210 db_format(char *buf, size_t bufsize, long val, int format, int alt, int width)
211 {
212 	const char *fmt;
213 
214 	if (format == DB_FORMAT_Z || db_radix == 16)
215 		fmt = alt ? "-%#*lx" : "-%*lx";
216 	else if (db_radix == 8)
217 		fmt = alt ? "-%#*lo" : "-%*lo";
218 	else
219 		fmt = alt ? "-%#*lu" : "-%*lu";
220 
221 	/* The leading '-' is a nasty (and beautiful) idea from NetBSD */
222 	if (val < 0 && format != DB_FORMAT_N)
223 		val = -val;
224 	else
225 		fmt++;
226 
227 	snprintf(buf, bufsize, fmt, width, val);
228 
229 	return (buf);
230 }
231 
232 void
233 db_stack_dump(void)
234 {
235 	static int intrace;
236 
237 	if (intrace) {
238 		printf("Faulted in traceback, aborting...\n");
239 		return;
240 	}
241 
242 	intrace = 1;
243 	printf("Starting stack trace...\n");
244 	db_stack_trace_print((db_expr_t)__builtin_frame_address(0), TRUE,
245 	    256 /* low limit */, "", printf);
246 	printf("End of stack trace.\n");
247 	intrace = 0;
248 }
249