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