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