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 #include <sys/thread2.h> 43 #include <sys/spinlock2.h> 44 45 #include <machine/stdarg.h> 46 47 #include <ddb/ddb.h> 48 #include <ddb/db_output.h> 49 50 /* 51 * Character output - tracks position in line. 52 * To do this correctly, we should know how wide 53 * the output device is - then we could zero 54 * the line position when the output device wraps 55 * around to the start of the next line. 56 * 57 * Instead, we count the number of spaces printed 58 * since the last printing character so that we 59 * don't print trailing spaces. This avoids most 60 * of the wraparounds. 61 */ 62 static int db_output_position = 0; /* output column */ 63 static int db_last_non_space = 0; /* last non-space character */ 64 db_expr_t db_tab_stop_width = 8; /* how wide are tab stops? */ 65 #define NEXT_TAB(i) \ 66 ((((i) + db_tab_stop_width) / db_tab_stop_width) * db_tab_stop_width) 67 db_expr_t db_max_width = 79; /* output line width */ 68 69 static void db_putchar (int c, void *arg); 70 71 /* 72 * Force pending whitespace. 73 */ 74 void 75 db_force_whitespace(void) 76 { 77 int last_print, next_tab; 78 79 last_print = db_last_non_space; 80 while (last_print < db_output_position) { 81 next_tab = NEXT_TAB(last_print); 82 if (next_tab <= db_output_position) { 83 while (last_print < next_tab) { /* DON'T send a tab!!! */ 84 cnputc(' '); 85 last_print++; 86 } 87 } 88 else { 89 cnputc(' '); 90 last_print++; 91 } 92 } 93 db_last_non_space = db_output_position; 94 } 95 96 /* 97 * Output character. Buffer whitespace. 98 * 99 * Parameters: 100 * arg: character to output 101 */ 102 static void 103 db_putchar(int c, void *arg) 104 { 105 /* 106 * If not in the debugger, output data to both the console and 107 * the message buffer. 108 */ 109 if (!db_active) { 110 kprintf("%c", c); 111 if (!db_active) 112 return; 113 if (c == '\r' || c == '\n') 114 db_check_interrupt(); 115 return; 116 } 117 118 crit_enter_hard(); 119 120 if (c > ' ' && c <= '~') { 121 /* 122 * Printing character. 123 * If we have spaces to print, print them first. 124 * Use tabs if possible. 125 */ 126 db_force_whitespace(); 127 cnputc(c); 128 db_output_position++; 129 db_last_non_space = db_output_position; 130 } 131 else if (c == '\n') { 132 /* Newline */ 133 cnputc(c); 134 db_output_position = 0; 135 db_last_non_space = 0; 136 db_check_interrupt(); 137 } 138 else if (c == '\r') { 139 /* Return */ 140 cnputc(c); 141 db_output_position = 0; 142 db_last_non_space = 0; 143 db_check_interrupt(); 144 } 145 else if (c == '\t') { 146 /* assume tabs every 8 positions */ 147 db_output_position = NEXT_TAB(db_output_position); 148 } 149 else if (c == ' ') { 150 /* space */ 151 db_output_position++; 152 } 153 else if (c == '\007') { 154 /* bell */ 155 cnputc(c); 156 } 157 /* other characters are assumed non-printing */ 158 crit_exit_hard(); 159 } 160 161 /* 162 * Return output position 163 */ 164 int 165 db_print_position(void) 166 { 167 return (db_output_position); 168 } 169 170 /* 171 * Printing 172 * 173 * NOTE: We bypass subr_prf's cons_spin here by using our own putchar 174 * function. 175 */ 176 void 177 db_printf(const char *fmt, ...) 178 { 179 __va_list listp; 180 181 __va_start(listp, fmt); 182 kvcprintf (fmt, db_putchar, NULL, db_radix, listp); 183 __va_end(listp); 184 /* DELAY(100000);*/ 185 } 186 187 void 188 db_vprintf(const char *fmt, __va_list va) 189 { 190 kvcprintf (fmt, db_putchar, NULL, db_radix, va); 191 /* DELAY(100000);*/ 192 } 193 194 int db_indent; 195 196 void 197 db_iprintf(const char *fmt,...) 198 { 199 int i; 200 __va_list listp; 201 202 for (i = db_indent; i >= 8; i -= 8) 203 db_printf("\t"); 204 while (--i >= 0) 205 db_printf(" "); 206 __va_start(listp, fmt); 207 kvcprintf (fmt, db_putchar, NULL, db_radix, listp); 208 __va_end(listp); 209 } 210 211 /* 212 * End line if too long. 213 */ 214 void 215 db_end_line(void) 216 { 217 if (db_output_position >= db_max_width) 218 db_printf("\n"); 219 } 220 221 /* 222 * Simple pager 223 */ 224 int 225 db_more(int *nl) 226 { 227 ++*nl; 228 if (*nl == 20) { 229 int c; 230 231 db_printf("--More--"); 232 c = cngetc(); 233 db_printf("\r"); 234 /* 235 * A whole screenfull or just one line? 236 */ 237 switch (c) { 238 case '\n': /* just one line */ 239 *nl = 19; 240 break; 241 case ' ': 242 *nl = 0; /* another screenfull */ 243 break; 244 default: /* exit */ 245 db_printf("\n"); 246 return(-1); 247 } 248 } 249 return(0); 250 } 251 252