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