xref: /dflybsd-src/sys/ddb/db_output.c (revision 88abd8b5763f2e5d4b4db5c5dc1b5bb4c489698b)
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  * $FreeBSD: src/sys/ddb/db_output.c,v 1.26 1999/08/28 00:41:09 peter Exp $
27  * $DragonFly: src/sys/ddb/db_output.c,v 1.9 2008/09/25 13:30:15 sephe Exp $
28  */
29 
30 /*
31  * 	Author: David B. Golub, Carnegie Mellon University
32  *	Date:	7/90
33  */
34 
35 /*
36  * Printf and character output for debugger.
37  */
38 
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/cons.h>
42 #include <sys/thread2.h>
43 #include <sys/spinlock2.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 
69 static void db_putchar (int c, void *arg);
70 
71 /*
72  * Force pending whitespace.
73  */
74 void
75 db_force_whitespace(void)
76 {
77 	int last_print, next_tab;
78 
79 	last_print = db_last_non_space;
80 	while (last_print < db_output_position) {
81 	    next_tab = NEXT_TAB(last_print);
82 	    if (next_tab <= db_output_position) {
83 		while (last_print < next_tab) { /* DON'T send a tab!!! */
84 			cnputc(' ');
85 			last_print++;
86 		}
87 	    }
88 	    else {
89 		cnputc(' ');
90 		last_print++;
91 	    }
92 	}
93 	db_last_non_space = db_output_position;
94 }
95 
96 /*
97  * Output character.  Buffer whitespace.
98  *
99  * Parameters:
100  *     arg:	character to output
101  */
102 static void
103 db_putchar(int c, void *arg)
104 {
105 	/*
106 	 * If not in the debugger, output data to both the console and
107 	 * the message buffer.
108 	 */
109 	if (!db_active) {
110 		kprintf("%c", c);
111 		if (!db_active)
112 			return;
113 		if (c == '\r' || c == '\n')
114 			db_check_interrupt();
115 		return;
116 	}
117 
118 	crit_enter_hard();
119 
120 	if (c > ' ' && c <= '~') {
121 	    /*
122 	     * Printing character.
123 	     * If we have spaces to print, print them first.
124 	     * Use tabs if possible.
125 	     */
126 	    db_force_whitespace();
127 	    cnputc(c);
128 	    db_output_position++;
129 	    db_last_non_space = db_output_position;
130 	}
131 	else if (c == '\n') {
132 	    /* Newline */
133 	    cnputc(c);
134 	    db_output_position = 0;
135 	    db_last_non_space = 0;
136 	    db_check_interrupt();
137 	}
138 	else if (c == '\r') {
139 	    /* Return */
140 	    cnputc(c);
141 	    db_output_position = 0;
142 	    db_last_non_space = 0;
143 	    db_check_interrupt();
144 	}
145 	else if (c == '\t') {
146 	    /* assume tabs every 8 positions */
147 	    db_output_position = NEXT_TAB(db_output_position);
148 	}
149 	else if (c == ' ') {
150 	    /* space */
151 	    db_output_position++;
152 	}
153 	else if (c == '\007') {
154 	    /* bell */
155 	    cnputc(c);
156 	}
157 	/* other characters are assumed non-printing */
158 	crit_exit_hard();
159 }
160 
161 /*
162  * Return output position
163  */
164 int
165 db_print_position(void)
166 {
167 	return (db_output_position);
168 }
169 
170 /*
171  * Printing
172  *
173  * NOTE: We bypass subr_prf's cons_spin here by using our own putchar
174  *	 function.
175  */
176 void
177 db_printf(const char *fmt, ...)
178 {
179 	__va_list listp;
180 
181 	__va_start(listp, fmt);
182 	kvcprintf (fmt, db_putchar, NULL, db_radix, listp);
183 	__va_end(listp);
184 /*	DELAY(100000);*/
185 }
186 
187 void
188 db_vprintf(const char *fmt, __va_list va)
189 {
190 	kvcprintf (fmt, db_putchar, NULL, db_radix, va);
191 /*	DELAY(100000);*/
192 }
193 
194 int db_indent;
195 
196 void
197 db_iprintf(const char *fmt,...)
198 {
199 	int i;
200 	__va_list listp;
201 
202 	for (i = db_indent; i >= 8; i -= 8)
203 		db_printf("\t");
204 	while (--i >= 0)
205 		db_printf(" ");
206 	__va_start(listp, fmt);
207 	kvcprintf (fmt, db_putchar, NULL, db_radix, listp);
208 	__va_end(listp);
209 }
210 
211 /*
212  * End line if too long.
213  */
214 void
215 db_end_line(void)
216 {
217 	if (db_output_position >= db_max_width)
218 	    db_printf("\n");
219 }
220 
221 /*
222  * Simple pager
223  */
224 int
225 db_more(int *nl)
226 {
227 	++*nl;
228 	if (*nl == 20) {
229 		int c;
230 
231 		db_printf("--More--");
232 		c = cngetc();
233 		db_printf("\r");
234 		/*
235 		 * A whole screenfull or just one line?
236 		 */
237 		switch (c) {
238 		case '\n':		/* just one line */
239 			*nl = 19;
240 			break;
241 		case ' ':
242 			*nl = 0;	/* another screenfull */
243 			break;
244 		default:		/* exit */
245 			db_printf("\n");
246 			return(-1);
247 		}
248 	}
249 	return(0);
250 }
251 
252