|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)format.c 5.3 (Berkeley) 6/29/90";
3: #endif
4:
5: /*
6: * adb - formats
7: */
8:
9: #include "defs.h"
10: #include <ctype.h>
11: #include <vis.h>
12:
13: extern char BADMOD[];
14: extern char NOFORK[];
15:
16: /* symbol desirability in exform() */
17: enum { IFEXACT, ALWAYS, NEVER } wantsym;
18:
19: char *exform();
20:
21: /*
22: * Execute the given format `ecount' times.
23: */
24: scanform(forcesym, fmt, space, ptype)
25: int forcesym;
26: char *fmt;
27: int space, ptype;
28: {
29: register char *p;
30: register int c, n;
31: register expr_t ntimes = ecount;
32: addr_t savdot, newdot;
33:
34: if (ntimes == 0)
35: return;
36: for (wantsym = forcesym ? ALWAYS : IFEXACT;; wantsym = IFEXACT) {
37: p = fmt;
38: savdot = dot;
39: while (p != NULL) { /* loop over format items */
40: n = 0; /* get optional count */
41: while (isdigit(c = *p++))
42: n = n * 10 + c - '0';
43: if (c == 0) /* end of format */
44: break;
45: p = exform(n ? n : 1, p - (c != '\\'), space, ptype);
46: }
47: dotinc = (newdot = dot) - savdot;
48: dot = savdot;
49: if (errflag != NULL && (long)ntimes < 0) {
50: errflag = NULL;
51: break;
52: }
53: checkerr();
54: if (--ntimes == 0)
55: break;
56: dot = newdot;
57: }
58: }
59:
60: /*
61: * Print a halfword or a word from dot.
62: */
63: showdot(fullword, space, ptype)
64: int fullword, space, ptype;
65: {
66: char c = fullword ? '4' : '2';
67:
68: wantsym = NEVER;
69: (void) exform(1, &c, space, ptype);
70: }
71:
72: /*
73: * The following are used inside exform().
74: *
75: * The various FT_ values specify the type of the object accessed
76: * by some format character. FT_DULL indicates that no object is
77: * accessed (or that it is done in some peculiar way).
78: * The fsize array holds the size (in bytes)
79: * of each of those types; the fmttypes[] array lists the type for
80: * each character. To save space, since there are many characters
81: * for some of the types, they are stored as strings.
82: */
83: enum { FT_DULL, FT_CHAR, FT_HW, FT_FW, FT_ADDR, FT_FLT, FT_DBL, FT_TM };
84: /* these may have to be turned into `#define's */
85:
86: static char fsize[] = { /* ordered by enumeration above! */
87: 0, sizeof(char), sizeof(hword_t), sizeof(expr_t),
88: sizeof(addr_t), sizeof(float), sizeof(double), sizeof(time_t)
89: };
90:
91: static struct fmttypes {
92: char *ft_chars;
93: int ft_type;
94: } fmttypes[] = {
95: { "\t\" +-NRST^inrst", FT_DULL },
96: { "1BCbc", FT_CHAR },
97: { "2doquvxz", FT_HW },
98: { "4DOQUVXZ", FT_FW },
99: { "p", FT_ADDR },
100: { "f", FT_FLT },
101: { "F", FT_DBL },
102: { "Y", FT_TM },
103: 0
104: };
105:
106: /*
107: * Execute a single format item `fcount' times; set
108: * dotinc and move dot. Return the address of the next
109: * format item, or NULL upon error reading an object.
110: *
111: * I must apologise for the length of this routine, but
112: * it is bloated mainly with type correctness.
113: */
114: char *
115: exform(fcount, fmt, space, ptype)
116: int fcount;
117: char *fmt;
118: int space, ptype;
119: {
120: register struct fmttypes *ftp;
121: register int sz;
122: register char *p, *s, fmtchar;
123: addr_t savdot, off;
124: struct nlist *sp;
125: union {
126: char c;
127: hword_t hw;
128: expr_t fw;
129: float f;
130: double d;
131: time_t tm;
132: addr_t a;
133: } obj;
134:
135: while (fcount > 0) {
136: /*
137: * First decode the type to be used with the expression.
138: * If address, print dot as a symbol, save it in var 0,
139: * and bypass all the nonsense.
140: */
141: p = fmt;
142: fmtchar = *p++;
143:
144: /* address: special */
145: if (fmtchar == 'a') {
146: pdot();
147: wantsym = NEVER; /* well, hardly ever */
148: var[0] = dot;
149: return (p);
150: }
151:
152: for (ftp = fmttypes; (s = ftp->ft_chars) != NULL; ftp++)
153: while (*s != 0)
154: if (*s++ == fmtchar)
155: goto found;
156: error(BADMOD);
157: /* NOTREACHED */
158: found:
159:
160: /* plop out a symbol, if desired */
161: if (wantsym == ALWAYS)
162: pdot();
163: else if (wantsym == IFEXACT &&
164: (sp = findsym(dot, ptype, &off)) != NULL && off == 0)
165: adbprintf("\n%s:%16t", sp->n_un.n_name); /* \n ??? */
166: wantsym = NEVER;
167:
168: /*
169: * Now read the sort of object we decided fmtchar represents,
170: * or compute it from the expression given for dot.
171: */
172: sz = fsize[ftp->ft_type];
173: if (space != SP_NONE) {
174: /* can just read into the union */
175: if (sz != 0)
176: (void) adbread(space, dot, &obj, sz);
177: else
178: obj.fw = edot;
179: } else {
180: /* must decode type in order to assign, alas */
181: switch (ftp->ft_type) {
182:
183: case FT_CHAR:
184: obj.c = edot;
185: break;
186:
187: case FT_HW:
188: obj.hw = edot;
189: break;
190:
191: case FT_FW:
192: obj.fw = edot;
193: break;
194:
195: case FT_DULL:
196: case FT_ADDR:
197: obj.a = dot;
198: break;
199:
200: case FT_FLT:
201: case FT_DBL:
202: obj.fw = 0;
203: etofloat(edot, &obj.c, ftp->ft_type == FT_DBL);
204: break;
205:
206: case FT_TM:
207: obj.fw = 0;
208: obj.tm = edot;
209: break;
210:
211: default:
212: panic("exform 1");
213: /* NOTREACHED */
214: }
215: }
216:
217: /* if we could not read the object, stop now. */
218: if (errflag)
219: return (NULL);
220: if (mkfault)
221: error((char *)NULL);
222:
223: /*
224: * Now copy the value read (or assigned) to var[0].
225: * Here some of the types are collapsed: since the
226: * idea is to be able to get the value back later
227: * by reading var[0] and going through the type
228: * decoding above, it sometimes suffices to record
229: * as many bits as fit in an expr_t (see expr.c).
230: *
231: * Note that double precision numbers generally lose
232: * bits, since sizeof(double) can be > sizeof(expr_t).
233: */
234: switch (ftp->ft_type) {
235:
236: case FT_CHAR:
237: var[0] = obj.c;
238: break;
239:
240: case FT_HW:
241: var[0] = obj.hw;
242: break;
243:
244: case FT_FW:
245: case FT_FLT:
246: case FT_DBL:
247: case FT_TM:
248: var[0] = obj.fw;
249: break;
250:
251: case FT_DULL:
252: case FT_ADDR:
253: var[0] = obj.a;
254: break;
255:
256: default:
257: panic("exform 2");
258: /* NOTREACHED */
259: }
260:
261: /* set the size, if this object has a size */
262: if (sz)
263: dotinc = sz;
264:
265: /* finally, do the command */
266: if (charpos() == 0)
267: adbprintf("%16m");
268: switch (fmtchar) {
269: /*
270: * Many of the formats translate to a %-8 or %-16
271: * edition of themselves; we use a single string,
272: * and modify the format part, for these.
273: */
274: static char cfmt[] = "%-*?";
275:
276: case ' ':
277: case '\t':
278: dotinc = 0;
279: break;
280:
281: case 't':
282: case 'T':
283: adbprintf("%*t", fcount);
284: return (p);
285:
286: case 'r':
287: case 'R':
288: adbprintf("%*m", fcount);
289: return (p);
290:
291: case 'p':
292: psymoff("%R", obj.a, ptype, maxoff, "%16t");
293: break;
294:
295: case 'c':
296: printc(obj.c);
297: break;
298:
299: case 'C':
300: printesc(obj.c);
301: break;
302:
303: case 'b':
304: case 'B':
305: adbprintf("%-8O", (expr_t)(u_char)obj.c);
306: break;
307:
308: case 's':
309: case 'S':
310: savdot = dot;
311: for (;;) {
312: if (adbread(space, dot, &obj.c, 1) != 1 ||
313: iserr() || obj.c == 0)
314: break;
315: dot = inkdot(1);
316: if (fmtchar == 'S')
317: printesc(obj.c);
318: else
319: printc(obj.c);
320: endline();
321: }
322: dotinc = dot - savdot + 1;
323: dot = savdot;
324: break;
325:
326: case '1':
327: adbprintf("%-8R", (expr_t)(u_char)obj.c);
328: break;
329:
330: case '2':
331: fmtchar = 'r';
332: /* FALLTHROUGH */
333:
334: case 'v':
335: case 'u': case 'd':
336: case 'o': case 'q':
337: case 'x': case 'z':
338: cfmt[3] = fmtchar;
339: adbprintf(cfmt, 8, obj.hw);
340: break;
341:
342: case '4':
343: fmtchar = 'R';
344: /* FALLTHROUGH */
345:
346: case 'V':
347: case 'U': case 'D':
348: case 'O': case 'Q':
349: case 'X': case 'Z':
350: cfmt[3] = fmtchar;
351: adbprintf(cfmt, 16, obj.fw);
352: break;
353:
354: case 'Y':
355: adbprintf("%-24Y", obj.tm);
356: break;
357:
358: case 'i':
359: printins(space); /* also sets dotinc */
360: printc('\n');
361: break;
362:
363: case 'f':
364: s = checkfloat((caddr_t)&obj.f, 0);
365: if (s != NULL)
366: adbprintf("%-16s", s);
367: else
368: adbprintf("%-16.9f", obj.f);
369: break;
370:
371: case 'F':
372: s = checkfloat((caddr_t)&obj.d, 1);
373: if (s != NULL)
374: adbprintf("%-32s", s);
375: else
376: adbprintf("%-32.18f", obj.d);
377: break;
378:
379: case 'n':
380: case 'N':
381: printc('\n');
382: dotinc = 0;
383: break;
384:
385: case '"':
386: while (*p != 0 && *p != '"')
387: printc(*p++);
388: if (*p)
389: p++;
390: dotinc = 0;
391: break;
392:
393: case '^':
394: dot = inkdot(-dotinc * fcount);
395: return (p);
396:
397: case '+':
398: dot = inkdot(fcount);
399: return (p);
400:
401: case '-':
402: dot = inkdot(-fcount);
403: return (p);
404:
405: default:
406: panic("exform 3");
407: /* NOTREACHED */
408: }
409: if (space != SP_NONE)
410: dot = inkdot(dotinc);
411: fcount--;
412: endline();
413: }
414: return (p);
415: }
416:
417: /*
418: * Print dot in its canonical format.
419: */
420: pdot()
421: {
422:
423: psymoff("%R", dot, SP_INSTR, maxoff, ":%16t");
424: }
425:
426: /*
427: * Print character c using ASCII escape conventions.
428: */
429: printesc(c)
430: register int c;
431:
432: {
433: char visbuf[5];
434:
435: vis(visbuf, (char)c, VIS_TAB | VIS_NL | VIS_NOSLASH, 0);
436: adbprintf("%s", visbuf);
437: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.