1*47822Sbostic /*-
2*47822Sbostic * Copyright (c) 1991 The Regents of the University of California.
3*47822Sbostic * All rights reserved.
4*47822Sbostic *
5*47822Sbostic * %sccs.include.proprietary.c%
6*47822Sbostic */
7*47822Sbostic
836559Sbostic #ifndef lint
9*47822Sbostic static char sccsid[] = "@(#)output.c 5.2 (Berkeley) 04/04/91";
10*47822Sbostic #endif /* not lint */
1136559Sbostic
1236559Sbostic /*
1336559Sbostic * adb - output
1436559Sbostic */
1536559Sbostic
1636559Sbostic #include "defs.h"
1736559Sbostic #include <ctype.h>
1836559Sbostic #include <stdio.h>
1936559Sbostic #include <varargs.h>
2036559Sbostic
2136559Sbostic extern char TOODEEP[];
2236559Sbostic
2336559Sbostic int infile;
2436559Sbostic int outfile = 1;
2536559Sbostic
2636559Sbostic char printbuf[LINELEN];
2736559Sbostic char *printptr = printbuf;
2836559Sbostic
2936559Sbostic
3036559Sbostic /*
3136559Sbostic * Print the string s.
3236559Sbostic */
prints(s)3336559Sbostic prints(s)
3436559Sbostic register char *s;
3536559Sbostic {
3636559Sbostic register int c;
3736559Sbostic
3836559Sbostic while ((c = *s++) != '\0')
3936559Sbostic printc(c);
4036559Sbostic }
4136559Sbostic
4236559Sbostic /*
4336559Sbostic * Print the character c.
4436559Sbostic */
printc(c)4536559Sbostic printc(c)
4636559Sbostic int c;
4736559Sbostic {
4836559Sbostic
4936559Sbostic if (mkfault)
5036559Sbostic return;
5136559Sbostic switch (c) {
5236559Sbostic
5336559Sbostic case 0:
5436559Sbostic return;
5536559Sbostic
5636559Sbostic case '\n':
5736559Sbostic sendout();
5836559Sbostic return;
5936559Sbostic
6036559Sbostic default:
6136559Sbostic if (isprint(c))
6236559Sbostic *printptr++ = c;
6336559Sbostic break;
6436559Sbostic }
6536559Sbostic if (printptr >= &printbuf[LINELEN - 1]) /* 1 == space for \n */
6636559Sbostic sendout();
6736559Sbostic }
6836559Sbostic
6936559Sbostic /*
7036559Sbostic * Send (write) out the contents of the print buffer, compressing
7136559Sbostic * spaces into tabs.
7236559Sbostic */
7336559Sbostic static
sendout()7436559Sbostic sendout()
7536559Sbostic {
7636559Sbostic register char *p, *q;
7736559Sbostic register int c, off = 0, spaces = 0, s;
7836559Sbostic #define tabsize(x) (8 - ((x) & 7))
7936559Sbostic
8036559Sbostic for (q = p = printbuf; p < printptr;) {
8136559Sbostic c = *p++;
8236559Sbostic switch (c) {
8336559Sbostic
8436559Sbostic case ' ':
8536559Sbostic spaces++;
8636559Sbostic break;
8736559Sbostic
8836559Sbostic case '\t':
8936559Sbostic spaces += tabsize(off + spaces);
9036559Sbostic break;
9136559Sbostic
9236559Sbostic default:
9336559Sbostic s = tabsize(off);
9436559Sbostic off += spaces + 1;
9536559Sbostic while (spaces >= s) {
9636559Sbostic *q++ = '\t';
9736559Sbostic spaces -= s;
9836559Sbostic s = 8;
9936559Sbostic }
10036559Sbostic while (--spaces >= 0)
10136559Sbostic *q++ = ' ';
10236559Sbostic spaces = 0;
10336559Sbostic *q++ = c;
10436559Sbostic }
10536559Sbostic }
10636559Sbostic *q++ = '\n';
10736559Sbostic (void) write(outfile, printbuf, q - printbuf);
10836559Sbostic printptr = printbuf;
10936559Sbostic #undef tabsize
11036559Sbostic }
11136559Sbostic
charpos()11236559Sbostic charpos()
11336559Sbostic {
11436559Sbostic
11536559Sbostic return (printptr - printbuf);
11636559Sbostic }
11736559Sbostic
endline()11836559Sbostic endline()
11936559Sbostic {
12036559Sbostic
12136559Sbostic if (printptr - printbuf >= maxcol)
12236559Sbostic printc('\n');
12336559Sbostic }
12436559Sbostic
flushbuf()12536559Sbostic flushbuf()
12636559Sbostic {
12736559Sbostic
12836559Sbostic if (printptr != printbuf)
12936559Sbostic sendout();
13036559Sbostic }
13136559Sbostic
13236559Sbostic /* this should not be necessary! */
13336559Sbostic #ifdef lint
13436559Sbostic #undef va_arg
13536559Sbostic #define va_arg(ap, type) (ap = ap, (type)0)
13636559Sbostic #endif
13736559Sbostic
13836559Sbostic /*
13936559Sbostic * Context passed between adbprintf and decodefmt.
14036559Sbostic */
14136559Sbostic struct prf {
14236559Sbostic char *fmt; /* format pointer */
14336559Sbostic va_list ap; /* argument pointer */
14436559Sbostic char *buf; /* digit buffer, or %s string */
14536559Sbostic int adj; /* 'l'eft (-) or 'r'ight adjustment */
14636559Sbostic int width; /* width from format */
14736559Sbostic int prec; /* precision from format */
14836559Sbostic };
14936559Sbostic
15036559Sbostic /*
15136559Sbostic * adb's very own version of printf() ... of course, all the format
15236559Sbostic * escapes are different. Noteworthy are the %<width>m and %<tabstop>t
15336559Sbostic * formats, which move the given width, or to the given tabstop, and
15436559Sbostic * the %?a format, which evaluates one argument, and if not zero, prints
15536559Sbostic * according to format a. (Note that any modifiers must appear in the
15636559Sbostic * `a' part, not in the %? part.)
15736559Sbostic */
15836559Sbostic /* VARARGS1 */
adbprintf(fmt,va_alist)15936559Sbostic adbprintf(fmt, va_alist)
16036559Sbostic char *fmt;
16136559Sbostic va_dcl
16236559Sbostic {
16336559Sbostic register char *s;
16436559Sbostic register int n, c;
16536559Sbostic struct prf prf;
16636559Sbostic char digits[130]; /* good to at least 128 bit expr_t */
16736559Sbostic
16836559Sbostic /* set up the fields adbprf needs */
16936559Sbostic prf.fmt = fmt;
17036559Sbostic va_start(prf.ap);
17136559Sbostic for (;;) {
17236559Sbostic /* look for % conversions */
17336559Sbostic s = prf.fmt;
17436559Sbostic while ((c = *s++) != '%') {
17536559Sbostic if (c == 0)
17636559Sbostic return;
17736559Sbostic printc(c);
17836559Sbostic }
17936559Sbostic prf.fmt = s;
18036559Sbostic prf.buf = digits;
18136559Sbostic dofmt(&prf); /* format one format */
18236559Sbostic n = strlen(s = prf.buf);
18336559Sbostic if (prf.prec >= 0 && n > prf.prec)
18436559Sbostic n = prf.prec;
18536559Sbostic c = prf.width - n;
18636559Sbostic if (prf.adj == 'r')
18736559Sbostic while (--c >= 0)
18836559Sbostic printc(' ');
18936559Sbostic while (--n >= 0)
19036559Sbostic printc(*s++);
19136559Sbostic while (--c >= 0)
19236559Sbostic printc(' ');
19336559Sbostic }
19436559Sbostic va_end(prf.ap);
19536559Sbostic }
19636559Sbostic
19736559Sbostic /*
19836559Sbostic * Do a single format.
19936559Sbostic */
20036559Sbostic static
dofmt(prf)20136559Sbostic dofmt(prf)
20236559Sbostic register struct prf *prf;
20336559Sbostic {
20436559Sbostic register char *s = prf->fmt;
20536559Sbostic register va_list ap = prf->ap;
20636559Sbostic register int c, n;
20736559Sbostic expr_t v;
20836559Sbostic int pluspref = 0;
20936559Sbostic static char null[] = "";
21036559Sbostic
21136559Sbostic prf->adj = 'r';
21236559Sbostic prf->width = 0;
21336559Sbostic prf->prec = -1;
21436559Sbostic more:
21536559Sbostic c = *s++;
21636559Sbostic sw:
21736559Sbostic switch (c) {
21836559Sbostic
21936559Sbostic case '-':
22036559Sbostic prf->adj = 'l';
22136559Sbostic goto more;
22236559Sbostic
22336559Sbostic case '+':
22436559Sbostic pluspref = 1;
22536559Sbostic goto more;
22636559Sbostic
22736559Sbostic case '*':
22836559Sbostic prf->width = va_arg(ap, int);
22936559Sbostic goto more;
23036559Sbostic
23136559Sbostic case '0': case '1': case '2': case '3': case '4':
23236559Sbostic case '5': case '6': case '7': case '8': case '9':
23336559Sbostic for (n = c - '0'; isdigit(c = *s++);)
23436559Sbostic n = 10 * n + c - '0';
23536559Sbostic prf->width = n;
23636559Sbostic goto sw;
23736559Sbostic
23836559Sbostic case '.':
23936559Sbostic c = *s++;
24036559Sbostic if (c == '*') {
24136559Sbostic prf->prec = va_arg(ap, int);
24236559Sbostic goto more;
24336559Sbostic }
24436559Sbostic for (n = 0; isdigit(c); c = *s++)
24536559Sbostic n = 10 * n + c - '0';
24636559Sbostic prf->prec = n;
24736559Sbostic goto sw;
24836559Sbostic
24936559Sbostic case 'v': case 'V':
25036559Sbostic /* print in signed version of current radix */
25136559Sbostic if ((n = radix) > 0)
25236559Sbostic n = -n;
25336559Sbostic goto rprint;
25436559Sbostic
25536559Sbostic case 'q': case 'Q': n = -8; goto rprint; /* octal */
25636559Sbostic case 'd': case 'D': n = -10; goto rprint; /* decimal */
25736559Sbostic case 'z': case 'Z': n = -16; goto rprint; /* hex */
25836559Sbostic case 'o': case 'O': n = 8; goto rprint; /* and */
25936559Sbostic case 'u': case 'U': n = 10; goto rprint; /* unsigned */
26036559Sbostic case 'x': case 'X': n = 16; goto rprint; /* versions */
26136559Sbostic
26236559Sbostic case 'r': case 'R':
26336559Sbostic n = radix;
26436559Sbostic rprint:
26536559Sbostic if (isupper(c))
26636559Sbostic v = n < 0 ? SF_ARG : UF_ARG;
26736559Sbostic else
26836559Sbostic v = n < 0 ? SH_ARG : UH_ARG;
26936559Sbostic printradix(prf->buf, v, n, pluspref);
27036559Sbostic break;
27136559Sbostic
27236559Sbostic case 'Y':
27336559Sbostic printdate(prf->buf, va_arg(ap, time_t));
27436559Sbostic break;
27536559Sbostic
27636559Sbostic case 'c':
27736559Sbostic *prf->buf = va_arg(ap, int);
27836559Sbostic prf->buf[1] = 0;
27936559Sbostic break;
28036559Sbostic
28136559Sbostic case 's':
28236559Sbostic prf->buf = va_arg(ap, char *);
28336559Sbostic break;
28436559Sbostic
28536559Sbostic case 'f':
28636559Sbostic /* here comes stdio ... sigh */
28736559Sbostic (void) sprintf(prf->buf, "%+*.*e", prf->width,
28836559Sbostic prf->prec >= 0 ? prf->prec : 16, va_arg(ap, double));
28936559Sbostic prf->prec = -1;
29036559Sbostic break;
29136559Sbostic
29236559Sbostic case 'm':
29336559Sbostic prf->buf = null;
29436559Sbostic break;
29536559Sbostic
29636559Sbostic case 't':
29736559Sbostic if (prf->width)
29836559Sbostic prf->width -= charpos() % prf->width;
29936559Sbostic prf->buf = null;
30036559Sbostic break;
30136559Sbostic
30236559Sbostic case '?':
30336559Sbostic c = va_arg(ap, int);
30436559Sbostic prf->fmt = s;
30536559Sbostic prf->ap = ap;
30636559Sbostic dofmt(prf);
30736559Sbostic if (c == 0)
30836559Sbostic prf->buf = null;
30936559Sbostic return;
31036559Sbostic
31136559Sbostic default:
31236559Sbostic panic("dofmt");
31336559Sbostic /* NOTREACHED */
31436559Sbostic }
31536559Sbostic prf->fmt = s;
31636559Sbostic prf->ap = ap;
31736559Sbostic }
31836559Sbostic
31936559Sbostic /*
32036559Sbostic * Print the date into the buffer at `p'.
32136559Sbostic */
32236559Sbostic static
printdate(p,tm)32336559Sbostic printdate(p, tm)
32436559Sbostic register char *p;
32536559Sbostic time_t tm;
32636559Sbostic {
32736559Sbostic char *asc = ctime(&tm);
32836559Sbostic char *strncpy();
32936559Sbostic
33036559Sbostic (void) strncpy(p, asc + 20, 4); /* "1988" */
33136559Sbostic (void) strncpy(p + 4, asc + 3, 16); /* " Aug 18 03:04:49" */
33236559Sbostic p[20] = 0;
33336559Sbostic }
33436559Sbostic
33536559Sbostic /*
33636559Sbostic * Print the value `val' in base `base' into the buffer at `p'.
33736559Sbostic * If base is negative, assume the number is signed.
33836559Sbostic */
33936559Sbostic static
printradix(p,val,base,pluspref)34036559Sbostic printradix(p, val, base, pluspref)
34136559Sbostic register char *p;
34236559Sbostic register expr_t val;
34336559Sbostic register int base;
34436559Sbostic int pluspref;
34536559Sbostic {
34636559Sbostic register char *d;
34736559Sbostic register expr_t high;
34836559Sbostic char digs[128]; /* good to 128 bits minimum */
34936559Sbostic
35036559Sbostic if (base < 0) {
35136559Sbostic base = -base;
35236559Sbostic if ((sexpr_t)val < 0) {
35336559Sbostic val = -val;
35436559Sbostic *p++ = '-';
35536559Sbostic } else if (pluspref)
35636559Sbostic *p++ = '+';
35736559Sbostic } else if (pluspref)
35836559Sbostic *p++ = '+';
35936559Sbostic
36036559Sbostic d = digs;
36136559Sbostic switch (base) {
36236559Sbostic
36336559Sbostic case 8:
36436559Sbostic while (val != 0) {
36536559Sbostic *d++ = val & 7;
36636559Sbostic val >>= 3;
36736559Sbostic }
36836559Sbostic *d++ = 0;
36936559Sbostic break;
37036559Sbostic
37136559Sbostic case 16:
37236559Sbostic do {
37336559Sbostic *d++ = val & 15;
37436559Sbostic } while ((val >>= 4) != 0);
37536559Sbostic break;
37636559Sbostic
37736559Sbostic default:
37836559Sbostic do {
37936559Sbostic high = val / base;
38036559Sbostic *d++ = val - (high * base);
38136559Sbostic } while ((val = high) != 0);
38236559Sbostic break;
38336559Sbostic }
38436559Sbostic while (d > digs)
38536559Sbostic *p++ = "0123456789abcdef"[*--d];
38636559Sbostic *p = 0;
38736559Sbostic }
38836559Sbostic
38936559Sbostic /*
39036559Sbostic * BEGIN XXX
39136559Sbostic * THIS BELONGS ELSEWHERE
39236559Sbostic */
39336559Sbostic #define MAXIFD 5
39436559Sbostic struct {
39536559Sbostic int fd;
39636559Sbostic expr_t v9;
39736559Sbostic } istack[MAXIFD];
39836559Sbostic int ifiledepth;
39936559Sbostic
iclose(stack,err)40036559Sbostic iclose(stack, err)
40136559Sbostic int stack, err;
40236559Sbostic {
40336559Sbostic
40436559Sbostic if (err) {
40536559Sbostic if (infile) {
40636559Sbostic (void) close(infile);
40736559Sbostic infile = 0;
40836559Sbostic }
40936559Sbostic while (--ifiledepth >= 0)
41036559Sbostic if (istack[ifiledepth].fd)
41136559Sbostic (void) close(istack[ifiledepth].fd);
41236559Sbostic ifiledepth = 0;
41336559Sbostic } else if (stack == 0) {
41436559Sbostic if (infile) {
41536559Sbostic (void) close(infile);
41636559Sbostic infile = 0;
41736559Sbostic }
41836559Sbostic } else if (stack > 0) {
41936559Sbostic if (ifiledepth >= MAXIFD)
42036559Sbostic error(TOODEEP);
42136559Sbostic istack[ifiledepth].fd = infile;
42236559Sbostic istack[ifiledepth].v9 = var[9];
42336559Sbostic ifiledepth++;
42436559Sbostic infile = 0;
42536559Sbostic } else {
42636559Sbostic if (infile) {
42736559Sbostic (void) close(infile);
42836559Sbostic infile = 0;
42936559Sbostic }
43036559Sbostic if (ifiledepth > 0) {
43136559Sbostic infile = istack[--ifiledepth].fd;
43236559Sbostic var[9] = istack[ifiledepth].v9;
43336559Sbostic }
43436559Sbostic }
43536559Sbostic }
43636559Sbostic
oclose()43736559Sbostic oclose()
43836559Sbostic {
43936559Sbostic
44036559Sbostic if (outfile != 1) {
44136559Sbostic flushbuf();
44236559Sbostic (void) close(outfile);
44336559Sbostic outfile = 1;
44436559Sbostic }
44536559Sbostic }
446