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