1 #ifndef lint 2 static char sccsid[] = "@(#)format.c 5.3 (Berkeley) 06/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 } 438