xref: /freebsd/sys/ddb/db_output.c (revision 7660b554bc59a07be0431c17e0e33815818baa69)
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$");
37 
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/cons.h>
41 
42 #include <machine/stdarg.h>
43 
44 #include <ddb/ddb.h>
45 #include <ddb/db_output.h>
46 
47 /*
48  *	Character output - tracks position in line.
49  *	To do this correctly, we should know how wide
50  *	the output device is - then we could zero
51  *	the line position when the output device wraps
52  *	around to the start of the next line.
53  *
54  *	Instead, we count the number of spaces printed
55  *	since the last printing character so that we
56  *	don't print trailing spaces.  This avoids most
57  *	of the wraparounds.
58  */
59 static int	db_output_position = 0;		/* output column */
60 static int	db_last_non_space = 0;		/* last non-space character */
61 db_expr_t	db_tab_stop_width = 8;		/* how wide are tab stops? */
62 #define	NEXT_TAB(i) \
63 	((((i) + db_tab_stop_width) / db_tab_stop_width) * db_tab_stop_width)
64 db_expr_t	db_max_width = 79;		/* output line width */
65 static int	db_newlines;			/* # lines this page */
66 static int	db_maxlines = -1;		/* max lines per page */
67 static db_page_calloutfcn_t *db_page_callout = NULL;
68 static void	*db_page_callout_arg = NULL;
69 
70 static void db_putchar(int c, void *arg);
71 
72 /*
73  * Force pending whitespace.
74  */
75 void
76 db_force_whitespace()
77 {
78 	register int last_print, next_tab;
79 
80 	last_print = db_last_non_space;
81 	while (last_print < db_output_position) {
82 	    next_tab = NEXT_TAB(last_print);
83 	    if (next_tab <= db_output_position) {
84 		while (last_print < next_tab) { /* DON'T send a tab!!! */
85 			cnputc(' ');
86 			last_print++;
87 		}
88 	    }
89 	    else {
90 		cnputc(' ');
91 		last_print++;
92 	    }
93 	}
94 	db_last_non_space = db_output_position;
95 }
96 
97 /*
98  * Output character.  Buffer whitespace.
99  */
100 static void
101 db_putchar(c, arg)
102 	int	c;		/* character to output */
103 	void *	arg;
104 {
105 
106 	if (c > ' ' && c <= '~') {
107 	    /*
108 	     * Printing character.
109 	     * If we have spaces to print, print them first.
110 	     * Use tabs if possible.
111 	     */
112 	    db_force_whitespace();
113 	    cnputc(c);
114 	    db_output_position++;
115 	    db_last_non_space = db_output_position;
116 	}
117 	else if (c == '\n') {
118 	    /* Newline */
119 	    cnputc(c);
120 	    db_output_position = 0;
121 	    db_last_non_space = 0;
122 	    db_check_interrupt();
123 	    if (db_maxlines > 0 && db_page_callout != NULL) {
124 		    db_newlines++;
125 		    if (db_newlines >= db_maxlines) {
126 			    db_maxlines = -1;
127 			    db_page_callout(db_page_callout_arg);
128 		    }
129 	    }
130 	}
131 	else if (c == '\r') {
132 	    /* Return */
133 	    cnputc(c);
134 	    db_output_position = 0;
135 	    db_last_non_space = 0;
136 	    db_check_interrupt();
137 	}
138 	else if (c == '\t') {
139 	    /* assume tabs every 8 positions */
140 	    db_output_position = NEXT_TAB(db_output_position);
141 	}
142 	else if (c == ' ') {
143 	    /* space */
144 	    db_output_position++;
145 	}
146 	else if (c == '\007') {
147 	    /* bell */
148 	    cnputc(c);
149 	}
150 	/* other characters are assumed non-printing */
151 }
152 
153 /*
154  * Register callout for providing a pager for output.
155  */
156 void
157 db_setup_paging(db_page_calloutfcn_t *callout, void *arg, int maxlines)
158 {
159 
160 	db_page_callout = callout;
161 	db_page_callout_arg = arg;
162 	db_maxlines = maxlines;
163 	db_newlines = 0;
164 }
165 
166 /*
167  * A simple paging callout function.  If the argument is not null, it
168  * points to an integer that will be set to 1 if the user asks to quit.
169  */
170 void
171 db_simple_pager(void *arg)
172 {
173 	int c;
174 
175 	db_printf("--More--\r");
176 	for (;;) {
177 		c = cngetc();
178 		switch (c) {
179 		case '\n':
180 			/* Just one more line. */
181 			db_setup_paging(db_simple_pager, arg, 1);
182 			return;
183 		case ' ':
184 			/* Another page. */
185 			db_setup_paging(db_simple_pager, arg,
186 			    DB_LINES_PER_PAGE);
187 			return;
188 		case 'q':
189 		case 'Q':
190 		case 'x':
191 		case 'X':
192 			/* Quit */
193 			if (arg != NULL) {
194 				*(int *)arg = 1;
195 				db_printf("\n");
196 				return;
197 			}
198 #if 0
199 			/* FALLTHROUGH */
200 		default:
201 			cnputc('\007');
202 #endif
203 		}
204 	}
205 }
206 
207 /*
208  * Return output position
209  */
210 int
211 db_print_position()
212 {
213 	return (db_output_position);
214 }
215 
216 /*
217  * Printing
218  */
219 void
220 #if __STDC__
221 db_printf(const char *fmt, ...)
222 #else
223 db_printf(fmt)
224 	const char *fmt;
225 #endif
226 {
227 	va_list	listp;
228 
229 	va_start(listp, fmt);
230 	kvprintf (fmt, db_putchar, NULL, db_radix, listp);
231 	va_end(listp);
232 }
233 
234 int db_indent;
235 
236 void
237 #if __STDC__
238 db_iprintf(const char *fmt,...)
239 #else
240 db_iprintf(fmt)
241 	const char *fmt;
242 #endif
243 {
244 	register int i;
245 	va_list listp;
246 
247 	for (i = db_indent; i >= 8; i -= 8)
248 		db_printf("\t");
249 	while (--i >= 0)
250 		db_printf(" ");
251 	va_start(listp, fmt);
252 	kvprintf (fmt, db_putchar, NULL, db_radix, listp);
253 	va_end(listp);
254 }
255 
256 /*
257  * End line if too long.
258  */
259 void
260 db_end_line()
261 {
262 	if (db_output_position >= db_max_width)
263 	    db_printf("\n");
264 }
265