1 #include <lib9.h>
2 #include <bio.h>
3 #include <ctype.h>
4 #include "mach.h"
5 #include "regexp.h"
6 #define Extern extern
7 #include "acid.h"
8 #include "y.tab.h"
9
10 void cvtatof(Node*, Node*);
11 void cvtatoi(Node*, Node*);
12 void cvtitoa(Node*, Node*);
13 void bprint(Node*, Node*);
14 void funcbound(Node*, Node*);
15 void printto(Node*, Node*);
16 void getfile(Node*, Node*);
17 void fmt(Node*, Node*);
18 void pcfile(Node*, Node*);
19 void pcline(Node*, Node*);
20 void setproc(Node*, Node*);
21 void strace(Node*, Node*);
22 void follow(Node*, Node*);
23 void reason(Node*, Node*);
24 void newproc(Node*, Node*);
25 void startstop(Node*, Node*);
26 void match(Node*, Node*);
27 void status(Node*, Node*);
28 void dokill(Node*,Node*);
29 void waitstop(Node*, Node*);
30 void stop(Node*, Node*);
31 void start(Node*, Node*);
32 void filepc(Node*, Node*);
33 void doerror(Node*, Node*);
34 void rc(Node*, Node*);
35 void doaccess(Node*, Node*);
36 void map(Node*, Node*);
37 void readfile(Node*, Node*);
38 void interpret(Node*, Node*);
39 void include(Node*, Node*);
40 void regexp(Node*, Node*);
41 void _bpcondset(Node*, Node*);
42 void _bpconddel(Node*, Node*);
43 void setdebug(Node*, Node*);
44
45 typedef struct Btab Btab;
46 struct Btab
47 {
48 char *name;
49 void (*fn)(Node*, Node*);
50 } tab[] =
51 {
52 "atof", cvtatof,
53 "atoi", cvtatoi,
54 "error", doerror,
55 "file", getfile,
56 "readfile", readfile,
57 "access", doaccess,
58 "filepc", filepc,
59 "fnbound", funcbound,
60 "fmt", fmt,
61 "follow", follow,
62 "itoa", cvtitoa,
63 "kill", dokill,
64 "match", match,
65 "newproc", newproc,
66 "pcfile", pcfile,
67 "pcline", pcline,
68 "print", bprint,
69 "printto", printto,
70 "rc", rc,
71 "reason", reason,
72 "setproc", setproc,
73 "sh", rc,
74 "start", start,
75 "startstop", startstop,
76 "status", status,
77 "stop", stop,
78 "strace", strace,
79 "waitstop", waitstop,
80 "map", map,
81 "interpret", interpret,
82 "include", include,
83 "regexp", regexp,
84 "debug", setdebug,
85 "_bpcondset", _bpcondset,
86 "_bpconddel", _bpconddel,
87 0
88 };
89
90 void
mkprint(Lsym * s)91 mkprint(Lsym *s)
92 {
93 prnt = gmalloc(sizeof(Node));
94 prnt->op = OCALL;
95 prnt->left = gmalloc(sizeof(Node));
96 prnt->left->sym = s;
97 }
98
99 void
installbuiltin(void)100 installbuiltin(void)
101 {
102 Btab *b;
103 Lsym *s;
104
105 b = tab;
106 while(b->name) {
107 s = look(b->name);
108 if(s == 0)
109 s = enter(b->name, Tid);
110
111 s->builtin = b->fn;
112 if(b->fn == bprint)
113 mkprint(s);
114 b++;
115 }
116 }
117
118 void
match(Node * r,Node * args)119 match(Node *r, Node *args)
120 {
121 int i;
122 List *f;
123 Node *av[Maxarg];
124 Node resi, resl;
125
126 na = 0;
127 flatten(av, args);
128 if(na != 2)
129 error("match(obj, list): arg count");
130
131 expr(av[1], &resl);
132 if(resl.type != TLIST)
133 error("match(obj, list): need list");
134 expr(av[0], &resi);
135
136 r->op = OCONST;
137 r->type = TINT;
138 r->nstore.fmt = 'D';
139 r->nstore.u0.sival = -1;
140
141 i = 0;
142 for(f = resl.nstore.u0.sl; f; f = f->next) {
143 if(resi.type == f->type) {
144 switch(resi.type) {
145 case TINT:
146 if(resi.nstore.u0.sival == f->lstore.u0.sival) {
147 r->nstore.u0.sival = i;
148 return;
149 }
150 break;
151 case TFLOAT:
152 if(resi.nstore.u0.sfval == f->lstore.u0.sfval) {
153 r->nstore.u0.sival = i;
154 return;
155 }
156 break;
157 case TSTRING:
158 if(scmp(resi.nstore.u0.sstring, f->lstore.u0.sstring)) {
159 r->nstore.u0.sival = i;
160 return;
161 }
162 break;
163 case TLIST:
164 error("match(obj, list): not defined for list");
165 }
166 }
167 i++;
168 }
169 }
170
171 void
newproc(Node * r,Node * args)172 newproc(Node *r, Node *args)
173 {
174 int i;
175 Node res;
176 char *p, *e;
177 char *argv[Maxarg], buf[Strsize];
178
179 i = 1;
180 argv[0] = aout;
181
182 if(args) {
183 expr(args, &res);
184 if(res.type != TSTRING)
185 error("newproc(): arg not string");
186 if(res.nstore.u0.sstring->len >= sizeof(buf))
187 error("newproc(): too many arguments");
188 memmove(buf, res.nstore.u0.sstring->string, res.nstore.u0.sstring->len);
189 buf[res.nstore.u0.sstring->len] = '\0';
190 p = buf;
191 e = buf+res.nstore.u0.sstring->len;
192 for(;;) {
193 while(p < e && (*p == '\t' || *p == ' '))
194 *p++ = '\0';
195 if(p >= e)
196 break;
197 argv[i++] = p;
198 if(i >= Maxarg)
199 error("newproc: too many arguments");
200 while(p < e && *p != '\t' && *p != ' ')
201 p++;
202 }
203 }
204 argv[i] = 0;
205 r->op = OCONST;
206 r->type = TINT;
207 r->nstore.fmt = 'D';
208 r->nstore.u0.sival = nproc(argv);
209 }
210 void
startstop(Node * r,Node * args)211 startstop(Node *r, Node *args)
212 {
213 Node res;
214
215 if(args == 0)
216 error("startstop(pid): no pid");
217 expr(args, &res);
218 if(res.type != TINT)
219 error("startstop(pid): arg type");
220 if(rdebug) {
221 Lsym *s;
222 r->op = OCONST;
223 r->type = TINT;
224 r->nstore.u0.sival = remcondstartstop(res.nstore.u0.sival);
225 r->nstore.fmt = 'D';
226
227 s = look("_breakid");
228 if(s)
229 s->v->vstore.u0.sival = (int)r->nstore.u0.sival;
230 } else
231 msg(res.nstore.u0.sival, "startstop");
232 notes(res.nstore.u0.sival);
233 dostop(res.nstore.u0.sival);
234 }
235
236 void
waitstop(Node * r,Node * args)237 waitstop(Node *r, Node *args)
238 {
239 Node res;
240
241 USED(r);
242 if(args == 0)
243 error("waitstop(pid): no pid");
244 expr(args, &res);
245 if(res.type != TINT)
246 error("waitstop(pid): arg type");
247
248 Bflush(bout);
249 msg(res.nstore.u0.sival, "waitstop");
250 notes(res.nstore.u0.sival);
251 dostop(res.nstore.u0.sival);
252 }
253
254 void
start(Node * r,Node * args)255 start(Node *r, Node *args)
256 {
257 Node res;
258
259 USED(r);
260 if(args == 0)
261 error("start(pid): no pid");
262 expr(args, &res);
263 if(res.type != TINT)
264 error("start(pid): arg type");
265
266 msg(res.nstore.u0.sival, "start");
267 }
268
269 void
stop(Node * r,Node * args)270 stop(Node *r, Node *args)
271 {
272 Node res;
273
274 USED(r);
275 if(args == 0)
276 error("stop(pid): no pid");
277 expr(args, &res);
278 if(res.type != TINT)
279 error("stop(pid): arg type");
280
281 Bflush(bout);
282 msg(res.nstore.u0.sival, "stop");
283 notes(res.nstore.u0.sival);
284 dostop(res.nstore.u0.sival);
285 }
286
287 void
dokill(Node * r,Node * args)288 dokill(Node *r, Node *args)
289 {
290 Node res;
291
292 USED(r);
293 if(args == 0)
294 error("kill(pid): no pid");
295 expr(args, &res);
296 if(res.type != TINT)
297 error("kill(pid): arg type");
298
299 msg(res.nstore.u0.sival, "kill");
300 deinstall(res.nstore.u0.sival);
301 }
302
303 void
status(Node * r,Node * args)304 status(Node *r, Node *args)
305 {
306 Node res;
307 char *p;
308
309 USED(r);
310 if(args == 0)
311 error("status(pid): no pid");
312 expr(args, &res);
313 if(res.type != TINT)
314 error("status(pid): arg type");
315
316 p = getstatus(res.nstore.u0.sival);
317 r->nstore.u0.sstring = strnode(p);
318 r->op = OCONST;
319 r->nstore.fmt = 's';
320 r->type = TSTRING;
321 }
322
323 void
reason(Node * r,Node * args)324 reason(Node *r, Node *args)
325 {
326 Node res;
327
328 if(args == 0)
329 error("reason(cause): no cause");
330 expr(args, &res);
331 if(res.type != TINT)
332 error("reason(cause): arg type");
333
334 r->op = OCONST;
335 r->type = TSTRING;
336 r->nstore.fmt = 's';
337 r->nstore.u0.sstring = strnode((*machdata->excep)(cormap, rget));
338 }
339
340 void
follow(Node * r,Node * args)341 follow(Node *r, Node *args)
342 {
343 int n, i;
344 Node res;
345 uvlong f[10];
346 List **tail, *l;
347
348 if(args == 0)
349 error("follow(addr): no addr");
350 expr(args, &res);
351 if(res.type != TINT)
352 error("follow(addr): arg type");
353
354 n = (*machdata->foll)(cormap, res.nstore.u0.sival, rget, f);
355 if (n < 0)
356 error("follow(addr): %r");
357 tail = &r->nstore.u0.sl;
358 for(i = 0; i < n; i++) {
359 l = al(TINT);
360 l->lstore.u0.sival = f[i];
361 l->lstore.fmt = 'X';
362 *tail = l;
363 tail = &l->next;
364 }
365 }
366
367 void
funcbound(Node * r,Node * args)368 funcbound(Node *r, Node *args)
369 {
370 int n;
371 Node res;
372 uvlong bounds[2];
373 List *l;
374
375 if(args == 0)
376 error("fnbound(addr): no addr");
377 expr(args, &res);
378 if(res.type != TINT)
379 error("fnbound(addr): arg type");
380
381 n = fnbound(res.nstore.u0.sival, bounds);
382 if (n != 0) {
383 r->nstore.u0.sl = al(TINT);
384 l = r->nstore.u0.sl;
385 l->lstore.u0.sival = bounds[0];
386 l->lstore.fmt = 'X';
387 l->next = al(TINT);
388 l = l->next;
389 l->lstore.u0.sival = bounds[1];
390 l->lstore.fmt = 'X';
391 }
392 }
393
394 void
setproc(Node * r,Node * args)395 setproc(Node *r, Node *args)
396 {
397 Node res;
398
399 USED(r);
400 if(args == 0)
401 error("setproc(pid): no pid");
402 expr(args, &res);
403 if(res.type != TINT)
404 error("setproc(pid): arg type");
405
406 sproc(res.nstore.u0.sival);
407 }
408
409 void
filepc(Node * r,Node * args)410 filepc(Node *r, Node *args)
411 {
412 Node res;
413 char *p, c;
414
415 if(args == 0)
416 error("filepc(filename:line): arg count");
417 expr(args, &res);
418 if(res.type != TSTRING)
419 error("filepc(filename:line): arg type");
420
421 p = strchr(res.nstore.u0.sstring->string, ':');
422 if(p == 0)
423 error("filepc(filename:line): bad arg format");
424
425 c = *p;
426 *p++ = '\0';
427 r->nstore.u0.sival = file2pc(res.nstore.u0.sstring->string, atoi(p));
428 p[-1] = c;
429 if(r->nstore.u0.sival == -1)
430 error("filepc(filename:line): can't find address");
431
432 r->op = OCONST;
433 r->type = TINT;
434 r->nstore.fmt = 'D';
435 }
436
437 void
interpret(Node * r,Node * args)438 interpret(Node *r, Node *args)
439 {
440 Node res;
441 int isave;
442
443 if(args == 0)
444 error("interpret(string): arg count");
445 expr(args, &res);
446 if(res.type != TSTRING)
447 error("interpret(string): arg type");
448
449 pushstr(&res);
450
451 isave = interactive;
452 interactive = 0;
453 r->nstore.u0.sival = yyparse();
454 interactive = isave;
455 popio();
456 r->op = OCONST;
457 r->type = TINT;
458 r->nstore.fmt = 'D';
459 }
460
461 void
include(Node * r,Node * args)462 include(Node *r, Node *args)
463 {
464 Node res;
465 int isave;
466
467 if(args == 0)
468 error("include(string): arg count");
469 expr(args, &res);
470 if(res.type != TSTRING)
471 error("include(string): arg type");
472
473 pushfile(res.nstore.u0.sstring->string);
474
475 isave = interactive;
476 interactive = 0;
477 r->nstore.u0.sival = yyparse();
478 interactive = isave;
479 popio();
480 r->op = OCONST;
481 r->type = TINT;
482 r->nstore.fmt = 'D';
483 }
484
485 void
rc(Node * r,Node * args)486 rc(Node *r, Node *args)
487 {
488 Node res;
489
490 char *p, *q;
491
492 USED(r);
493 if(args == 0)
494 error("error(string): arg count");
495 expr(args, &res);
496 if(res.type != TSTRING)
497 error("error(string): arg type");
498
499 p = runcmd(res.nstore.u0.sstring->string);
500 q = strrchr(p, ':');
501 if (q)
502 p = q+1;
503
504 r->op = OCONST;
505 r->type = TSTRING;
506 r->nstore.u0.sstring = strnode(p);
507 r->nstore.fmt = 's';
508 }
509
510 void
doerror(Node * r,Node * args)511 doerror(Node *r, Node *args)
512 {
513 Node res;
514
515 USED(r);
516 if(args == 0)
517 error("error(string): arg count");
518 expr(args, &res);
519 if(res.type != TSTRING)
520 error("error(string): arg type");
521
522 error(res.nstore.u0.sstring->string);
523 }
524
525 void
doaccess(Node * r,Node * args)526 doaccess(Node *r, Node *args)
527 {
528 Node res;
529
530 if(args == 0)
531 error("access(filename): arg count");
532 expr(args, &res);
533 if(res.type != TSTRING)
534 error("access(filename): arg type");
535
536 r->op = OCONST;
537 r->type = TINT;
538 r->nstore.u0.sival = 0;
539 if(access(res.nstore.u0.sstring->string, OREAD) == 0)
540 r->nstore.u0.sival = 1;
541 }
542
543 void
readfile(Node * r,Node * args)544 readfile(Node *r, Node *args)
545 {
546 Node res;
547 int n, fd;
548 char *buf;
549 Dir *db;
550
551 if(args == 0)
552 error("readfile(filename): arg count");
553 expr(args, &res);
554 if(res.type != TSTRING)
555 error("readfile(filename): arg type");
556
557 fd = open(res.nstore.u0.sstring->string, OREAD);
558 if(fd < 0)
559 return;
560
561 db = dirfstat(fd);
562 if(db == nil || db->length == 0)
563 n = 8192;
564 else
565 n = db->length;
566 free(db);
567
568 buf = gmalloc(n);
569 n = read(fd, buf, n);
570
571 if(n > 0) {
572 r->op = OCONST;
573 r->type = TSTRING;
574 r->nstore.u0.sstring = strnodlen(buf, n);
575 r->nstore.fmt = 's';
576 }
577 free(buf);
578 close(fd);
579 }
580
581 void
getfile(Node * r,Node * args)582 getfile(Node *r, Node *args)
583 {
584 int n;
585 char *p;
586 Node res;
587 String *s;
588 Biobuf *bp;
589 List **l, *new;
590
591 if(args == 0)
592 error("file(filename): arg count");
593 expr(args, &res);
594 if(res.type != TSTRING)
595 error("file(filename): arg type");
596
597 r->op = OCONST;
598 r->type = TLIST;
599 r->nstore.u0.sl = 0;
600
601 p = res.nstore.u0.sstring->string;
602 bp = Bopen(p, OREAD);
603 if(bp == 0)
604 return;
605
606 l = &r->nstore.u0.sl;
607 for(;;) {
608 p = Brdline(bp, '\n');
609 n = BLINELEN(bp);
610 if(p == 0) {
611 if(n == 0)
612 break;
613 s = strnodlen(0, n);
614 Bread(bp, s->string, n);
615 }
616 else
617 s = strnodlen(p, n-1);
618
619 new = al(TSTRING);
620 new->lstore.u0.sstring = s;
621 new->lstore.fmt = 's';
622 *l = new;
623 l = &new->next;
624 }
625 Bterm(bp);
626 }
627
628 void
cvtatof(Node * r,Node * args)629 cvtatof(Node *r, Node *args)
630 {
631 Node res;
632
633 if(args == 0)
634 error("atof(string): arg count");
635 expr(args, &res);
636 if(res.type != TSTRING)
637 error("atof(string): arg type");
638
639 r->op = OCONST;
640 r->type = TFLOAT;
641 r->nstore.u0.sfval = atof(res.nstore.u0.sstring->string);
642 r->nstore.fmt = 'f';
643 }
644
645 void
cvtatoi(Node * r,Node * args)646 cvtatoi(Node *r, Node *args)
647 {
648 Node res;
649
650 if(args == 0)
651 error("atoi(string): arg count");
652 expr(args, &res);
653 if(res.type != TSTRING)
654 error("atoi(string): arg type");
655
656 r->op = OCONST;
657 r->type = TINT;
658 r->nstore.u0.sival = strtoul(res.nstore.u0.sstring->string, 0, 0);
659 r->nstore.fmt = 'D';
660 }
661
662 void
cvtitoa(Node * r,Node * args)663 cvtitoa(Node *r, Node *args)
664 {
665 Node res;
666 char buf[128];
667
668 if(args == 0)
669 error("itoa(integer): arg count");
670 expr(args, &res);
671 if(res.type != TINT)
672 error("itoa(integer): arg type");
673
674 sprint(buf, "%d", (int)res.nstore.u0.sival);
675 r->op = OCONST;
676 r->type = TSTRING;
677 r->nstore.u0.sstring = strnode(buf);
678 r->nstore.fmt = 's';
679 }
680
681 List*
mapent(Map * m)682 mapent(Map *m)
683 {
684 int i;
685 List *l, *n, **t, *h;
686
687 h = 0;
688 t = &h;
689 for(i = 0; i < m->nsegs; i++) {
690 if(m->seg[i].inuse == 0)
691 continue;
692 l = al(TSTRING);
693 n = al(TLIST);
694 n->lstore.u0.sl = l;
695 *t = n;
696 t = &n->next;
697 l->lstore.u0.sstring = strnode(m->seg[i].name);
698 l->lstore.fmt = 's';
699 l->next = al(TINT);
700 l = l->next;
701 l->lstore.u0.sival = m->seg[i].b;
702 l->lstore.fmt = 'X';
703 l->next = al(TINT);
704 l = l->next;
705 l->lstore.u0.sival = m->seg[i].e;
706 l->lstore.fmt = 'X';
707 l->next = al(TINT);
708 l = l->next;
709 l->lstore.u0.sival = m->seg[i].f;
710 l->lstore.fmt = 'X';
711 }
712 return h;
713 }
714
715 void
map(Node * r,Node * args)716 map(Node *r, Node *args)
717 {
718 int i;
719 Map *m;
720 List *l;
721 char *ent;
722 Node *av[Maxarg], res;
723
724 na = 0;
725 flatten(av, args);
726
727 if(na != 0) {
728 expr(av[0], &res);
729 if(res.type != TLIST)
730 error("map(list): map needs a list");
731 if(listlen(res.nstore.u0.sl) != 4)
732 error("map(list): list must have 4 entries");
733
734 l = res.nstore.u0.sl;
735 if(l->type != TSTRING)
736 error("map name must be a string");
737 ent = l->lstore.u0.sstring->string;
738 m = symmap;
739 i = findseg(m, ent);
740 if(i < 0) {
741 m = cormap;
742 i = findseg(m, ent);
743 }
744 if(i < 0)
745 error("%s is not a map entry", ent);
746 l = l->next;
747 if(l->type != TINT)
748 error("map entry not int");
749 m->seg[i].b = l->lstore.u0.sival;
750 if (strcmp(ent, "text") == 0)
751 textseg(l->lstore.u0.sival, &fhdr);
752 l = l->next;
753 if(l->type != TINT)
754 error("map entry not int");
755 m->seg[i].e = l->lstore.u0.sival;
756 l = l->next;
757 if(l->type != TINT)
758 error("map entry not int");
759 m->seg[i].f = l->lstore.u0.sival;
760 }
761
762 r->type = TLIST;
763 r->nstore.u0.sl = 0;
764 if(symmap)
765 r->nstore.u0.sl = mapent(symmap);
766 if(cormap) {
767 if(r->nstore.u0.sl == 0)
768 r->nstore.u0.sl = mapent(cormap);
769 else {
770 for(l = r->nstore.u0.sl; l->next; l = l->next)
771 ;
772 l->next = mapent(cormap);
773 }
774 }
775 }
776
777 void
flatten(Node ** av,Node * n)778 flatten(Node **av, Node *n)
779 {
780 if(n == 0)
781 return;
782
783 switch(n->op) {
784 case OLIST:
785 flatten(av, n->left);
786 flatten(av, n->right);
787 break;
788 default:
789 av[na++] = n;
790 if(na >= Maxarg)
791 error("too many function arguments");
792 break;
793 }
794 }
795
796 void
strace(Node * r,Node * args)797 strace(Node *r, Node *args)
798 {
799 Node *av[Maxarg], *n, res;
800 ulong pc, sp;
801
802 na = 0;
803 flatten(av, args);
804 if(na != 3)
805 error("strace(pc, sp, link): arg count");
806
807 n = av[0];
808 expr(n, &res);
809 if(res.type != TINT)
810 error("strace(pc, sp, link): pc bad type");
811 pc = res.nstore.u0.sival;
812
813 n = av[1];
814 expr(n, &res);
815 if(res.type != TINT)
816 error("strace(pc, sp, link): sp bad type");
817 sp = res.nstore.u0.sival;
818
819 n = av[2];
820 expr(n, &res);
821 if(res.type != TINT)
822 error("strace(pc, sp, link): link bad type");
823
824 tracelist = 0;
825 if ((*machdata->ctrace)(cormap, pc, sp, res.nstore.u0.sival, trlist) <= 0)
826 error("no stack frame");
827 r->type = TLIST;
828 r->nstore.u0.sl = tracelist;
829 }
830
831 void
regerror(char * msg)832 regerror(char *msg)
833 {
834 error(msg);
835 }
836
837 void
regexp(Node * r,Node * args)838 regexp(Node *r, Node *args)
839 {
840 Node res;
841 Reprog *rp;
842 Node *av[Maxarg];
843
844 na = 0;
845 flatten(av, args);
846 if(na != 2)
847 error("regexp(pattern, string): arg count");
848 expr(av[0], &res);
849 if(res.type != TSTRING)
850 error("regexp(pattern, string): pattern must be string");
851 rp = regcomp(res.nstore.u0.sstring->string);
852 if(rp == 0)
853 return;
854
855 expr(av[1], &res);
856 if(res.type != TSTRING)
857 error("regexp(pattern, string): bad string");
858
859 r->nstore.fmt = 'D';
860 r->type = TINT;
861 r->nstore.u0.sival = regexec(rp, res.nstore.u0.sstring->string, 0, 0);
862 free(rp);
863 }
864
865 char vfmt[] = "aBbcCdDfFgGiIoOqQrRsuUVxXYZ";
866
867 void
fmt(Node * r,Node * args)868 fmt(Node *r, Node *args)
869 {
870 Node res;
871 Node *av[Maxarg];
872
873 na = 0;
874 flatten(av, args);
875 if(na != 2)
876 error("fmt(obj, fmt): arg count");
877 expr(av[1], &res);
878 if(res.type != TINT || strchr(vfmt, res.nstore.u0.sival) == 0)
879 error("fmt(obj, fmt): bad format '%c'", (char)res.nstore.u0.sival);
880 expr(av[0], r);
881 r->nstore.fmt = res.nstore.u0.sival;
882 }
883
884 void
patom(char type,Store * res)885 patom(char type, Store *res)
886 {
887 int i;
888 char buf[512];
889 extern char *typenames[];
890
891 switch(res->fmt) {
892 case 'c':
893 Bprint(bout, "%c", (int)res->u0.sival);
894 break;
895 case 'C':
896 if(res->u0.sival < ' ' || res->u0.sival >= 0x7f)
897 Bprint(bout, "%3d", (int)res->u0.sival&0xff);
898 else
899 Bprint(bout, "%3c", (int)res->u0.sival);
900 break;
901 case 'r':
902 Bprint(bout, "%C", (int)res->u0.sival);
903 break;
904 case 'B':
905 memset(buf, '0', 34);
906 buf[1] = 'b';
907 for(i = 0; i < 32; i++) {
908 if(res->u0.sival & (1<<i))
909 buf[33-i] = '1';
910 }
911 buf[35] = '\0';
912 Bprint(bout, "%s", buf);
913 break;
914 case 'b':
915 Bprint(bout, "%3d", (int)res->u0.sival&0xff);
916 break;
917 case 'X':
918 Bprint(bout, "%.8ux", (int)res->u0.sival);
919 break;
920 case 'x':
921 Bprint(bout, "%.4ux", (int)res->u0.sival&0xffff);
922 break;
923 case 'Y':
924 Bprint(bout, "%.16llux", res->u0.sival);
925 break;
926 case 'D':
927 Bprint(bout, "%d", (int)res->u0.sival);
928 break;
929 case 'd':
930 Bprint(bout, "%d", (ushort)res->u0.sival);
931 break;
932 case 'u':
933 Bprint(bout, "%ud", (int)res->u0.sival&0xffff);
934 break;
935 case 'U':
936 Bprint(bout, "%lud", (ulong)res->u0.sival);
937 break;
938 case 'Z':
939 Bprint(bout, "%llud", res->u0.sival);
940 break;
941 case 'V':
942 Bprint(bout, "%lld", res->u0.sival);
943 break;
944 case 'o':
945 Bprint(bout, "0%.11uo", (int)res->u0.sival&0xffff);
946 break;
947 case 'O':
948 Bprint(bout, "0%.6uo", (int)res->u0.sival);
949 break;
950 case 'q':
951 Bprint(bout, "0%.11o", (short)(res->u0.sival&0xffff));
952 break;
953 case 'Q':
954 Bprint(bout, "0%.6o", (int)res->u0.sival);
955 break;
956 case 'f':
957 case 'F':
958 if(type != TFLOAT)
959 Bprint(bout, "*%c<%s>*", res->fmt, typenames[type]);
960 else
961 Bprint(bout, "%g", res->u0.sfval);
962 break;
963 case 's':
964 case 'g':
965 case 'G':
966 if(type != TSTRING)
967 Bprint(bout, "*%c<%s>*", res->fmt, typenames[type]);
968 else
969 Bwrite(bout, res->u0.sstring->string, res->u0.sstring->len);
970 break;
971 case 'R':
972 if(type != TSTRING)
973 Bprint(bout, "*%c<%s>*", res->fmt, typenames[type]);
974 else
975 Bprint(bout, "%S", (Rune*)res->u0.sstring->string);
976 break;
977 case 'a':
978 case 'A':
979 symoff(buf, sizeof(buf), res->u0.sival, CANY);
980 Bprint(bout, "%s", buf);
981 break;
982 case 'I':
983 case 'i':
984 if(type != TINT)
985 Bprint(bout, "*%c<%s>*", res->fmt, typenames[type]);
986 else {
987 if ((*machdata->das)(symmap, res->u0.sival, res->fmt, buf, sizeof(buf)) < 0)
988 Bprint(bout, "no instruction: %r");
989 else
990 Bprint(bout, "%s", buf);
991 }
992 break;
993 }
994 }
995
996 void
blprint(List * l)997 blprint(List *l)
998 {
999 Bprint(bout, "{");
1000 while(l) {
1001 switch(l->type) {
1002 default:
1003 patom(l->type, &l->lstore);
1004 break;
1005 case TSTRING:
1006 Bputc(bout, '"');
1007 patom(l->type, &l->lstore);
1008 Bputc(bout, '"');
1009 break;
1010 case TLIST:
1011 blprint(l->lstore.u0.sl);
1012 break;
1013 case TCODE:
1014 pcode(l->lstore.u0.scc, 0);
1015 break;
1016 }
1017 l = l->next;
1018 if(l)
1019 Bprint(bout, ", ");
1020 }
1021 Bprint(bout, "}");
1022 }
1023
1024 int
comx(Node res)1025 comx(Node res)
1026 {
1027 Lsym *sl;
1028 Node *n, xx;
1029
1030 if(res.nstore.fmt != 'a' && res.nstore.fmt != 'A')
1031 return 0;
1032
1033 if(res.nstore.comt == 0 || res.nstore.comt->base == 0)
1034 return 0;
1035
1036 sl = res.nstore.comt->base;
1037 if(sl->proc) {
1038 res.left = ZN;
1039 res.right = ZN;
1040 n = an(ONAME, ZN, ZN);
1041 n->sym = sl;
1042 n = an(OCALL, n, &res);
1043 n->left->sym = sl;
1044 expr(n, &xx);
1045 return 1;
1046 }
1047 print("(%s)", sl->name);
1048 return 0;
1049 }
1050
1051 void
bprint(Node * r,Node * args)1052 bprint(Node *r, Node *args)
1053 {
1054 int i, nas;
1055 Node res, *av[Maxarg];
1056
1057 USED(r);
1058 na = 0;
1059 flatten(av, args);
1060 nas = na;
1061 for(i = 0; i < nas; i++) {
1062 expr(av[i], &res);
1063 switch(res.type) {
1064 default:
1065 if(comx(res))
1066 break;
1067 patom(res.type, &res.nstore);
1068 break;
1069 case TCODE:
1070 pcode(res.nstore.u0.scc, 0);
1071 break;
1072 case TLIST:
1073 blprint(res.nstore.u0.sl);
1074 break;
1075 }
1076 }
1077 if(ret == 0)
1078 Bputc(bout, '\n');
1079 }
1080
1081 void
printto(Node * r,Node * args)1082 printto(Node *r, Node *args)
1083 {
1084 int fd;
1085 Biobuf *b;
1086 int i, nas;
1087 Node res, *av[Maxarg];
1088
1089 USED(r);
1090 na = 0;
1091 flatten(av, args);
1092 nas = na;
1093
1094 expr(av[0], &res);
1095 if(res.type != TSTRING)
1096 error("printto(string, ...): need string");
1097
1098 fd = create(res.nstore.u0.sstring->string, OWRITE, 0666);
1099 if(fd < 0)
1100 fd = open(res.nstore.u0.sstring->string, OWRITE);
1101 if(fd < 0)
1102 error("printto: open %s: %r", res.nstore.u0.sstring->string);
1103
1104 b = gmalloc(sizeof(Biobuf));
1105 Binit(b, fd, OWRITE);
1106
1107 Bflush(bout);
1108 io[iop++] = bout;
1109 bout = b;
1110
1111 for(i = 1; i < nas; i++) {
1112 expr(av[i], &res);
1113 switch(res.type) {
1114 default:
1115 if(comx(res))
1116 break;
1117 patom(res.type, &res.nstore);
1118 break;
1119 case TLIST:
1120 blprint(res.nstore.u0.sl);
1121 break;
1122 }
1123 }
1124 if(ret == 0)
1125 Bputc(bout, '\n');
1126
1127 Bterm(b);
1128 close(fd);
1129 free(b);
1130 bout = io[--iop];
1131 }
1132
1133 void
pcfile(Node * r,Node * args)1134 pcfile(Node *r, Node *args)
1135 {
1136 Node res;
1137 char *p, buf[128];
1138
1139 if(args == 0)
1140 error("pcfile(addr): arg count");
1141 expr(args, &res);
1142 if(res.type != TINT)
1143 error("pcfile(addr): arg type");
1144
1145 r->type = TSTRING;
1146 r->nstore.fmt = 's';
1147 if(fileline(buf, sizeof(buf), res.nstore.u0.sival) == 0) {
1148 r->nstore.u0.sstring = strnode("?file?");
1149 return;
1150 }
1151 p = strrchr(buf, ':');
1152 if(p == 0)
1153 error("pcfile(addr): funny file %s", buf);
1154 *p = '\0';
1155 r->nstore.u0.sstring = strnode(buf);
1156 }
1157
1158 void
pcline(Node * r,Node * args)1159 pcline(Node *r, Node *args)
1160 {
1161 Node res;
1162 char *p, buf[128];
1163
1164 if(args == 0)
1165 error("pcline(addr): arg count");
1166 expr(args, &res);
1167 if(res.type != TINT)
1168 error("pcline(addr): arg type");
1169
1170 r->type = TINT;
1171 r->nstore.fmt = 'D';
1172 if(fileline(buf, sizeof(buf), res.nstore.u0.sival) == 0) {
1173 r->nstore.u0.sival = 0;
1174 return;
1175 }
1176
1177 p = strrchr(buf, ':');
1178 if(p == 0)
1179 error("pcline(addr): funny file %s", buf);
1180 r->nstore.u0.sival = atoi(p+1);
1181 }
1182
1183 void
_bpcondset(Node * r,Node * args)1184 _bpcondset(Node *r, Node *args)
1185 {
1186 Node id, p, addr, conds;
1187 Node *av[Maxarg];
1188 List *l;
1189 char *op;
1190 List *val;
1191 ulong pid;
1192
1193 USED(r);
1194
1195 if(!rdebug)
1196 error("_bpcondset(id, pid, addr, conds): only available with remote debugger\n");
1197
1198 if(args == 0)
1199 error("_bpcondset(id, pid, addr, conds): not enough args");
1200 na = 0;
1201 flatten(av, args);
1202 if(na != 4)
1203 error("_bpcondset(id, pid, addr, conds): %s args",
1204 na > 4 ? "too many" : "too few");
1205 expr(av[0], &id);
1206 expr(av[1], &p);
1207 expr(av[2], &addr);
1208 expr(av[3], &conds);
1209 if(id.type != TINT)
1210 error("_bpcondset(id, pid, addr, conds): id: integer expected");
1211 if(p.type != TINT)
1212 error("_bpcondset(pid, addr, conds): pid: integer expected");
1213 if(addr.type != TINT)
1214 error("_bpcondset(pid, addr, conds): addr: integer expected");
1215 if(conds.type != TLIST)
1216 error("_bpcondset(pid, addr, conds): conds: list expected");
1217 l = conds.nstore.u0.sl;
1218 remcondset('n', (ulong)id.nstore.u0.sival);
1219 pid = (ulong)p.nstore.u0.sival;
1220 if (pid != 0)
1221 remcondset('k', pid);
1222 while(l != nil) {
1223 if(l->type != TLIST || listlen(l->lstore.u0.sl) != 2)
1224 error("_bpcondset(addr, list): list elements are {\"op\", val} pairs");
1225 if(l->lstore.u0.sl->type != TSTRING)
1226 error("_bpcondset(addr, list): list elements are {string, val} pairs");
1227 op = l->lstore.u0.sl->lstore.u0.sstring->string;
1228 val = l->lstore.u0.sl->next;
1229 if(val->type != TINT)
1230 error("_bpcondset(addr, list): list elements are {string, int} pairs");
1231 remcondset(op[0], (ulong)val->lstore.u0.sival);
1232 l = l->next;
1233 }
1234 remcondset('b', (ulong)addr.nstore.u0.sival);
1235 }
1236
1237 void
_bpconddel(Node * r,Node * args)1238 _bpconddel(Node *r, Node *args)
1239 {
1240 Node res;
1241
1242 USED(r);
1243 if(!rdebug)
1244 error("_bpconddel(id): only available with remote debugger\n");
1245
1246 expr(args, &res);
1247 if(res.type != TINT)
1248 error("_bpconddel(id): arg type");
1249
1250 remcondset('d', (ulong)res.nstore.u0.sival);
1251 }
1252
1253 void
setdebug(Node * r,Node * args)1254 setdebug(Node *r, Node *args)
1255 {
1256 Node res;
1257
1258 USED(r);
1259 expr(args, &res);
1260 if (res.type != TINT)
1261 error("debug(type): bad type");
1262 setdbg_opt((char)res.nstore.u0.sival, 1);
1263 }
1264
1265
1266 void
setdbg_opt(char c,int prflag)1267 setdbg_opt(char c, int prflag)
1268 {
1269 switch(c) {
1270 case 'p':
1271 if (protodebug) {
1272 protodebug = 0;
1273 if (prflag)
1274 print("Serial protocol debug is OFF\n");
1275 } else {
1276 protodebug = 1;
1277 if (prflag)
1278 print("Serial protocol debug is ON\n");
1279 }
1280 break;
1281 default:
1282 print("Invalid debug flag(%c), supported values: p\n", c);
1283 break;
1284 }
1285 }
1286