xref: /csrg-svn/old/adb/common_source/output.c (revision 47822)
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