]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/db/command.c
mothra: never snarf the "Go:" box
[plan9front.git] / sys / src / cmd / db / command.c
1 /*
2  *
3  *      debugger
4  *
5  */
6
7 #include "defs.h"
8 #include "fns.h"
9
10 char    BADEQ[] = "unexpected `='";
11
12 BOOL    executing;
13 extern  Rune    *lp;
14
15 char    eqformat[ARB] = "z";
16 char    stformat[ARB] = "zMi";
17
18 ADDR    ditto;
19
20 ADDR    dot;
21 int     dotinc;
22 WORD    adrval, cntval, loopcnt;
23 int     adrflg, cntflg;
24
25 /* command decoding */
26
27 command(char *buf, int defcom)
28 {
29         char    *reg;
30         char    savc;
31         Rune    *savlp=lp;
32         char    savlc = lastc;
33         char    savpc = peekc;
34         static char lastcom = '=', savecom = '=';
35
36         if (defcom == 0)
37                 defcom = lastcom;
38         if (buf) {
39                 if (*buf==EOR)
40                         return(FALSE);
41                 clrinp();
42                 lp=(Rune*)buf;
43         }
44         do {
45                 adrflg=expr(0);         /* first address */
46                 if (adrflg){
47                         dot=expv;
48                         ditto=expv;
49                 }
50                 adrval=dot;
51
52                 if (rdc()==',' && expr(0)) {    /* count */
53                         cntflg=TRUE;
54                         cntval=expv;
55                 } else {
56                         cntflg=FALSE;
57                         cntval=1;
58                         reread();
59                 }
60
61                 if (!eol(rdc()))
62                         lastcom=lastc;          /* command */
63                 else {
64                         if (adrflg==0)
65                                 dot=inkdot(dotinc);
66                         reread();
67                         lastcom=defcom;
68                 }
69                 switch(lastcom) {
70                 case '/':
71                 case '=':
72                 case '?':
73                         savecom = lastcom;
74                         acommand(lastcom);
75                         break;
76
77                 case '>':
78                         lastcom = savecom; 
79                         savc=rdc();
80                         if (reg=regname(savc))
81                                 rput(cormap, reg, dot);
82                         else    
83                                 error("bad variable");
84                         break;
85
86                 case '!':
87                         lastcom=savecom;
88                         shell(); 
89                         break;
90
91                 case '$':
92                         lastcom=savecom;
93                         printtrace(nextchar()); 
94                         break;
95
96                 case ':':
97                         if (!executing) { 
98                                 executing=TRUE;
99                                 subpcs(nextchar());
100                                 executing=FALSE;
101                                 lastcom=savecom;
102                         }
103                         break;
104
105                 case 0:
106                         prints(DBNAME);
107                         break;
108
109                 default: 
110                         error("bad command");
111                 }
112                 flushbuf();
113         } while (rdc()==';');
114         if (buf == 0)
115                 reread();
116         else {
117                 clrinp();
118                 lp=savlp;
119                 lastc = savlc;
120                 peekc = savpc;
121         }
122
123         if(adrflg)
124                 return dot;
125         return 1;
126 }
127
128 /*
129  * [/?][wml]
130  */
131
132 void
133 acommand(int pc)
134 {
135         int eqcom;
136         Map *map;
137         char *fmt;
138         char buf[512];
139
140         if (pc == '=') {
141                 eqcom = 1;
142                 fmt = eqformat;
143                 map = dotmap;
144         } else {
145                 eqcom = 0;
146                 fmt = stformat;
147                 if (pc == '/')
148                         map = cormap;
149                 else
150                         map = symmap;
151         }
152         if (!map) {
153                 snprint(buf, sizeof(buf), "no map for %c", pc);
154                 error(buf);
155         }
156
157         switch (rdc())
158         {
159         case 'm':
160                 if (eqcom)
161                         error(BADEQ); 
162                 cmdmap(map);
163                 break;
164
165         case 'L':
166         case 'l':
167                 if (eqcom)
168                         error(BADEQ); 
169                 cmdsrc(lastc, map);
170                 break;
171
172         case 'W':
173         case 'w':
174                 if (eqcom)
175                         error(BADEQ); 
176                 cmdwrite(lastc, map);
177                 break;
178
179         default:
180                 reread();
181                 getformat(fmt);
182                 scanform(cntval, !eqcom, fmt, map, eqcom);
183         }
184 }
185
186 void
187 cmdsrc(int c, Map *map)
188 {
189         ulong w;
190         long locval, locmsk;
191         ADDR savdot;
192         ushort sh;
193         char buf[512];
194         int ret;
195
196         if (c == 'L')
197                 dotinc = 4;
198         else
199                 dotinc = 2;
200         savdot=dot;
201         expr(1); 
202         locval=expv;
203         if (expr(0))
204                 locmsk=expv; 
205         else
206                 locmsk = ~0;
207         if (c == 'L')
208                 while ((ret = get4(map, dot, &w)) > 0 &&  (w&locmsk) != locval)
209                         dot = inkdot(dotinc);
210         else
211                 while ((ret = get2(map, dot, &sh)) > 0 && (sh&locmsk) != locval)
212                         dot = inkdot(dotinc);
213         if (ret < 0) { 
214                 dot=savdot; 
215                 error("%r");
216         }
217         symoff(buf, 512, dot, CANY);
218         dprint(buf);
219 }
220
221 static char badwrite[] = "can't write process memory or text image";
222
223 void
224 cmdwrite(int wcom, Map *map)
225 {
226         ADDR savdot;
227         char *format;
228         int pass;
229
230         if (wcom == 'w')
231                 format = "x";
232         else
233                 format = "X";
234         expr(1);
235         pass = 0;
236         do {
237                 pass++;  
238                 savdot=dot;
239                 exform(1, 1, format, map, 0, pass);
240                 dot=savdot;
241                 if (wcom == 'W') {
242                         if (put4(map, dot, expv) <= 0)
243                                 error(badwrite);
244                 } else {
245                         if (put2(map, dot, expv) <= 0)
246                                 error(badwrite);
247                 }
248                 savdot=dot;
249                 dprint("=%8t"); 
250                 exform(1, 0, format, map, 0, pass);
251                 newline();
252         } while (expr(0));
253         dot=savdot;
254 }
255
256 /*
257  * collect a register name; return register offset
258  * this is not what i'd call a good division of labour
259  */
260
261 char *
262 regname(int regnam)
263 {
264         static char buf[64];
265         char *p;
266         int c;
267
268         p = buf;
269         *p++ = regnam;
270         while (isalnum(c = readchar())) {
271                 if (p >= buf+sizeof(buf)-1)
272                         error("register name too long");
273                 *p++ = c;
274         }
275         *p = 0;
276         reread();
277         return (buf);
278 }
279
280 /*
281  * shell escape
282  */
283
284 void
285 shell(void)
286 {
287         int     rc, unixpid;
288         char *argp = (char*)lp;
289
290         while (lastc!=EOR)
291                 rdc();
292         if ((unixpid=fork())==0) {
293                 *lp=0;
294                 execl("/bin/rc", "rc", "-c", argp, nil);
295                 exits("execl");                         /* botch */
296         } else if (unixpid == -1) {
297                 error("cannot fork");
298         } else {
299                 mkfault = 0;
300                 while ((rc = waitpid()) != unixpid){
301                         if(rc == -1 && mkfault){
302                                 mkfault = 0;
303                                 continue;
304                         }
305                         break;
306                 }
307                 prints("!"); 
308                 reread();
309         }
310 }