1 #ifndef lint 2 static char sccsid[] = "@(#)command.c 5.1 (Berkeley) 01/16/89"; 3 #endif 4 5 /* 6 * adb - commands 7 */ 8 9 #include "defs.h" 10 #include <ctype.h> 11 #include <sys/wait.h> 12 13 extern char BADEQ[]; /* "unexpected `='" */ 14 extern char NOMATCH[]; /* "cannot locate value" */ 15 extern char BADVAR[]; /* "bad variable" */ 16 extern char BADCOM[]; /* "bad command" */ 17 extern char NOFORK[]; /* "try again" */ 18 19 /* 20 * executing is used in main() to see if it is necessary to 21 * delete any breakpoints that might have been set; if an 22 * error occurs while a subprocess command is running, executing 23 * will be set. 24 */ 25 int executing; 26 27 /* lastcom remembers the previous command */ 28 static struct { 29 int c; /* the command */ 30 int star; /* true iff it was in alternate space */ 31 } lastcom; 32 33 /* 34 * Execute the given command buffer. 35 * If defcom is nonzero, it is used as the default command. 36 */ 37 command(buf, defcom) 38 char *buf; 39 int defcom; 40 { 41 42 lp = buf; 43 do { 44 cmds(defcom); 45 flushbuf(); 46 } while (rdc() == ';'); 47 unreadc(); 48 } 49 50 static 51 cmds(defcom) 52 int defcom; 53 { 54 int c; 55 struct reglist *reg; 56 57 /* 58 * Pick up the optional first expression (`dot'), 59 * then, if the next character is a comma, pick up 60 * the second optional expression (`ecount'). 61 */ 62 if (gavedot = oexpr()) 63 ditto = dot = edot = expv; 64 else 65 edot = dot; /* probably equal, but possibly truncating */ 66 if (rdc() == ',') { 67 if (!oexpr()) 68 error("count expected"); 69 gavecount = 1; 70 ecount = expv; 71 } else { 72 gavecount = 0; 73 ecount = 1; 74 unreadc(); 75 } 76 77 /* 78 * Pick up the command. If there is no command, do the 79 * previous (or default) command, and if no dot was given, 80 * use the `next' dot. 81 */ 82 c = rdc(); 83 if (eol(c)) { 84 if (defcom != 0) { 85 lastcom.c = defcom; 86 lastcom.star = 0; 87 } 88 if (!gavedot) 89 dot = inkdot(dotinc); 90 unreadc(); 91 } else { 92 lastcom.c = c; 93 lastcom.star = 0; 94 } 95 96 switch (lastcom.c) { 97 98 case '=': 99 fmtcom(SP_NONE, 1); 100 break; 101 102 case '/': 103 fmtcom(SP_DATA, 0); 104 break; 105 106 case '?': 107 fmtcom(SP_INSTR, 0); 108 break; 109 110 case '>': 111 lastcom.c = 0; 112 if ((reg = reglookup()) != NULL) { 113 if (setreg(reg, edot)) 114 prints("register write failed"); 115 break; 116 } 117 if ((c = varlookup(rdc())) != -1) 118 var[c] = edot; 119 else 120 error(BADVAR); 121 break; 122 123 case '!': 124 lastcom.c = 0; 125 shell(); 126 break; 127 128 case '$': 129 lastcom.c = 0; 130 printtrace(nextchar()); 131 break; 132 133 case ':': 134 if (!executing) { 135 executing = 1; 136 subpcs(nextchar()); 137 executing = 0; 138 lastcom.c = 0; 139 } 140 break; 141 142 case 0: 143 prints("adb\n"); 144 break; 145 146 default: 147 error(BADCOM); 148 /* NOTREACHED */ 149 } 150 } 151 152 /* 153 * Perform a format-based command (one in ? / or =). 154 */ 155 static 156 fmtcom(space, eqcom) 157 int space, eqcom; 158 { 159 /* special commands m, lL, wW do not operate in SP_NONE (`=') */ 160 void mcom(), lcom(), wcom(); 161 static struct fcmd { 162 int c; 163 void (*fn)(); 164 } fcmd[] = { 165 { 'm', mcom }, 166 { 'l', lcom }, { 'L', lcom }, 167 { 'w', wcom }, { 'W', wcom }, 168 0 169 }; 170 register struct fcmd *f; 171 register int c; 172 int ptype = space; 173 static char stformat[LINELEN] = "X\"= \"^i"; 174 static char eqformat[LINELEN] = "z"; 175 176 /* 177 * Are we operating in the alternate `star' space? 178 */ 179 if (!eqcom) { 180 if (rdc() == '*') 181 lastcom.star = 1; 182 else 183 unreadc(); 184 if (lastcom.star) { 185 space |= SP_STAR; 186 /* print as data for instr, and vice versa */ 187 ptype = (SP_DATA + SP_INSTR) - ptype; 188 } 189 } 190 191 /* 192 * Check for the special commands first. 193 */ 194 c = rdc(); 195 for (f = fcmd; f->c; f++) { 196 if (c == f->c) { 197 if (eqcom) 198 error(BADEQ); 199 (*f->fn)(space, ptype, isupper(c)); 200 return; 201 } 202 } 203 unreadc(); 204 getformat(eqcom ? eqformat : stformat, LINELEN); 205 scanform(!eqcom, eqcom ? eqformat : stformat, space, ptype); 206 } 207 208 /* 209 * Set a map (?m, /m commands). 210 */ 211 /* ARGSUSED */ 212 static void 213 mcom(space, ptype, fullword) 214 int space, ptype, fullword; 215 { 216 register struct map *smap; 217 register struct m1 *mm; 218 char c; 219 220 smap = space & SP_DATA ? &datmap : &txtmap; 221 mm = space & SP_STAR ? &smap->m2 : &smap->m1; 222 if (oexpr()) { 223 mm->b = expv; 224 if (oexpr()) { 225 mm->e = expv; 226 if (oexpr()) 227 mm->f = expv; 228 } 229 } 230 if ((c = rdc()) == '?') 231 smap->ufd = symfile.fd; 232 else if (c == '/') 233 smap->ufd = corefile.fd; 234 else 235 unreadc(); 236 } 237 238 /* 239 * Locate a value (l, L commands). 240 */ 241 static void 242 lcom(space, ptype, fullword) 243 int space, ptype, fullword; 244 { 245 register expr_t val, mask; 246 addr_t savdot; 247 248 /* search for exp */ 249 savdot = dot; 250 val = rexpr(); 251 if (oexpr()) 252 mask = expv; 253 else 254 mask = ~0L; 255 if (fullword) { 256 expr_t w; 257 258 dotinc = sizeof(w); 259 for (;;) { 260 (void) adbread(space, dot, &w, sizeof(w)); 261 if (iserr() || (w & mask) == val) 262 break; 263 dot = inkdot(sizeof(w)); 264 } 265 } else { 266 hword_t hw; 267 268 dotinc = sizeof(hw); 269 mask = (hword_t)mask; 270 val = (hword_t)val; 271 for (;;) { 272 (void) adbread(space, dot, &hw, sizeof(hw)); 273 if (iserr() || (hw & mask) == val) 274 break; 275 dot = inkdot(sizeof(hw)); 276 } 277 } 278 if (iserr()) { 279 dot = savdot; 280 errflag = NOMATCH; 281 } 282 psymoff("%R", dot, ptype, maxoff, ""); 283 } 284 285 /* 286 * Write new values (w, W). 287 */ 288 static void 289 wcom(space, ptype, fullword) 290 int space, ptype, fullword; 291 { 292 addr_t savdot; 293 hword_t hw; 294 295 (void) rexpr(); 296 do { 297 savdot = dot; 298 pdot(); 299 showdot(fullword, space, ptype); /* also advances */ 300 errflag = NULL; 301 dot = savdot; 302 if (fullword) 303 (void) adbwrite(space, dot, &expv, sizeof(expv)); 304 else { 305 hw = expv; 306 (void) adbwrite(space, dot, &hw, sizeof(hw)); 307 } 308 savdot = dot; 309 adbprintf("=%8t"); 310 showdot(fullword, space, ptype); 311 printc('\n'); 312 } while (oexpr() && !iserr()); 313 dot = savdot; 314 checkerr(); 315 } 316 317 /* 318 * Do a shell escape. 319 * 320 * THE vfork CODE BELOW IS CURRENTLY BROKEN 321 * MUST CHANGE signal TO sigvec BELOW 322 */ 323 static 324 shell() 325 { 326 int rc, unixpid; 327 union wait status; 328 char *argp = lp; 329 char *getenv(), *eshell = getenv("SHELL"); 330 331 if (eshell == 0) 332 eshell = "/bin/sh"; 333 while (readchar() != '\n') 334 /* void */; 335 #ifndef VFORK 336 #define vfork fork 337 #endif 338 if ((unixpid = vfork()) == 0) { 339 *lp = 0; 340 (void) signal(SIGINT, sigint); 341 (void) signal(SIGQUIT, sigquit); 342 execl(eshell, "sh", "-c", argp, (char *)NULL); 343 _exit(16); 344 /* NOTREACHED */ 345 } 346 #ifdef VFORK 347 *lp = '\n'; 348 #endif 349 if (unixpid == -1) 350 error(NOFORK); 351 (void) signal(SIGINT, SIG_IGN); 352 while ((rc = wait(&status)) != unixpid && rc != -1) 353 /* void */; 354 (void) signal(SIGINT, intcatch); 355 prints("!"); 356 unreadc(); 357 } 358 359 /* 360 * Read a format into the given buffer. If nothing is 361 * read, leave the buffer alone. 362 */ 363 static 364 getformat(buf, n) 365 char *buf; 366 register int n; 367 { 368 register char *p = buf; 369 register int c, quote = 0; 370 371 while ((c = readchar()), quote ? c != '\n' : !eol(c)) { 372 if (c == '"') 373 quote = !quote; 374 if (--n > 0) 375 *p++ = c; 376 } 377 unreadc(); 378 if (p != buf) /* nonempty */ 379 *p++ = 0; 380 } 381 382 /* 383 * Convert a (one-character) variable name to an index, or -1 for 384 * error. 385 */ 386 varlookup(name) 387 register int name; 388 { 389 390 if (isdigit(name)) 391 return (name - '0'); 392 if (isalpha(name)) 393 return (isupper(name) ? name - 'a' + 10 : name - 'A' + 10); 394 return (-1); 395 } 396 397 /* 398 * If the text at the current input point matches a register name, 399 * consume that text and return a pointer to the register; otherwise 400 * leave it unconsumed and return NULL. 401 */ 402 struct reglist * 403 reglookup() 404 { 405 register struct reglist *p; 406 register char *a, *b, c0, c1; 407 char *oldlp = lp; 408 extern struct reglist reglist[]; 409 410 c0 = rdc(); 411 c1 = readchar(); 412 for (p = reglist; (a = p->r_name) != NULL; p++) { 413 if (*a++ != c0 || *a++ != c1) 414 continue; 415 b = lp; 416 do { 417 if (*a == 0) { /* name matched: stop short */ 418 lp = b; 419 return (p); 420 } 421 } while (*a++ == *b++); 422 } 423 lp = oldlp; 424 return (NULL); 425 } 426