15b81b6b3SRodney W. Grimes /* 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> 415de6c5b5SNate Lawson #include <sys/kernel.h> 425de6c5b5SNate Lawson #include <sys/sysctl.h> 435ccbc3ccSBruce Evans 44f540b106SGarrett Wollman #include <machine/stdarg.h> 455ccbc3ccSBruce Evans 46f540b106SGarrett Wollman #include <ddb/ddb.h> 47058284fcSBruce Evans #include <ddb/db_output.h> 485b81b6b3SRodney W. Grimes 495b81b6b3SRodney W. Grimes /* 505b81b6b3SRodney W. Grimes * Character output - tracks position in line. 515b81b6b3SRodney W. Grimes * To do this correctly, we should know how wide 525b81b6b3SRodney W. Grimes * the output device is - then we could zero 535b81b6b3SRodney W. Grimes * the line position when the output device wraps 545b81b6b3SRodney W. Grimes * around to the start of the next line. 555b81b6b3SRodney W. Grimes * 565b81b6b3SRodney W. Grimes * Instead, we count the number of spaces printed 575b81b6b3SRodney W. Grimes * since the last printing character so that we 585b81b6b3SRodney W. Grimes * don't print trailing spaces. This avoids most 595b81b6b3SRodney W. Grimes * of the wraparounds. 605b81b6b3SRodney W. Grimes */ 61f73a856dSPoul-Henning Kamp static int db_output_position = 0; /* output column */ 62f73a856dSPoul-Henning Kamp static int db_last_non_space = 0; /* last non-space character */ 633da6ef3cSBruce Evans db_expr_t db_tab_stop_width = 8; /* how wide are tab stops? */ 645b81b6b3SRodney W. Grimes #define NEXT_TAB(i) \ 655b81b6b3SRodney W. Grimes ((((i) + db_tab_stop_width) / db_tab_stop_width) * db_tab_stop_width) 663da6ef3cSBruce Evans db_expr_t db_max_width = 79; /* output line width */ 671e16f609SJohn Baldwin static int db_newlines; /* # lines this page */ 681e16f609SJohn Baldwin static int db_maxlines = -1; /* max lines per page */ 691e16f609SJohn Baldwin static db_page_calloutfcn_t *db_page_callout = NULL; 701e16f609SJohn Baldwin static void *db_page_callout_arg = NULL; 715de6c5b5SNate Lawson static int ddb_use_printf = 0; 725de6c5b5SNate Lawson SYSCTL_INT(_debug, OID_AUTO, ddb_use_printf, CTLFLAG_RW, &ddb_use_printf, 0, 735de6c5b5SNate Lawson "use printf for all ddb output"); 745b81b6b3SRodney W. Grimes 7514e10f99SAlfred Perlstein static void db_putchar(int c, void *arg); 766ddbf1e2SGary Palmer 775b81b6b3SRodney W. Grimes /* 785b81b6b3SRodney W. Grimes * Force pending whitespace. 795b81b6b3SRodney W. Grimes */ 805b81b6b3SRodney W. Grimes void 815b81b6b3SRodney W. Grimes db_force_whitespace() 825b81b6b3SRodney W. Grimes { 835b81b6b3SRodney W. Grimes register int last_print, next_tab; 845b81b6b3SRodney W. Grimes 855b81b6b3SRodney W. Grimes last_print = db_last_non_space; 865b81b6b3SRodney W. Grimes while (last_print < db_output_position) { 875b81b6b3SRodney W. Grimes next_tab = NEXT_TAB(last_print); 885b81b6b3SRodney W. Grimes if (next_tab <= db_output_position) { 895b81b6b3SRodney W. Grimes while (last_print < next_tab) { /* DON'T send a tab!!! */ 905b81b6b3SRodney W. Grimes cnputc(' '); 915b81b6b3SRodney W. Grimes last_print++; 925b81b6b3SRodney W. Grimes } 935b81b6b3SRodney W. Grimes } 945b81b6b3SRodney W. Grimes else { 955b81b6b3SRodney W. Grimes cnputc(' '); 965b81b6b3SRodney W. Grimes last_print++; 975b81b6b3SRodney W. Grimes } 985b81b6b3SRodney W. Grimes } 995b81b6b3SRodney W. Grimes db_last_non_space = db_output_position; 1005b81b6b3SRodney W. Grimes } 1015b81b6b3SRodney W. Grimes 1025b81b6b3SRodney W. Grimes /* 1035b81b6b3SRodney W. Grimes * Output character. Buffer whitespace. 1045b81b6b3SRodney W. Grimes */ 1056ddbf1e2SGary Palmer static void 1066ddbf1e2SGary Palmer db_putchar(c, arg) 1075b81b6b3SRodney W. Grimes int c; /* character to output */ 1086ddbf1e2SGary Palmer void * arg; 1095b81b6b3SRodney W. Grimes { 1101e16f609SJohn Baldwin 1115de6c5b5SNate Lawson /* 1125de6c5b5SNate Lawson * If not in the debugger or the user requests it, output data to 1135de6c5b5SNate Lawson * both the console and the message buffer. 1145de6c5b5SNate Lawson */ 1155de6c5b5SNate Lawson if (!db_active || ddb_use_printf) { 1165de6c5b5SNate Lawson printf("%c", c); 1175de6c5b5SNate Lawson if (!db_active) 1185de6c5b5SNate Lawson return; 1195de6c5b5SNate Lawson if (c == '\r' || c == '\n') 1205de6c5b5SNate Lawson db_check_interrupt(); 1215de6c5b5SNate Lawson if (c == '\n' && db_maxlines > 0 && db_page_callout != NULL) { 1225de6c5b5SNate Lawson db_newlines++; 1235de6c5b5SNate Lawson if (db_newlines >= db_maxlines) { 1245de6c5b5SNate Lawson db_maxlines = -1; 1255de6c5b5SNate Lawson db_page_callout(db_page_callout_arg); 1265de6c5b5SNate Lawson } 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(); 1491e16f609SJohn Baldwin if (db_maxlines > 0 && db_page_callout != NULL) { 1501e16f609SJohn Baldwin db_newlines++; 1511e16f609SJohn Baldwin if (db_newlines >= db_maxlines) { 1521e16f609SJohn Baldwin db_maxlines = -1; 1531e16f609SJohn Baldwin db_page_callout(db_page_callout_arg); 1541e16f609SJohn Baldwin } 1551e16f609SJohn Baldwin } 1568a129caeSDavid Greenman } 1578a129caeSDavid Greenman else if (c == '\r') { 1585b81b6b3SRodney W. Grimes /* Return */ 1595b81b6b3SRodney W. Grimes cnputc(c); 1605b81b6b3SRodney W. Grimes db_output_position = 0; 1615b81b6b3SRodney W. Grimes db_last_non_space = 0; 1625b81b6b3SRodney W. Grimes db_check_interrupt(); 1635b81b6b3SRodney W. Grimes } 1645b81b6b3SRodney W. Grimes else if (c == '\t') { 1655b81b6b3SRodney W. Grimes /* assume tabs every 8 positions */ 1665b81b6b3SRodney W. Grimes db_output_position = NEXT_TAB(db_output_position); 1675b81b6b3SRodney W. Grimes } 1685b81b6b3SRodney W. Grimes else if (c == ' ') { 1695b81b6b3SRodney W. Grimes /* space */ 1705b81b6b3SRodney W. Grimes db_output_position++; 1715b81b6b3SRodney W. Grimes } 1725b81b6b3SRodney W. Grimes else if (c == '\007') { 1735b81b6b3SRodney W. Grimes /* bell */ 1745b81b6b3SRodney W. Grimes cnputc(c); 1755b81b6b3SRodney W. Grimes } 1765b81b6b3SRodney W. Grimes /* other characters are assumed non-printing */ 1775b81b6b3SRodney W. Grimes } 1785b81b6b3SRodney W. Grimes 1795b81b6b3SRodney W. Grimes /* 1801e16f609SJohn Baldwin * Register callout for providing a pager for output. 1811e16f609SJohn Baldwin */ 1821e16f609SJohn Baldwin void 1831e16f609SJohn Baldwin db_setup_paging(db_page_calloutfcn_t *callout, void *arg, int maxlines) 1841e16f609SJohn Baldwin { 1851e16f609SJohn Baldwin 1861e16f609SJohn Baldwin db_page_callout = callout; 1871e16f609SJohn Baldwin db_page_callout_arg = arg; 1881e16f609SJohn Baldwin db_maxlines = maxlines; 1891e16f609SJohn Baldwin db_newlines = 0; 1901e16f609SJohn Baldwin } 1911e16f609SJohn Baldwin 1921e16f609SJohn Baldwin /* 1931e16f609SJohn Baldwin * A simple paging callout function. If the argument is not null, it 1941e16f609SJohn Baldwin * points to an integer that will be set to 1 if the user asks to quit. 1951e16f609SJohn Baldwin */ 1961e16f609SJohn Baldwin void 1971e16f609SJohn Baldwin db_simple_pager(void *arg) 1981e16f609SJohn Baldwin { 1991e16f609SJohn Baldwin int c; 2001e16f609SJohn Baldwin 2011e16f609SJohn Baldwin db_printf("--More--\r"); 2021e16f609SJohn Baldwin for (;;) { 2031e16f609SJohn Baldwin c = cngetc(); 2041e16f609SJohn Baldwin switch (c) { 2051e16f609SJohn Baldwin case '\n': 2061e16f609SJohn Baldwin /* Just one more line. */ 2071e16f609SJohn Baldwin db_setup_paging(db_simple_pager, arg, 1); 2081e16f609SJohn Baldwin return; 2091e16f609SJohn Baldwin case ' ': 2101e16f609SJohn Baldwin /* Another page. */ 2111e16f609SJohn Baldwin db_setup_paging(db_simple_pager, arg, 2121e16f609SJohn Baldwin DB_LINES_PER_PAGE); 2131e16f609SJohn Baldwin return; 2141e16f609SJohn Baldwin case 'q': 2151e16f609SJohn Baldwin case 'Q': 2161e16f609SJohn Baldwin case 'x': 2171e16f609SJohn Baldwin case 'X': 2181e16f609SJohn Baldwin /* Quit */ 2191e16f609SJohn Baldwin if (arg != NULL) { 2201e16f609SJohn Baldwin *(int *)arg = 1; 2211e16f609SJohn Baldwin db_printf("\n"); 2221e16f609SJohn Baldwin return; 2231e16f609SJohn Baldwin } 2241e16f609SJohn Baldwin #if 0 2251e16f609SJohn Baldwin /* FALLTHROUGH */ 2261e16f609SJohn Baldwin default: 2271e16f609SJohn Baldwin cnputc('\007'); 2281e16f609SJohn Baldwin #endif 2291e16f609SJohn Baldwin } 2301e16f609SJohn Baldwin } 2311e16f609SJohn Baldwin } 2321e16f609SJohn Baldwin 2331e16f609SJohn Baldwin /* 2345b81b6b3SRodney W. Grimes * Return output position 2355b81b6b3SRodney W. Grimes */ 2365b81b6b3SRodney W. Grimes int 2375b81b6b3SRodney W. Grimes db_print_position() 2385b81b6b3SRodney W. Grimes { 2395b81b6b3SRodney W. Grimes return (db_output_position); 2405b81b6b3SRodney W. Grimes } 2415b81b6b3SRodney W. Grimes 2425b81b6b3SRodney W. Grimes /* 2435b81b6b3SRodney W. Grimes * Printing 2445b81b6b3SRodney W. Grimes */ 245381fe1aaSGarrett Wollman void 246b9478d12SBruce Evans #if __STDC__ 247381fe1aaSGarrett Wollman db_printf(const char *fmt, ...) 248b9478d12SBruce Evans #else 249b9478d12SBruce Evans db_printf(fmt) 250b9478d12SBruce Evans const char *fmt; 251b9478d12SBruce Evans #endif 2525b81b6b3SRodney W. Grimes { 2535b81b6b3SRodney W. Grimes va_list listp; 254c7c34a24SBruce Evans 255c7c34a24SBruce Evans va_start(listp, fmt); 256c7c34a24SBruce Evans kvprintf (fmt, db_putchar, NULL, db_radix, listp); 257c7c34a24SBruce Evans va_end(listp); 258c7c34a24SBruce Evans } 259c7c34a24SBruce Evans 260c7c34a24SBruce Evans int db_indent; 261c7c34a24SBruce Evans 262c7c34a24SBruce Evans void 263b9478d12SBruce Evans #if __STDC__ 264c7c34a24SBruce Evans db_iprintf(const char *fmt,...) 265b9478d12SBruce Evans #else 266b9478d12SBruce Evans db_iprintf(fmt) 267b9478d12SBruce Evans const char *fmt; 268b9478d12SBruce Evans #endif 269c7c34a24SBruce Evans { 270c7c34a24SBruce Evans register int i; 271c7c34a24SBruce Evans va_list listp; 272c7c34a24SBruce Evans 273c7c34a24SBruce Evans for (i = db_indent; i >= 8; i -= 8) 274c7c34a24SBruce Evans db_printf("\t"); 275c7c34a24SBruce Evans while (--i >= 0) 276c7c34a24SBruce Evans db_printf(" "); 2775b81b6b3SRodney W. Grimes va_start(listp, fmt); 278791d77e0SPoul-Henning Kamp kvprintf (fmt, db_putchar, NULL, db_radix, listp); 2795b81b6b3SRodney W. Grimes va_end(listp); 2805b81b6b3SRodney W. Grimes } 2815b81b6b3SRodney W. Grimes 2825b81b6b3SRodney W. Grimes /* 283572de915SRodney W. Grimes * End line if too long. 284572de915SRodney W. Grimes */ 285572de915SRodney W. Grimes void 286572de915SRodney W. Grimes db_end_line() 287572de915SRodney W. Grimes { 288572de915SRodney W. Grimes if (db_output_position >= db_max_width) 289572de915SRodney W. Grimes db_printf("\n"); 290572de915SRodney W. Grimes } 291