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