xref: /dragonfly/sys/ddb/db_output.c (revision c3b249e6)
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 
43 #include <machine/stdarg.h>
44 
45 #include <ddb/ddb.h>
46 #include <ddb/db_output.h>
47 
48 /*
49  *	Character output - tracks position in line.
50  *	To do this correctly, we should know how wide
51  *	the output device is - then we could zero
52  *	the line position when the output device wraps
53  *	around to the start of the next line.
54  *
55  *	Instead, we count the number of spaces printed
56  *	since the last printing character so that we
57  *	don't print trailing spaces.  This avoids most
58  *	of the wraparounds.
59  */
60 static int	db_output_position = 0;		/* output column */
61 static int	db_last_non_space = 0;		/* last non-space character */
62 db_expr_t	db_tab_stop_width = 8;		/* how wide are tab stops? */
63 #define	NEXT_TAB(i) \
64 	((((i) + db_tab_stop_width) / db_tab_stop_width) * db_tab_stop_width)
65 db_expr_t	db_max_width = 79;		/* output line width */
66 
67 static void db_putchar (int c, void *arg);
68 
69 /*
70  * Force pending whitespace.
71  */
72 void
73 db_force_whitespace(void)
74 {
75 	int last_print, next_tab;
76 
77 	last_print = db_last_non_space;
78 	while (last_print < db_output_position) {
79 	    next_tab = NEXT_TAB(last_print);
80 	    if (next_tab <= db_output_position) {
81 		while (last_print < next_tab) { /* DON'T send a tab!!! */
82 			cnputc(' ');
83 			last_print++;
84 		}
85 	    }
86 	    else {
87 		cnputc(' ');
88 		last_print++;
89 	    }
90 	}
91 	db_last_non_space = db_output_position;
92 }
93 
94 /*
95  * Output character.  Buffer whitespace.
96  *
97  * Parameters:
98  *     arg:	character to output
99  */
100 static void
101 db_putchar(int c, void *arg)
102 {
103 	/*
104 	 * If not in the debugger, output data to both the console and
105 	 * the message buffer.
106 	 */
107 	if (!db_active) {
108 		kprintf("%c", c);
109 		if (!db_active)
110 			return;
111 		if (c == '\r' || c == '\n')
112 			db_check_interrupt();
113 		return;
114 	}
115 
116 	if (c > ' ' && c <= '~') {
117 	    /*
118 	     * Printing character.
119 	     * If we have spaces to print, print them first.
120 	     * Use tabs if possible.
121 	     */
122 	    db_force_whitespace();
123 	    cnputc(c);
124 	    db_output_position++;
125 	    db_last_non_space = db_output_position;
126 	}
127 	else if (c == '\n') {
128 	    /* Newline */
129 	    cnputc(c);
130 	    db_output_position = 0;
131 	    db_last_non_space = 0;
132 	    db_check_interrupt();
133 	}
134 	else if (c == '\r') {
135 	    /* Return */
136 	    cnputc(c);
137 	    db_output_position = 0;
138 	    db_last_non_space = 0;
139 	    db_check_interrupt();
140 	}
141 	else if (c == '\t') {
142 	    /* assume tabs every 8 positions */
143 	    db_output_position = NEXT_TAB(db_output_position);
144 	}
145 	else if (c == ' ') {
146 	    /* space */
147 	    db_output_position++;
148 	}
149 	else if (c == '\007') {
150 	    /* bell */
151 	    cnputc(c);
152 	}
153 	/* other characters are assumed non-printing */
154 }
155 
156 /*
157  * Return output position
158  */
159 int
160 db_print_position(void)
161 {
162 	return (db_output_position);
163 }
164 
165 /*
166  * Printing
167  */
168 void
169 db_printf(const char *fmt, ...)
170 {
171 	__va_list listp;
172 
173 	__va_start(listp, fmt);
174 	kvcprintf (fmt, db_putchar, NULL, db_radix, listp);
175 	__va_end(listp);
176 }
177 
178 void
179 db_vprintf(const char *fmt, __va_list va)
180 {
181 	kvcprintf (fmt, db_putchar, NULL, db_radix, va);
182 }
183 
184 int db_indent;
185 
186 void
187 db_iprintf(const char *fmt,...)
188 {
189 	int i;
190 	__va_list listp;
191 
192 	for (i = db_indent; i >= 8; i -= 8)
193 		db_printf("\t");
194 	while (--i >= 0)
195 		db_printf(" ");
196 	__va_start(listp, fmt);
197 	kvcprintf (fmt, db_putchar, NULL, db_radix, listp);
198 	__va_end(listp);
199 }
200 
201 /*
202  * End line if too long.
203  */
204 void
205 db_end_line(void)
206 {
207 	if (db_output_position >= db_max_width)
208 	    db_printf("\n");
209 }
210 
211 /*
212  * Simple pager
213  */
214 int
215 db_more(int *nl)
216 {
217 	++*nl;
218 	if (*nl == 20) {
219 		int c;
220 
221 		db_printf("--More--");
222 		c = cngetc();
223 		db_printf("\r");
224 		/*
225 		 * A whole screenfull or just one line?
226 		 */
227 		switch (c) {
228 		case '\n':		/* just one line */
229 			*nl = 19;
230 			break;
231 		case ' ':
232 			*nl = 0;	/* another screenfull */
233 			break;
234 		default:		/* exit */
235 			db_printf("\n");
236 			return(-1);
237 		}
238 	}
239 	return(0);
240 }
241 
242