]> git.lizzy.rs Git - plan9front.git/blob - cmd.c
e1871c017913a0832fdc5e89e0a10ca5e648e4ab
[plan9front.git] / cmd.c
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <mach.h>
5 #include <ctype.h>
6 #include "arm.h"
7
8 char    buf[128], lastcmd[128];
9 char    fmt = 'X';
10 int     width = 60;
11 int     inc;
12
13 ulong   expr(char*);
14 ulong   expr1(char*);
15 char*   term(char*, ulong*);
16
17 char*
18 nextc(char *p)
19 {
20         while(*p && (*p == ' ' || *p == '\t') && *p != '\n')
21                 p++;
22
23         if(*p == '\n')
24                 *p = '\0';
25
26         return p;
27 }
28
29 char*
30 numsym(char *addr, ulong *val)
31 {
32         char tsym[128], *t;
33         static char *delim = "`'<>/\\@*|-~+-/=?\n";
34         Symbol s;
35         char c;
36
37         t = tsym;
38         while(c = *addr) {
39                 if(strchr(delim, c))
40                         break;
41                 *t++ = c;
42                 addr++;
43         }
44         t[0] = '\0';
45
46         if(strcmp(tsym, ".") == 0) {
47                 *val = dot;
48                 return addr;
49         }
50
51         if(lookup(0, tsym, &s))
52                 *val = s.value;
53         else {
54                 if(tsym[0] == '#')
55                         *val = strtoul(tsym+1, 0, 16);
56                 else
57                         *val = strtoul(tsym, 0, 0);
58         }
59         return addr;
60 }
61
62 ulong
63 expr(char *addr)
64 {
65         ulong t, t2;
66         char op;
67
68         if(*addr == '\0')
69                 return dot;
70
71         addr = numsym(addr, &t);
72
73         if(*addr == '\0')
74                 return t;
75
76         addr = nextc(addr);
77         op = *addr++;
78         numsym(addr, &t2);
79         switch(op) {
80         default:
81                 Bprint(bioout, "expr syntax\n");
82                 return 0;
83         case '+':
84                 t += t2;
85                 break;
86         case '-':
87                 t -= t2;
88                 break;
89         case '%':
90                 t /= t2;
91                 break;
92         case '&':
93                 t &= t2;
94                 break;
95         case '|':
96                 t |= t2;
97                 break;
98         }
99
100         return t;
101 }
102
103 int
104 buildargv(char *str, char **args, int max)
105 {
106         int na = 0;
107
108         while (na < max) {
109                 while((*str == ' ' || *str == '\t' || *str == '\n') && *str != '\0')
110                         str++;
111
112                 if(*str == '\0')
113                         return na;
114
115                 args[na++] = str;
116                 while(!(*str == ' ' || *str == '\t'|| *str == '\n') && *str != '\0')
117                         str++;
118
119                 if(*str == '\n')
120                         *str = '\0';
121
122                 if(*str == '\0')
123                         break;
124
125                 *str++ = '\0';
126         }
127         return na;
128 }
129
130 void
131 colon(char *addr, char *cp)
132 {
133         int argc;
134         char *argv[100];
135         char tbuf[512];
136
137         cp = nextc(cp);
138         switch(*cp) {
139         default:
140                 Bprint(bioout, "?\n");
141                 return;
142         case 'b':
143                 breakpoint(addr, cp+1);
144                 return;
145
146         case 'd':
147                 delbpt(addr);
148                 return;
149
150         /* These fall through to print the stopped address */
151         case 'r':
152                 reset();
153                 argc = buildargv(cp+1, argv, 100);
154                 initstk(argc, argv);
155                 count = 0;
156                 atbpt = 0;
157                 run();
158                 break;
159         case 'c':
160                 count = 0;
161                 atbpt = 0;
162                 run();
163                 break;
164         case 's':
165                 cp = nextc(cp+1);
166                 count = 0;
167                 if(*cp)
168                         count = strtoul(cp, 0, 0);
169                 if(count == 0)
170                         count = 1;
171                 atbpt = 0;
172                 run();
173                 break;
174         }
175
176         dot = reg.r[15];
177         Bprint(bioout, "%s at #%lux ", atbpt? "breakpoint": "stopped", dot);
178         symoff(tbuf, sizeof(tbuf), dot, CTEXT);
179         Bprint(bioout, tbuf);
180         if(fmt == 'z')
181                 printsource(dot);
182
183         Bprint(bioout, "\n");
184 }
185
186
187 void
188 dollar(char *cp)
189 {
190         cp = nextc(cp);
191         switch(*cp) {
192         default:
193                 Bprint(bioout, "?\n");
194                 break;
195
196         case 'c':
197                 stktrace(*cp);
198                 break;
199
200         case 'C':
201                 stktrace(*cp);
202                 break;
203                 
204         case 'b':
205                 dobplist();
206                 break;
207
208         case 'r':
209                 dumpreg();
210                 break;
211
212         case 'R':
213                 dumpreg();
214
215         case 'f':
216                 dumpfreg();
217                 break;
218
219         case 'F':
220                 dumpdreg();
221                 break;
222
223         case 'q':
224                 exits(0);
225                 break;
226
227         case 'Q':
228                 isum();
229                 tlbsum();
230                 segsum();
231                 break;
232
233         case 't':
234                 cp++;
235                 switch(*cp) {
236                 default:
237                         Bprint(bioout, ":t[0sic]\n");
238                         break;
239                 case '\0':
240                         trace = 1;
241                         break;
242                 case '0':
243                         trace = 0;
244                         sysdbg = 0;
245                         calltree = 0;
246                         break;
247                 case 's':
248                         sysdbg = 1;
249                         break;
250                 case 'i':
251                         trace = 1;
252                         break;
253                 case 'c':
254                         calltree = 1;
255                         break;
256                 }
257                 break;
258
259         case 'i':
260                 cp++;
261                 switch(*cp) {
262                 default:
263                         Bprint(bioout, "$i[itsa]\n");
264                         break;
265                 case 'i':
266                         isum();
267                         break;
268                 case 't':
269                         tlbsum();
270                         break;
271                 case 's':
272                         segsum();
273                         break;
274                 case 'a':
275                         isum();
276                         tlbsum();
277                         segsum();
278                         iprofile();
279                         break;
280                 case 'p':
281                         iprofile();
282                         break;
283                 }
284         }
285 }
286
287 int
288 pfmt(char fmt, int mem, ulong val)
289 {
290         int c, i;
291         Symbol s;
292         char *p, ch, str[1024];
293
294         c = 0;
295         switch(fmt) {
296         default:
297                 Bprint(bioout, "bad modifier\n");
298                 return 0;
299         case 'o':
300                 c = Bprint(bioout, "%-4lo ", mem? (ushort)getmem_2(dot): val);
301                 inc = 2;
302                 break;
303
304         case 'O':
305                 c = Bprint(bioout, "%-8lo ", mem? getmem_4(dot): val);
306                 inc = 4;
307                 break;
308
309         case 'q':
310                 c = Bprint(bioout, "%-4lo ", mem? (short)getmem_2(dot): val);
311                 inc = 2;
312                 break;
313
314         case 'Q':
315                 c = Bprint(bioout, "%-8lo ", mem? (long)getmem_4(dot): val);
316                 inc = 4;
317                 break;
318
319         case 'd':
320                 c = Bprint(bioout, "%-5ld ", mem? (short)getmem_2(dot): val);
321                 inc = 2;
322                 break;
323
324
325         case 'D':
326                 c = Bprint(bioout, "%-8ld ", mem? (long)getmem_4(dot): val);
327                 inc = 4;
328                 break;
329
330         case 'x':
331                 c = Bprint(bioout, "#%-4lux ", mem? (long)getmem_2(dot): val);
332                 inc = 2;
333                 break;
334
335         case 'X':
336                 c = Bprint(bioout, "#%-8lux ", mem? (long)getmem_4(dot): val);
337                 inc = 4;
338                 break;
339
340         case 'u':
341                 c = Bprint(bioout, "%-5ld ", mem? (ushort)getmem_2(dot): val);
342                 inc = 2;
343                 break;
344
345         case 'U':
346                 c = Bprint(bioout, "%-8ld ", mem? (ulong)getmem_4(dot): val);
347                 inc = 4;
348                 break;
349
350         case 'b':
351                 c = Bprint(bioout, "%-3ld ", mem? getmem_b(dot): val);
352                 inc = 1;
353                 break;
354
355         case 'c':
356                 c = Bprint(bioout, "%c ", (int)(mem? getmem_b(dot): val));
357                 inc = 1;
358                 break;
359
360         case 'C':
361                 ch = mem? getmem_b(dot): val;
362                 if(isprint(ch))
363                         c = Bprint(bioout, "%c ", ch);
364                 else
365                         c = Bprint(bioout, "\\x%.2x ", ch);
366                 inc = 1;
367                 break;
368
369         case 's':
370                 i = 0;
371                 while(ch = getmem_b(dot+i))
372                         str[i++] = ch;
373                 str[i] = '\0';
374                 dot += i;
375                 c = Bprint(bioout, "%s", str);
376                 inc = 0;
377                 break;
378
379         case 'S':
380                 i = 0;
381                 while(ch = getmem_b(dot+i))
382                         str[i++] = ch;
383                 str[i] = '\0';
384                 dot += i;
385                 for(p = str; *p; p++)
386                         if(isprint(*p))
387                                 c += Bprint(bioout, "%c", *p);
388                         else
389                                 c += Bprint(bioout, "\\x%.2ux", *p);
390                 inc = 0;
391                 break;
392
393         case 'Y':
394                 p = ctime(mem? getmem_b(dot): val);
395                 p[30] = '\0';
396                 c = Bprint(bioout, "%s", p);
397                 inc = 4;
398                 break;
399
400         case 'a':
401                 symoff(str, sizeof(str), dot, CTEXT);
402                 c = Bprint(bioout, str);
403                 inc = 0;
404                 break;
405
406         case 'e':
407                 for(i = 0; globalsym(&s, i); i++)
408                         Bprint(bioout, "%-15s #%lux\n", s.name, getmem_4(s.value));
409                 inc = 0;
410                 break;
411
412         case 'I':
413         case 'i':
414                 inc = machdata->das(symmap, dot, fmt, str, sizeof(str));
415                 if(inc < 0) {
416                         Bprint(bioout, "5i: %r\n");
417                         return 0;
418                 }
419                 c = Bprint(bioout, "\t%s", str);
420                 break;
421
422         case 'n':
423                 c = width+1;
424                 inc = 0;
425                 break;
426
427         case '-':
428                 c = 0;
429                 inc = -1;
430                 break;
431
432         case '+':
433                 c = 0;
434                 inc = 1;
435                 break;
436
437         case '^':
438                 c = 0;
439                 if(inc > 0)
440                         inc = -inc;
441                 break;
442
443         case 'z':
444                 if(findsym(dot, CTEXT, &s))
445                         Bprint(bioout, "  %s() ", s.name);
446                 printsource(dot);
447                 inc = 0;
448                 break;
449         }
450         return c;
451 }
452
453 void
454 eval(char *addr, char *p)
455 {
456         ulong val;
457
458         val = expr(addr);
459         p = nextc(p);
460         if(*p == '\0') {
461                 p[0] = fmt;
462                 p[1] = '\0';
463         }
464         pfmt(*p, 0, val);
465         Bprint(bioout, "\n");
466 }
467
468 void
469 quesie(char *p)
470 {
471         int c, count, i;
472         char tbuf[512];
473
474         c = 0;
475         symoff(tbuf, sizeof(tbuf), dot, CTEXT);
476         Bprint(bioout, "%s?\t", tbuf);
477
478         while(*p) {
479                 p = nextc(p);
480                 if(*p == '"') {
481                         for(p++; *p && *p != '"'; p++) {
482                                 Bputc(bioout, *p);
483                                 c++;
484                         }
485                         if(*p)
486                                 p++;
487                         continue;
488                 }
489                 count = 0;
490                 while(*p >= '0' && *p <= '9')
491                         count = count*10 + (*p++ - '0');
492                 if(count == 0)
493                         count = 1;
494                 p = nextc(p);
495                 if(*p == '\0') {
496                         p[0] = fmt;
497                         p[1] = '\0';
498                 }
499                 for(i = 0; i < count; i++) {
500                         c += pfmt(*p, 1, 0);
501                         dot += inc;
502                         if(c > width) {
503                                 Bprint(bioout, "\n");
504                                 symoff(tbuf, sizeof(tbuf), dot, CTEXT);
505                                 Bprint(bioout, "%s?\t", tbuf);
506                                 c = 0;
507                         }
508                 }
509                 fmt = *p++;
510                 p = nextc(p);
511         }
512         Bprint(bioout, "\n");
513 }
514
515 void
516 catcher(void *a, char *msg)
517 {
518         static int hit = 0;
519
520         hit++;
521         if(hit > 5)
522                 exits(0);
523         USED(a);
524         if(strcmp(msg, "interrupt") != 0)
525                 noted(NDFLT);
526
527         count = 1;
528         print("5i\n");
529         noted(NCONT);
530 }
531
532 void
533 setreg(char *addr, char *cp)
534 {
535         int rn;
536
537         dot = expr(addr);
538         cp = nextc(cp);
539         if(strcmp(cp, "pc") == 0) {
540                 reg.r[15] = dot;
541                 return;
542         }
543         if(strcmp(cp, "sp") == 0) {
544                 reg.r[13] = dot;
545                 return;
546         }
547         if(*cp++ == 'r') {
548                 rn = strtoul(cp, 0, 10);
549                 if(rn > 0 && rn < 16) {
550                         reg.r[rn] = dot;
551                         return;
552                 }
553         }
554         Bprint(bioout, "bad register\n");
555 }
556
557 void
558 cmd(void)
559 {
560         char *p, *a, *cp, *gotint;
561         char addr[128];
562         static char *cmdlet = ":$?/=>";
563         int n, i;
564
565         notify(catcher);
566
567         dot = reg.r[15];
568         setjmp(errjmp);
569
570         for(;;) {
571                 Bflush(bioout);
572                 p = buf;
573                 n = 0;
574                 while(n < sizeof(buf)) {
575                         i = Bgetc(bin);
576                         if(i < 0)
577                                 exits(0);
578                         *p++ = i;
579                         n++;
580                         if(i == '\n')
581                                 break;
582                 }
583
584                 if(buf[0] == '\n')
585                         strcpy(buf, lastcmd);
586                 else {
587                         buf[n-1] = '\0';
588                         strcpy(lastcmd, buf);
589                 }
590                 p = buf;
591                 a = addr;
592
593                 for(;;) {
594                         p = nextc(p);
595                         if(*p == 0 || strchr(cmdlet, *p))
596                                 break;
597                         *a++ = *p++;
598                 }
599
600                 *a = '\0';
601                 cmdcount = 1;
602                 cp = strchr(addr, ',');
603                 if(cp != 0) {
604                         if(cp[1] == '#')
605                                 cmdcount = strtoul(cp+2, &gotint, 16);
606                         else
607                                 cmdcount = strtoul(cp+1, &gotint, 0);
608                         *cp = '\0';
609                 }
610
611                 switch(*p) {
612                 case '$':
613                         dollar(p+1);
614                         break;
615                 case ':':
616                         colon(addr, p+1);
617                         break;
618                 case '/':
619                 case '?':
620                         dot = expr(addr);
621                         for(i = 0; i < cmdcount; i++)
622                                 quesie(p+1);
623                         break;
624                 case '=':
625                         eval(addr, p+1);
626                         break;
627                 case '>':
628                         setreg(addr, p+1);
629                         break;
630                 default:
631                         Bprint(bioout, "?\n");
632                         break;
633                 }
634         }
635 }