1 /*- 2 * Copyright (c) 1991 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.proprietary.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)output.c 5.2 (Berkeley) 04/04/91"; 10 #endif /* not lint */ 11 12 /* 13 * adb - output 14 */ 15 16 #include "defs.h" 17 #include <ctype.h> 18 #include <stdio.h> 19 #include <varargs.h> 20 21 extern char TOODEEP[]; 22 23 int infile; 24 int outfile = 1; 25 26 char printbuf[LINELEN]; 27 char *printptr = printbuf; 28 29 30 /* 31 * Print the string s. 32 */ 33 prints(s) 34 register char *s; 35 { 36 register int c; 37 38 while ((c = *s++) != '\0') 39 printc(c); 40 } 41 42 /* 43 * Print the character c. 44 */ 45 printc(c) 46 int c; 47 { 48 49 if (mkfault) 50 return; 51 switch (c) { 52 53 case 0: 54 return; 55 56 case '\n': 57 sendout(); 58 return; 59 60 default: 61 if (isprint(c)) 62 *printptr++ = c; 63 break; 64 } 65 if (printptr >= &printbuf[LINELEN - 1]) /* 1 == space for \n */ 66 sendout(); 67 } 68 69 /* 70 * Send (write) out the contents of the print buffer, compressing 71 * spaces into tabs. 72 */ 73 static 74 sendout() 75 { 76 register char *p, *q; 77 register int c, off = 0, spaces = 0, s; 78 #define tabsize(x) (8 - ((x) & 7)) 79 80 for (q = p = printbuf; p < printptr;) { 81 c = *p++; 82 switch (c) { 83 84 case ' ': 85 spaces++; 86 break; 87 88 case '\t': 89 spaces += tabsize(off + spaces); 90 break; 91 92 default: 93 s = tabsize(off); 94 off += spaces + 1; 95 while (spaces >= s) { 96 *q++ = '\t'; 97 spaces -= s; 98 s = 8; 99 } 100 while (--spaces >= 0) 101 *q++ = ' '; 102 spaces = 0; 103 *q++ = c; 104 } 105 } 106 *q++ = '\n'; 107 (void) write(outfile, printbuf, q - printbuf); 108 printptr = printbuf; 109 #undef tabsize 110 } 111 112 charpos() 113 { 114 115 return (printptr - printbuf); 116 } 117 118 endline() 119 { 120 121 if (printptr - printbuf >= maxcol) 122 printc('\n'); 123 } 124 125 flushbuf() 126 { 127 128 if (printptr != printbuf) 129 sendout(); 130 } 131 132 /* this should not be necessary! */ 133 #ifdef lint 134 #undef va_arg 135 #define va_arg(ap, type) (ap = ap, (type)0) 136 #endif 137 138 /* 139 * Context passed between adbprintf and decodefmt. 140 */ 141 struct prf { 142 char *fmt; /* format pointer */ 143 va_list ap; /* argument pointer */ 144 char *buf; /* digit buffer, or %s string */ 145 int adj; /* 'l'eft (-) or 'r'ight adjustment */ 146 int width; /* width from format */ 147 int prec; /* precision from format */ 148 }; 149 150 /* 151 * adb's very own version of printf() ... of course, all the format 152 * escapes are different. Noteworthy are the %<width>m and %<tabstop>t 153 * formats, which move the given width, or to the given tabstop, and 154 * the %?a format, which evaluates one argument, and if not zero, prints 155 * according to format a. (Note that any modifiers must appear in the 156 * `a' part, not in the %? part.) 157 */ 158 /* VARARGS1 */ 159 adbprintf(fmt, va_alist) 160 char *fmt; 161 va_dcl 162 { 163 register char *s; 164 register int n, c; 165 struct prf prf; 166 char digits[130]; /* good to at least 128 bit expr_t */ 167 168 /* set up the fields adbprf needs */ 169 prf.fmt = fmt; 170 va_start(prf.ap); 171 for (;;) { 172 /* look for % conversions */ 173 s = prf.fmt; 174 while ((c = *s++) != '%') { 175 if (c == 0) 176 return; 177 printc(c); 178 } 179 prf.fmt = s; 180 prf.buf = digits; 181 dofmt(&prf); /* format one format */ 182 n = strlen(s = prf.buf); 183 if (prf.prec >= 0 && n > prf.prec) 184 n = prf.prec; 185 c = prf.width - n; 186 if (prf.adj == 'r') 187 while (--c >= 0) 188 printc(' '); 189 while (--n >= 0) 190 printc(*s++); 191 while (--c >= 0) 192 printc(' '); 193 } 194 va_end(prf.ap); 195 } 196 197 /* 198 * Do a single format. 199 */ 200 static 201 dofmt(prf) 202 register struct prf *prf; 203 { 204 register char *s = prf->fmt; 205 register va_list ap = prf->ap; 206 register int c, n; 207 expr_t v; 208 int pluspref = 0; 209 static char null[] = ""; 210 211 prf->adj = 'r'; 212 prf->width = 0; 213 prf->prec = -1; 214 more: 215 c = *s++; 216 sw: 217 switch (c) { 218 219 case '-': 220 prf->adj = 'l'; 221 goto more; 222 223 case '+': 224 pluspref = 1; 225 goto more; 226 227 case '*': 228 prf->width = va_arg(ap, int); 229 goto more; 230 231 case '0': case '1': case '2': case '3': case '4': 232 case '5': case '6': case '7': case '8': case '9': 233 for (n = c - '0'; isdigit(c = *s++);) 234 n = 10 * n + c - '0'; 235 prf->width = n; 236 goto sw; 237 238 case '.': 239 c = *s++; 240 if (c == '*') { 241 prf->prec = va_arg(ap, int); 242 goto more; 243 } 244 for (n = 0; isdigit(c); c = *s++) 245 n = 10 * n + c - '0'; 246 prf->prec = n; 247 goto sw; 248 249 case 'v': case 'V': 250 /* print in signed version of current radix */ 251 if ((n = radix) > 0) 252 n = -n; 253 goto rprint; 254 255 case 'q': case 'Q': n = -8; goto rprint; /* octal */ 256 case 'd': case 'D': n = -10; goto rprint; /* decimal */ 257 case 'z': case 'Z': n = -16; goto rprint; /* hex */ 258 case 'o': case 'O': n = 8; goto rprint; /* and */ 259 case 'u': case 'U': n = 10; goto rprint; /* unsigned */ 260 case 'x': case 'X': n = 16; goto rprint; /* versions */ 261 262 case 'r': case 'R': 263 n = radix; 264 rprint: 265 if (isupper(c)) 266 v = n < 0 ? SF_ARG : UF_ARG; 267 else 268 v = n < 0 ? SH_ARG : UH_ARG; 269 printradix(prf->buf, v, n, pluspref); 270 break; 271 272 case 'Y': 273 printdate(prf->buf, va_arg(ap, time_t)); 274 break; 275 276 case 'c': 277 *prf->buf = va_arg(ap, int); 278 prf->buf[1] = 0; 279 break; 280 281 case 's': 282 prf->buf = va_arg(ap, char *); 283 break; 284 285 case 'f': 286 /* here comes stdio ... sigh */ 287 (void) sprintf(prf->buf, "%+*.*e", prf->width, 288 prf->prec >= 0 ? prf->prec : 16, va_arg(ap, double)); 289 prf->prec = -1; 290 break; 291 292 case 'm': 293 prf->buf = null; 294 break; 295 296 case 't': 297 if (prf->width) 298 prf->width -= charpos() % prf->width; 299 prf->buf = null; 300 break; 301 302 case '?': 303 c = va_arg(ap, int); 304 prf->fmt = s; 305 prf->ap = ap; 306 dofmt(prf); 307 if (c == 0) 308 prf->buf = null; 309 return; 310 311 default: 312 panic("dofmt"); 313 /* NOTREACHED */ 314 } 315 prf->fmt = s; 316 prf->ap = ap; 317 } 318 319 /* 320 * Print the date into the buffer at `p'. 321 */ 322 static 323 printdate(p, tm) 324 register char *p; 325 time_t tm; 326 { 327 char *asc = ctime(&tm); 328 char *strncpy(); 329 330 (void) strncpy(p, asc + 20, 4); /* "1988" */ 331 (void) strncpy(p + 4, asc + 3, 16); /* " Aug 18 03:04:49" */ 332 p[20] = 0; 333 } 334 335 /* 336 * Print the value `val' in base `base' into the buffer at `p'. 337 * If base is negative, assume the number is signed. 338 */ 339 static 340 printradix(p, val, base, pluspref) 341 register char *p; 342 register expr_t val; 343 register int base; 344 int pluspref; 345 { 346 register char *d; 347 register expr_t high; 348 char digs[128]; /* good to 128 bits minimum */ 349 350 if (base < 0) { 351 base = -base; 352 if ((sexpr_t)val < 0) { 353 val = -val; 354 *p++ = '-'; 355 } else if (pluspref) 356 *p++ = '+'; 357 } else if (pluspref) 358 *p++ = '+'; 359 360 d = digs; 361 switch (base) { 362 363 case 8: 364 while (val != 0) { 365 *d++ = val & 7; 366 val >>= 3; 367 } 368 *d++ = 0; 369 break; 370 371 case 16: 372 do { 373 *d++ = val & 15; 374 } while ((val >>= 4) != 0); 375 break; 376 377 default: 378 do { 379 high = val / base; 380 *d++ = val - (high * base); 381 } while ((val = high) != 0); 382 break; 383 } 384 while (d > digs) 385 *p++ = "0123456789abcdef"[*--d]; 386 *p = 0; 387 } 388 389 /* 390 * BEGIN XXX 391 * THIS BELONGS ELSEWHERE 392 */ 393 #define MAXIFD 5 394 struct { 395 int fd; 396 expr_t v9; 397 } istack[MAXIFD]; 398 int ifiledepth; 399 400 iclose(stack, err) 401 int stack, err; 402 { 403 404 if (err) { 405 if (infile) { 406 (void) close(infile); 407 infile = 0; 408 } 409 while (--ifiledepth >= 0) 410 if (istack[ifiledepth].fd) 411 (void) close(istack[ifiledepth].fd); 412 ifiledepth = 0; 413 } else if (stack == 0) { 414 if (infile) { 415 (void) close(infile); 416 infile = 0; 417 } 418 } else if (stack > 0) { 419 if (ifiledepth >= MAXIFD) 420 error(TOODEEP); 421 istack[ifiledepth].fd = infile; 422 istack[ifiledepth].v9 = var[9]; 423 ifiledepth++; 424 infile = 0; 425 } else { 426 if (infile) { 427 (void) close(infile); 428 infile = 0; 429 } 430 if (ifiledepth > 0) { 431 infile = istack[--ifiledepth].fd; 432 var[9] = istack[ifiledepth].v9; 433 } 434 } 435 } 436 437 oclose() 438 { 439 440 if (outfile != 1) { 441 flushbuf(); 442 (void) close(outfile); 443 outfile = 1; 444 } 445 } 446