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