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