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 * PATCHES MAGIC LEVEL PATCH THAT GOT US HERE 27 * -------------------- ----- ---------------------- 28 * CURRENT PATCH LEVEL: 4 00083 29 * -------------------- ----- ---------------------- 30 * 31 * 14 Mar 93 Chris G. Demetriou Fixed so that tab is not output, 32 * use spaces instead. 33 */ 34 /* 35 * db_output.c,v 1.3 1993/05/20 03:39:21 cgd Exp 36 * 37 * HISTORY 38 * db_output.c,v 39 * Revision 1.3 1993/05/20 03:39:21 cgd 40 * add explicit rcs id 41 * 42 * Revision 1.2 1993/03/21 18:08:08 cgd 43 * after 0.2.2 "stable" patches applied 44 * 45 * Revision 1.1.1.1 93/03/21 09:46:26 cgd 46 * initial import of 386bsd-0.1 sources 47 * 48 * Revision 1.1 1992/03/25 21:45:18 pace 49 * Initial revision 50 * 51 * Revision 2.3 91/02/05 17:06:45 mrt 52 * Changed to new Mach copyright 53 * [91/01/31 16:18:41 mrt] 54 * 55 * Revision 2.2 90/08/27 21:51:25 dbg 56 * Put extra features of db_doprnt in _doprnt. 57 * [90/08/20 dbg] 58 * Reduce lint. 59 * [90/08/07 dbg] 60 * Created. 61 * [90/07/25 dbg] 62 * 63 */ 64 /* 65 * Author: David B. Golub, Carnegie Mellon University 66 * Date: 7/90 67 */ 68 69 /* 70 * Printf and character output for debugger. 71 */ 72 73 #include "param.h" 74 #include <machine/stdarg.h> 75 76 /* 77 * Character output - tracks position in line. 78 * To do this correctly, we should know how wide 79 * the output device is - then we could zero 80 * the line position when the output device wraps 81 * around to the start of the next line. 82 * 83 * Instead, we count the number of spaces printed 84 * since the last printing character so that we 85 * don't print trailing spaces. This avoids most 86 * of the wraparounds. 87 */ 88 89 #ifndef DB_MAX_LINE 90 #define DB_MAX_LINE 24 /* maximum line */ 91 #define DB_MAX_WIDTH 80 /* maximum width */ 92 #endif DB_MAX_LINE 93 94 #define DB_MIN_MAX_WIDTH 20 /* minimum max width */ 95 #define DB_MIN_MAX_LINE 3 /* minimum max line */ 96 #define CTRL(c) ((c) & 0xff) 97 98 int db_output_position = 0; /* output column */ 99 int db_output_line = 0; /* output line number */ 100 int db_last_non_space = 0; /* last non-space character */ 101 int db_tab_stop_width = 8; /* how wide are tab stops? */ 102 #define NEXT_TAB(i) \ 103 ((((i) + db_tab_stop_width) / db_tab_stop_width) * db_tab_stop_width) 104 int db_max_line = DB_MAX_LINE; /* output max lines */ 105 int db_max_width = DB_MAX_WIDTH; /* output line width */ 106 107 extern void db_check_interrupt(); 108 109 /* 110 * Force pending whitespace. 111 */ 112 void 113 db_force_whitespace() 114 { 115 register int last_print, next_tab; 116 117 last_print = db_last_non_space; 118 while (last_print < db_output_position) { 119 next_tab = NEXT_TAB(last_print); 120 if (next_tab <= db_output_position) { 121 while (last_print < next_tab) { /* DON'T send a tab!!! */ 122 cnputc(' '); 123 last_print++; 124 } 125 } 126 else { 127 cnputc(' '); 128 last_print++; 129 } 130 } 131 db_last_non_space = db_output_position; 132 } 133 134 static void 135 db_more() 136 { 137 register char *p; 138 int quit_output = 0; 139 140 for (p = "--db_more--"; *p; p++) 141 cnputc(*p); 142 switch(cngetc()) { 143 case ' ': 144 db_output_line = 0; 145 break; 146 case 'q': 147 case CTRL('c'): 148 db_output_line = 0; 149 quit_output = 1; 150 break; 151 default: 152 db_output_line--; 153 break; 154 } 155 p = "\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b"; 156 while (*p) 157 cnputc(*p++); 158 if (quit_output) { 159 db_error(0); 160 /* NOTREACHED */ 161 } 162 } 163 164 /* 165 * Output character. Buffer whitespace. 166 */ 167 db_putchar(c) 168 int c; /* character to output */ 169 { 170 if (db_max_line >= DB_MIN_MAX_LINE && db_output_line >= db_max_line-1) 171 db_more(); 172 if (c > ' ' && c <= '~') { 173 /* 174 * Printing character. 175 * If we have spaces to print, print them first. 176 * Use tabs if possible. 177 */ 178 db_force_whitespace(); 179 cnputc(c); 180 db_output_position++; 181 if (db_max_width >= DB_MIN_MAX_WIDTH 182 && db_output_position >= db_max_width-1) { 183 /* auto new line */ 184 cnputc('\n'); 185 db_output_position = 0; 186 db_last_non_space = 0; 187 db_output_line++; 188 } 189 db_last_non_space = db_output_position; 190 } 191 else if (c == '\n') { 192 /* Return */ 193 cnputc(c); 194 db_output_position = 0; 195 db_last_non_space = 0; 196 db_output_line++; 197 db_check_interrupt(); 198 } 199 else if (c == '\t') { 200 /* assume tabs every 8 positions */ 201 db_output_position = NEXT_TAB(db_output_position); 202 } 203 else if (c == ' ') { 204 /* space */ 205 db_output_position++; 206 } 207 else if (c == '\007') { 208 /* bell */ 209 cnputc(c); 210 } 211 /* other characters are assumed non-printing */ 212 } 213 214 /* 215 * Return output position 216 */ 217 int 218 db_print_position() 219 { 220 return (db_output_position); 221 } 222 223 /* 224 * Printing 225 */ 226 extern int db_radix; 227 228 /*VARARGS1*/ 229 db_printf(char *fmt, ...) 230 { 231 va_list listp; 232 va_start(listp, fmt); 233 db_printf_guts (fmt, listp); 234 va_end(listp); 235 } 236 237 /* alternate name */ 238 239 /*VARARGS1*/ 240 kdbprintf(char *fmt, ...) 241 { 242 va_list listp; 243 va_start(listp, fmt); 244 db_printf_guts (fmt, listp); 245 va_end(listp); 246 } 247 248 /* 249 * End line if too long. 250 */ 251 void 252 db_end_line() 253 { 254 if (db_output_position >= db_max_width) 255 db_printf("\n"); 256 } 257 258 /* 259 * Put a number (base <= 16) in a buffer in reverse order; return an 260 * optional length and a pointer to the NULL terminated (preceded?) 261 * buffer. 262 */ 263 static char * 264 db_ksprintn(ul, base, lenp) 265 register u_long ul; 266 register int base, *lenp; 267 { /* A long in base 8, plus NULL. */ 268 static char buf[sizeof(long) * NBBY / 3 + 2]; 269 register char *p; 270 271 p = buf; 272 do { 273 *++p = "0123456789abcdef"[ul % base]; 274 } while (ul /= base); 275 if (lenp) 276 *lenp = p - buf; 277 return (p); 278 } 279 280 db_printf_guts(fmt, ap) 281 register const char *fmt; 282 va_list ap; 283 { 284 register char *p; 285 register int ch, n; 286 u_long ul; 287 int base, lflag, tmp, width; 288 char padc; 289 int ladjust; 290 int sharpflag; 291 int neg; 292 293 for (;;) { 294 padc = ' '; 295 width = 0; 296 while ((ch = *(u_char *)fmt++) != '%') { 297 if (ch == '\0') 298 return; 299 db_putchar(ch); 300 } 301 lflag = 0; 302 ladjust = 0; 303 sharpflag = 0; 304 neg = 0; 305 reswitch: switch (ch = *(u_char *)fmt++) { 306 case '0': 307 padc = '0'; 308 goto reswitch; 309 case '1': case '2': case '3': case '4': 310 case '5': case '6': case '7': case '8': case '9': 311 for (width = 0;; ++fmt) { 312 width = width * 10 + ch - '0'; 313 ch = *fmt; 314 if (ch < '0' || ch > '9') 315 break; 316 } 317 goto reswitch; 318 case 'l': 319 lflag = 1; 320 goto reswitch; 321 case '-': 322 ladjust = 1; 323 goto reswitch; 324 case '#': 325 sharpflag = 1; 326 goto reswitch; 327 case 'b': 328 ul = va_arg(ap, int); 329 p = va_arg(ap, char *); 330 for (p = db_ksprintn(ul, *p++, NULL); ch = *p--;) 331 db_putchar(ch); 332 333 if (!ul) 334 break; 335 336 for (tmp = 0; n = *p++;) { 337 if (ul & (1 << (n - 1))) { 338 db_putchar(tmp ? ',' : '<'); 339 for (; (n = *p) > ' '; ++p) 340 db_putchar(n); 341 tmp = 1; 342 } else 343 for (; *p > ' '; ++p); 344 } 345 if (tmp) 346 db_putchar('>'); 347 break; 348 case '*': 349 width = va_arg (ap, int); 350 if (width < 0) { 351 ladjust = !ladjust; 352 width = -width; 353 } 354 goto reswitch; 355 case 'c': 356 db_putchar(va_arg(ap, int)); 357 break; 358 case 's': 359 p = va_arg(ap, char *); 360 width -= strlen (p); 361 if (!ladjust && width > 0) 362 while (width--) 363 db_putchar (padc); 364 while (ch = *p++) 365 db_putchar(ch); 366 if (ladjust && width > 0) 367 while (width--) 368 db_putchar (padc); 369 break; 370 case 'r': 371 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 372 if ((long)ul < 0) { 373 neg = 1; 374 ul = -(long)ul; 375 } 376 base = db_radix; 377 if (base < 8 || base > 16) 378 base = 10; 379 goto number; 380 case 'n': 381 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 382 base = db_radix; 383 if (base < 8 || base > 16) 384 base = 10; 385 goto number; 386 case 'd': 387 ul = lflag ? va_arg(ap, long) : va_arg(ap, int); 388 if ((long)ul < 0) { 389 neg = 1; 390 ul = -(long)ul; 391 } 392 base = 10; 393 goto number; 394 case 'o': 395 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 396 base = 8; 397 goto number; 398 case 'u': 399 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 400 base = 10; 401 goto number; 402 case 'z': 403 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 404 if ((long)ul < 0) { 405 neg = 1; 406 ul = -(long)ul; 407 } 408 base = 16; 409 goto number; 410 case 'x': 411 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 412 base = 16; 413 number: p = (char *)db_ksprintn(ul, base, &tmp); 414 if (sharpflag && ul != 0) { 415 if (base == 8) 416 tmp++; 417 else if (base == 16) 418 tmp += 2; 419 } 420 if (neg) 421 tmp++; 422 423 if (!ladjust && width && (width -= tmp) > 0) 424 while (width--) 425 db_putchar(padc); 426 if (neg) 427 db_putchar ('-'); 428 if (sharpflag && ul != 0) { 429 if (base == 8) { 430 db_putchar ('0'); 431 } else if (base == 16) { 432 db_putchar ('0'); 433 db_putchar ('x'); 434 } 435 } 436 if (ladjust && width && (width -= tmp) > 0) 437 while (width--) 438 db_putchar(padc); 439 440 while (ch = *p--) 441 db_putchar(ch); 442 break; 443 default: 444 db_putchar('%'); 445 if (lflag) 446 db_putchar('l'); 447 /* FALLTHROUGH */ 448 case '%': 449 db_putchar(ch); 450 } 451 } 452 } 453 454