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