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 */ 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 */ 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 * 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 */ 427 pdot() 428 { 429 430 psymoff("%R", dot, SP_INSTR, maxoff, ":%16t"); 431 } 432 433 /* 434 * Print character c using ASCII escape conventions. 435 */ 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