136559Sbostic #ifndef lint 2*37335Storek static char sccsid[] = "@(#)command.c 5.2 (Berkeley) 04/09/89"; 336559Sbostic #endif 436559Sbostic 536559Sbostic /* 636559Sbostic * adb - commands 736559Sbostic */ 836559Sbostic 936559Sbostic #include "defs.h" 1036559Sbostic #include <ctype.h> 1136559Sbostic #include <sys/wait.h> 1236559Sbostic 1336559Sbostic extern char BADEQ[]; /* "unexpected `='" */ 1436559Sbostic extern char NOMATCH[]; /* "cannot locate value" */ 1536559Sbostic extern char BADVAR[]; /* "bad variable" */ 1636559Sbostic extern char BADCOM[]; /* "bad command" */ 1736559Sbostic extern char NOFORK[]; /* "try again" */ 1836559Sbostic 1936559Sbostic /* 2036559Sbostic * executing is used in main() to see if it is necessary to 2136559Sbostic * delete any breakpoints that might have been set; if an 2236559Sbostic * error occurs while a subprocess command is running, executing 2336559Sbostic * will be set. 2436559Sbostic */ 2536559Sbostic int executing; 2636559Sbostic 2736559Sbostic /* lastcom remembers the previous command */ 2836559Sbostic static struct { 2936559Sbostic int c; /* the command */ 3036559Sbostic int star; /* true iff it was in alternate space */ 3136559Sbostic } lastcom; 3236559Sbostic 3336559Sbostic /* 3436559Sbostic * Execute the given command buffer. 3536559Sbostic * If defcom is nonzero, it is used as the default command. 3636559Sbostic */ 3736559Sbostic command(buf, defcom) 3836559Sbostic char *buf; 3936559Sbostic int defcom; 4036559Sbostic { 4136559Sbostic 4236559Sbostic lp = buf; 4336559Sbostic do { 4436559Sbostic cmds(defcom); 4536559Sbostic flushbuf(); 4636559Sbostic } while (rdc() == ';'); 4736559Sbostic unreadc(); 4836559Sbostic } 4936559Sbostic 5036559Sbostic static 5136559Sbostic cmds(defcom) 5236559Sbostic int defcom; 5336559Sbostic { 5436559Sbostic int c; 5536559Sbostic struct reglist *reg; 5636559Sbostic 5736559Sbostic /* 5836559Sbostic * Pick up the optional first expression (`dot'), 5936559Sbostic * then, if the next character is a comma, pick up 6036559Sbostic * the second optional expression (`ecount'). 6136559Sbostic */ 6236559Sbostic if (gavedot = oexpr()) 6336559Sbostic ditto = dot = edot = expv; 6436559Sbostic else 6536559Sbostic edot = dot; /* probably equal, but possibly truncating */ 6636559Sbostic if (rdc() == ',') { 6736559Sbostic if (!oexpr()) 6836559Sbostic error("count expected"); 6936559Sbostic gavecount = 1; 7036559Sbostic ecount = expv; 7136559Sbostic } else { 7236559Sbostic gavecount = 0; 7336559Sbostic ecount = 1; 7436559Sbostic unreadc(); 7536559Sbostic } 7636559Sbostic 7736559Sbostic /* 7836559Sbostic * Pick up the command. If there is no command, do the 7936559Sbostic * previous (or default) command, and if no dot was given, 8036559Sbostic * use the `next' dot. 8136559Sbostic */ 8236559Sbostic c = rdc(); 8336559Sbostic if (eol(c)) { 8436559Sbostic if (defcom != 0) { 8536559Sbostic lastcom.c = defcom; 8636559Sbostic lastcom.star = 0; 8736559Sbostic } 8836559Sbostic if (!gavedot) 8936559Sbostic dot = inkdot(dotinc); 9036559Sbostic unreadc(); 9136559Sbostic } else { 9236559Sbostic lastcom.c = c; 9336559Sbostic lastcom.star = 0; 9436559Sbostic } 9536559Sbostic 9636559Sbostic switch (lastcom.c) { 9736559Sbostic 9836559Sbostic case '=': 9936559Sbostic fmtcom(SP_NONE, 1); 10036559Sbostic break; 10136559Sbostic 10236559Sbostic case '/': 10336559Sbostic fmtcom(SP_DATA, 0); 10436559Sbostic break; 10536559Sbostic 10636559Sbostic case '?': 10736559Sbostic fmtcom(SP_INSTR, 0); 10836559Sbostic break; 10936559Sbostic 11036559Sbostic case '>': 11136559Sbostic lastcom.c = 0; 11236559Sbostic if ((reg = reglookup()) != NULL) { 11336559Sbostic if (setreg(reg, edot)) 11436559Sbostic prints("register write failed"); 11536559Sbostic break; 11636559Sbostic } 11736559Sbostic if ((c = varlookup(rdc())) != -1) 11836559Sbostic var[c] = edot; 11936559Sbostic else 12036559Sbostic error(BADVAR); 12136559Sbostic break; 12236559Sbostic 12336559Sbostic case '!': 12436559Sbostic lastcom.c = 0; 12536559Sbostic shell(); 12636559Sbostic break; 12736559Sbostic 12836559Sbostic case '$': 12936559Sbostic lastcom.c = 0; 13036559Sbostic printtrace(nextchar()); 13136559Sbostic break; 13236559Sbostic 13336559Sbostic case ':': 13436559Sbostic if (!executing) { 13536559Sbostic executing = 1; 13636559Sbostic subpcs(nextchar()); 13736559Sbostic executing = 0; 13836559Sbostic lastcom.c = 0; 13936559Sbostic } 14036559Sbostic break; 14136559Sbostic 14236559Sbostic case 0: 14336559Sbostic prints("adb\n"); 14436559Sbostic break; 14536559Sbostic 14636559Sbostic default: 14736559Sbostic error(BADCOM); 14836559Sbostic /* NOTREACHED */ 14936559Sbostic } 15036559Sbostic } 15136559Sbostic 15236559Sbostic /* 15336559Sbostic * Perform a format-based command (one in ? / or =). 15436559Sbostic */ 15536559Sbostic static 15636559Sbostic fmtcom(space, eqcom) 15736559Sbostic int space, eqcom; 15836559Sbostic { 15936559Sbostic /* special commands m, lL, wW do not operate in SP_NONE (`=') */ 16036559Sbostic void mcom(), lcom(), wcom(); 16136559Sbostic static struct fcmd { 16236559Sbostic int c; 16336559Sbostic void (*fn)(); 16436559Sbostic } fcmd[] = { 16536559Sbostic { 'm', mcom }, 16636559Sbostic { 'l', lcom }, { 'L', lcom }, 16736559Sbostic { 'w', wcom }, { 'W', wcom }, 16836559Sbostic 0 16936559Sbostic }; 17036559Sbostic register struct fcmd *f; 17136559Sbostic register int c; 17236559Sbostic int ptype = space; 17336559Sbostic static char stformat[LINELEN] = "X\"= \"^i"; 17436559Sbostic static char eqformat[LINELEN] = "z"; 17536559Sbostic 17636559Sbostic /* 17736559Sbostic * Are we operating in the alternate `star' space? 17836559Sbostic */ 17936559Sbostic if (!eqcom) { 18036559Sbostic if (rdc() == '*') 18136559Sbostic lastcom.star = 1; 18236559Sbostic else 18336559Sbostic unreadc(); 18436559Sbostic if (lastcom.star) { 18536559Sbostic space |= SP_STAR; 18636559Sbostic /* print as data for instr, and vice versa */ 18736559Sbostic ptype = (SP_DATA + SP_INSTR) - ptype; 18836559Sbostic } 18936559Sbostic } 19036559Sbostic 19136559Sbostic /* 19236559Sbostic * Check for the special commands first. 19336559Sbostic */ 19436559Sbostic c = rdc(); 19536559Sbostic for (f = fcmd; f->c; f++) { 19636559Sbostic if (c == f->c) { 19736559Sbostic if (eqcom) 19836559Sbostic error(BADEQ); 19936559Sbostic (*f->fn)(space, ptype, isupper(c)); 20036559Sbostic return; 20136559Sbostic } 20236559Sbostic } 20336559Sbostic unreadc(); 20436559Sbostic getformat(eqcom ? eqformat : stformat, LINELEN); 20536559Sbostic scanform(!eqcom, eqcom ? eqformat : stformat, space, ptype); 20636559Sbostic } 20736559Sbostic 20836559Sbostic /* 20936559Sbostic * Set a map (?m, /m commands). 21036559Sbostic */ 21136559Sbostic /* ARGSUSED */ 21236559Sbostic static void 21336559Sbostic mcom(space, ptype, fullword) 21436559Sbostic int space, ptype, fullword; 21536559Sbostic { 21636559Sbostic register struct map *smap; 21736559Sbostic register struct m1 *mm; 21836559Sbostic char c; 21936559Sbostic 22036559Sbostic smap = space & SP_DATA ? &datmap : &txtmap; 22136559Sbostic mm = space & SP_STAR ? &smap->m2 : &smap->m1; 22236559Sbostic if (oexpr()) { 22336559Sbostic mm->b = expv; 22436559Sbostic if (oexpr()) { 22536559Sbostic mm->e = expv; 22636559Sbostic if (oexpr()) 22736559Sbostic mm->f = expv; 22836559Sbostic } 22936559Sbostic } 23036559Sbostic if ((c = rdc()) == '?') 23136559Sbostic smap->ufd = symfile.fd; 23236559Sbostic else if (c == '/') 23336559Sbostic smap->ufd = corefile.fd; 23436559Sbostic else 23536559Sbostic unreadc(); 23636559Sbostic } 23736559Sbostic 23836559Sbostic /* 23936559Sbostic * Locate a value (l, L commands). 24036559Sbostic */ 24136559Sbostic static void 24236559Sbostic lcom(space, ptype, fullword) 24336559Sbostic int space, ptype, fullword; 24436559Sbostic { 24536559Sbostic register expr_t val, mask; 24636559Sbostic addr_t savdot; 24736559Sbostic 24836559Sbostic /* search for exp */ 24936559Sbostic savdot = dot; 25036559Sbostic val = rexpr(); 25136559Sbostic if (oexpr()) 25236559Sbostic mask = expv; 25336559Sbostic else 25436559Sbostic mask = ~0L; 25536559Sbostic if (fullword) { 25636559Sbostic expr_t w; 25736559Sbostic 25836559Sbostic dotinc = sizeof(w); 25936559Sbostic for (;;) { 26036559Sbostic (void) adbread(space, dot, &w, sizeof(w)); 26136559Sbostic if (iserr() || (w & mask) == val) 26236559Sbostic break; 26336559Sbostic dot = inkdot(sizeof(w)); 26436559Sbostic } 26536559Sbostic } else { 26636559Sbostic hword_t hw; 26736559Sbostic 26836559Sbostic dotinc = sizeof(hw); 26936559Sbostic mask = (hword_t)mask; 27036559Sbostic val = (hword_t)val; 27136559Sbostic for (;;) { 27236559Sbostic (void) adbread(space, dot, &hw, sizeof(hw)); 27336559Sbostic if (iserr() || (hw & mask) == val) 27436559Sbostic break; 27536559Sbostic dot = inkdot(sizeof(hw)); 27636559Sbostic } 27736559Sbostic } 27836559Sbostic if (iserr()) { 27936559Sbostic dot = savdot; 28036559Sbostic errflag = NOMATCH; 28136559Sbostic } 28236559Sbostic psymoff("%R", dot, ptype, maxoff, ""); 28336559Sbostic } 28436559Sbostic 28536559Sbostic /* 28636559Sbostic * Write new values (w, W). 28736559Sbostic */ 28836559Sbostic static void 28936559Sbostic wcom(space, ptype, fullword) 29036559Sbostic int space, ptype, fullword; 29136559Sbostic { 29236559Sbostic addr_t savdot; 29336559Sbostic hword_t hw; 29436559Sbostic 29536559Sbostic (void) rexpr(); 29636559Sbostic do { 29736559Sbostic savdot = dot; 29836559Sbostic pdot(); 29936559Sbostic showdot(fullword, space, ptype); /* also advances */ 30036559Sbostic errflag = NULL; 30136559Sbostic dot = savdot; 30236559Sbostic if (fullword) 30336559Sbostic (void) adbwrite(space, dot, &expv, sizeof(expv)); 30436559Sbostic else { 30536559Sbostic hw = expv; 30636559Sbostic (void) adbwrite(space, dot, &hw, sizeof(hw)); 30736559Sbostic } 30836559Sbostic savdot = dot; 30936559Sbostic adbprintf("=%8t"); 31036559Sbostic showdot(fullword, space, ptype); 31136559Sbostic printc('\n'); 31236559Sbostic } while (oexpr() && !iserr()); 31336559Sbostic dot = savdot; 31436559Sbostic checkerr(); 31536559Sbostic } 31636559Sbostic 31736559Sbostic /* 31836559Sbostic * Do a shell escape. 31936559Sbostic * 32036559Sbostic * THE vfork CODE BELOW IS CURRENTLY BROKEN 32136559Sbostic * MUST CHANGE signal TO sigvec BELOW 32236559Sbostic */ 32336559Sbostic static 32436559Sbostic shell() 32536559Sbostic { 32636559Sbostic int rc, unixpid; 32736559Sbostic union wait status; 32836559Sbostic char *argp = lp; 32936559Sbostic char *getenv(), *eshell = getenv("SHELL"); 33036559Sbostic 33136559Sbostic if (eshell == 0) 33236559Sbostic eshell = "/bin/sh"; 33336559Sbostic while (readchar() != '\n') 33436559Sbostic /* void */; 33536559Sbostic #ifndef VFORK 33636559Sbostic #define vfork fork 33736559Sbostic #endif 33836559Sbostic if ((unixpid = vfork()) == 0) { 33936559Sbostic *lp = 0; 34036559Sbostic (void) signal(SIGINT, sigint); 34136559Sbostic (void) signal(SIGQUIT, sigquit); 34236559Sbostic execl(eshell, "sh", "-c", argp, (char *)NULL); 34336559Sbostic _exit(16); 34436559Sbostic /* NOTREACHED */ 34536559Sbostic } 34636559Sbostic #ifdef VFORK 34736559Sbostic *lp = '\n'; 34836559Sbostic #endif 34936559Sbostic if (unixpid == -1) 35036559Sbostic error(NOFORK); 35136559Sbostic (void) signal(SIGINT, SIG_IGN); 35236559Sbostic while ((rc = wait(&status)) != unixpid && rc != -1) 35336559Sbostic /* void */; 35436559Sbostic (void) signal(SIGINT, intcatch); 35536559Sbostic prints("!"); 35636559Sbostic unreadc(); 35736559Sbostic } 35836559Sbostic 35936559Sbostic /* 36036559Sbostic * Read a format into the given buffer. If nothing is 36136559Sbostic * read, leave the buffer alone. 36236559Sbostic */ 36336559Sbostic static 36436559Sbostic getformat(buf, n) 36536559Sbostic char *buf; 36636559Sbostic register int n; 36736559Sbostic { 36836559Sbostic register char *p = buf; 36936559Sbostic register int c, quote = 0; 37036559Sbostic 37136559Sbostic while ((c = readchar()), quote ? c != '\n' : !eol(c)) { 37236559Sbostic if (c == '"') 37336559Sbostic quote = !quote; 37436559Sbostic if (--n > 0) 37536559Sbostic *p++ = c; 37636559Sbostic } 37736559Sbostic unreadc(); 37836559Sbostic if (p != buf) /* nonempty */ 37936559Sbostic *p++ = 0; 38036559Sbostic } 38136559Sbostic 38236559Sbostic /* 38336559Sbostic * Convert a (one-character) variable name to an index, or -1 for 38436559Sbostic * error. 38536559Sbostic */ 38636559Sbostic varlookup(name) 38736559Sbostic register int name; 38836559Sbostic { 38936559Sbostic 39036559Sbostic if (isdigit(name)) 39136559Sbostic return (name - '0'); 39236559Sbostic if (isalpha(name)) 393*37335Storek return (isupper(name) ? name - 'A' + 10 : name - 'a' + 10); 39436559Sbostic return (-1); 39536559Sbostic } 39636559Sbostic 39736559Sbostic /* 39836559Sbostic * If the text at the current input point matches a register name, 39936559Sbostic * consume that text and return a pointer to the register; otherwise 40036559Sbostic * leave it unconsumed and return NULL. 40136559Sbostic */ 40236559Sbostic struct reglist * 40336559Sbostic reglookup() 40436559Sbostic { 40536559Sbostic register struct reglist *p; 40636559Sbostic register char *a, *b, c0, c1; 40736559Sbostic char *oldlp = lp; 40836559Sbostic extern struct reglist reglist[]; 40936559Sbostic 41036559Sbostic c0 = rdc(); 41136559Sbostic c1 = readchar(); 41236559Sbostic for (p = reglist; (a = p->r_name) != NULL; p++) { 41336559Sbostic if (*a++ != c0 || *a++ != c1) 41436559Sbostic continue; 41536559Sbostic b = lp; 41636559Sbostic do { 41736559Sbostic if (*a == 0) { /* name matched: stop short */ 41836559Sbostic lp = b; 41936559Sbostic return (p); 42036559Sbostic } 42136559Sbostic } while (*a++ == *b++); 42236559Sbostic } 42336559Sbostic lp = oldlp; 42436559Sbostic return (NULL); 42536559Sbostic } 426