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