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