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