.Xr botch fix
[unix-history] / usr / src / old / adb / common_source / command.c
CommitLineData
f582ecdc 1#ifndef lint
fef2e2de 2static char sccsid[] = "@(#)command.c 5.4 (Berkeley) %G%";
f582ecdc
KB
3#endif
4
5/*
6 * adb - commands
7 */
8
9#include "defs.h"
10#include <ctype.h>
11#include <sys/wait.h>
fef2e2de 12#include <paths.h>
f582ecdc
KB
13
14extern char BADEQ[]; /* "unexpected `='" */
15extern char NOMATCH[]; /* "cannot locate value" */
16extern char BADVAR[]; /* "bad variable" */
17extern char BADCOM[]; /* "bad command" */
18extern 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 */
26int executing;
27
28/* lastcom remembers the previous command */
29static 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 */
38command(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
51static
52cmds(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 */
156static
157fmtcom(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 */
213static void
214mcom(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 */
242static void
243lcom(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 */
289static void
290wcom(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 */
324static
325shell()
326{
327 int rc, unixpid;
328 union wait status;
329 char *argp = lp;
330 char *getenv(), *eshell = getenv("SHELL");
331
332 if (eshell == 0)
67000472 333 eshell = _PATH_BSHELL;
f582ecdc
KB
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 */
364static
365getformat(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 */
387varlookup(name)
388 register int name;
389{
390
391 if (isdigit(name))
392 return (name - '0');
393 if (isalpha(name))
27649f68 394 return (isupper(name) ? name - 'A' + 10 : name - 'a' + 10);
f582ecdc
KB
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 */
403struct reglist *
404reglookup()
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}