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