xref: /dragonfly/sys/ddb/db_output.c (revision 6b5c5d0d)
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.8 2006/12/18 20:41:01 dillon 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 	if (c > ' ' && c <= '~') {
104 	    /*
105 	     * Printing character.
106 	     * If we have spaces to print, print them first.
107 	     * Use tabs if possible.
108 	     */
109 	    db_force_whitespace();
110 	    cnputc(c);
111 	    db_output_position++;
112 	    db_last_non_space = db_output_position;
113 	}
114 	else if (c == '\n') {
115 	    /* Newline */
116 	    cnputc(c);
117 	    db_output_position = 0;
118 	    db_last_non_space = 0;
119 	    db_check_interrupt();
120 	}
121 	else if (c == '\r') {
122 	    /* Return */
123 	    cnputc(c);
124 	    db_output_position = 0;
125 	    db_last_non_space = 0;
126 	    db_check_interrupt();
127 	}
128 	else if (c == '\t') {
129 	    /* assume tabs every 8 positions */
130 	    db_output_position = NEXT_TAB(db_output_position);
131 	}
132 	else if (c == ' ') {
133 	    /* space */
134 	    db_output_position++;
135 	}
136 	else if (c == '\007') {
137 	    /* bell */
138 	    cnputc(c);
139 	}
140 	/* other characters are assumed non-printing */
141 }
142 
143 /*
144  * Return output position
145  */
146 int
147 db_print_position(void)
148 {
149 	return (db_output_position);
150 }
151 
152 /*
153  * Printing
154  */
155 void
156 db_printf(const char *fmt, ...)
157 {
158 	__va_list listp;
159 
160 	__va_start(listp, fmt);
161 	kvcprintf (fmt, db_putchar, NULL, db_radix, listp);
162 	__va_end(listp);
163 }
164 
165 int db_indent;
166 
167 void
168 db_iprintf(const char *fmt,...)
169 {
170 	int i;
171 	__va_list listp;
172 
173 	for (i = db_indent; i >= 8; i -= 8)
174 		db_printf("\t");
175 	while (--i >= 0)
176 		db_printf(" ");
177 	__va_start(listp, fmt);
178 	kvcprintf (fmt, db_putchar, NULL, db_radix, listp);
179 	__va_end(listp);
180 }
181 
182 /*
183  * End line if too long.
184  */
185 void
186 db_end_line(void)
187 {
188 	if (db_output_position >= db_max_width)
189 	    db_printf("\n");
190 }
191 
192 /*
193  * Simple pager
194  */
195 int
196 db_more(int *nl)
197 {
198 	++*nl;
199 	if (*nl == 20) {
200 		int c;
201 
202 		db_printf("--More--");
203 		c = cngetc();
204 		db_printf("\r");
205 		/*
206 		 * A whole screenfull or just one line?
207 		 */
208 		switch (c) {
209 		case '\n':		/* just one line */
210 			*nl = 19;
211 			break;
212 		case ' ':
213 			*nl = 0;	/* another screenfull */
214 			break;
215 		default:		/* exit */
216 			db_printf("\n");
217 			return(-1);
218 		}
219 	}
220 	return(0);
221 }
222 
223