1*fd52c9a2Sbostic /*-
2*fd52c9a2Sbostic * Copyright (c) 1991 The Regents of the University of California.
3*fd52c9a2Sbostic * All rights reserved.
4*fd52c9a2Sbostic *
5*fd52c9a2Sbostic * %sccs.include.proprietary.c%
6*fd52c9a2Sbostic */
7*fd52c9a2Sbostic
82d162a28Sbostic #ifndef lint
9*fd52c9a2Sbostic static char sccsid[] = "@(#)output.c 5.2 (Berkeley) 04/04/91";
10*fd52c9a2Sbostic #endif /* not lint */
112d162a28Sbostic
122d162a28Sbostic /*
132d162a28Sbostic * adb - output
142d162a28Sbostic */
152d162a28Sbostic
162d162a28Sbostic #include "defs.h"
172d162a28Sbostic #include <ctype.h>
182d162a28Sbostic #include <stdio.h>
192d162a28Sbostic #include <varargs.h>
202d162a28Sbostic
212d162a28Sbostic extern char TOODEEP[];
222d162a28Sbostic
232d162a28Sbostic int infile;
242d162a28Sbostic int outfile = 1;
252d162a28Sbostic
262d162a28Sbostic char printbuf[LINELEN];
272d162a28Sbostic char *printptr = printbuf;
282d162a28Sbostic
292d162a28Sbostic
302d162a28Sbostic /*
312d162a28Sbostic * Print the string s.
322d162a28Sbostic */
prints(s)332d162a28Sbostic prints(s)
342d162a28Sbostic register char *s;
352d162a28Sbostic {
362d162a28Sbostic register int c;
372d162a28Sbostic
382d162a28Sbostic while ((c = *s++) != '\0')
392d162a28Sbostic printc(c);
402d162a28Sbostic }
412d162a28Sbostic
422d162a28Sbostic /*
432d162a28Sbostic * Print the character c.
442d162a28Sbostic */
printc(c)452d162a28Sbostic printc(c)
462d162a28Sbostic int c;
472d162a28Sbostic {
482d162a28Sbostic
492d162a28Sbostic if (mkfault)
502d162a28Sbostic return;
512d162a28Sbostic switch (c) {
522d162a28Sbostic
532d162a28Sbostic case 0:
542d162a28Sbostic return;
552d162a28Sbostic
562d162a28Sbostic case '\n':
572d162a28Sbostic sendout();
582d162a28Sbostic return;
592d162a28Sbostic
602d162a28Sbostic default:
612d162a28Sbostic if (isprint(c))
622d162a28Sbostic *printptr++ = c;
632d162a28Sbostic break;
642d162a28Sbostic }
652d162a28Sbostic if (printptr >= &printbuf[LINELEN - 1]) /* 1 == space for \n */
662d162a28Sbostic sendout();
672d162a28Sbostic }
682d162a28Sbostic
692d162a28Sbostic /*
702d162a28Sbostic * Send (write) out the contents of the print buffer, compressing
712d162a28Sbostic * spaces into tabs.
722d162a28Sbostic */
732d162a28Sbostic static
sendout()742d162a28Sbostic sendout()
752d162a28Sbostic {
762d162a28Sbostic register char *p, *q;
772d162a28Sbostic register int c, off = 0, spaces = 0, s;
782d162a28Sbostic #define tabsize(x) (8 - ((x) & 7))
792d162a28Sbostic
802d162a28Sbostic for (q = p = printbuf; p < printptr;) {
812d162a28Sbostic c = *p++;
822d162a28Sbostic switch (c) {
832d162a28Sbostic
842d162a28Sbostic case ' ':
852d162a28Sbostic spaces++;
862d162a28Sbostic break;
872d162a28Sbostic
882d162a28Sbostic case '\t':
892d162a28Sbostic spaces += tabsize(off + spaces);
902d162a28Sbostic break;
912d162a28Sbostic
922d162a28Sbostic default:
932d162a28Sbostic s = tabsize(off);
942d162a28Sbostic off += spaces + 1;
952d162a28Sbostic while (spaces >= s) {
962d162a28Sbostic *q++ = '\t';
972d162a28Sbostic spaces -= s;
982d162a28Sbostic s = 8;
992d162a28Sbostic }
1002d162a28Sbostic while (--spaces >= 0)
1012d162a28Sbostic *q++ = ' ';
1022d162a28Sbostic spaces = 0;
1032d162a28Sbostic *q++ = c;
1042d162a28Sbostic }
1052d162a28Sbostic }
1062d162a28Sbostic *q++ = '\n';
1072d162a28Sbostic (void) write(outfile, printbuf, q - printbuf);
1082d162a28Sbostic printptr = printbuf;
1092d162a28Sbostic #undef tabsize
1102d162a28Sbostic }
1112d162a28Sbostic
charpos()1122d162a28Sbostic charpos()
1132d162a28Sbostic {
1142d162a28Sbostic
1152d162a28Sbostic return (printptr - printbuf);
1162d162a28Sbostic }
1172d162a28Sbostic
endline()1182d162a28Sbostic endline()
1192d162a28Sbostic {
1202d162a28Sbostic
1212d162a28Sbostic if (printptr - printbuf >= maxcol)
1222d162a28Sbostic printc('\n');
1232d162a28Sbostic }
1242d162a28Sbostic
flushbuf()1252d162a28Sbostic flushbuf()
1262d162a28Sbostic {
1272d162a28Sbostic
1282d162a28Sbostic if (printptr != printbuf)
1292d162a28Sbostic sendout();
1302d162a28Sbostic }
1312d162a28Sbostic
1322d162a28Sbostic /* this should not be necessary! */
1332d162a28Sbostic #ifdef lint
1342d162a28Sbostic #undef va_arg
1352d162a28Sbostic #define va_arg(ap, type) (ap = ap, (type)0)
1362d162a28Sbostic #endif
1372d162a28Sbostic
1382d162a28Sbostic /*
1392d162a28Sbostic * Context passed between adbprintf and decodefmt.
1402d162a28Sbostic */
1412d162a28Sbostic struct prf {
1422d162a28Sbostic char *fmt; /* format pointer */
1432d162a28Sbostic va_list ap; /* argument pointer */
1442d162a28Sbostic char *buf; /* digit buffer, or %s string */
1452d162a28Sbostic int adj; /* 'l'eft (-) or 'r'ight adjustment */
1462d162a28Sbostic int width; /* width from format */
1472d162a28Sbostic int prec; /* precision from format */
1482d162a28Sbostic };
1492d162a28Sbostic
1502d162a28Sbostic /*
1512d162a28Sbostic * adb's very own version of printf() ... of course, all the format
1522d162a28Sbostic * escapes are different. Noteworthy are the %<width>m and %<tabstop>t
1532d162a28Sbostic * formats, which move the given width, or to the given tabstop, and
1542d162a28Sbostic * the %?a format, which evaluates one argument, and if not zero, prints
1552d162a28Sbostic * according to format a. (Note that any modifiers must appear in the
1562d162a28Sbostic * `a' part, not in the %? part.)
1572d162a28Sbostic */
1582d162a28Sbostic /* VARARGS1 */
adbprintf(fmt,va_alist)1592d162a28Sbostic adbprintf(fmt, va_alist)
1602d162a28Sbostic char *fmt;
1612d162a28Sbostic va_dcl
1622d162a28Sbostic {
1632d162a28Sbostic register char *s;
1642d162a28Sbostic register int n, c;
1652d162a28Sbostic struct prf prf;
1662d162a28Sbostic char digits[130]; /* good to at least 128 bit expr_t */
1672d162a28Sbostic
1682d162a28Sbostic /* set up the fields adbprf needs */
1692d162a28Sbostic prf.fmt = fmt;
1702d162a28Sbostic va_start(prf.ap);
1712d162a28Sbostic for (;;) {
1722d162a28Sbostic /* look for % conversions */
1732d162a28Sbostic s = prf.fmt;
1742d162a28Sbostic while ((c = *s++) != '%') {
1752d162a28Sbostic if (c == 0)
1762d162a28Sbostic return;
1772d162a28Sbostic printc(c);
1782d162a28Sbostic }
1792d162a28Sbostic prf.fmt = s;
1802d162a28Sbostic prf.buf = digits;
1812d162a28Sbostic dofmt(&prf); /* format one format */
1822d162a28Sbostic n = strlen(s = prf.buf);
1832d162a28Sbostic if (prf.prec >= 0 && n > prf.prec)
1842d162a28Sbostic n = prf.prec;
1852d162a28Sbostic c = prf.width - n;
1862d162a28Sbostic if (prf.adj == 'r')
1872d162a28Sbostic while (--c >= 0)
1882d162a28Sbostic printc(' ');
1892d162a28Sbostic while (--n >= 0)
1902d162a28Sbostic printc(*s++);
1912d162a28Sbostic while (--c >= 0)
1922d162a28Sbostic printc(' ');
1932d162a28Sbostic }
1942d162a28Sbostic va_end(prf.ap);
1952d162a28Sbostic }
1962d162a28Sbostic
1972d162a28Sbostic /*
1982d162a28Sbostic * Do a single format.
1992d162a28Sbostic */
2002d162a28Sbostic static
dofmt(prf)2012d162a28Sbostic dofmt(prf)
2022d162a28Sbostic register struct prf *prf;
2032d162a28Sbostic {
2042d162a28Sbostic register char *s = prf->fmt;
2052d162a28Sbostic register va_list ap = prf->ap;
2062d162a28Sbostic register int c, n;
2072d162a28Sbostic expr_t v;
2082d162a28Sbostic int pluspref = 0;
2092d162a28Sbostic static char null[] = "";
2102d162a28Sbostic
2112d162a28Sbostic prf->adj = 'r';
2122d162a28Sbostic prf->width = 0;
2132d162a28Sbostic prf->prec = -1;
2142d162a28Sbostic more:
2152d162a28Sbostic c = *s++;
2162d162a28Sbostic sw:
2172d162a28Sbostic switch (c) {
2182d162a28Sbostic
2192d162a28Sbostic case '-':
2202d162a28Sbostic prf->adj = 'l';
2212d162a28Sbostic goto more;
2222d162a28Sbostic
2232d162a28Sbostic case '+':
2242d162a28Sbostic pluspref = 1;
2252d162a28Sbostic goto more;
2262d162a28Sbostic
2272d162a28Sbostic case '*':
2282d162a28Sbostic prf->width = va_arg(ap, int);
2292d162a28Sbostic goto more;
2302d162a28Sbostic
2312d162a28Sbostic case '0': case '1': case '2': case '3': case '4':
2322d162a28Sbostic case '5': case '6': case '7': case '8': case '9':
2332d162a28Sbostic for (n = c - '0'; isdigit(c = *s++);)
2342d162a28Sbostic n = 10 * n + c - '0';
2352d162a28Sbostic prf->width = n;
2362d162a28Sbostic goto sw;
2372d162a28Sbostic
2382d162a28Sbostic case '.':
2392d162a28Sbostic c = *s++;
2402d162a28Sbostic if (c == '*') {
2412d162a28Sbostic prf->prec = va_arg(ap, int);
2422d162a28Sbostic goto more;
2432d162a28Sbostic }
2442d162a28Sbostic for (n = 0; isdigit(c); c = *s++)
2452d162a28Sbostic n = 10 * n + c - '0';
2462d162a28Sbostic prf->prec = n;
2472d162a28Sbostic goto sw;
2482d162a28Sbostic
2492d162a28Sbostic case 'v': case 'V':
2502d162a28Sbostic /* print in signed version of current radix */
2512d162a28Sbostic if ((n = radix) > 0)
2522d162a28Sbostic n = -n;
2532d162a28Sbostic goto rprint;
2542d162a28Sbostic
2552d162a28Sbostic case 'q': case 'Q': n = -8; goto rprint; /* octal */
2562d162a28Sbostic case 'd': case 'D': n = -10; goto rprint; /* decimal */
2572d162a28Sbostic case 'z': case 'Z': n = -16; goto rprint; /* hex */
2582d162a28Sbostic case 'o': case 'O': n = 8; goto rprint; /* and */
2592d162a28Sbostic case 'u': case 'U': n = 10; goto rprint; /* unsigned */
2602d162a28Sbostic case 'x': case 'X': n = 16; goto rprint; /* versions */
2612d162a28Sbostic
2622d162a28Sbostic case 'r': case 'R':
2632d162a28Sbostic n = radix;
2642d162a28Sbostic rprint:
2652d162a28Sbostic if (isupper(c))
2662d162a28Sbostic v = n < 0 ? SF_ARG : UF_ARG;
2672d162a28Sbostic else
2682d162a28Sbostic v = n < 0 ? SH_ARG : UH_ARG;
2692d162a28Sbostic printradix(prf->buf, v, n, pluspref);
2702d162a28Sbostic break;
2712d162a28Sbostic
2722d162a28Sbostic case 'Y':
2732d162a28Sbostic printdate(prf->buf, va_arg(ap, time_t));
2742d162a28Sbostic break;
2752d162a28Sbostic
2762d162a28Sbostic case 'c':
2772d162a28Sbostic *prf->buf = va_arg(ap, int);
2782d162a28Sbostic prf->buf[1] = 0;
2792d162a28Sbostic break;
2802d162a28Sbostic
2812d162a28Sbostic case 's':
2822d162a28Sbostic prf->buf = va_arg(ap, char *);
2832d162a28Sbostic break;
2842d162a28Sbostic
2852d162a28Sbostic case 'f':
2862d162a28Sbostic /* here comes stdio ... sigh */
2872d162a28Sbostic (void) sprintf(prf->buf, "%+*.*e", prf->width,
2882d162a28Sbostic prf->prec >= 0 ? prf->prec : 16, va_arg(ap, double));
2892d162a28Sbostic prf->prec = -1;
2902d162a28Sbostic break;
2912d162a28Sbostic
2922d162a28Sbostic case 'm':
2932d162a28Sbostic prf->buf = null;
2942d162a28Sbostic break;
2952d162a28Sbostic
2962d162a28Sbostic case 't':
2972d162a28Sbostic if (prf->width)
2982d162a28Sbostic prf->width -= charpos() % prf->width;
2992d162a28Sbostic prf->buf = null;
3002d162a28Sbostic break;
3012d162a28Sbostic
3022d162a28Sbostic case '?':
3032d162a28Sbostic c = va_arg(ap, int);
3042d162a28Sbostic prf->fmt = s;
3052d162a28Sbostic prf->ap = ap;
3062d162a28Sbostic dofmt(prf);
3072d162a28Sbostic if (c == 0)
3082d162a28Sbostic prf->buf = null;
3092d162a28Sbostic return;
3102d162a28Sbostic
3112d162a28Sbostic default:
3122d162a28Sbostic panic("dofmt");
3132d162a28Sbostic /* NOTREACHED */
3142d162a28Sbostic }
3152d162a28Sbostic prf->fmt = s;
3162d162a28Sbostic prf->ap = ap;
3172d162a28Sbostic }
3182d162a28Sbostic
3192d162a28Sbostic /*
3202d162a28Sbostic * Print the date into the buffer at `p'.
3212d162a28Sbostic */
3222d162a28Sbostic static
printdate(p,tm)3232d162a28Sbostic printdate(p, tm)
3242d162a28Sbostic register char *p;
3252d162a28Sbostic time_t tm;
3262d162a28Sbostic {
3272d162a28Sbostic char *asc = ctime(&tm);
3282d162a28Sbostic char *strncpy();
3292d162a28Sbostic
3302d162a28Sbostic (void) strncpy(p, asc + 20, 4); /* "1988" */
3312d162a28Sbostic (void) strncpy(p + 4, asc + 3, 16); /* " Aug 18 03:04:49" */
3322d162a28Sbostic p[20] = 0;
3332d162a28Sbostic }
3342d162a28Sbostic
3352d162a28Sbostic /*
3362d162a28Sbostic * Print the value `val' in base `base' into the buffer at `p'.
3372d162a28Sbostic * If base is negative, assume the number is signed.
3382d162a28Sbostic */
3392d162a28Sbostic static
printradix(p,val,base,pluspref)3402d162a28Sbostic printradix(p, val, base, pluspref)
3412d162a28Sbostic register char *p;
3422d162a28Sbostic register expr_t val;
3432d162a28Sbostic register int base;
3442d162a28Sbostic int pluspref;
3452d162a28Sbostic {
3462d162a28Sbostic register char *d;
3472d162a28Sbostic register expr_t high;
3482d162a28Sbostic char digs[128]; /* good to 128 bits minimum */
3492d162a28Sbostic
3502d162a28Sbostic if (base < 0) {
3512d162a28Sbostic base = -base;
3522d162a28Sbostic if ((sexpr_t)val < 0) {
3532d162a28Sbostic val = -val;
3542d162a28Sbostic *p++ = '-';
3552d162a28Sbostic } else if (pluspref)
3562d162a28Sbostic *p++ = '+';
3572d162a28Sbostic } else if (pluspref)
3582d162a28Sbostic *p++ = '+';
3592d162a28Sbostic
3602d162a28Sbostic d = digs;
3612d162a28Sbostic switch (base) {
3622d162a28Sbostic
3632d162a28Sbostic case 8:
3642d162a28Sbostic while (val != 0) {
3652d162a28Sbostic *d++ = val & 7;
3662d162a28Sbostic val >>= 3;
3672d162a28Sbostic }
3682d162a28Sbostic *d++ = 0;
3692d162a28Sbostic break;
3702d162a28Sbostic
3712d162a28Sbostic case 16:
3722d162a28Sbostic do {
3732d162a28Sbostic *d++ = val & 15;
3742d162a28Sbostic } while ((val >>= 4) != 0);
3752d162a28Sbostic break;
3762d162a28Sbostic
3772d162a28Sbostic default:
3782d162a28Sbostic do {
3792d162a28Sbostic high = val / base;
3802d162a28Sbostic *d++ = val - (high * base);
3812d162a28Sbostic } while ((val = high) != 0);
3822d162a28Sbostic break;
3832d162a28Sbostic }
3842d162a28Sbostic while (d > digs)
3852d162a28Sbostic *p++ = "0123456789abcdef"[*--d];
3862d162a28Sbostic *p = 0;
3872d162a28Sbostic }
3882d162a28Sbostic
3892d162a28Sbostic /*
3902d162a28Sbostic * BEGIN XXX
3912d162a28Sbostic * THIS BELONGS ELSEWHERE
3922d162a28Sbostic */
3932d162a28Sbostic #define MAXIFD 5
3942d162a28Sbostic struct {
3952d162a28Sbostic int fd;
3962d162a28Sbostic expr_t v9;
3972d162a28Sbostic } istack[MAXIFD];
3982d162a28Sbostic int ifiledepth;
3992d162a28Sbostic
iclose(stack,err)4002d162a28Sbostic iclose(stack, err)
4012d162a28Sbostic int stack, err;
4022d162a28Sbostic {
4032d162a28Sbostic
4042d162a28Sbostic if (err) {
4052d162a28Sbostic if (infile) {
4062d162a28Sbostic (void) close(infile);
4072d162a28Sbostic infile = 0;
4082d162a28Sbostic }
4092d162a28Sbostic while (--ifiledepth >= 0)
4102d162a28Sbostic if (istack[ifiledepth].fd)
4112d162a28Sbostic (void) close(istack[ifiledepth].fd);
4122d162a28Sbostic ifiledepth = 0;
4132d162a28Sbostic } else if (stack == 0) {
4142d162a28Sbostic if (infile) {
4152d162a28Sbostic (void) close(infile);
4162d162a28Sbostic infile = 0;
4172d162a28Sbostic }
4182d162a28Sbostic } else if (stack > 0) {
4192d162a28Sbostic if (ifiledepth >= MAXIFD)
4202d162a28Sbostic error(TOODEEP);
4212d162a28Sbostic istack[ifiledepth].fd = infile;
4222d162a28Sbostic istack[ifiledepth].v9 = var[9];
4232d162a28Sbostic ifiledepth++;
4242d162a28Sbostic infile = 0;
4252d162a28Sbostic } else {
4262d162a28Sbostic if (infile) {
4272d162a28Sbostic (void) close(infile);
4282d162a28Sbostic infile = 0;
4292d162a28Sbostic }
4302d162a28Sbostic if (ifiledepth > 0) {
4312d162a28Sbostic infile = istack[--ifiledepth].fd;
4322d162a28Sbostic var[9] = istack[ifiledepth].v9;
4332d162a28Sbostic }
4342d162a28Sbostic }
4352d162a28Sbostic }
4362d162a28Sbostic
oclose()4372d162a28Sbostic oclose()
4382d162a28Sbostic {
4392d162a28Sbostic
4402d162a28Sbostic if (outfile != 1) {
4412d162a28Sbostic flushbuf();
4422d162a28Sbostic (void) close(outfile);
4432d162a28Sbostic outfile = 1;
4442d162a28Sbostic }
4452d162a28Sbostic }
446