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