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