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 * $Id: db_output.c,v 1.3 1993/05/20 03:39:21 cgd Exp $ 36 * 37 * HISTORY 38 * $Log: 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 int db_output_position = 0; /* output column */ 89 int db_last_non_space = 0; /* last non-space character */ 90 int db_tab_stop_width = 8; /* how wide are tab stops? */ 91 #define NEXT_TAB(i) \ 92 ((((i) + db_tab_stop_width) / db_tab_stop_width) * db_tab_stop_width) 93 int db_max_width = 80; /* output line width */ 94 95 extern void db_check_interrupt(); 96 97 /* 98 * Force pending whitespace. 99 */ 100 void 101 db_force_whitespace() 102 { 103 register int last_print, next_tab; 104 105 last_print = db_last_non_space; 106 while (last_print < db_output_position) { 107 next_tab = NEXT_TAB(last_print); 108 if (next_tab <= db_output_position) { 109 while (last_print < next_tab) { /* DON'T send a tab!!! */ 110 cnputc(' '); 111 last_print++; 112 } 113 } 114 else { 115 cnputc(' '); 116 last_print++; 117 } 118 } 119 db_last_non_space = db_output_position; 120 } 121 122 /* 123 * Output character. Buffer whitespace. 124 */ 125 db_putchar(c) 126 int c; /* character to output */ 127 { 128 if (c > ' ' && c <= '~') { 129 /* 130 * Printing character. 131 * If we have spaces to print, print them first. 132 * Use tabs if possible. 133 */ 134 db_force_whitespace(); 135 cnputc(c); 136 db_output_position++; 137 db_last_non_space = db_output_position; 138 } 139 else if (c == '\n') { 140 /* Return */ 141 cnputc(c); 142 db_output_position = 0; 143 db_last_non_space = 0; 144 db_check_interrupt(); 145 } 146 else if (c == '\t') { 147 /* assume tabs every 8 positions */ 148 db_output_position = NEXT_TAB(db_output_position); 149 } 150 else if (c == ' ') { 151 /* space */ 152 db_output_position++; 153 } 154 else if (c == '\007') { 155 /* bell */ 156 cnputc(c); 157 } 158 /* other characters are assumed non-printing */ 159 } 160 161 /* 162 * Return output position 163 */ 164 int 165 db_print_position() 166 { 167 return (db_output_position); 168 } 169 170 /* 171 * End line if too long. 172 */ 173 void 174 db_end_line() 175 { 176 if (db_output_position >= db_max_width) 177 db_printf("\n"); 178 } 179 180 /* 181 * Printing 182 */ 183 extern int db_radix; 184 185 /*VARARGS1*/ 186 db_printf(char *fmt, ...) 187 { 188 va_list listp; 189 va_start(listp, fmt); 190 db_printf_guts (fmt, listp); 191 va_end(listp); 192 } 193 194 /* alternate name */ 195 196 /*VARARGS1*/ 197 kdbprintf(char *fmt, ...) 198 { 199 va_list listp; 200 va_start(listp, fmt); 201 db_printf_guts (fmt, listp); 202 va_end(listp); 203 } 204 205 /* 206 * Put a number (base <= 16) in a buffer in reverse order; return an 207 * optional length and a pointer to the NULL terminated (preceded?) 208 * buffer. 209 */ 210 static char * 211 db_ksprintn(ul, base, lenp) 212 register u_long ul; 213 register int base, *lenp; 214 { /* A long in base 8, plus NULL. */ 215 static char buf[sizeof(long) * NBBY / 3 + 2]; 216 register char *p; 217 218 p = buf; 219 do { 220 *++p = "0123456789abcdef"[ul % base]; 221 } while (ul /= base); 222 if (lenp) 223 *lenp = p - buf; 224 return (p); 225 } 226 227 db_printf_guts(fmt, ap) 228 register const char *fmt; 229 va_list ap; 230 { 231 register char *p; 232 register int ch, n; 233 u_long ul; 234 int base, lflag, tmp, width; 235 char padc; 236 int ladjust; 237 int sharpflag; 238 int neg; 239 240 for (;;) { 241 padc = ' '; 242 width = 0; 243 while ((ch = *(u_char *)fmt++) != '%') { 244 if (ch == '\0') 245 return; 246 db_putchar(ch); 247 } 248 lflag = 0; 249 ladjust = 0; 250 sharpflag = 0; 251 neg = 0; 252 reswitch: switch (ch = *(u_char *)fmt++) { 253 case '0': 254 padc = '0'; 255 goto reswitch; 256 case '1': case '2': case '3': case '4': 257 case '5': case '6': case '7': case '8': case '9': 258 for (width = 0;; ++fmt) { 259 width = width * 10 + ch - '0'; 260 ch = *fmt; 261 if (ch < '0' || ch > '9') 262 break; 263 } 264 goto reswitch; 265 case 'l': 266 lflag = 1; 267 goto reswitch; 268 case '-': 269 ladjust = 1; 270 goto reswitch; 271 case '#': 272 sharpflag = 1; 273 goto reswitch; 274 case 'b': 275 ul = va_arg(ap, int); 276 p = va_arg(ap, char *); 277 for (p = db_ksprintn(ul, *p++, NULL); ch = *p--;) 278 db_putchar(ch); 279 280 if (!ul) 281 break; 282 283 for (tmp = 0; n = *p++;) { 284 if (ul & (1 << (n - 1))) { 285 db_putchar(tmp ? ',' : '<'); 286 for (; (n = *p) > ' '; ++p) 287 db_putchar(n); 288 tmp = 1; 289 } else 290 for (; *p > ' '; ++p); 291 } 292 if (tmp) 293 db_putchar('>'); 294 break; 295 case '*': 296 width = va_arg (ap, int); 297 if (width < 0) { 298 ladjust = !ladjust; 299 width = -width; 300 } 301 goto reswitch; 302 case 'c': 303 db_putchar(va_arg(ap, int)); 304 break; 305 case 's': 306 p = va_arg(ap, char *); 307 width -= strlen (p); 308 if (!ladjust && width > 0) 309 while (width--) 310 db_putchar (padc); 311 while (ch = *p++) 312 db_putchar(ch); 313 if (ladjust && width > 0) 314 while (width--) 315 db_putchar (padc); 316 break; 317 case 'r': 318 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 319 if ((long)ul < 0) { 320 neg = 1; 321 ul = -(long)ul; 322 } 323 base = db_radix; 324 if (base < 8 || base > 16) 325 base = 10; 326 goto number; 327 case 'n': 328 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 329 base = db_radix; 330 if (base < 8 || base > 16) 331 base = 10; 332 goto number; 333 case 'd': 334 ul = lflag ? va_arg(ap, long) : va_arg(ap, int); 335 if ((long)ul < 0) { 336 neg = 1; 337 ul = -(long)ul; 338 } 339 base = 10; 340 goto number; 341 case 'o': 342 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 343 base = 8; 344 goto number; 345 case 'u': 346 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 347 base = 10; 348 goto number; 349 case 'z': 350 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 351 if ((long)ul < 0) { 352 neg = 1; 353 ul = -(long)ul; 354 } 355 base = 16; 356 goto number; 357 case 'x': 358 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 359 base = 16; 360 number: p = (char *)db_ksprintn(ul, base, &tmp); 361 if (sharpflag && ul != 0) { 362 if (base == 8) 363 tmp++; 364 else if (base == 16) 365 tmp += 2; 366 } 367 if (neg) 368 tmp++; 369 370 if (!ladjust && width && (width -= tmp) > 0) 371 while (width--) 372 db_putchar(padc); 373 if (neg) 374 db_putchar ('-'); 375 if (sharpflag && ul != 0) { 376 if (base == 8) { 377 db_putchar ('0'); 378 } else if (base == 16) { 379 db_putchar ('0'); 380 db_putchar ('x'); 381 } 382 } 383 if (ladjust && width && (width -= tmp) > 0) 384 while (width--) 385 db_putchar(padc); 386 387 while (ch = *p--) 388 db_putchar(ch); 389 break; 390 default: 391 db_putchar('%'); 392 if (lflag) 393 db_putchar('l'); 394 /* FALLTHROUGH */ 395 case '%': 396 db_putchar(ch); 397 } 398 } 399 } 400 401