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