1*36559Sbostic #ifndef lint
2*36559Sbostic static char sccsid[] = "@(#)command.c	5.1 (Berkeley) 01/16/89";
3*36559Sbostic #endif
4*36559Sbostic 
5*36559Sbostic /*
6*36559Sbostic  * adb - commands
7*36559Sbostic  */
8*36559Sbostic 
9*36559Sbostic #include "defs.h"
10*36559Sbostic #include <ctype.h>
11*36559Sbostic #include <sys/wait.h>
12*36559Sbostic 
13*36559Sbostic extern char BADEQ[];		/* "unexpected `='" */
14*36559Sbostic extern char NOMATCH[];		/* "cannot locate value" */
15*36559Sbostic extern char BADVAR[];		/* "bad variable" */
16*36559Sbostic extern char BADCOM[];		/* "bad command" */
17*36559Sbostic extern char NOFORK[];		/* "try again" */
18*36559Sbostic 
19*36559Sbostic /*
20*36559Sbostic  * executing is used in main() to see if it is necessary to
21*36559Sbostic  * delete any breakpoints that might have been set; if an
22*36559Sbostic  * error occurs while a subprocess command is running, executing
23*36559Sbostic  * will be set.
24*36559Sbostic  */
25*36559Sbostic int	executing;
26*36559Sbostic 
27*36559Sbostic /* lastcom remembers the previous command */
28*36559Sbostic static struct {
29*36559Sbostic 	int	c;		/* the command */
30*36559Sbostic 	int	star;		/* true iff it was in alternate space */
31*36559Sbostic } lastcom;
32*36559Sbostic 
33*36559Sbostic /*
34*36559Sbostic  * Execute the given command buffer.
35*36559Sbostic  * If defcom is nonzero, it is used as the default command.
36*36559Sbostic  */
37*36559Sbostic command(buf, defcom)
38*36559Sbostic 	char *buf;
39*36559Sbostic 	int defcom;
40*36559Sbostic {
41*36559Sbostic 
42*36559Sbostic 	lp = buf;
43*36559Sbostic 	do {
44*36559Sbostic 		cmds(defcom);
45*36559Sbostic 		flushbuf();
46*36559Sbostic 	} while (rdc() == ';');
47*36559Sbostic 	unreadc();
48*36559Sbostic }
49*36559Sbostic 
50*36559Sbostic static
51*36559Sbostic cmds(defcom)
52*36559Sbostic 	int defcom;
53*36559Sbostic {
54*36559Sbostic 	int c;
55*36559Sbostic 	struct reglist *reg;
56*36559Sbostic 
57*36559Sbostic 	/*
58*36559Sbostic 	 * Pick up the optional first expression (`dot'),
59*36559Sbostic 	 * then, if the next character is a comma, pick up
60*36559Sbostic 	 * the second optional expression (`ecount').
61*36559Sbostic 	 */
62*36559Sbostic 	if (gavedot = oexpr())
63*36559Sbostic 		ditto = dot = edot = expv;
64*36559Sbostic 	else
65*36559Sbostic 		edot = dot;	/* probably equal, but possibly truncating */
66*36559Sbostic 	if (rdc() == ',') {
67*36559Sbostic 		if (!oexpr())
68*36559Sbostic 			error("count expected");
69*36559Sbostic 		gavecount = 1;
70*36559Sbostic 		ecount = expv;
71*36559Sbostic 	} else {
72*36559Sbostic 		gavecount = 0;
73*36559Sbostic 		ecount = 1;
74*36559Sbostic 		unreadc();
75*36559Sbostic 	}
76*36559Sbostic 
77*36559Sbostic 	/*
78*36559Sbostic 	 * Pick up the command.  If there is no command, do the
79*36559Sbostic 	 * previous (or default) command, and if no dot was given,
80*36559Sbostic 	 * use the `next' dot.
81*36559Sbostic 	 */
82*36559Sbostic 	c = rdc();
83*36559Sbostic 	if (eol(c)) {
84*36559Sbostic 		if (defcom != 0) {
85*36559Sbostic 			lastcom.c = defcom;
86*36559Sbostic 			lastcom.star = 0;
87*36559Sbostic 		}
88*36559Sbostic 		if (!gavedot)
89*36559Sbostic 			dot = inkdot(dotinc);
90*36559Sbostic 		unreadc();
91*36559Sbostic 	} else {
92*36559Sbostic 		lastcom.c = c;
93*36559Sbostic 		lastcom.star = 0;
94*36559Sbostic 	}
95*36559Sbostic 
96*36559Sbostic 	switch (lastcom.c) {
97*36559Sbostic 
98*36559Sbostic 	case '=':
99*36559Sbostic 		fmtcom(SP_NONE, 1);
100*36559Sbostic 		break;
101*36559Sbostic 
102*36559Sbostic 	case '/':
103*36559Sbostic 		fmtcom(SP_DATA, 0);
104*36559Sbostic 		break;
105*36559Sbostic 
106*36559Sbostic 	case '?':
107*36559Sbostic 		fmtcom(SP_INSTR, 0);
108*36559Sbostic 		break;
109*36559Sbostic 
110*36559Sbostic 	case '>':
111*36559Sbostic 		lastcom.c = 0;
112*36559Sbostic 		if ((reg = reglookup()) != NULL) {
113*36559Sbostic 			if (setreg(reg, edot))
114*36559Sbostic 				prints("register write failed");
115*36559Sbostic 			break;
116*36559Sbostic 		}
117*36559Sbostic 		if ((c = varlookup(rdc())) != -1)
118*36559Sbostic 			var[c] = edot;
119*36559Sbostic 		else
120*36559Sbostic 			error(BADVAR);
121*36559Sbostic 		break;
122*36559Sbostic 
123*36559Sbostic 	case '!':
124*36559Sbostic 		lastcom.c = 0;
125*36559Sbostic 		shell();
126*36559Sbostic 		break;
127*36559Sbostic 
128*36559Sbostic 	case '$':
129*36559Sbostic 		lastcom.c = 0;
130*36559Sbostic 		printtrace(nextchar());
131*36559Sbostic 		break;
132*36559Sbostic 
133*36559Sbostic 	case ':':
134*36559Sbostic 		if (!executing) {
135*36559Sbostic 			executing = 1;
136*36559Sbostic 			subpcs(nextchar());
137*36559Sbostic 			executing = 0;
138*36559Sbostic 			lastcom.c = 0;
139*36559Sbostic 		}
140*36559Sbostic 		break;
141*36559Sbostic 
142*36559Sbostic 	case 0:
143*36559Sbostic 		prints("adb\n");
144*36559Sbostic 		break;
145*36559Sbostic 
146*36559Sbostic 	default:
147*36559Sbostic 		error(BADCOM);
148*36559Sbostic 		/* NOTREACHED */
149*36559Sbostic 	}
150*36559Sbostic }
151*36559Sbostic 
152*36559Sbostic /*
153*36559Sbostic  * Perform a format-based command (one in ? / or =).
154*36559Sbostic  */
155*36559Sbostic static
156*36559Sbostic fmtcom(space, eqcom)
157*36559Sbostic 	int space, eqcom;
158*36559Sbostic {
159*36559Sbostic 	/* special commands m, lL, wW do not operate in SP_NONE (`=') */
160*36559Sbostic 	void mcom(), lcom(), wcom();
161*36559Sbostic 	static struct fcmd {
162*36559Sbostic 		int	c;
163*36559Sbostic 		void	(*fn)();
164*36559Sbostic 	} fcmd[] = {
165*36559Sbostic 		{ 'm', mcom },
166*36559Sbostic 		{ 'l', lcom }, { 'L', lcom },
167*36559Sbostic 		{ 'w', wcom }, { 'W', wcom },
168*36559Sbostic 		0
169*36559Sbostic 	};
170*36559Sbostic 	register struct fcmd *f;
171*36559Sbostic 	register int c;
172*36559Sbostic 	int ptype = space;
173*36559Sbostic 	static char stformat[LINELEN] = "X\"= \"^i";
174*36559Sbostic 	static char eqformat[LINELEN] = "z";
175*36559Sbostic 
176*36559Sbostic 	/*
177*36559Sbostic 	 * Are we operating in the alternate `star' space?
178*36559Sbostic 	 */
179*36559Sbostic 	if (!eqcom) {
180*36559Sbostic 		if (rdc() == '*')
181*36559Sbostic 			lastcom.star = 1;
182*36559Sbostic 		else
183*36559Sbostic 			unreadc();
184*36559Sbostic 		if (lastcom.star) {
185*36559Sbostic 			space |= SP_STAR;
186*36559Sbostic 			/* print as data for instr, and vice versa */
187*36559Sbostic 			ptype = (SP_DATA + SP_INSTR) - ptype;
188*36559Sbostic 		}
189*36559Sbostic 	}
190*36559Sbostic 
191*36559Sbostic 	/*
192*36559Sbostic 	 * Check for the special commands first.
193*36559Sbostic 	 */
194*36559Sbostic 	c = rdc();
195*36559Sbostic 	for (f = fcmd; f->c; f++) {
196*36559Sbostic 		if (c == f->c) {
197*36559Sbostic 			if (eqcom)
198*36559Sbostic 				error(BADEQ);
199*36559Sbostic 			(*f->fn)(space, ptype, isupper(c));
200*36559Sbostic 			return;
201*36559Sbostic 		}
202*36559Sbostic 	}
203*36559Sbostic 	unreadc();
204*36559Sbostic 	getformat(eqcom ? eqformat : stformat, LINELEN);
205*36559Sbostic 	scanform(!eqcom, eqcom ? eqformat : stformat, space, ptype);
206*36559Sbostic }
207*36559Sbostic 
208*36559Sbostic /*
209*36559Sbostic  * Set a map (?m, /m commands).
210*36559Sbostic  */
211*36559Sbostic /* ARGSUSED */
212*36559Sbostic static void
213*36559Sbostic mcom(space, ptype, fullword)
214*36559Sbostic 	int space, ptype, fullword;
215*36559Sbostic {
216*36559Sbostic 	register struct map *smap;
217*36559Sbostic 	register struct m1 *mm;
218*36559Sbostic 	char c;
219*36559Sbostic 
220*36559Sbostic 	smap = space & SP_DATA ? &datmap : &txtmap;
221*36559Sbostic 	mm = space & SP_STAR ? &smap->m2 : &smap->m1;
222*36559Sbostic 	if (oexpr()) {
223*36559Sbostic 		mm->b = expv;
224*36559Sbostic 		if (oexpr()) {
225*36559Sbostic 			mm->e = expv;
226*36559Sbostic 			if (oexpr())
227*36559Sbostic 				mm->f = expv;
228*36559Sbostic 		}
229*36559Sbostic 	}
230*36559Sbostic 	if ((c = rdc()) == '?')
231*36559Sbostic 		smap->ufd = symfile.fd;
232*36559Sbostic 	else if (c == '/')
233*36559Sbostic 		smap->ufd = corefile.fd;
234*36559Sbostic 	else
235*36559Sbostic 		unreadc();
236*36559Sbostic }
237*36559Sbostic 
238*36559Sbostic /*
239*36559Sbostic  * Locate a value (l, L commands).
240*36559Sbostic  */
241*36559Sbostic static void
242*36559Sbostic lcom(space, ptype, fullword)
243*36559Sbostic 	int space, ptype, fullword;
244*36559Sbostic {
245*36559Sbostic 	register expr_t val, mask;
246*36559Sbostic 	addr_t savdot;
247*36559Sbostic 
248*36559Sbostic 	/* search for exp */
249*36559Sbostic 	savdot = dot;
250*36559Sbostic 	val = rexpr();
251*36559Sbostic 	if (oexpr())
252*36559Sbostic 		mask = expv;
253*36559Sbostic 	else
254*36559Sbostic 		mask = ~0L;
255*36559Sbostic 	if (fullword) {
256*36559Sbostic 		expr_t w;
257*36559Sbostic 
258*36559Sbostic 		dotinc = sizeof(w);
259*36559Sbostic 		for (;;) {
260*36559Sbostic 			(void) adbread(space, dot, &w, sizeof(w));
261*36559Sbostic 			if (iserr() || (w & mask) == val)
262*36559Sbostic 				break;
263*36559Sbostic 			dot = inkdot(sizeof(w));
264*36559Sbostic 		}
265*36559Sbostic 	} else {
266*36559Sbostic 		hword_t hw;
267*36559Sbostic 
268*36559Sbostic 		dotinc = sizeof(hw);
269*36559Sbostic 		mask = (hword_t)mask;
270*36559Sbostic 		val = (hword_t)val;
271*36559Sbostic 		for (;;) {
272*36559Sbostic 			(void) adbread(space, dot, &hw, sizeof(hw));
273*36559Sbostic 			if (iserr() || (hw & mask) == val)
274*36559Sbostic 				break;
275*36559Sbostic 			dot = inkdot(sizeof(hw));
276*36559Sbostic 		}
277*36559Sbostic 	}
278*36559Sbostic 	if (iserr()) {
279*36559Sbostic 		dot = savdot;
280*36559Sbostic 		errflag = NOMATCH;
281*36559Sbostic 	}
282*36559Sbostic 	psymoff("%R", dot, ptype, maxoff, "");
283*36559Sbostic }
284*36559Sbostic 
285*36559Sbostic /*
286*36559Sbostic  * Write new values (w, W).
287*36559Sbostic  */
288*36559Sbostic static void
289*36559Sbostic wcom(space, ptype, fullword)
290*36559Sbostic 	int space, ptype, fullword;
291*36559Sbostic {
292*36559Sbostic 	addr_t savdot;
293*36559Sbostic 	hword_t hw;
294*36559Sbostic 
295*36559Sbostic 	(void) rexpr();
296*36559Sbostic 	do {
297*36559Sbostic 		savdot = dot;
298*36559Sbostic 		pdot();
299*36559Sbostic 		showdot(fullword, space, ptype);	/* also advances */
300*36559Sbostic 		errflag = NULL;
301*36559Sbostic 		dot = savdot;
302*36559Sbostic 		if (fullword)
303*36559Sbostic 			(void) adbwrite(space, dot, &expv, sizeof(expv));
304*36559Sbostic 		else {
305*36559Sbostic 			hw = expv;
306*36559Sbostic 			(void) adbwrite(space, dot, &hw, sizeof(hw));
307*36559Sbostic 		}
308*36559Sbostic 		savdot = dot;
309*36559Sbostic 		adbprintf("=%8t");
310*36559Sbostic 		showdot(fullword, space, ptype);
311*36559Sbostic 		printc('\n');
312*36559Sbostic 	} while (oexpr() && !iserr());
313*36559Sbostic 	dot = savdot;
314*36559Sbostic 	checkerr();
315*36559Sbostic }
316*36559Sbostic 
317*36559Sbostic /*
318*36559Sbostic  * Do a shell escape.
319*36559Sbostic  *
320*36559Sbostic  * THE vfork CODE BELOW IS CURRENTLY BROKEN
321*36559Sbostic  * MUST CHANGE signal TO sigvec BELOW
322*36559Sbostic  */
323*36559Sbostic static
324*36559Sbostic shell()
325*36559Sbostic {
326*36559Sbostic 	int rc, unixpid;
327*36559Sbostic 	union wait status;
328*36559Sbostic 	char *argp = lp;
329*36559Sbostic 	char *getenv(), *eshell = getenv("SHELL");
330*36559Sbostic 
331*36559Sbostic 	if (eshell == 0)
332*36559Sbostic 		eshell = "/bin/sh";
333*36559Sbostic 	while (readchar() != '\n')
334*36559Sbostic 		/* void */;
335*36559Sbostic #ifndef VFORK
336*36559Sbostic #define vfork fork
337*36559Sbostic #endif
338*36559Sbostic 	if ((unixpid = vfork()) == 0) {
339*36559Sbostic 		*lp = 0;
340*36559Sbostic 		(void) signal(SIGINT, sigint);
341*36559Sbostic 		(void) signal(SIGQUIT, sigquit);
342*36559Sbostic 		execl(eshell, "sh", "-c", argp, (char *)NULL);
343*36559Sbostic 		_exit(16);
344*36559Sbostic 		/* NOTREACHED */
345*36559Sbostic 	}
346*36559Sbostic #ifdef VFORK
347*36559Sbostic 	*lp = '\n';
348*36559Sbostic #endif
349*36559Sbostic 	if (unixpid == -1)
350*36559Sbostic 		error(NOFORK);
351*36559Sbostic 	(void) signal(SIGINT, SIG_IGN);
352*36559Sbostic 	while ((rc = wait(&status)) != unixpid && rc != -1)
353*36559Sbostic 		/* void */;
354*36559Sbostic 	(void) signal(SIGINT, intcatch);
355*36559Sbostic 	prints("!");
356*36559Sbostic 	unreadc();
357*36559Sbostic }
358*36559Sbostic 
359*36559Sbostic /*
360*36559Sbostic  * Read a format into the given buffer.  If nothing is
361*36559Sbostic  * read, leave the buffer alone.
362*36559Sbostic  */
363*36559Sbostic static
364*36559Sbostic getformat(buf, n)
365*36559Sbostic 	char *buf;
366*36559Sbostic 	register int n;
367*36559Sbostic {
368*36559Sbostic 	register char *p = buf;
369*36559Sbostic 	register int c, quote = 0;
370*36559Sbostic 
371*36559Sbostic 	while ((c = readchar()), quote ? c != '\n' : !eol(c)) {
372*36559Sbostic 		if (c == '"')
373*36559Sbostic 			quote = !quote;
374*36559Sbostic 		if (--n > 0)
375*36559Sbostic 			*p++ = c;
376*36559Sbostic 	}
377*36559Sbostic 	unreadc();
378*36559Sbostic 	if (p != buf)		/* nonempty */
379*36559Sbostic 		*p++ = 0;
380*36559Sbostic }
381*36559Sbostic 
382*36559Sbostic /*
383*36559Sbostic  * Convert a (one-character) variable name to an index, or -1 for
384*36559Sbostic  * error.
385*36559Sbostic  */
386*36559Sbostic varlookup(name)
387*36559Sbostic 	register int name;
388*36559Sbostic {
389*36559Sbostic 
390*36559Sbostic 	if (isdigit(name))
391*36559Sbostic 		return (name - '0');
392*36559Sbostic 	if (isalpha(name))
393*36559Sbostic 		return (isupper(name) ? name - 'a' + 10 : name - 'A' + 10);
394*36559Sbostic 	return (-1);
395*36559Sbostic }
396*36559Sbostic 
397*36559Sbostic /*
398*36559Sbostic  * If the text at the current input point matches a register name,
399*36559Sbostic  * consume that text and return a pointer to the register; otherwise
400*36559Sbostic  * leave it unconsumed and return NULL.
401*36559Sbostic  */
402*36559Sbostic struct reglist *
403*36559Sbostic reglookup()
404*36559Sbostic {
405*36559Sbostic 	register struct reglist *p;
406*36559Sbostic 	register char *a, *b, c0, c1;
407*36559Sbostic 	char *oldlp = lp;
408*36559Sbostic 	extern struct reglist reglist[];
409*36559Sbostic 
410*36559Sbostic 	c0 = rdc();
411*36559Sbostic 	c1 = readchar();
412*36559Sbostic 	for (p = reglist; (a = p->r_name) != NULL; p++) {
413*36559Sbostic 		if (*a++ != c0 || *a++ != c1)
414*36559Sbostic 			continue;
415*36559Sbostic 		b = lp;
416*36559Sbostic 		do {
417*36559Sbostic 			if (*a == 0) {	/* name matched: stop short */
418*36559Sbostic 				lp = b;
419*36559Sbostic 				return (p);
420*36559Sbostic 			}
421*36559Sbostic 		} while (*a++ == *b++);
422*36559Sbostic 	}
423*36559Sbostic 	lp = oldlp;
424*36559Sbostic 	return (NULL);
425*36559Sbostic }
426