xref: /original-bsd/old/adb/common_source/format.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[] = "@(#)format.c	5.4 (Berkeley) 04/04/91";
10*fd52c9a2Sbostic #endif /* not lint */
112d162a28Sbostic 
122d162a28Sbostic /*
132d162a28Sbostic  * adb - formats
142d162a28Sbostic  */
152d162a28Sbostic 
162d162a28Sbostic #include "defs.h"
172d162a28Sbostic #include <ctype.h>
185faf1b7aSmarc #include <vis.h>
192d162a28Sbostic 
202d162a28Sbostic extern char BADMOD[];
212d162a28Sbostic extern char NOFORK[];
222d162a28Sbostic 
232d162a28Sbostic /* symbol desirability in exform() */
242d162a28Sbostic enum { IFEXACT, ALWAYS, NEVER } wantsym;
252d162a28Sbostic 
262d162a28Sbostic char	*exform();
272d162a28Sbostic 
282d162a28Sbostic /*
292d162a28Sbostic  * Execute the given format `ecount' times.
302d162a28Sbostic  */
scanform(forcesym,fmt,space,ptype)312d162a28Sbostic scanform(forcesym, fmt, space, ptype)
322d162a28Sbostic 	int forcesym;
332d162a28Sbostic 	char *fmt;
342d162a28Sbostic 	int space, ptype;
352d162a28Sbostic {
362d162a28Sbostic 	register char *p;
372d162a28Sbostic 	register int c, n;
382d162a28Sbostic 	register expr_t ntimes = ecount;
392d162a28Sbostic 	addr_t savdot, newdot;
402d162a28Sbostic 
412d162a28Sbostic 	if (ntimes == 0)
422d162a28Sbostic 		return;
432d162a28Sbostic 	for (wantsym = forcesym ? ALWAYS : IFEXACT;; wantsym = IFEXACT) {
442d162a28Sbostic 		p = fmt;
452d162a28Sbostic 		savdot = dot;
462d162a28Sbostic 		while (p != NULL) {	/* loop over format items */
472d162a28Sbostic 			n = 0;		/* get optional count */
482d162a28Sbostic 			while (isdigit(c = *p++))
492d162a28Sbostic 				n = n * 10 + c - '0';
502d162a28Sbostic 			if (c == 0)	/* end of format */
512d162a28Sbostic 				break;
522d162a28Sbostic 			p = exform(n ? n : 1, p - (c != '\\'), space, ptype);
532d162a28Sbostic 		}
542d162a28Sbostic 		dotinc = (newdot = dot) - savdot;
552d162a28Sbostic 		dot = savdot;
562d162a28Sbostic 		if (errflag != NULL && (long)ntimes < 0) {
572d162a28Sbostic 			errflag = NULL;
582d162a28Sbostic 			break;
592d162a28Sbostic 		}
602d162a28Sbostic 		checkerr();
612d162a28Sbostic 		if (--ntimes == 0)
622d162a28Sbostic 			break;
632d162a28Sbostic 		dot = newdot;
642d162a28Sbostic 	}
652d162a28Sbostic }
662d162a28Sbostic 
672d162a28Sbostic /*
682d162a28Sbostic  * Print a halfword or a word from dot.
692d162a28Sbostic  */
showdot(fullword,space,ptype)702d162a28Sbostic showdot(fullword, space, ptype)
712d162a28Sbostic 	int fullword, space, ptype;
722d162a28Sbostic {
732d162a28Sbostic 	char c = fullword ? '4' : '2';
742d162a28Sbostic 
752d162a28Sbostic 	wantsym = NEVER;
762d162a28Sbostic 	(void) exform(1, &c, space, ptype);
772d162a28Sbostic }
782d162a28Sbostic 
792d162a28Sbostic /*
802d162a28Sbostic  * The following are used inside exform().
812d162a28Sbostic  *
822d162a28Sbostic  * The various FT_ values specify the type of the object accessed
832d162a28Sbostic  * by some format character.  FT_DULL indicates that no object is
842d162a28Sbostic  * accessed (or that it is done in some peculiar way).
852d162a28Sbostic  * The fsize array holds the size (in bytes)
862d162a28Sbostic  * of each of those types; the fmttypes[] array lists the type for
872d162a28Sbostic  * each character.  To save space, since there are many characters
882d162a28Sbostic  * for some of the types, they are stored as strings.
892d162a28Sbostic  */
902d162a28Sbostic enum { FT_DULL, FT_CHAR, FT_HW, FT_FW, FT_ADDR, FT_FLT, FT_DBL, FT_TM };
912d162a28Sbostic 	/* these may have to be turned into `#define's */
922d162a28Sbostic 
932d162a28Sbostic static char fsize[] = {		/* ordered by enumeration above! */
942d162a28Sbostic 	0, sizeof(char), sizeof(hword_t), sizeof(expr_t),
952d162a28Sbostic 	sizeof(addr_t), sizeof(float), sizeof(double), sizeof(time_t)
962d162a28Sbostic };
972d162a28Sbostic 
982d162a28Sbostic static struct fmttypes {
992d162a28Sbostic 	char	*ft_chars;
1002d162a28Sbostic 	int	ft_type;
1012d162a28Sbostic } fmttypes[] = {
1022d162a28Sbostic 	{ "\t\" +-NRST^inrst", FT_DULL },
1032d162a28Sbostic 	{ "1BCbc", FT_CHAR },
1042d162a28Sbostic 	{ "2doquvxz", FT_HW },
1052d162a28Sbostic 	{ "4DOQUVXZ", FT_FW },
1062d162a28Sbostic 	{ "p", FT_ADDR },
1072d162a28Sbostic 	{ "f", FT_FLT },
1082d162a28Sbostic 	{ "F", FT_DBL },
1092d162a28Sbostic 	{ "Y", FT_TM },
1102d162a28Sbostic 	0
1112d162a28Sbostic };
1122d162a28Sbostic 
1132d162a28Sbostic /*
1142d162a28Sbostic  * Execute a single format item `fcount' times; set
1152d162a28Sbostic  * dotinc and move dot.  Return the address of the next
1162d162a28Sbostic  * format item, or NULL upon error reading an object.
1172d162a28Sbostic  *
1182d162a28Sbostic  * I must apologise for the length of this routine, but
1192d162a28Sbostic  * it is bloated mainly with type correctness.
1202d162a28Sbostic  */
1212d162a28Sbostic char *
exform(fcount,fmt,space,ptype)1222d162a28Sbostic exform(fcount, fmt, space, ptype)
1232d162a28Sbostic 	int fcount;
1242d162a28Sbostic 	char *fmt;
1252d162a28Sbostic 	int space, ptype;
1262d162a28Sbostic {
1272d162a28Sbostic 	register struct fmttypes *ftp;
1282d162a28Sbostic 	register int sz;
1292d162a28Sbostic 	register char *p, *s, fmtchar;
1302d162a28Sbostic 	addr_t savdot, off;
1312d162a28Sbostic 	struct nlist *sp;
1322d162a28Sbostic 	union {
1332d162a28Sbostic 		char c;
1342d162a28Sbostic 		hword_t hw;
1352d162a28Sbostic 		expr_t fw;
1362d162a28Sbostic 		float f;
1372d162a28Sbostic 		double d;
1382d162a28Sbostic 		time_t tm;
1392d162a28Sbostic 		addr_t a;
1402d162a28Sbostic 	} obj;
1412d162a28Sbostic 
1422d162a28Sbostic 	while (fcount > 0) {
1432d162a28Sbostic 		/*
1442d162a28Sbostic 		 * First decode the type to be used with the expression.
1452d162a28Sbostic 		 * If address, print dot as a symbol, save it in var 0,
1462d162a28Sbostic 		 * and bypass all the nonsense.
1472d162a28Sbostic 		 */
1482d162a28Sbostic 		p = fmt;
1492d162a28Sbostic 		fmtchar = *p++;
1502d162a28Sbostic 
1512d162a28Sbostic 		/* address: special */
1522d162a28Sbostic 		if (fmtchar == 'a') {
1532d162a28Sbostic 			pdot();
1542d162a28Sbostic 			wantsym = NEVER;	/* well, hardly ever */
1552d162a28Sbostic 			var[0] = dot;
1562d162a28Sbostic 			return (p);
1572d162a28Sbostic 		}
1582d162a28Sbostic 
1592d162a28Sbostic 		for (ftp = fmttypes; (s = ftp->ft_chars) != NULL; ftp++)
1602d162a28Sbostic 			while (*s != 0)
1612d162a28Sbostic 				if (*s++ == fmtchar)
1622d162a28Sbostic 					goto found;
1632d162a28Sbostic 		error(BADMOD);
1642d162a28Sbostic 		/* NOTREACHED */
1652d162a28Sbostic found:
1662d162a28Sbostic 
1672d162a28Sbostic 		/* plop out a symbol, if desired */
1682d162a28Sbostic 		if (wantsym == ALWAYS)
1692d162a28Sbostic 			pdot();
1702d162a28Sbostic 		else if (wantsym == IFEXACT &&
1712d162a28Sbostic 		    (sp = findsym(dot, ptype, &off)) != NULL && off == 0)
1722d162a28Sbostic 			adbprintf("\n%s:%16t", sp->n_un.n_name); /* \n ??? */
1732d162a28Sbostic 		wantsym = NEVER;
1742d162a28Sbostic 
1752d162a28Sbostic 		/*
1762d162a28Sbostic 		 * Now read the sort of object we decided fmtchar represents,
1772d162a28Sbostic 		 * or compute it from the expression given for dot.
1782d162a28Sbostic 		 */
1792d162a28Sbostic 		sz = fsize[ftp->ft_type];
1802d162a28Sbostic 		if (space != SP_NONE) {
1812d162a28Sbostic 			/* can just read into the union */
1822d162a28Sbostic 			if (sz != 0)
1832d162a28Sbostic 				(void) adbread(space, dot, &obj, sz);
1842d162a28Sbostic 			else
1852d162a28Sbostic 				obj.fw = edot;
1862d162a28Sbostic 		} else {
1872d162a28Sbostic 			/* must decode type in order to assign, alas */
1882d162a28Sbostic 			switch (ftp->ft_type) {
1892d162a28Sbostic 
1902d162a28Sbostic 			case FT_CHAR:
1912d162a28Sbostic 				obj.c = edot;
1922d162a28Sbostic 				break;
1932d162a28Sbostic 
1942d162a28Sbostic 			case FT_HW:
1952d162a28Sbostic 				obj.hw = edot;
1962d162a28Sbostic 				break;
1972d162a28Sbostic 
1982d162a28Sbostic 			case FT_FW:
1992d162a28Sbostic 				obj.fw = edot;
2002d162a28Sbostic 				break;
2012d162a28Sbostic 
2022d162a28Sbostic 			case FT_DULL:
2032d162a28Sbostic 			case FT_ADDR:
2042d162a28Sbostic 				obj.a = dot;
2052d162a28Sbostic 				break;
2062d162a28Sbostic 
2072d162a28Sbostic 			case FT_FLT:
2082d162a28Sbostic 			case FT_DBL:
2092d162a28Sbostic 				obj.fw = 0;
2102d162a28Sbostic 				etofloat(edot, &obj.c, ftp->ft_type == FT_DBL);
2112d162a28Sbostic 				break;
2122d162a28Sbostic 
2132d162a28Sbostic 			case FT_TM:
2142d162a28Sbostic 				obj.fw = 0;
2152d162a28Sbostic 				obj.tm = edot;
2162d162a28Sbostic 				break;
2172d162a28Sbostic 
2182d162a28Sbostic 			default:
2192d162a28Sbostic 				panic("exform 1");
2202d162a28Sbostic 				/* NOTREACHED */
2212d162a28Sbostic 			}
2222d162a28Sbostic 		}
2232d162a28Sbostic 
2242d162a28Sbostic 		/* if we could not read the object, stop now. */
2252d162a28Sbostic 		if (errflag)
2262d162a28Sbostic 			return (NULL);
2272d162a28Sbostic 		if (mkfault)
2282d162a28Sbostic 			error((char *)NULL);
2292d162a28Sbostic 
2302d162a28Sbostic 		/*
2312d162a28Sbostic 		 * Now copy the value read (or assigned) to var[0].
2322d162a28Sbostic 		 * Here some of the types are collapsed: since the
2332d162a28Sbostic 		 * idea is to be able to get the value back later
2342d162a28Sbostic 		 * by reading var[0] and going through the type
2352d162a28Sbostic 		 * decoding above, it sometimes suffices to record
2362d162a28Sbostic 		 * as many bits as fit in an expr_t (see expr.c).
2372d162a28Sbostic 		 *
2382d162a28Sbostic 		 * Note that double precision numbers generally lose
2392d162a28Sbostic 		 * bits, since sizeof(double) can be > sizeof(expr_t).
2402d162a28Sbostic 		 */
2412d162a28Sbostic 		switch (ftp->ft_type) {
2422d162a28Sbostic 
2432d162a28Sbostic 		case FT_CHAR:
2442d162a28Sbostic 			var[0] = obj.c;
2452d162a28Sbostic 			break;
2462d162a28Sbostic 
2472d162a28Sbostic 		case FT_HW:
2482d162a28Sbostic 			var[0] = obj.hw;
2492d162a28Sbostic 			break;
2502d162a28Sbostic 
2512d162a28Sbostic 		case FT_FW:
2522d162a28Sbostic 		case FT_FLT:
2532d162a28Sbostic 		case FT_DBL:
2542d162a28Sbostic 		case FT_TM:
2552d162a28Sbostic 			var[0] = obj.fw;
2562d162a28Sbostic 			break;
2572d162a28Sbostic 
2582d162a28Sbostic 		case FT_DULL:
2592d162a28Sbostic 		case FT_ADDR:
2602d162a28Sbostic 			var[0] = obj.a;
2612d162a28Sbostic 			break;
2622d162a28Sbostic 
2632d162a28Sbostic 		default:
2642d162a28Sbostic 			panic("exform 2");
2652d162a28Sbostic 			/* NOTREACHED */
2662d162a28Sbostic 		}
2672d162a28Sbostic 
2682d162a28Sbostic 		/* set the size, if this object has a size */
2692d162a28Sbostic 		if (sz)
2702d162a28Sbostic 			dotinc = sz;
2712d162a28Sbostic 
2722d162a28Sbostic 		/* finally, do the command */
2732d162a28Sbostic 		if (charpos() == 0)
2742d162a28Sbostic 			adbprintf("%16m");
2752d162a28Sbostic 		switch (fmtchar) {
2762d162a28Sbostic 			/*
2772d162a28Sbostic 			 * Many of the formats translate to a %-8 or %-16
2782d162a28Sbostic 			 * edition of themselves; we use a single string,
2792d162a28Sbostic 			 * and modify the format part, for these.
2802d162a28Sbostic 			 */
2812d162a28Sbostic 			static char cfmt[] = "%-*?";
2822d162a28Sbostic 
2832d162a28Sbostic 		case ' ':
2842d162a28Sbostic 		case '\t':
2852d162a28Sbostic 			dotinc = 0;
2862d162a28Sbostic 			break;
2872d162a28Sbostic 
2882d162a28Sbostic 		case 't':
2892d162a28Sbostic 		case 'T':
2902d162a28Sbostic 			adbprintf("%*t", fcount);
2912d162a28Sbostic 			return (p);
2922d162a28Sbostic 
2932d162a28Sbostic 		case 'r':
2942d162a28Sbostic 		case 'R':
2952d162a28Sbostic 			adbprintf("%*m", fcount);
2962d162a28Sbostic 			return (p);
2972d162a28Sbostic 
2982d162a28Sbostic 		case 'p':
2992d162a28Sbostic 			psymoff("%R", obj.a, ptype, maxoff, "%16t");
3002d162a28Sbostic 			break;
3012d162a28Sbostic 
3022d162a28Sbostic 		case 'c':
3032d162a28Sbostic 			printc(obj.c);
3042d162a28Sbostic 			break;
3052d162a28Sbostic 
3062d162a28Sbostic 		case 'C':
3072d162a28Sbostic 			printesc(obj.c);
3082d162a28Sbostic 			break;
3092d162a28Sbostic 
3102d162a28Sbostic 		case 'b':
3112d162a28Sbostic 		case 'B':
3122d162a28Sbostic 			adbprintf("%-8O", (expr_t)(u_char)obj.c);
3132d162a28Sbostic 			break;
3142d162a28Sbostic 
3152d162a28Sbostic 		case 's':
3162d162a28Sbostic 		case 'S':
3172d162a28Sbostic 			savdot = dot;
3182d162a28Sbostic 			for (;;) {
3192d162a28Sbostic 				if (adbread(space, dot, &obj.c, 1) != 1 ||
3202d162a28Sbostic 				    iserr() || obj.c == 0)
3212d162a28Sbostic 					break;
3222d162a28Sbostic 				dot = inkdot(1);
3232d162a28Sbostic 				if (fmtchar == 'S')
3242d162a28Sbostic 					printesc(obj.c);
3252d162a28Sbostic 				else
3262d162a28Sbostic 					printc(obj.c);
3272d162a28Sbostic 				endline();
3282d162a28Sbostic 			}
3292d162a28Sbostic 			dotinc = dot - savdot + 1;
3302d162a28Sbostic 			dot = savdot;
3312d162a28Sbostic 			break;
3322d162a28Sbostic 
3332d162a28Sbostic 		case '1':
3342d162a28Sbostic 			adbprintf("%-8R", (expr_t)(u_char)obj.c);
3352d162a28Sbostic 			break;
3362d162a28Sbostic 
3372d162a28Sbostic 		case '2':
3382d162a28Sbostic 			fmtchar = 'r';
3392d162a28Sbostic 			/* FALLTHROUGH */
3402d162a28Sbostic 
3412d162a28Sbostic 		case 'v':
3422d162a28Sbostic 		case 'u': case 'd':
3432d162a28Sbostic 		case 'o': case 'q':
3442d162a28Sbostic 		case 'x': case 'z':
3452d162a28Sbostic 			cfmt[3] = fmtchar;
3462d162a28Sbostic 			adbprintf(cfmt, 8, obj.hw);
3472d162a28Sbostic 			break;
3482d162a28Sbostic 
3492d162a28Sbostic 		case '4':
3502d162a28Sbostic 			fmtchar = 'R';
3512d162a28Sbostic 			/* FALLTHROUGH */
3522d162a28Sbostic 
3532d162a28Sbostic 		case 'V':
3542d162a28Sbostic 		case 'U': case 'D':
3552d162a28Sbostic 		case 'O': case 'Q':
3562d162a28Sbostic 		case 'X': case 'Z':
3572d162a28Sbostic 			cfmt[3] = fmtchar;
3582d162a28Sbostic 			adbprintf(cfmt, 16, obj.fw);
3592d162a28Sbostic 			break;
3602d162a28Sbostic 
3612d162a28Sbostic 		case 'Y':
3622d162a28Sbostic 			adbprintf("%-24Y", obj.tm);
3632d162a28Sbostic 			break;
3642d162a28Sbostic 
3652d162a28Sbostic 		case 'i':
3662d162a28Sbostic 			printins(space);	/* also sets dotinc */
3672d162a28Sbostic 			printc('\n');
3682d162a28Sbostic 			break;
3692d162a28Sbostic 
3702d162a28Sbostic 		case 'f':
3712d162a28Sbostic 			s = checkfloat((caddr_t)&obj.f, 0);
3722d162a28Sbostic 			if (s != NULL)
3732d162a28Sbostic 				adbprintf("%-16s", s);
3742d162a28Sbostic 			else
3752d162a28Sbostic 				adbprintf("%-16.9f", obj.f);
3762d162a28Sbostic 			break;
3772d162a28Sbostic 
3782d162a28Sbostic 		case 'F':
3792d162a28Sbostic 			s = checkfloat((caddr_t)&obj.d, 1);
3802d162a28Sbostic 			if (s != NULL)
3812d162a28Sbostic 				adbprintf("%-32s", s);
3822d162a28Sbostic 			else
3832d162a28Sbostic 				adbprintf("%-32.18f", obj.d);
3842d162a28Sbostic 			break;
3852d162a28Sbostic 
3862d162a28Sbostic 		case 'n':
3872d162a28Sbostic 		case 'N':
3882d162a28Sbostic 			printc('\n');
3892d162a28Sbostic 			dotinc = 0;
3902d162a28Sbostic 			break;
3912d162a28Sbostic 
3922d162a28Sbostic 		case '"':
3932d162a28Sbostic 			while (*p != 0 && *p != '"')
3942d162a28Sbostic 				printc(*p++);
3952d162a28Sbostic 			if (*p)
3962d162a28Sbostic 				p++;
3972d162a28Sbostic 			dotinc = 0;
3982d162a28Sbostic 			break;
3992d162a28Sbostic 
4002d162a28Sbostic 		case '^':
4012d162a28Sbostic 			dot = inkdot(-dotinc * fcount);
4022d162a28Sbostic 			return (p);
4032d162a28Sbostic 
4042d162a28Sbostic 		case '+':
4052d162a28Sbostic 			dot = inkdot(fcount);
4062d162a28Sbostic 			return (p);
4072d162a28Sbostic 
4082d162a28Sbostic 		case '-':
4092d162a28Sbostic 			dot = inkdot(-fcount);
4102d162a28Sbostic 			return (p);
4112d162a28Sbostic 
4122d162a28Sbostic 		default:
4132d162a28Sbostic 			panic("exform 3");
4142d162a28Sbostic 			/* NOTREACHED */
4152d162a28Sbostic 		}
4162d162a28Sbostic 		if (space != SP_NONE)
4172d162a28Sbostic 			dot = inkdot(dotinc);
4182d162a28Sbostic 		fcount--;
4192d162a28Sbostic 		endline();
4202d162a28Sbostic 	}
4212d162a28Sbostic 	return (p);
4222d162a28Sbostic }
4232d162a28Sbostic 
4242d162a28Sbostic /*
4252d162a28Sbostic  * Print dot in its canonical format.
4262d162a28Sbostic  */
pdot()4272d162a28Sbostic pdot()
4282d162a28Sbostic {
4292d162a28Sbostic 
4302d162a28Sbostic 	psymoff("%R", dot, SP_INSTR, maxoff, ":%16t");
4312d162a28Sbostic }
4322d162a28Sbostic 
4332d162a28Sbostic /*
4342d162a28Sbostic  * Print character c using ASCII escape conventions.
4352d162a28Sbostic  */
printesc(c)4362d162a28Sbostic printesc(c)
4372d162a28Sbostic 	register int c;
4382d162a28Sbostic 
4392d162a28Sbostic {
4405faf1b7aSmarc 	char visbuf[5];
4412d162a28Sbostic 
4425faf1b7aSmarc 	vis(visbuf, (char)c, VIS_TAB | VIS_NL | VIS_NOSLASH, 0);
4435faf1b7aSmarc 	adbprintf("%s", visbuf);
4442d162a28Sbostic }
445