db_output.c revision 3140
1211201Stakawata/* 2211201Stakawata * Mach Operating System 3211201Stakawata * Copyright (c) 1991,1990 Carnegie Mellon University 4211201Stakawata * All Rights Reserved. 5211201Stakawata * 6211201Stakawata * Permission to use, copy, modify and distribute this software and its 7211201Stakawata * documentation is hereby granted, provided that both the copyright 8211201Stakawata * notice and this permission notice appear in all copies of the 9211201Stakawata * software, derivative works or modified versions, and any portions 10211201Stakawata * thereof, and that both notices appear in supporting documentation. 11211201Stakawata * 12211201Stakawata * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 13211201Stakawata * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 14211201Stakawata * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 15211201Stakawata * 16211201Stakawata * Carnegie Mellon requests users of this software to return to 17211201Stakawata * 18211201Stakawata * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 19211201Stakawata * School of Computer Science 20211201Stakawata * Carnegie Mellon University 21211201Stakawata * Pittsburgh PA 15213-3890 22211201Stakawata * 23211201Stakawata * any improvements or extensions that they make and grant Carnegie the 24211201Stakawata * rights to redistribute these changes. 25211201Stakawata * 26211201Stakawata * $Id: db_output.c,v 1.8 1994/08/27 16:14:09 davidg Exp $ 27211201Stakawata */ 28211201Stakawata 29211201Stakawata/* 30211201Stakawata * Author: David B. Golub, Carnegie Mellon University 31211201Stakawata * Date: 7/90 32211201Stakawata */ 33211201Stakawata 34211201Stakawata/* 35211201Stakawata * Printf and character output for debugger. 36211201Stakawata */ 37211201Stakawata 38211201Stakawata#include <sys/param.h> 39211201Stakawata#include <sys/systm.h> 40211201Stakawata#include <machine/stdarg.h> 41211201Stakawata#include <ddb/ddb.h> 42211201Stakawata#include <machine/cons.h> 43211201Stakawata 44211201Stakawata/* 45211201Stakawata * Character output - tracks position in line. 46211201Stakawata * To do this correctly, we should know how wide 47211201Stakawata * the output device is - then we could zero 48211201Stakawata * the line position when the output device wraps 49211201Stakawata * around to the start of the next line. 50211201Stakawata * 51211201Stakawata * Instead, we count the number of spaces printed 52211201Stakawata * since the last printing character so that we 53211201Stakawata * don't print trailing spaces. This avoids most 54211201Stakawata * of the wraparounds. 55211201Stakawata */ 56211201Stakawataint db_output_position = 0; /* output column */ 57211201Stakawataint db_last_non_space = 0; /* last non-space character */ 58211201Stakawataint db_tab_stop_width = 8; /* how wide are tab stops? */ 59211201Stakawata#define NEXT_TAB(i) \ 60211201Stakawata ((((i) + db_tab_stop_width) / db_tab_stop_width) * db_tab_stop_width) 61211201Stakawataint db_max_width = 80; /* output line width */ 62211201Stakawata 63211201Stakawata 64211201Stakawatastatic void db_printf_guts(const char *, va_list); 65211201Stakawata 66211201Stakawata/* 67211201Stakawata * Force pending whitespace. 68211201Stakawata */ 69211201Stakawatavoid 70211201Stakawatadb_force_whitespace() 71211201Stakawata{ 72211201Stakawata register int last_print, next_tab; 73211201Stakawata 74211201Stakawata last_print = db_last_non_space; 75211201Stakawata while (last_print < db_output_position) { 76211201Stakawata next_tab = NEXT_TAB(last_print); 77211201Stakawata if (next_tab <= db_output_position) { 78211201Stakawata while (last_print < next_tab) { /* DON'T send a tab!!! */ 79211201Stakawata cnputc(' '); 80211201Stakawata last_print++; 81211201Stakawata } 82211201Stakawata } 83211201Stakawata else { 84211201Stakawata cnputc(' '); 85211201Stakawata last_print++; 86211201Stakawata } 87211201Stakawata } 88211201Stakawata db_last_non_space = db_output_position; 89211201Stakawata} 90211201Stakawata 91211201Stakawata/* 92211201Stakawata * Output character. Buffer whitespace. 93211201Stakawata */ 94211201Stakawatavoid 95211201Stakawatadb_putchar(c) 96211201Stakawata int c; /* character to output */ 97211201Stakawata{ 98211201Stakawata if (c > ' ' && c <= '~') { 99211201Stakawata /* 100211201Stakawata * Printing character. 101211201Stakawata * If we have spaces to print, print them first. 102211201Stakawata * Use tabs if possible. 103211201Stakawata */ 104211201Stakawata db_force_whitespace(); 105211201Stakawata cnputc(c); 106211201Stakawata db_output_position++; 107211201Stakawata db_last_non_space = db_output_position; 108211201Stakawata } 109211201Stakawata else if (c == '\n') { 110211201Stakawata /* Newline */ 111211201Stakawata cnputc(c); 112211201Stakawata db_output_position = 0; 113211201Stakawata db_last_non_space = 0; 114211201Stakawata db_check_interrupt(); 115211201Stakawata } 116211201Stakawata else if (c == '\r') { 117211201Stakawata /* Return */ 118211201Stakawata cnputc(c); 119211201Stakawata db_output_position = 0; 120211201Stakawata db_last_non_space = 0; 121211201Stakawata db_check_interrupt(); 122211201Stakawata } 123211201Stakawata else if (c == '\t') { 124211201Stakawata /* assume tabs every 8 positions */ 125211201Stakawata db_output_position = NEXT_TAB(db_output_position); 126211201Stakawata } 127211201Stakawata else if (c == ' ') { 128211201Stakawata /* space */ 129211201Stakawata db_output_position++; 130211201Stakawata } 131211201Stakawata else if (c == '\007') { 132211201Stakawata /* bell */ 133211201Stakawata cnputc(c); 134211201Stakawata } 135211201Stakawata /* other characters are assumed non-printing */ 136211201Stakawata} 137211201Stakawata 138211201Stakawata/* 139211201Stakawata * Return output position 140211201Stakawata */ 141211201Stakawataint 142211201Stakawatadb_print_position() 143211201Stakawata{ 144211201Stakawata return (db_output_position); 145211201Stakawata} 146211201Stakawata 147211201Stakawata/* 148211201Stakawata * Printing 149211201Stakawata */ 150211201Stakawatavoid 151211201Stakawatadb_printf(const char *fmt, ...) 152211201Stakawata{ 153211201Stakawata va_list listp; 154211201Stakawata va_start(listp, fmt); 155211201Stakawata db_printf_guts (fmt, listp); 156211201Stakawata va_end(listp); 157211201Stakawata} 158211201Stakawata 159211201Stakawata/* alternate name */ 160211201Stakawata 161211201Stakawata/*VARARGS1*/ 162211201Stakawatavoid 163211201Stakawatakdbprintf(char *fmt, ...) 164211201Stakawata{ 165211201Stakawata va_list listp; 166211201Stakawata va_start(listp, fmt); 167211201Stakawata db_printf_guts (fmt, listp); 168211201Stakawata va_end(listp); 169211201Stakawata} 170211201Stakawata 171211201Stakawata/* 172211201Stakawata * End line if too long. 173211201Stakawata */ 174211201Stakawatavoid 175211201Stakawatadb_end_line() 176211201Stakawata{ 177211201Stakawata if (db_output_position >= db_max_width) 178211201Stakawata db_printf("\n"); 179211201Stakawata} 180211201Stakawata 181211201Stakawata/* 182211201Stakawata * Put a number (base <= 16) in a buffer in reverse order; return an 183211201Stakawata * optional length and a pointer to the NULL terminated (preceded?) 184211201Stakawata * buffer. 185211201Stakawata */ 186211201Stakawatastatic char * 187211201Stakawatadb_ksprintn(ul, base, lenp) 188211201Stakawata register u_long ul; 189211201Stakawata register int base, *lenp; 190211201Stakawata{ /* A long in base 8, plus NULL. */ 191211201Stakawata static char buf[sizeof(long) * NBBY / 3 + 2]; 192211201Stakawata register char *p; 193211201Stakawata 194211201Stakawata p = buf; 195211201Stakawata do { 196211201Stakawata *++p = "0123456789abcdef"[ul % base]; 197211201Stakawata } while (ul /= base); 198211201Stakawata if (lenp) 199211201Stakawata *lenp = p - buf; 200211201Stakawata return (p); 201211201Stakawata} 202211201Stakawata 203211201Stakawatastatic void 204211201Stakawatadb_printf_guts(fmt, ap) 205211201Stakawata register const char *fmt; 206211201Stakawata va_list ap; 207211201Stakawata{ 208211201Stakawata register char *p; 209211201Stakawata register int ch, n; 210211201Stakawata u_long ul; 211211201Stakawata int base, lflag, tmp, width; 212211201Stakawata char padc; 213211201Stakawata int ladjust; 214211201Stakawata int sharpflag; 215211201Stakawata int neg; 216211201Stakawata 217211201Stakawata for (;;) { 218211201Stakawata padc = ' '; 219211201Stakawata width = 0; 220211201Stakawata while ((ch = *(u_char *)fmt++) != '%') { 221211201Stakawata if (ch == '\0') 222211201Stakawata return; 223211201Stakawata db_putchar(ch); 224211201Stakawata } 225211201Stakawata lflag = 0; 226211201Stakawata ladjust = 0; 227211201Stakawata sharpflag = 0; 228211201Stakawata neg = 0; 229211201Stakawatareswitch: switch (ch = *(u_char *)fmt++) { 230211201Stakawata case '0': 231211201Stakawata padc = '0'; 232211201Stakawata goto reswitch; 233211201Stakawata case '1': case '2': case '3': case '4': 234211201Stakawata case '5': case '6': case '7': case '8': case '9': 235211201Stakawata for (width = 0;; ++fmt) { 236211201Stakawata width = width * 10 + ch - '0'; 237211201Stakawata ch = *fmt; 238211201Stakawata if (ch < '0' || ch > '9') 239211201Stakawata break; 240211201Stakawata } 241211201Stakawata goto reswitch; 242211201Stakawata case 'l': 243211201Stakawata lflag = 1; 244211201Stakawata goto reswitch; 245211201Stakawata case '-': 246211201Stakawata ladjust = 1; 247211201Stakawata goto reswitch; 248211201Stakawata case '#': 249211201Stakawata sharpflag = 1; 250211201Stakawata goto reswitch; 251211201Stakawata case 'b': 252211201Stakawata ul = va_arg(ap, int); 253211201Stakawata p = va_arg(ap, char *); 254211201Stakawata for (p = db_ksprintn(ul, *p++, NULL); *p;p--) 255211201Stakawata db_putchar(*p); 256211201Stakawata 257211201Stakawata if (!ul) 258211201Stakawata break; 259211201Stakawata 260211201Stakawata for (tmp = 0; *p;) { 261211201Stakawata n = *p++; 262211201Stakawata if (ul & (1 << (n - 1))) { 263211201Stakawata db_putchar(tmp ? ',' : '<'); 264211201Stakawata for (; (n = *p) > ' '; ++p) 265211201Stakawata db_putchar(n); 266211201Stakawata tmp = 1; 267211201Stakawata } else 268211201Stakawata for (; *p > ' '; ++p); 269211201Stakawata } 270211201Stakawata if (tmp) 271211201Stakawata db_putchar('>'); 272211201Stakawata break; 273211201Stakawata case '*': 274211201Stakawata width = va_arg (ap, int); 275211201Stakawata if (width < 0) { 276211201Stakawata ladjust = !ladjust; 277211201Stakawata width = -width; 278211201Stakawata } 279211201Stakawata goto reswitch; 280211201Stakawata case 'c': 281211201Stakawata db_putchar(va_arg(ap, int)); 282211201Stakawata break; 283211201Stakawata case 's': 284211201Stakawata p = va_arg(ap, char *); 285211201Stakawata width -= strlen (p); 286211201Stakawata if (!ladjust && width > 0) 287211201Stakawata while (width--) 288211201Stakawata db_putchar (padc); 289211201Stakawata for (;*p;p++) 290211201Stakawata db_putchar(*p); 291211201Stakawata if (ladjust && width > 0) 292211201Stakawata while (width--) 293211201Stakawata db_putchar (padc); 294211201Stakawata break; 295211201Stakawata case 'r': 296211201Stakawata ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 297211201Stakawata if ((long)ul < 0) { 298211201Stakawata neg = 1; 299211201Stakawata ul = -(long)ul; 300211201Stakawata } 301211201Stakawata base = db_radix; 302211201Stakawata if (base < 8 || base > 16) 303211201Stakawata base = 10; 304211201Stakawata goto number; 305211201Stakawata case 'n': 306211201Stakawata ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 307211201Stakawata base = db_radix; 308211201Stakawata if (base < 8 || base > 16) 309211201Stakawata base = 10; 310211201Stakawata goto number; 311211201Stakawata case 'd': 312211201Stakawata ul = lflag ? va_arg(ap, long) : va_arg(ap, int); 313211201Stakawata if ((long)ul < 0) { 314211201Stakawata neg = 1; 315211201Stakawata ul = -(long)ul; 316211201Stakawata } 317211201Stakawata base = 10; 318211201Stakawata goto number; 319211201Stakawata case 'o': 320211201Stakawata ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 321211201Stakawata base = 8; 322211201Stakawata goto number; 323211201Stakawata case 'u': 324211201Stakawata ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 325211201Stakawata base = 10; 326211201Stakawata goto number; 327211201Stakawata case 'z': 328211201Stakawata ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 329211201Stakawata if ((long)ul < 0) { 330211201Stakawata neg = 1; 331211201Stakawata ul = -(long)ul; 332211201Stakawata } 333211201Stakawata base = 16; 334211201Stakawata goto number; 335211201Stakawata case 'x': 336211201Stakawata ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 337211201Stakawata base = 16; 338211201Stakawatanumber: p = (char *)db_ksprintn(ul, base, &tmp); 339211201Stakawata if (sharpflag && ul != 0) { 340211201Stakawata if (base == 8) 341211201Stakawata tmp++; 342211201Stakawata else if (base == 16) 343211201Stakawata tmp += 2; 344211201Stakawata } 345211201Stakawata if (neg) 346211201Stakawata tmp++; 347211201Stakawata 348211201Stakawata if (!ladjust && width && (width -= tmp) > 0) 349211201Stakawata while (width--) 350211201Stakawata db_putchar(padc); 351211201Stakawata if (neg) 352211201Stakawata db_putchar ('-'); 353211201Stakawata if (sharpflag && ul != 0) { 354211201Stakawata if (base == 8) { 355211201Stakawata db_putchar ('0'); 356211201Stakawata } else if (base == 16) { 357211201Stakawata db_putchar ('0'); 358211201Stakawata db_putchar ('x'); 359211201Stakawata } 360211201Stakawata } 361211201Stakawata if (ladjust && width && (width -= tmp) > 0) 362211201Stakawata while (width--) 363211201Stakawata db_putchar(padc); 364211201Stakawata 365211201Stakawata for (;*p;p--) 366211201Stakawata db_putchar(*p); 367211201Stakawata break; 368211201Stakawata default: 369211201Stakawata db_putchar('%'); 370211201Stakawata if (lflag) 371211201Stakawata db_putchar('l'); 372211201Stakawata /* FALLTHROUGH */ 373211201Stakawata case '%': 374211201Stakawata db_putchar(ch); 375211201Stakawata } 376211201Stakawata } 377211201Stakawata} 378211201Stakawata 379211201Stakawata