xref: /freebsd/sys/ddb/db_output.c (revision c7eeb59df08ca7dc4dd49425f93ffb66f9cd0351)
1dd3cb568SWarner Losh /*-
25b81b6b3SRodney W. Grimes  * Mach Operating System
35b81b6b3SRodney W. Grimes  * Copyright (c) 1991,1990 Carnegie Mellon University
45b81b6b3SRodney W. Grimes  * All Rights Reserved.
55b81b6b3SRodney W. Grimes  *
65b81b6b3SRodney W. Grimes  * Permission to use, copy, modify and distribute this software and its
75b81b6b3SRodney W. Grimes  * documentation is hereby granted, provided that both the copyright
85b81b6b3SRodney W. Grimes  * notice and this permission notice appear in all copies of the
95b81b6b3SRodney W. Grimes  * software, derivative works or modified versions, and any portions
105b81b6b3SRodney W. Grimes  * thereof, and that both notices appear in supporting documentation.
115b81b6b3SRodney W. Grimes  *
125b81b6b3SRodney W. Grimes  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
135b81b6b3SRodney W. Grimes  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
145b81b6b3SRodney W. Grimes  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
155b81b6b3SRodney W. Grimes  *
165b81b6b3SRodney W. Grimes  * Carnegie Mellon requests users of this software to return to
175b81b6b3SRodney W. Grimes  *
185b81b6b3SRodney W. Grimes  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
195b81b6b3SRodney W. Grimes  *  School of Computer Science
205b81b6b3SRodney W. Grimes  *  Carnegie Mellon University
215b81b6b3SRodney W. Grimes  *  Pittsburgh PA 15213-3890
225b81b6b3SRodney W. Grimes  *
235b81b6b3SRodney W. Grimes  * any improvements or extensions that they make and grant Carnegie the
245b81b6b3SRodney W. Grimes  * rights to redistribute these changes.
255b81b6b3SRodney W. Grimes  */
265b81b6b3SRodney W. Grimes /*
275b81b6b3SRodney W. Grimes  * 	Author: David B. Golub, Carnegie Mellon University
285b81b6b3SRodney W. Grimes  *	Date:	7/90
295b81b6b3SRodney W. Grimes  */
305b81b6b3SRodney W. Grimes 
315b81b6b3SRodney W. Grimes /*
325b81b6b3SRodney W. Grimes  * Printf and character output for debugger.
335b81b6b3SRodney W. Grimes  */
345b81b6b3SRodney W. Grimes 
35753960f7SDavid E. O'Brien #include <sys/cdefs.h>
36753960f7SDavid E. O'Brien __FBSDID("$FreeBSD$");
37753960f7SDavid E. O'Brien 
38f540b106SGarrett Wollman #include <sys/param.h>
39f540b106SGarrett Wollman #include <sys/systm.h>
40ce9edcf5SPoul-Henning Kamp #include <sys/cons.h>
4137224cd3SMarcel Moolenaar #include <sys/kdb.h>
425de6c5b5SNate Lawson #include <sys/kernel.h>
435de6c5b5SNate Lawson #include <sys/sysctl.h>
445ccbc3ccSBruce Evans 
45f540b106SGarrett Wollman #include <machine/stdarg.h>
465ccbc3ccSBruce Evans 
47f540b106SGarrett Wollman #include <ddb/ddb.h>
48058284fcSBruce Evans #include <ddb/db_output.h>
495b81b6b3SRodney W. Grimes 
505b81b6b3SRodney W. Grimes /*
515b81b6b3SRodney W. Grimes  *	Character output - tracks position in line.
525b81b6b3SRodney W. Grimes  *	To do this correctly, we should know how wide
535b81b6b3SRodney W. Grimes  *	the output device is - then we could zero
545b81b6b3SRodney W. Grimes  *	the line position when the output device wraps
555b81b6b3SRodney W. Grimes  *	around to the start of the next line.
565b81b6b3SRodney W. Grimes  *
575b81b6b3SRodney W. Grimes  *	Instead, we count the number of spaces printed
585b81b6b3SRodney W. Grimes  *	since the last printing character so that we
595b81b6b3SRodney W. Grimes  *	don't print trailing spaces.  This avoids most
605b81b6b3SRodney W. Grimes  *	of the wraparounds.
615b81b6b3SRodney W. Grimes  */
62f73a856dSPoul-Henning Kamp static int	db_output_position = 0;		/* output column */
63f73a856dSPoul-Henning Kamp static int	db_last_non_space = 0;		/* last non-space character */
643da6ef3cSBruce Evans db_expr_t	db_tab_stop_width = 8;		/* how wide are tab stops? */
655b81b6b3SRodney W. Grimes #define	NEXT_TAB(i) \
665b81b6b3SRodney W. Grimes 	((((i) + db_tab_stop_width) / db_tab_stop_width) * db_tab_stop_width)
673da6ef3cSBruce Evans db_expr_t	db_max_width = 79;		/* output line width */
68d39d4a6eSJohn Baldwin db_expr_t	db_lines_per_page = 20;		/* lines per page */
6919e9205aSJohn Baldwin volatile int	db_pager_quit;			/* user requested quit */
701e16f609SJohn Baldwin static int	db_newlines;			/* # lines this page */
7119e9205aSJohn Baldwin static int	db_maxlines;			/* max lines/page when paging */
725de6c5b5SNate Lawson static int	ddb_use_printf = 0;
735de6c5b5SNate Lawson SYSCTL_INT(_debug, OID_AUTO, ddb_use_printf, CTLFLAG_RW, &ddb_use_printf, 0,
745de6c5b5SNate Lawson     "use printf for all ddb output");
755b81b6b3SRodney W. Grimes 
7614e10f99SAlfred Perlstein static void	db_putchar(int c, void *arg);
7719e9205aSJohn Baldwin static void	db_pager(void);
786ddbf1e2SGary Palmer 
795b81b6b3SRodney W. Grimes /*
805b81b6b3SRodney W. Grimes  * Force pending whitespace.
815b81b6b3SRodney W. Grimes  */
825b81b6b3SRodney W. Grimes void
835b81b6b3SRodney W. Grimes db_force_whitespace()
845b81b6b3SRodney W. Grimes {
855b81b6b3SRodney W. Grimes 	register int last_print, next_tab;
865b81b6b3SRodney W. Grimes 
875b81b6b3SRodney W. Grimes 	last_print = db_last_non_space;
885b81b6b3SRodney W. Grimes 	while (last_print < db_output_position) {
895b81b6b3SRodney W. Grimes 	    next_tab = NEXT_TAB(last_print);
905b81b6b3SRodney W. Grimes 	    if (next_tab <= db_output_position) {
915b81b6b3SRodney W. Grimes 		while (last_print < next_tab) { /* DON'T send a tab!!! */
925b81b6b3SRodney W. Grimes 			cnputc(' ');
935b81b6b3SRodney W. Grimes 			last_print++;
945b81b6b3SRodney W. Grimes 		}
955b81b6b3SRodney W. Grimes 	    }
965b81b6b3SRodney W. Grimes 	    else {
975b81b6b3SRodney W. Grimes 		cnputc(' ');
985b81b6b3SRodney W. Grimes 		last_print++;
995b81b6b3SRodney W. Grimes 	    }
1005b81b6b3SRodney W. Grimes 	}
1015b81b6b3SRodney W. Grimes 	db_last_non_space = db_output_position;
1025b81b6b3SRodney W. Grimes }
1035b81b6b3SRodney W. Grimes 
1045b81b6b3SRodney W. Grimes /*
1055b81b6b3SRodney W. Grimes  * Output character.  Buffer whitespace.
1065b81b6b3SRodney W. Grimes  */
1076ddbf1e2SGary Palmer static void
1086ddbf1e2SGary Palmer db_putchar(c, arg)
1095b81b6b3SRodney W. Grimes 	int	c;		/* character to output */
1106ddbf1e2SGary Palmer 	void *	arg;
1115b81b6b3SRodney W. Grimes {
1121e16f609SJohn Baldwin 
1135de6c5b5SNate Lawson 	/*
1145de6c5b5SNate Lawson 	 * If not in the debugger or the user requests it, output data to
1155de6c5b5SNate Lawson 	 * both the console and the message buffer.
1165de6c5b5SNate Lawson 	 */
11737224cd3SMarcel Moolenaar 	if (!kdb_active || ddb_use_printf) {
1185de6c5b5SNate Lawson 		printf("%c", c);
11937224cd3SMarcel Moolenaar 		if (!kdb_active)
1205de6c5b5SNate Lawson 			return;
1215de6c5b5SNate Lawson 		if (c == '\r' || c == '\n')
1225de6c5b5SNate Lawson 			db_check_interrupt();
12319e9205aSJohn Baldwin 		if (c == '\n' && db_maxlines > 0) {
1245de6c5b5SNate Lawson 			db_newlines++;
12519e9205aSJohn Baldwin 			if (db_newlines >= db_maxlines)
12619e9205aSJohn Baldwin 				db_pager();
1275de6c5b5SNate Lawson 		}
1285de6c5b5SNate Lawson 		return;
1295de6c5b5SNate Lawson 	}
1305de6c5b5SNate Lawson 
1315de6c5b5SNate Lawson 	/* Otherwise, output data directly to the console. */
1325b81b6b3SRodney W. Grimes 	if (c > ' ' && c <= '~') {
1335b81b6b3SRodney W. Grimes 	    /*
1345b81b6b3SRodney W. Grimes 	     * Printing character.
1355b81b6b3SRodney W. Grimes 	     * If we have spaces to print, print them first.
1365b81b6b3SRodney W. Grimes 	     * Use tabs if possible.
1375b81b6b3SRodney W. Grimes 	     */
1385b81b6b3SRodney W. Grimes 	    db_force_whitespace();
1395b81b6b3SRodney W. Grimes 	    cnputc(c);
1405b81b6b3SRodney W. Grimes 	    db_output_position++;
1415b81b6b3SRodney W. Grimes 	    db_last_non_space = db_output_position;
1425b81b6b3SRodney W. Grimes 	}
1435b81b6b3SRodney W. Grimes 	else if (c == '\n') {
1448a129caeSDavid Greenman 	    /* Newline */
1458a129caeSDavid Greenman 	    cnputc(c);
1468a129caeSDavid Greenman 	    db_output_position = 0;
1478a129caeSDavid Greenman 	    db_last_non_space = 0;
1488a129caeSDavid Greenman 	    db_check_interrupt();
14919e9205aSJohn Baldwin 	    if (db_maxlines > 0) {
1501e16f609SJohn Baldwin 		    db_newlines++;
15119e9205aSJohn Baldwin 		    if (db_newlines >= db_maxlines)
15219e9205aSJohn Baldwin 			    db_pager();
1531e16f609SJohn Baldwin 	    }
1548a129caeSDavid Greenman 	}
1558a129caeSDavid Greenman 	else if (c == '\r') {
1565b81b6b3SRodney W. Grimes 	    /* Return */
1575b81b6b3SRodney W. Grimes 	    cnputc(c);
1585b81b6b3SRodney W. Grimes 	    db_output_position = 0;
1595b81b6b3SRodney W. Grimes 	    db_last_non_space = 0;
1605b81b6b3SRodney W. Grimes 	    db_check_interrupt();
1615b81b6b3SRodney W. Grimes 	}
1625b81b6b3SRodney W. Grimes 	else if (c == '\t') {
1635b81b6b3SRodney W. Grimes 	    /* assume tabs every 8 positions */
1645b81b6b3SRodney W. Grimes 	    db_output_position = NEXT_TAB(db_output_position);
1655b81b6b3SRodney W. Grimes 	}
1665b81b6b3SRodney W. Grimes 	else if (c == ' ') {
1675b81b6b3SRodney W. Grimes 	    /* space */
1685b81b6b3SRodney W. Grimes 	    db_output_position++;
1695b81b6b3SRodney W. Grimes 	}
1705b81b6b3SRodney W. Grimes 	else if (c == '\007') {
1715b81b6b3SRodney W. Grimes 	    /* bell */
1725b81b6b3SRodney W. Grimes 	    cnputc(c);
1735b81b6b3SRodney W. Grimes 	}
1745b81b6b3SRodney W. Grimes 	/* other characters are assumed non-printing */
1755b81b6b3SRodney W. Grimes }
1765b81b6b3SRodney W. Grimes 
1775b81b6b3SRodney W. Grimes /*
17819e9205aSJohn Baldwin  * Turn on the pager.
1791e16f609SJohn Baldwin  */
1801e16f609SJohn Baldwin void
18119e9205aSJohn Baldwin db_enable_pager(void)
1821e16f609SJohn Baldwin {
18319e9205aSJohn Baldwin 	if (db_maxlines == 0) {
18419e9205aSJohn Baldwin 		db_maxlines = db_lines_per_page;
1851e16f609SJohn Baldwin 		db_newlines = 0;
18619e9205aSJohn Baldwin 		db_pager_quit = 0;
1871e16f609SJohn Baldwin 	}
188da927f93SOlivier Houchard }
1891e16f609SJohn Baldwin 
1901e16f609SJohn Baldwin /*
19119e9205aSJohn Baldwin  * Turn off the pager.
1921e16f609SJohn Baldwin  */
1931e16f609SJohn Baldwin void
19419e9205aSJohn Baldwin db_disable_pager(void)
19519e9205aSJohn Baldwin {
19619e9205aSJohn Baldwin 	db_maxlines = 0;
19719e9205aSJohn Baldwin }
19819e9205aSJohn Baldwin 
19919e9205aSJohn Baldwin /*
20019e9205aSJohn Baldwin  * A simple paging callout function.  It supports several simple more(1)-like
20119e9205aSJohn Baldwin  * commands as well as a quit command that sets db_pager_quit which db
20219e9205aSJohn Baldwin  * commands can poll to see if they should terminate early.
20319e9205aSJohn Baldwin  */
20419e9205aSJohn Baldwin void
20519e9205aSJohn Baldwin db_pager(void)
2061e16f609SJohn Baldwin {
207d39d4a6eSJohn Baldwin 	int c, done;
2081e16f609SJohn Baldwin 
2091e16f609SJohn Baldwin 	db_printf("--More--\r");
210d39d4a6eSJohn Baldwin 	done = 0;
211d39d4a6eSJohn Baldwin 	while (!done) {
2121e16f609SJohn Baldwin 		c = cngetc();
2131e16f609SJohn Baldwin 		switch (c) {
214d39d4a6eSJohn Baldwin 		case 'e':
215d39d4a6eSJohn Baldwin 		case 'j':
2161e16f609SJohn Baldwin 		case '\n':
2171e16f609SJohn Baldwin 			/* Just one more line. */
21819e9205aSJohn Baldwin 			db_maxlines = 1;
219d39d4a6eSJohn Baldwin 			done++;
220d39d4a6eSJohn Baldwin 			break;
221d39d4a6eSJohn Baldwin 		case 'd':
222d39d4a6eSJohn Baldwin 			/* Half a page. */
22319e9205aSJohn Baldwin 			db_maxlines = db_lines_per_page / 2;
224d39d4a6eSJohn Baldwin 			done++;
225d39d4a6eSJohn Baldwin 			break;
226d39d4a6eSJohn Baldwin 		case 'f':
2271e16f609SJohn Baldwin 		case ' ':
2281e16f609SJohn Baldwin 			/* Another page. */
22919e9205aSJohn Baldwin 			db_maxlines = db_lines_per_page;
230d39d4a6eSJohn Baldwin 			done++;
231d39d4a6eSJohn Baldwin 			break;
2321e16f609SJohn Baldwin 		case 'q':
2331e16f609SJohn Baldwin 		case 'Q':
2341e16f609SJohn Baldwin 		case 'x':
2351e16f609SJohn Baldwin 		case 'X':
2361e16f609SJohn Baldwin 			/* Quit */
23719e9205aSJohn Baldwin 			db_maxlines = 0;
23819e9205aSJohn Baldwin 			db_pager_quit = 1;
239d39d4a6eSJohn Baldwin 			done++;
240d39d4a6eSJohn Baldwin 			break;
2411e16f609SJohn Baldwin #if 0
2421e16f609SJohn Baldwin 			/* FALLTHROUGH */
2431e16f609SJohn Baldwin 		default:
2441e16f609SJohn Baldwin 			cnputc('\007');
2451e16f609SJohn Baldwin #endif
2461e16f609SJohn Baldwin 		}
2471e16f609SJohn Baldwin 	}
248c7eeb59dSBruce Evans 	db_printf("        ");
249c7eeb59dSBruce Evans 	db_force_whitespace();
250d39d4a6eSJohn Baldwin 	db_printf("\r");
25119e9205aSJohn Baldwin 	db_newlines = 0;
2521e16f609SJohn Baldwin }
2531e16f609SJohn Baldwin 
2541e16f609SJohn Baldwin /*
2555b81b6b3SRodney W. Grimes  * Return output position
2565b81b6b3SRodney W. Grimes  */
2575b81b6b3SRodney W. Grimes int
2585b81b6b3SRodney W. Grimes db_print_position()
2595b81b6b3SRodney W. Grimes {
2605b81b6b3SRodney W. Grimes 	return (db_output_position);
2615b81b6b3SRodney W. Grimes }
2625b81b6b3SRodney W. Grimes 
2635b81b6b3SRodney W. Grimes /*
2645b81b6b3SRodney W. Grimes  * Printing
2655b81b6b3SRodney W. Grimes  */
266381fe1aaSGarrett Wollman void
267b9478d12SBruce Evans #if __STDC__
268381fe1aaSGarrett Wollman db_printf(const char *fmt, ...)
269b9478d12SBruce Evans #else
270b9478d12SBruce Evans db_printf(fmt)
271b9478d12SBruce Evans 	const char *fmt;
272b9478d12SBruce Evans #endif
2735b81b6b3SRodney W. Grimes {
2745b81b6b3SRodney W. Grimes 	va_list	listp;
275c7c34a24SBruce Evans 
276c7c34a24SBruce Evans 	va_start(listp, fmt);
277c7c34a24SBruce Evans 	kvprintf (fmt, db_putchar, NULL, db_radix, listp);
278c7c34a24SBruce Evans 	va_end(listp);
279c7c34a24SBruce Evans }
280c7c34a24SBruce Evans 
281c7c34a24SBruce Evans int db_indent;
282c7c34a24SBruce Evans 
283c7c34a24SBruce Evans void
284b9478d12SBruce Evans #if __STDC__
285c7c34a24SBruce Evans db_iprintf(const char *fmt,...)
286b9478d12SBruce Evans #else
287b9478d12SBruce Evans db_iprintf(fmt)
288b9478d12SBruce Evans 	const char *fmt;
289b9478d12SBruce Evans #endif
290c7c34a24SBruce Evans {
291c7c34a24SBruce Evans 	register int i;
292c7c34a24SBruce Evans 	va_list listp;
293c7c34a24SBruce Evans 
294c7c34a24SBruce Evans 	for (i = db_indent; i >= 8; i -= 8)
295c7c34a24SBruce Evans 		db_printf("\t");
296c7c34a24SBruce Evans 	while (--i >= 0)
297c7c34a24SBruce Evans 		db_printf(" ");
2985b81b6b3SRodney W. Grimes 	va_start(listp, fmt);
299791d77e0SPoul-Henning Kamp 	kvprintf (fmt, db_putchar, NULL, db_radix, listp);
3005b81b6b3SRodney W. Grimes 	va_end(listp);
3015b81b6b3SRodney W. Grimes }
3025b81b6b3SRodney W. Grimes 
3035b81b6b3SRodney W. Grimes /*
304572de915SRodney W. Grimes  * End line if too long.
305572de915SRodney W. Grimes  */
306572de915SRodney W. Grimes void
3072481da74SBruce Evans db_end_line(int field_width)
308572de915SRodney W. Grimes {
3092481da74SBruce Evans 	if (db_output_position + field_width > db_max_width)
310572de915SRodney W. Grimes 	    db_printf("\n");
311572de915SRodney W. Grimes }
312