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