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