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