db_output.c revision 12662
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 * $Id: db_output.c,v 1.13 1995/11/29 10:25:29 phk Exp $ 27 */ 28 29/* 30 * Author: David B. Golub, Carnegie Mellon University 31 * Date: 7/90 32 */ 33 34/* 35 * Printf and character output for debugger. 36 */ 37 38#include <sys/param.h> 39#include <sys/systm.h> 40#include <vm/vm_param.h> 41#include <machine/stdarg.h> 42#include <ddb/ddb.h> 43#include <ddb/db_output.h> 44#include <machine/cons.h> 45 46/* 47 * Character output - tracks position in line. 48 * To do this correctly, we should know how wide 49 * the output device is - then we could zero 50 * the line position when the output device wraps 51 * around to the start of the next line. 52 * 53 * Instead, we count the number of spaces printed 54 * since the last printing character so that we 55 * don't print trailing spaces. This avoids most 56 * of the wraparounds. 57 */ 58static int db_output_position = 0; /* output column */ 59static int db_last_non_space = 0; /* last non-space character */ 60int db_tab_stop_width = 8; /* how wide are tab stops? */ 61#define NEXT_TAB(i) \ 62 ((((i) + db_tab_stop_width) / db_tab_stop_width) * db_tab_stop_width) 63int db_max_width = 80; /* output line width */ 64 65static char *db_ksprintn __P((u_long ul, int base, int *lenp)); 66static void db_printf_guts __P((const char *, va_list)); 67 68/* 69 * Force pending whitespace. 70 */ 71void 72db_force_whitespace() 73{ 74 register int last_print, next_tab; 75 76 last_print = db_last_non_space; 77 while (last_print < db_output_position) { 78 next_tab = NEXT_TAB(last_print); 79 if (next_tab <= db_output_position) { 80 while (last_print < next_tab) { /* DON'T send a tab!!! */ 81 cnputc(' '); 82 last_print++; 83 } 84 } 85 else { 86 cnputc(' '); 87 last_print++; 88 } 89 } 90 db_last_non_space = db_output_position; 91} 92 93/* 94 * Output character. Buffer whitespace. 95 */ 96void 97db_putchar(c) 98 int c; /* character to output */ 99{ 100 if (c > ' ' && c <= '~') { 101 /* 102 * Printing character. 103 * If we have spaces to print, print them first. 104 * Use tabs if possible. 105 */ 106 db_force_whitespace(); 107 cnputc(c); 108 db_output_position++; 109 db_last_non_space = db_output_position; 110 } 111 else if (c == '\n') { 112 /* Newline */ 113 cnputc(c); 114 db_output_position = 0; 115 db_last_non_space = 0; 116 db_check_interrupt(); 117 } 118 else if (c == '\r') { 119 /* Return */ 120 cnputc(c); 121 db_output_position = 0; 122 db_last_non_space = 0; 123 db_check_interrupt(); 124 } 125 else if (c == '\t') { 126 /* assume tabs every 8 positions */ 127 db_output_position = NEXT_TAB(db_output_position); 128 } 129 else if (c == ' ') { 130 /* space */ 131 db_output_position++; 132 } 133 else if (c == '\007') { 134 /* bell */ 135 cnputc(c); 136 } 137 /* other characters are assumed non-printing */ 138} 139 140/* 141 * Return output position 142 */ 143int 144db_print_position() 145{ 146 return (db_output_position); 147} 148 149/* 150 * Printing 151 */ 152void 153db_printf(const char *fmt, ...) 154{ 155 va_list listp; 156 va_start(listp, fmt); 157 db_printf_guts (fmt, listp); 158 va_end(listp); 159} 160 161/* 162 * End line if too long. 163 */ 164void 165db_end_line() 166{ 167 if (db_output_position >= db_max_width) 168 db_printf("\n"); 169} 170 171/* 172 * Put a number (base <= 16) in a buffer in reverse order; return an 173 * optional length and a pointer to the NULL terminated (preceded?) 174 * buffer. 175 */ 176static char * 177db_ksprintn(ul, base, lenp) 178 register u_long ul; 179 register int base, *lenp; 180{ /* A long in base 8, plus NULL. */ 181 static char buf[sizeof(long) * NBBY / 3 + 2]; 182 register char *p; 183 184 p = buf; 185 do { 186 *++p = "0123456789abcdef"[ul % base]; 187 } while (ul /= base); 188 if (lenp) 189 *lenp = p - buf; 190 return (p); 191} 192 193static void 194db_printf_guts(fmt, ap) 195 register const char *fmt; 196 va_list ap; 197{ 198 register char *p; 199 register int ch, n; 200 u_long ul; 201 int base, lflag, tmp, width; 202 char padc; 203 int ladjust; 204 int sharpflag; 205 int neg; 206 207 for (;;) { 208 padc = ' '; 209 width = 0; 210 while ((ch = *(u_char *)fmt++) != '%') { 211 if (ch == '\0') 212 return; 213 db_putchar(ch); 214 } 215 lflag = 0; 216 ladjust = 0; 217 sharpflag = 0; 218 neg = 0; 219reswitch: switch (ch = *(u_char *)fmt++) { 220 case '0': 221 padc = '0'; 222 goto reswitch; 223 case '1': case '2': case '3': case '4': 224 case '5': case '6': case '7': case '8': case '9': 225 for (width = 0;; ++fmt) { 226 width = width * 10 + ch - '0'; 227 ch = *fmt; 228 if (ch < '0' || ch > '9') 229 break; 230 } 231 goto reswitch; 232 case 'l': 233 lflag = 1; 234 goto reswitch; 235 case '-': 236 ladjust = 1; 237 goto reswitch; 238 case '#': 239 sharpflag = 1; 240 goto reswitch; 241 case 'b': 242 ul = va_arg(ap, int); 243 p = va_arg(ap, char *); 244 for (p = db_ksprintn(ul, *p++, NULL); *p;p--) 245 db_putchar(*p); 246 247 if (!ul) 248 break; 249 250 for (tmp = 0; *p;) { 251 n = *p++; 252 if (ul & (1 << (n - 1))) { 253 db_putchar(tmp ? ',' : '<'); 254 for (; (n = *p) > ' '; ++p) 255 db_putchar(n); 256 tmp = 1; 257 } else 258 for (; *p > ' '; ++p); 259 } 260 if (tmp) 261 db_putchar('>'); 262 break; 263 case '*': 264 width = va_arg (ap, int); 265 if (width < 0) { 266 ladjust = !ladjust; 267 width = -width; 268 } 269 goto reswitch; 270 case 'c': 271 db_putchar(va_arg(ap, int)); 272 break; 273 case 's': 274 p = va_arg(ap, char *); 275 if (p == NULL) 276 p = "(null)"; 277 width -= strlen (p); 278 if (!ladjust && width > 0) 279 while (width--) 280 db_putchar (padc); 281 for (;*p;p++) 282 db_putchar(*p); 283 if (ladjust && width > 0) 284 while (width--) 285 db_putchar (padc); 286 break; 287 case 'r': 288 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 289 if ((long)ul < 0) { 290 neg = 1; 291 ul = -(long)ul; 292 } 293 base = db_radix; 294 if (base < 8 || base > 16) 295 base = 10; 296 goto number; 297 case 'n': 298 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 299 base = db_radix; 300 if (base < 8 || base > 16) 301 base = 10; 302 goto number; 303 case 'd': 304 ul = lflag ? va_arg(ap, long) : va_arg(ap, int); 305 if ((long)ul < 0) { 306 neg = 1; 307 ul = -(long)ul; 308 } 309 base = 10; 310 goto number; 311 case 'o': 312 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 313 base = 8; 314 goto number; 315 case 'u': 316 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 317 base = 10; 318 goto number; 319 case 'z': 320 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 321 if ((long)ul < 0) { 322 neg = 1; 323 ul = -(long)ul; 324 } 325 base = 16; 326 goto number; 327 case 'x': 328 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 329 base = 16; 330number: p = (char *)db_ksprintn(ul, base, &tmp); 331 if (sharpflag && ul != 0) { 332 if (base == 8) 333 tmp++; 334 else if (base == 16) 335 tmp += 2; 336 } 337 if (neg) 338 tmp++; 339 340 if (!ladjust && width && (width -= tmp) > 0) 341 while (width--) 342 db_putchar(padc); 343 if (neg) 344 db_putchar ('-'); 345 if (sharpflag && ul != 0) { 346 if (base == 8) { 347 db_putchar ('0'); 348 } else if (base == 16) { 349 db_putchar ('0'); 350 db_putchar ('x'); 351 } 352 } 353 if (ladjust && width && (width -= tmp) > 0) 354 while (width--) 355 db_putchar(padc); 356 357 for (;*p;p--) 358 db_putchar(*p); 359 break; 360 default: 361 db_putchar('%'); 362 if (lflag) 363 db_putchar('l'); 364 /* FALLTHROUGH */ 365 case '%': 366 db_putchar(ch); 367 } 368 } 369} 370