]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/vi/cmd.c
exec(2): fix prototypes
[plan9front.git] / sys / src / cmd / vi / cmd.c
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <mach.h>
5 #include <ctype.h>
6 #define Extern extern
7 #include "mips.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         int nr;
192
193         cp = nextc(cp);
194         switch(*cp) {
195         default:
196                 Bprint(bioout, "?\n");
197                 break;
198
199         case 'c':
200                 stktrace(*cp);
201                 break;
202
203         case 'C':
204                 stktrace(*cp);
205                 break;
206                 
207         case 'b':
208                 dobplist();
209                 break;
210
211         case 'r':
212                 dumpreg();
213                 break;
214
215         case 'R':
216                 dumpreg();
217
218         case 'f':
219                 dumpfreg();
220                 break;
221
222         case 'F':
223                 dumpdreg();
224                 break;
225
226         case 'q':
227                 exits(0);
228                 break;
229
230         case 'Q':
231                 isum();
232                 tlbsum();
233                 segsum();
234                 break;
235
236         case 't':
237                 cp++;
238                 switch(*cp) {
239                 default:
240                         Bprint(bioout, "$t[0sicr#]\n");
241                         break;
242                 case '\0':
243                         trace = 1;
244                         break;
245                 case '0':
246                         trace = 0;
247                         sysdbg = 0;
248                         calltree = 0;
249                         break;
250                 case 's':
251                         sysdbg = 1;
252                         break;
253                 case 'i':
254                         trace = 1;
255                         break;
256                 case 'c':
257                         calltree = 1;
258                         break;
259                 case 'r':
260                         nr = atoi(cp+1);
261                         if(nr < 0 || nr > 31) {
262                                 print("bad register\n");
263                                 break;
264                         }
265                         rtrace ^= (1<<nr);
266                         print("%.8ux\n", rtrace);
267                         break;
268                 }
269                 break;
270
271         case 'i':
272                 cp++;
273                 switch(*cp) {
274                 default:
275                         Bprint(bioout, "$i[itsa]\n");
276                         break;
277                 case 'i':
278                         isum();
279                         break;
280                 case 't':
281                         tlbsum();
282                         break;
283                 case 's':
284                         segsum();
285                         break;
286                 case 'a':
287                         isum();
288                         tlbsum();
289                         segsum();
290                         iprofile();
291                         break;
292                 case 'p':
293                         iprofile();
294                         break;
295                 }
296         }
297 }
298
299 int
300 pfmt(char fmt, int mem, ulong val)
301 {
302         int c, i;
303         Symbol s;
304         char *p, ch, str[1024];
305
306         c = 0;
307         switch(fmt) {
308         default:
309                 Bprint(bioout, "bad modifier\n");
310                 return 0;
311         case 'o':
312                 c = Bprint(bioout, "%-4lo ", mem ? (ushort)getmem_2(dot) : val);
313                 inc = 2;
314                 break;
315
316         case 'O':
317                 c = Bprint(bioout, "%-8lo ", mem ? getmem_4(dot) : val);
318                 inc = 4;
319                 break;
320
321         case 'q':
322                 c = Bprint(bioout, "%-4lo ", mem ? (short)getmem_2(dot) : val);
323                 inc = 2;
324                 break;
325
326         case 'Q':
327                 c = Bprint(bioout, "%-8lo ", mem ? (long)getmem_4(dot) : val);
328                 inc = 4;
329                 break;
330
331         case 'd':
332                 c = Bprint(bioout, "%-5ld ", mem ? (short)getmem_2(dot) : val);
333                 inc = 2;
334                 break;
335
336
337         case 'D':
338                 c = Bprint(bioout, "%-8ld ", mem ? (long)getmem_4(dot) : val);
339                 inc = 4;
340                 break;
341
342         case 'x':
343                 c = Bprint(bioout, "#%-4lux ", mem ? (long)getmem_2(dot) : val);
344                 inc = 2;
345                 break;
346
347         case 'X':
348                 c = Bprint(bioout, "#%-8lux ", mem ? (long)getmem_4(dot) : val);
349                 inc = 4;
350                 break;
351
352         case 'u':
353                 c = Bprint(bioout, "%-5ld ", mem ? (ushort)getmem_2(dot) : val);
354                 inc = 2;
355                 break;
356
357         case 'U':
358                 c = Bprint(bioout, "%-8ld ", mem ? (ulong)getmem_4(dot) : val);
359                 inc = 4;
360                 break;
361
362         case 'b':
363                 c = Bprint(bioout, "%-3ld ", mem ? getmem_b(dot) : val);
364                 inc = 1;
365                 break;
366
367         case 'c':
368                 c = Bprint(bioout, "%c ", (int)(mem ? getmem_b(dot) : val));
369                 inc = 1;
370                 break;
371
372         case 'C':
373                 ch = mem ? getmem_b(dot) : val;
374                 if(isprint(ch))
375                         c = Bprint(bioout, "%c ", ch);
376                 else
377                         c = Bprint(bioout, "\\x%.2x ", ch);
378                 inc = 1;
379                 break;
380
381         case 's':
382                 i = 0;
383                 while(ch = getmem_b(dot+i))
384                         str[i++] = ch;
385                 str[i] = '\0';
386                 dot += i;
387                 c = Bprint(bioout, "%s", str);
388                 inc = 0;
389                 break;
390
391         case 'S':
392                 i = 0;
393                 while(ch = getmem_b(dot+i))
394                         str[i++] = ch;
395                 str[i] = '\0';
396                 dot += i;
397                 for(p = str; *p; p++)
398                         if(isprint(*p))
399                                 c += Bprint(bioout, "%c", *p);
400                         else
401                                 c += Bprint(bioout, "\\x%.2ux", *p);
402                 inc = 0;
403                 break;
404
405         case 'Y':
406                 p = ctime(mem ? getmem_b(dot) : val);
407                 p[30] = '\0';
408                 c = Bprint(bioout, "%s", p);
409                 inc = 4;
410                 break;
411
412         case 'a':
413                 symoff(str, sizeof(str), dot, CTEXT);
414                 c = Bprint(bioout, str);
415                 inc = 0;
416                 break;
417
418         case 'e':
419                 for (i = 0; globalsym(&s, i); i++)
420                         Bprint(bioout, "%-15s #%lux\n", s.name, getmem_4(s.value));
421                 inc = 0;
422                 break;
423
424         case 'i':
425                 inc = _mipscoinst(symmap, dot, str, sizeof(str));
426                 if (inc < 0) {
427                         Bprint(bioout, "vi: %r\n");
428                         return 0;
429                 }
430                 c = Bprint(bioout, str);
431                 break;
432
433         case 'n':
434                 c = width+1;
435                 inc = 0;
436                 break;
437
438         case '-':
439                 c = 0;
440                 inc = -1;
441                 break;
442
443         case '+':
444                 c = 0;
445                 inc = 1;
446                 break;
447
448         case '^':
449                 c = 0;
450                 if(inc > 0)
451                         inc = -inc;
452                 break;
453
454         case 'z':
455                 if (findsym(dot, CTEXT, &s))
456                         Bprint(bioout, "  %s() ", s.name);
457                 printsource(dot);
458                 inc = 0;
459                 break;
460         }
461         return c;
462 }
463
464 void
465 eval(char *addr, char *p)
466 {
467         ulong val;
468
469         val = expr(addr);
470         p = nextc(p);
471         if(*p == '\0') {
472                 p[0] = fmt;
473                 p[1] = '\0';
474         }
475         pfmt(*p, 0, val);
476         Bprint(bioout, "\n");
477 }
478
479 void
480 quesie(char *p)
481 {
482         int c, count, i;
483         char tbuf[512];
484
485         c = 0;
486         symoff(tbuf, sizeof(tbuf), dot, CTEXT);
487         Bprint(bioout, "%s?\t", tbuf);
488
489         while(*p) {
490                 p = nextc(p);
491                 if(*p == '"') {
492                         for(p++; *p && *p != '"'; p++) {
493                                 Bputc(bioout, *p);
494                                 c++;
495                         }
496                         if(*p)
497                                 p++;
498                         continue;
499                 }
500                 count = 0;
501                 while(*p >= '0' && *p <= '9')
502                         count = count*10 + (*p++ - '0');
503                 if(count == 0)
504                         count = 1;
505                 p = nextc(p);
506                 if(*p == '\0') {
507                         p[0] = fmt;
508                         p[1] = '\0';
509                 }
510                 for(i = 0; i < count; i++) {
511                         c += pfmt(*p, 1, 0);
512                         dot += inc;
513                         if(c > width) {
514                                 Bprint(bioout, "\n");
515                                 symoff(tbuf, sizeof(tbuf), dot, CTEXT);
516                                 Bprint(bioout, "%s?\t", tbuf);
517                                 c = 0;
518                         }
519                 }
520                 fmt = *p++;
521                 p = nextc(p);
522         }
523         Bprint(bioout, "\n");
524 }
525
526 void
527 catcher(void *a, char *msg)
528 {
529         USED(a);
530         if(strcmp(msg, "interrupt") != 0)
531                 noted(NDFLT);
532
533         count = 1;
534         print("vi\n");
535         noted(NCONT);
536 }
537
538 void
539 setreg(char *addr, char *cp)
540 {
541         int rn;
542
543         dot = expr(addr);
544         cp = nextc(cp);
545         if(strcmp(cp, "pc") == 0) {
546                 reg.pc = dot;
547                 return;
548         }
549         if(strcmp(cp, "sp") == 0) {
550                 reg.r[29] = dot;
551                 return;
552         }
553         if(strcmp(cp, "mh") == 0) {
554                 reg.mhi = dot;
555                 return;
556         }
557         if(strcmp(cp, "ml") == 0) {
558                 reg.mlo = dot;
559                 return;
560         }
561         if(*cp++ == 'r') {
562                 rn = strtoul(cp, 0, 10);
563                 if(rn > 0 && rn < 32) {
564                         reg.r[rn] = dot;
565                         return;
566                 }
567         }
568         Bprint(bioout, "bad register\n");
569 }
570
571 void
572 cmd(void)
573 {
574         char *p, *a, *cp, *gotint;
575         char addr[128];
576         static char *cmdlet = ":$?/=>";
577         int n, i;
578
579         notify(catcher);
580
581         dot = reg.pc;
582         setjmp(errjmp);
583
584         for(;;) {
585                 Bflush(bioout);
586                 p = buf;
587                 n = 0;
588                 for(;;) {
589                         i = Bgetc(bin);
590                         if(i < 0)
591                                 exits(0);
592                         *p++ = i;
593                         n++;
594                         if(i == '\n')
595                                 break;
596                 }
597
598                 if(buf[0] == '\n')
599                         strcpy(buf, lastcmd);
600                 else {
601                         buf[n-1] = '\0';
602                         strcpy(lastcmd, buf);
603                 }
604                 p = buf;
605                 a = addr;
606
607                 for(;;) {
608                         p = nextc(p);
609                         if(*p == 0 || strchr(cmdlet, *p))
610                                 break;
611                         *a++ = *p++;
612                 }
613
614                 *a = '\0';
615                 cmdcount = 1;
616                 cp = strchr(addr, ',');
617                 if(cp != 0) {
618                         if(cp[1] == '#')
619                                 cmdcount = strtoul(cp+2, &gotint, 16);
620                         else
621                                 cmdcount = strtoul(cp+1, &gotint, 0);
622                         *cp = '\0';
623                 }
624
625                 switch(*p) {
626                 case '$':
627                         dollar(p+1);
628                         break;
629                 case ':':
630                         colon(addr, p+1);
631                         break;
632                 case '/':
633                 case '?':
634                         dot = expr(addr);
635                         for(i = 0; i < cmdcount; i++)
636                                 quesie(p+1);
637                         break;
638                 case '=':
639                         eval(addr, p+1);
640                         break;
641                 case '>':
642                         setreg(addr, p+1);
643                         break;
644                 default:
645                         Bprint(bioout, "?\n");
646                         break;
647                 }
648         }
649 }