xref: /original-bsd/old/adb/common_source/output.c (revision fd52c9a2)
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