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