xref: /csrg-svn/old/adb/common_source/format.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[] = "@(#)format.c	5.4 (Berkeley) 04/04/91";
10*47822Sbostic #endif /* not lint */
1136559Sbostic 
1236559Sbostic /*
1336559Sbostic  * adb - formats
1436559Sbostic  */
1536559Sbostic 
1636559Sbostic #include "defs.h"
1736559Sbostic #include <ctype.h>
1844636Smarc #include <vis.h>
1936559Sbostic 
2036559Sbostic extern char BADMOD[];
2136559Sbostic extern char NOFORK[];
2236559Sbostic 
2336559Sbostic /* symbol desirability in exform() */
2436559Sbostic enum { IFEXACT, ALWAYS, NEVER } wantsym;
2536559Sbostic 
2636559Sbostic char	*exform();
2736559Sbostic 
2836559Sbostic /*
2936559Sbostic  * Execute the given format `ecount' times.
3036559Sbostic  */
scanform(forcesym,fmt,space,ptype)3136559Sbostic scanform(forcesym, fmt, space, ptype)
3236559Sbostic 	int forcesym;
3336559Sbostic 	char *fmt;
3436559Sbostic 	int space, ptype;
3536559Sbostic {
3636559Sbostic 	register char *p;
3736559Sbostic 	register int c, n;
3836559Sbostic 	register expr_t ntimes = ecount;
3936559Sbostic 	addr_t savdot, newdot;
4036559Sbostic 
4136559Sbostic 	if (ntimes == 0)
4236559Sbostic 		return;
4336559Sbostic 	for (wantsym = forcesym ? ALWAYS : IFEXACT;; wantsym = IFEXACT) {
4436559Sbostic 		p = fmt;
4536559Sbostic 		savdot = dot;
4636559Sbostic 		while (p != NULL) {	/* loop over format items */
4736559Sbostic 			n = 0;		/* get optional count */
4836559Sbostic 			while (isdigit(c = *p++))
4936559Sbostic 				n = n * 10 + c - '0';
5036559Sbostic 			if (c == 0)	/* end of format */
5136559Sbostic 				break;
5236559Sbostic 			p = exform(n ? n : 1, p - (c != '\\'), space, ptype);
5336559Sbostic 		}
5436559Sbostic 		dotinc = (newdot = dot) - savdot;
5536559Sbostic 		dot = savdot;
5636559Sbostic 		if (errflag != NULL && (long)ntimes < 0) {
5736559Sbostic 			errflag = NULL;
5836559Sbostic 			break;
5936559Sbostic 		}
6036559Sbostic 		checkerr();
6136559Sbostic 		if (--ntimes == 0)
6236559Sbostic 			break;
6336559Sbostic 		dot = newdot;
6436559Sbostic 	}
6536559Sbostic }
6636559Sbostic 
6736559Sbostic /*
6836559Sbostic  * Print a halfword or a word from dot.
6936559Sbostic  */
showdot(fullword,space,ptype)7036559Sbostic showdot(fullword, space, ptype)
7136559Sbostic 	int fullword, space, ptype;
7236559Sbostic {
7336559Sbostic 	char c = fullword ? '4' : '2';
7436559Sbostic 
7536559Sbostic 	wantsym = NEVER;
7636559Sbostic 	(void) exform(1, &c, space, ptype);
7736559Sbostic }
7836559Sbostic 
7936559Sbostic /*
8036559Sbostic  * The following are used inside exform().
8136559Sbostic  *
8236559Sbostic  * The various FT_ values specify the type of the object accessed
8336559Sbostic  * by some format character.  FT_DULL indicates that no object is
8436559Sbostic  * accessed (or that it is done in some peculiar way).
8536559Sbostic  * The fsize array holds the size (in bytes)
8636559Sbostic  * of each of those types; the fmttypes[] array lists the type for
8736559Sbostic  * each character.  To save space, since there are many characters
8836559Sbostic  * for some of the types, they are stored as strings.
8936559Sbostic  */
9036559Sbostic enum { FT_DULL, FT_CHAR, FT_HW, FT_FW, FT_ADDR, FT_FLT, FT_DBL, FT_TM };
9136559Sbostic 	/* these may have to be turned into `#define's */
9236559Sbostic 
9336559Sbostic static char fsize[] = {		/* ordered by enumeration above! */
9436559Sbostic 	0, sizeof(char), sizeof(hword_t), sizeof(expr_t),
9536559Sbostic 	sizeof(addr_t), sizeof(float), sizeof(double), sizeof(time_t)
9636559Sbostic };
9736559Sbostic 
9836559Sbostic static struct fmttypes {
9936559Sbostic 	char	*ft_chars;
10036559Sbostic 	int	ft_type;
10136559Sbostic } fmttypes[] = {
10236559Sbostic 	{ "\t\" +-NRST^inrst", FT_DULL },
10336559Sbostic 	{ "1BCbc", FT_CHAR },
10436559Sbostic 	{ "2doquvxz", FT_HW },
10536559Sbostic 	{ "4DOQUVXZ", FT_FW },
10636559Sbostic 	{ "p", FT_ADDR },
10736559Sbostic 	{ "f", FT_FLT },
10836559Sbostic 	{ "F", FT_DBL },
10936559Sbostic 	{ "Y", FT_TM },
11036559Sbostic 	0
11136559Sbostic };
11236559Sbostic 
11336559Sbostic /*
11436559Sbostic  * Execute a single format item `fcount' times; set
11536559Sbostic  * dotinc and move dot.  Return the address of the next
11636559Sbostic  * format item, or NULL upon error reading an object.
11736559Sbostic  *
11836559Sbostic  * I must apologise for the length of this routine, but
11936559Sbostic  * it is bloated mainly with type correctness.
12036559Sbostic  */
12136559Sbostic char *
exform(fcount,fmt,space,ptype)12236559Sbostic exform(fcount, fmt, space, ptype)
12336559Sbostic 	int fcount;
12436559Sbostic 	char *fmt;
12536559Sbostic 	int space, ptype;
12636559Sbostic {
12736559Sbostic 	register struct fmttypes *ftp;
12836559Sbostic 	register int sz;
12936559Sbostic 	register char *p, *s, fmtchar;
13036559Sbostic 	addr_t savdot, off;
13136559Sbostic 	struct nlist *sp;
13236559Sbostic 	union {
13336559Sbostic 		char c;
13436559Sbostic 		hword_t hw;
13536559Sbostic 		expr_t fw;
13636559Sbostic 		float f;
13736559Sbostic 		double d;
13836559Sbostic 		time_t tm;
13936559Sbostic 		addr_t a;
14036559Sbostic 	} obj;
14136559Sbostic 
14236559Sbostic 	while (fcount > 0) {
14336559Sbostic 		/*
14436559Sbostic 		 * First decode the type to be used with the expression.
14536559Sbostic 		 * If address, print dot as a symbol, save it in var 0,
14636559Sbostic 		 * and bypass all the nonsense.
14736559Sbostic 		 */
14836559Sbostic 		p = fmt;
14936559Sbostic 		fmtchar = *p++;
15036559Sbostic 
15136559Sbostic 		/* address: special */
15236559Sbostic 		if (fmtchar == 'a') {
15336559Sbostic 			pdot();
15436559Sbostic 			wantsym = NEVER;	/* well, hardly ever */
15536559Sbostic 			var[0] = dot;
15636559Sbostic 			return (p);
15736559Sbostic 		}
15836559Sbostic 
15936559Sbostic 		for (ftp = fmttypes; (s = ftp->ft_chars) != NULL; ftp++)
16036559Sbostic 			while (*s != 0)
16136559Sbostic 				if (*s++ == fmtchar)
16236559Sbostic 					goto found;
16336559Sbostic 		error(BADMOD);
16436559Sbostic 		/* NOTREACHED */
16536559Sbostic found:
16636559Sbostic 
16736559Sbostic 		/* plop out a symbol, if desired */
16836559Sbostic 		if (wantsym == ALWAYS)
16936559Sbostic 			pdot();
17036559Sbostic 		else if (wantsym == IFEXACT &&
17136559Sbostic 		    (sp = findsym(dot, ptype, &off)) != NULL && off == 0)
17236559Sbostic 			adbprintf("\n%s:%16t", sp->n_un.n_name); /* \n ??? */
17336559Sbostic 		wantsym = NEVER;
17436559Sbostic 
17536559Sbostic 		/*
17636559Sbostic 		 * Now read the sort of object we decided fmtchar represents,
17736559Sbostic 		 * or compute it from the expression given for dot.
17836559Sbostic 		 */
17936559Sbostic 		sz = fsize[ftp->ft_type];
18036559Sbostic 		if (space != SP_NONE) {
18136559Sbostic 			/* can just read into the union */
18236559Sbostic 			if (sz != 0)
18336559Sbostic 				(void) adbread(space, dot, &obj, sz);
18436559Sbostic 			else
18536559Sbostic 				obj.fw = edot;
18636559Sbostic 		} else {
18736559Sbostic 			/* must decode type in order to assign, alas */
18836559Sbostic 			switch (ftp->ft_type) {
18936559Sbostic 
19036559Sbostic 			case FT_CHAR:
19136559Sbostic 				obj.c = edot;
19236559Sbostic 				break;
19336559Sbostic 
19436559Sbostic 			case FT_HW:
19536559Sbostic 				obj.hw = edot;
19636559Sbostic 				break;
19736559Sbostic 
19836559Sbostic 			case FT_FW:
19936559Sbostic 				obj.fw = edot;
20036559Sbostic 				break;
20136559Sbostic 
20236559Sbostic 			case FT_DULL:
20336559Sbostic 			case FT_ADDR:
20436559Sbostic 				obj.a = dot;
20536559Sbostic 				break;
20636559Sbostic 
20736559Sbostic 			case FT_FLT:
20836559Sbostic 			case FT_DBL:
20936559Sbostic 				obj.fw = 0;
21036559Sbostic 				etofloat(edot, &obj.c, ftp->ft_type == FT_DBL);
21136559Sbostic 				break;
21236559Sbostic 
21336559Sbostic 			case FT_TM:
21436559Sbostic 				obj.fw = 0;
21536559Sbostic 				obj.tm = edot;
21636559Sbostic 				break;
21736559Sbostic 
21836559Sbostic 			default:
21936559Sbostic 				panic("exform 1");
22036559Sbostic 				/* NOTREACHED */
22136559Sbostic 			}
22236559Sbostic 		}
22336559Sbostic 
22436559Sbostic 		/* if we could not read the object, stop now. */
22536559Sbostic 		if (errflag)
22636559Sbostic 			return (NULL);
22736559Sbostic 		if (mkfault)
22836559Sbostic 			error((char *)NULL);
22936559Sbostic 
23036559Sbostic 		/*
23136559Sbostic 		 * Now copy the value read (or assigned) to var[0].
23236559Sbostic 		 * Here some of the types are collapsed: since the
23336559Sbostic 		 * idea is to be able to get the value back later
23436559Sbostic 		 * by reading var[0] and going through the type
23536559Sbostic 		 * decoding above, it sometimes suffices to record
23636559Sbostic 		 * as many bits as fit in an expr_t (see expr.c).
23736559Sbostic 		 *
23836559Sbostic 		 * Note that double precision numbers generally lose
23936559Sbostic 		 * bits, since sizeof(double) can be > sizeof(expr_t).
24036559Sbostic 		 */
24136559Sbostic 		switch (ftp->ft_type) {
24236559Sbostic 
24336559Sbostic 		case FT_CHAR:
24436559Sbostic 			var[0] = obj.c;
24536559Sbostic 			break;
24636559Sbostic 
24736559Sbostic 		case FT_HW:
24836559Sbostic 			var[0] = obj.hw;
24936559Sbostic 			break;
25036559Sbostic 
25136559Sbostic 		case FT_FW:
25236559Sbostic 		case FT_FLT:
25336559Sbostic 		case FT_DBL:
25436559Sbostic 		case FT_TM:
25536559Sbostic 			var[0] = obj.fw;
25636559Sbostic 			break;
25736559Sbostic 
25836559Sbostic 		case FT_DULL:
25936559Sbostic 		case FT_ADDR:
26036559Sbostic 			var[0] = obj.a;
26136559Sbostic 			break;
26236559Sbostic 
26336559Sbostic 		default:
26436559Sbostic 			panic("exform 2");
26536559Sbostic 			/* NOTREACHED */
26636559Sbostic 		}
26736559Sbostic 
26836559Sbostic 		/* set the size, if this object has a size */
26936559Sbostic 		if (sz)
27036559Sbostic 			dotinc = sz;
27136559Sbostic 
27236559Sbostic 		/* finally, do the command */
27336559Sbostic 		if (charpos() == 0)
27436559Sbostic 			adbprintf("%16m");
27536559Sbostic 		switch (fmtchar) {
27636559Sbostic 			/*
27736559Sbostic 			 * Many of the formats translate to a %-8 or %-16
27836559Sbostic 			 * edition of themselves; we use a single string,
27936559Sbostic 			 * and modify the format part, for these.
28036559Sbostic 			 */
28136559Sbostic 			static char cfmt[] = "%-*?";
28236559Sbostic 
28336559Sbostic 		case ' ':
28436559Sbostic 		case '\t':
28536559Sbostic 			dotinc = 0;
28636559Sbostic 			break;
28736559Sbostic 
28836559Sbostic 		case 't':
28936559Sbostic 		case 'T':
29036559Sbostic 			adbprintf("%*t", fcount);
29136559Sbostic 			return (p);
29236559Sbostic 
29336559Sbostic 		case 'r':
29436559Sbostic 		case 'R':
29536559Sbostic 			adbprintf("%*m", fcount);
29636559Sbostic 			return (p);
29736559Sbostic 
29836559Sbostic 		case 'p':
29936559Sbostic 			psymoff("%R", obj.a, ptype, maxoff, "%16t");
30036559Sbostic 			break;
30136559Sbostic 
30236559Sbostic 		case 'c':
30336559Sbostic 			printc(obj.c);
30436559Sbostic 			break;
30536559Sbostic 
30636559Sbostic 		case 'C':
30736559Sbostic 			printesc(obj.c);
30836559Sbostic 			break;
30936559Sbostic 
31036559Sbostic 		case 'b':
31136559Sbostic 		case 'B':
31236559Sbostic 			adbprintf("%-8O", (expr_t)(u_char)obj.c);
31336559Sbostic 			break;
31436559Sbostic 
31536559Sbostic 		case 's':
31636559Sbostic 		case 'S':
31736559Sbostic 			savdot = dot;
31836559Sbostic 			for (;;) {
31936559Sbostic 				if (adbread(space, dot, &obj.c, 1) != 1 ||
32036559Sbostic 				    iserr() || obj.c == 0)
32136559Sbostic 					break;
32236559Sbostic 				dot = inkdot(1);
32336559Sbostic 				if (fmtchar == 'S')
32436559Sbostic 					printesc(obj.c);
32536559Sbostic 				else
32636559Sbostic 					printc(obj.c);
32736559Sbostic 				endline();
32836559Sbostic 			}
32936559Sbostic 			dotinc = dot - savdot + 1;
33036559Sbostic 			dot = savdot;
33136559Sbostic 			break;
33236559Sbostic 
33336559Sbostic 		case '1':
33436559Sbostic 			adbprintf("%-8R", (expr_t)(u_char)obj.c);
33536559Sbostic 			break;
33636559Sbostic 
33736559Sbostic 		case '2':
33836559Sbostic 			fmtchar = 'r';
33936559Sbostic 			/* FALLTHROUGH */
34036559Sbostic 
34136559Sbostic 		case 'v':
34236559Sbostic 		case 'u': case 'd':
34336559Sbostic 		case 'o': case 'q':
34436559Sbostic 		case 'x': case 'z':
34536559Sbostic 			cfmt[3] = fmtchar;
34636559Sbostic 			adbprintf(cfmt, 8, obj.hw);
34736559Sbostic 			break;
34836559Sbostic 
34936559Sbostic 		case '4':
35036559Sbostic 			fmtchar = 'R';
35136559Sbostic 			/* FALLTHROUGH */
35236559Sbostic 
35336559Sbostic 		case 'V':
35436559Sbostic 		case 'U': case 'D':
35536559Sbostic 		case 'O': case 'Q':
35636559Sbostic 		case 'X': case 'Z':
35736559Sbostic 			cfmt[3] = fmtchar;
35836559Sbostic 			adbprintf(cfmt, 16, obj.fw);
35936559Sbostic 			break;
36036559Sbostic 
36136559Sbostic 		case 'Y':
36236559Sbostic 			adbprintf("%-24Y", obj.tm);
36336559Sbostic 			break;
36436559Sbostic 
36536559Sbostic 		case 'i':
36636559Sbostic 			printins(space);	/* also sets dotinc */
36736559Sbostic 			printc('\n');
36836559Sbostic 			break;
36936559Sbostic 
37036559Sbostic 		case 'f':
37136559Sbostic 			s = checkfloat((caddr_t)&obj.f, 0);
37236559Sbostic 			if (s != NULL)
37336559Sbostic 				adbprintf("%-16s", s);
37436559Sbostic 			else
37536559Sbostic 				adbprintf("%-16.9f", obj.f);
37636559Sbostic 			break;
37736559Sbostic 
37836559Sbostic 		case 'F':
37936559Sbostic 			s = checkfloat((caddr_t)&obj.d, 1);
38036559Sbostic 			if (s != NULL)
38136559Sbostic 				adbprintf("%-32s", s);
38236559Sbostic 			else
38336559Sbostic 				adbprintf("%-32.18f", obj.d);
38436559Sbostic 			break;
38536559Sbostic 
38636559Sbostic 		case 'n':
38736559Sbostic 		case 'N':
38836559Sbostic 			printc('\n');
38936559Sbostic 			dotinc = 0;
39036559Sbostic 			break;
39136559Sbostic 
39236559Sbostic 		case '"':
39336559Sbostic 			while (*p != 0 && *p != '"')
39436559Sbostic 				printc(*p++);
39536559Sbostic 			if (*p)
39636559Sbostic 				p++;
39736559Sbostic 			dotinc = 0;
39836559Sbostic 			break;
39936559Sbostic 
40036559Sbostic 		case '^':
40136559Sbostic 			dot = inkdot(-dotinc * fcount);
40236559Sbostic 			return (p);
40336559Sbostic 
40436559Sbostic 		case '+':
40536559Sbostic 			dot = inkdot(fcount);
40636559Sbostic 			return (p);
40736559Sbostic 
40836559Sbostic 		case '-':
40936559Sbostic 			dot = inkdot(-fcount);
41036559Sbostic 			return (p);
41136559Sbostic 
41236559Sbostic 		default:
41336559Sbostic 			panic("exform 3");
41436559Sbostic 			/* NOTREACHED */
41536559Sbostic 		}
41636559Sbostic 		if (space != SP_NONE)
41736559Sbostic 			dot = inkdot(dotinc);
41836559Sbostic 		fcount--;
41936559Sbostic 		endline();
42036559Sbostic 	}
42136559Sbostic 	return (p);
42236559Sbostic }
42336559Sbostic 
42436559Sbostic /*
42536559Sbostic  * Print dot in its canonical format.
42636559Sbostic  */
pdot()42736559Sbostic pdot()
42836559Sbostic {
42936559Sbostic 
43036559Sbostic 	psymoff("%R", dot, SP_INSTR, maxoff, ":%16t");
43136559Sbostic }
43236559Sbostic 
43336559Sbostic /*
43436559Sbostic  * Print character c using ASCII escape conventions.
43536559Sbostic  */
printesc(c)43636559Sbostic printesc(c)
43736559Sbostic 	register int c;
43836559Sbostic 
43936559Sbostic {
44044636Smarc 	char visbuf[5];
44136559Sbostic 
44244636Smarc 	vis(visbuf, (char)c, VIS_TAB | VIS_NL | VIS_NOSLASH, 0);
44344636Smarc 	adbprintf("%s", visbuf);
44436559Sbostic }
445