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(' '); 93086fec57SRobert Watson db_capture_writech(' '); 945b81b6b3SRodney W. Grimes last_print++; 955b81b6b3SRodney W. Grimes } 965b81b6b3SRodney W. Grimes } 975b81b6b3SRodney W. Grimes else { 985b81b6b3SRodney W. Grimes cnputc(' '); 99086fec57SRobert Watson db_capture_writech(' '); 1005b81b6b3SRodney W. Grimes last_print++; 1015b81b6b3SRodney W. Grimes } 1025b81b6b3SRodney W. Grimes } 1035b81b6b3SRodney W. Grimes db_last_non_space = db_output_position; 1045b81b6b3SRodney W. Grimes } 1055b81b6b3SRodney W. Grimes 1065b81b6b3SRodney W. Grimes /* 1075b81b6b3SRodney W. Grimes * Output character. Buffer whitespace. 1085b81b6b3SRodney W. Grimes */ 1096ddbf1e2SGary Palmer static void 1106ddbf1e2SGary Palmer db_putchar(c, arg) 1115b81b6b3SRodney W. Grimes int c; /* character to output */ 1126ddbf1e2SGary Palmer void * arg; 1135b81b6b3SRodney W. Grimes { 1141e16f609SJohn Baldwin 1155de6c5b5SNate Lawson /* 1165de6c5b5SNate Lawson * If not in the debugger or the user requests it, output data to 1175de6c5b5SNate Lawson * both the console and the message buffer. 1185de6c5b5SNate Lawson */ 11937224cd3SMarcel Moolenaar if (!kdb_active || ddb_use_printf) { 1205de6c5b5SNate Lawson printf("%c", c); 12137224cd3SMarcel Moolenaar if (!kdb_active) 1225de6c5b5SNate Lawson return; 1235de6c5b5SNate Lawson if (c == '\r' || c == '\n') 1245de6c5b5SNate Lawson db_check_interrupt(); 12519e9205aSJohn Baldwin if (c == '\n' && db_maxlines > 0) { 1265de6c5b5SNate Lawson db_newlines++; 12719e9205aSJohn Baldwin if (db_newlines >= db_maxlines) 12819e9205aSJohn Baldwin db_pager(); 1295de6c5b5SNate Lawson } 1305de6c5b5SNate Lawson return; 1315de6c5b5SNate Lawson } 1325de6c5b5SNate Lawson 1335de6c5b5SNate Lawson /* Otherwise, output data directly to the console. */ 1345b81b6b3SRodney W. Grimes if (c > ' ' && c <= '~') { 1355b81b6b3SRodney W. Grimes /* 1365b81b6b3SRodney W. Grimes * Printing character. 1375b81b6b3SRodney W. Grimes * If we have spaces to print, print them first. 1385b81b6b3SRodney W. Grimes * Use tabs if possible. 1395b81b6b3SRodney W. Grimes */ 1405b81b6b3SRodney W. Grimes db_force_whitespace(); 1415b81b6b3SRodney W. Grimes cnputc(c); 142086fec57SRobert Watson db_capture_writech(c); 1435b81b6b3SRodney W. Grimes db_output_position++; 1445b81b6b3SRodney W. Grimes db_last_non_space = db_output_position; 1455b81b6b3SRodney W. Grimes } 1465b81b6b3SRodney W. Grimes else if (c == '\n') { 1478a129caeSDavid Greenman /* Newline */ 1488a129caeSDavid Greenman cnputc(c); 149086fec57SRobert Watson db_capture_writech(c); 1508a129caeSDavid Greenman db_output_position = 0; 1518a129caeSDavid Greenman db_last_non_space = 0; 1528a129caeSDavid Greenman db_check_interrupt(); 15319e9205aSJohn Baldwin if (db_maxlines > 0) { 1541e16f609SJohn Baldwin db_newlines++; 15519e9205aSJohn Baldwin if (db_newlines >= db_maxlines) 15619e9205aSJohn Baldwin db_pager(); 1571e16f609SJohn Baldwin } 1588a129caeSDavid Greenman } 1598a129caeSDavid Greenman else if (c == '\r') { 1605b81b6b3SRodney W. Grimes /* Return */ 1615b81b6b3SRodney W. Grimes cnputc(c); 162086fec57SRobert Watson db_capture_writech(c); 1635b81b6b3SRodney W. Grimes db_output_position = 0; 1645b81b6b3SRodney W. Grimes db_last_non_space = 0; 1655b81b6b3SRodney W. Grimes db_check_interrupt(); 1665b81b6b3SRodney W. Grimes } 1675b81b6b3SRodney W. Grimes else if (c == '\t') { 1685b81b6b3SRodney W. Grimes /* assume tabs every 8 positions */ 1695b81b6b3SRodney W. Grimes db_output_position = NEXT_TAB(db_output_position); 1705b81b6b3SRodney W. Grimes } 1715b81b6b3SRodney W. Grimes else if (c == ' ') { 1725b81b6b3SRodney W. Grimes /* space */ 1735b81b6b3SRodney W. Grimes db_output_position++; 1745b81b6b3SRodney W. Grimes } 1755b81b6b3SRodney W. Grimes else if (c == '\007') { 1765b81b6b3SRodney W. Grimes /* bell */ 1775b81b6b3SRodney W. Grimes cnputc(c); 178086fec57SRobert Watson /* No need to beep in a log: db_capture_writech(c); */ 1795b81b6b3SRodney W. Grimes } 1805b81b6b3SRodney W. Grimes /* other characters are assumed non-printing */ 1815b81b6b3SRodney W. Grimes } 1825b81b6b3SRodney W. Grimes 1835b81b6b3SRodney W. Grimes /* 18419e9205aSJohn Baldwin * Turn on the pager. 1851e16f609SJohn Baldwin */ 1861e16f609SJohn Baldwin void 18719e9205aSJohn Baldwin db_enable_pager(void) 1881e16f609SJohn Baldwin { 18919e9205aSJohn Baldwin if (db_maxlines == 0) { 19019e9205aSJohn Baldwin db_maxlines = db_lines_per_page; 1911e16f609SJohn Baldwin db_newlines = 0; 19219e9205aSJohn Baldwin db_pager_quit = 0; 1931e16f609SJohn Baldwin } 194da927f93SOlivier Houchard } 1951e16f609SJohn Baldwin 1961e16f609SJohn Baldwin /* 19719e9205aSJohn Baldwin * Turn off the pager. 1981e16f609SJohn Baldwin */ 1991e16f609SJohn Baldwin void 20019e9205aSJohn Baldwin db_disable_pager(void) 20119e9205aSJohn Baldwin { 20219e9205aSJohn Baldwin db_maxlines = 0; 20319e9205aSJohn Baldwin } 20419e9205aSJohn Baldwin 20519e9205aSJohn Baldwin /* 20619e9205aSJohn Baldwin * A simple paging callout function. It supports several simple more(1)-like 20719e9205aSJohn Baldwin * commands as well as a quit command that sets db_pager_quit which db 20819e9205aSJohn Baldwin * commands can poll to see if they should terminate early. 20919e9205aSJohn Baldwin */ 21019e9205aSJohn Baldwin void 21119e9205aSJohn Baldwin db_pager(void) 2121e16f609SJohn Baldwin { 213d39d4a6eSJohn Baldwin int c, done; 2141e16f609SJohn Baldwin 215086fec57SRobert Watson db_capture_enterpager(); 2161e16f609SJohn Baldwin db_printf("--More--\r"); 217d39d4a6eSJohn Baldwin done = 0; 218d39d4a6eSJohn Baldwin while (!done) { 2191e16f609SJohn Baldwin c = cngetc(); 2201e16f609SJohn Baldwin switch (c) { 221d39d4a6eSJohn Baldwin case 'e': 222d39d4a6eSJohn Baldwin case 'j': 2231e16f609SJohn Baldwin case '\n': 2241e16f609SJohn Baldwin /* Just one more line. */ 22519e9205aSJohn Baldwin db_maxlines = 1; 226d39d4a6eSJohn Baldwin done++; 227d39d4a6eSJohn Baldwin break; 228d39d4a6eSJohn Baldwin case 'd': 229d39d4a6eSJohn Baldwin /* Half a page. */ 23019e9205aSJohn Baldwin db_maxlines = db_lines_per_page / 2; 231d39d4a6eSJohn Baldwin done++; 232d39d4a6eSJohn Baldwin break; 233d39d4a6eSJohn Baldwin case 'f': 2341e16f609SJohn Baldwin case ' ': 2351e16f609SJohn Baldwin /* Another page. */ 23619e9205aSJohn Baldwin db_maxlines = db_lines_per_page; 237d39d4a6eSJohn Baldwin done++; 238d39d4a6eSJohn Baldwin break; 2391e16f609SJohn Baldwin case 'q': 2401e16f609SJohn Baldwin case 'Q': 2411e16f609SJohn Baldwin case 'x': 2421e16f609SJohn Baldwin case 'X': 2431e16f609SJohn Baldwin /* Quit */ 24419e9205aSJohn Baldwin db_maxlines = 0; 24519e9205aSJohn Baldwin db_pager_quit = 1; 246d39d4a6eSJohn Baldwin done++; 247d39d4a6eSJohn Baldwin break; 2481e16f609SJohn Baldwin #if 0 2491e16f609SJohn Baldwin /* FALLTHROUGH */ 2501e16f609SJohn Baldwin default: 2511e16f609SJohn Baldwin cnputc('\007'); 2521e16f609SJohn Baldwin #endif 2531e16f609SJohn Baldwin } 2541e16f609SJohn Baldwin } 255c7eeb59dSBruce Evans db_printf(" "); 256c7eeb59dSBruce Evans db_force_whitespace(); 257d39d4a6eSJohn Baldwin db_printf("\r"); 25819e9205aSJohn Baldwin db_newlines = 0; 259086fec57SRobert Watson db_capture_exitpager(); 2601e16f609SJohn Baldwin } 2611e16f609SJohn Baldwin 2621e16f609SJohn Baldwin /* 2635b81b6b3SRodney W. Grimes * Return output position 2645b81b6b3SRodney W. Grimes */ 2655b81b6b3SRodney W. Grimes int 2665b81b6b3SRodney W. Grimes db_print_position() 2675b81b6b3SRodney W. Grimes { 2685b81b6b3SRodney W. Grimes return (db_output_position); 2695b81b6b3SRodney W. Grimes } 2705b81b6b3SRodney W. Grimes 2715b81b6b3SRodney W. Grimes /* 2725b81b6b3SRodney W. Grimes * Printing 2735b81b6b3SRodney W. Grimes */ 274381fe1aaSGarrett Wollman void 275b9478d12SBruce Evans #if __STDC__ 276381fe1aaSGarrett Wollman db_printf(const char *fmt, ...) 277b9478d12SBruce Evans #else 278b9478d12SBruce Evans db_printf(fmt) 279b9478d12SBruce Evans const char *fmt; 280b9478d12SBruce Evans #endif 2815b81b6b3SRodney W. Grimes { 2825b81b6b3SRodney W. Grimes va_list listp; 283c7c34a24SBruce Evans 284c7c34a24SBruce Evans va_start(listp, fmt); 285c7c34a24SBruce Evans kvprintf (fmt, db_putchar, NULL, db_radix, listp); 286c7c34a24SBruce Evans va_end(listp); 287c7c34a24SBruce Evans } 288c7c34a24SBruce Evans 289c7c34a24SBruce Evans int db_indent; 290c7c34a24SBruce Evans 291c7c34a24SBruce Evans void 292b9478d12SBruce Evans #if __STDC__ 293c7c34a24SBruce Evans db_iprintf(const char *fmt,...) 294b9478d12SBruce Evans #else 295b9478d12SBruce Evans db_iprintf(fmt) 296b9478d12SBruce Evans const char *fmt; 297b9478d12SBruce Evans #endif 298c7c34a24SBruce Evans { 299c7c34a24SBruce Evans register int i; 300c7c34a24SBruce Evans va_list listp; 301c7c34a24SBruce Evans 302c7c34a24SBruce Evans for (i = db_indent; i >= 8; i -= 8) 303c7c34a24SBruce Evans db_printf("\t"); 304c7c34a24SBruce Evans while (--i >= 0) 305c7c34a24SBruce Evans db_printf(" "); 3065b81b6b3SRodney W. Grimes va_start(listp, fmt); 307791d77e0SPoul-Henning Kamp kvprintf (fmt, db_putchar, NULL, db_radix, listp); 3085b81b6b3SRodney W. Grimes va_end(listp); 3095b81b6b3SRodney W. Grimes } 3105b81b6b3SRodney W. Grimes 3115b81b6b3SRodney W. Grimes /* 312572de915SRodney W. Grimes * End line if too long. 313572de915SRodney W. Grimes */ 314572de915SRodney W. Grimes void 3152481da74SBruce Evans db_end_line(int field_width) 316572de915SRodney W. Grimes { 3172481da74SBruce Evans if (db_output_position + field_width > db_max_width) 318572de915SRodney W. Grimes db_printf("\n"); 319572de915SRodney W. Grimes } 320