Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <ctype.h>
5 #include <mach.h>
6 #include <regexp.h>
7 #define Extern extern
8 #include "acid.h"
9 #include "y.tab.h"
11 void cvtatof(Node*, Node*);
12 void cvtatoi(Node*, Node*);
13 void cvtitoa(Node*, Node*);
14 void bprint(Node*, Node*);
15 void funcbound(Node*, Node*);
16 void printto(Node*, Node*);
17 void getfile(Node*, Node*);
18 void fmt(Node*, Node*);
19 void pcfile(Node*, Node*);
20 void pcline(Node*, Node*);
21 void setproc(Node*, Node*);
22 void strace(Node*, Node*);
23 void follow(Node*, Node*);
24 void reason(Node*, Node*);
25 void newproc(Node*, Node*);
26 void startstop(Node*, Node*);
27 void match(Node*, Node*);
28 void status(Node*, Node*);
29 void xkill(Node*,Node*);
30 void waitstop(Node*, Node*);
31 void sysstop(Node*, Node*);
32 void stop(Node*, Node*);
33 void start(Node*, Node*);
34 void filepc(Node*, Node*);
35 void doerror(Node*, Node*);
36 void rc(Node*, Node*);
37 void doaccess(Node*, Node*);
38 void map(Node*, Node*);
39 void readfile(Node*, Node*);
40 void interpret(Node*, Node*);
41 void include(Node*, Node*);
42 void includepipe(Node*, Node*);
43 void regexp(Node*, Node*);
44 void textfile(Node*, Node*);
45 void deltextfile(Node*, Node*);
46 void stringn(Node*, Node*);
47 void xregister(Node*, Node*);
48 void refconst(Node*, Node*);
49 void dolook(Node*, Node*);
51 typedef struct Btab Btab;
52 struct Btab
53 {
54 char *name;
55 void (*fn)(Node*, Node*);
56 } tab[] =
57 {
58 "access", doaccess,
59 "atof", cvtatof,
60 "atoi", cvtatoi,
61 "deltextfile", deltextfile,
62 "error", doerror,
63 "file", getfile,
64 "filepc", filepc,
65 "fnbound", funcbound,
66 "fmt", fmt,
67 "follow", follow,
68 "include", include,
69 "includepipe", includepipe,
70 "interpret", interpret,
71 "itoa", cvtitoa,
72 "kill", xkill,
73 "map", map,
74 "match", match,
75 "newproc", newproc,
76 "pcfile", pcfile,
77 "pcline", pcline,
78 "print", bprint,
79 "printto", printto,
80 "rc", rc,
81 "readfile", readfile,
82 "reason", reason,
83 "refconst", refconst,
84 "regexp", regexp,
85 "register", xregister,
86 "setproc", setproc,
87 "start", start,
88 "startstop", startstop,
89 "status", status,
90 "stop", stop,
91 "strace", strace,
92 "stringn", stringn,
93 "sysstop", sysstop,
94 "textfile", textfile,
95 "var", dolook,
96 "waitstop", waitstop,
97 0
98 };
100 void
101 mkprint(Lsym *s)
103 prnt = malloc(sizeof(Node));
104 memset(prnt, 0, sizeof(Node));
105 prnt->op = OCALL;
106 prnt->left = malloc(sizeof(Node));
107 memset(prnt->left, 0, sizeof(Node));
108 prnt->left->sym = s;
111 void
112 installbuiltin(void)
114 Btab *b;
115 Lsym *s;
117 b = tab;
118 while(b->name) {
119 s = look(b->name);
120 if(s == 0)
121 s = enter(b->name, Tid);
123 s->builtin = b->fn;
124 if(b->fn == bprint)
125 mkprint(s);
126 b++;
130 void
131 match(Node *r, Node *args)
133 int i;
134 List *f;
135 Node *av[Maxarg];
136 Node resi, resl;
138 na = 0;
139 flatten(av, args);
140 if(na != 2)
141 error("match(obj, list): arg count");
143 expr(av[1], &resl);
144 if(resl.type != TLIST)
145 error("match(obj, list): need list");
146 expr(av[0], &resi);
148 r->op = OCONST;
149 r->type = TINT;
150 r->store.fmt = 'D';
151 r->store.u.ival = -1;
153 i = 0;
154 for(f = resl.store.u.l; f; f = f->next) {
155 if(resi.type == f->type) {
156 switch(resi.type) {
157 case TINT:
158 if(resi.store.u.ival == f->store.u.ival) {
159 r->store.u.ival = i;
160 return;
162 break;
163 case TFLOAT:
164 if(resi.store.u.fval == f->store.u.fval) {
165 r->store.u.ival = i;
166 return;
168 break;
169 case TSTRING:
170 if(scmp(resi.store.u.string, f->store.u.string)) {
171 r->store.u.ival = i;
172 return;
174 break;
175 case TLIST:
176 error("match(obj, list): not defined for list");
179 i++;
183 void
184 newproc(Node *r, Node *args)
186 int i;
187 Node res;
188 char *p, *e;
189 char *argv[Maxarg], buf[Strsize];
191 i = 1;
192 argv[0] = symfil;
194 if(args) {
195 expr(args, &res);
196 if(res.type != TSTRING)
197 error("newproc(): arg not string");
198 if(res.store.u.string->len >= sizeof(buf))
199 error("newproc(): too many arguments");
200 memmove(buf, res.store.u.string->string, res.store.u.string->len);
201 buf[res.store.u.string->len] = '\0';
202 p = buf;
203 e = buf+res.store.u.string->len;
204 for(;;) {
205 while(p < e && (*p == '\t' || *p == ' '))
206 *p++ = '\0';
207 if(p >= e)
208 break;
209 argv[i++] = p;
210 if(i >= Maxarg)
211 error("newproc: too many arguments");
212 while(p < e && *p != '\t' && *p != ' ')
213 p++;
216 argv[i] = 0;
217 r->op = OCONST;
218 r->type = TINT;
219 r->store.fmt = 'D';
220 r->store.u.ival = nproc(argv);
223 void
224 startstop(Node *r, Node *args)
226 Node res;
228 USED(r);
229 if(args == 0)
230 error("startstop(pid): no pid");
231 expr(args, &res);
232 if(res.type != TINT)
233 error("startstop(pid): arg type");
235 msg(res.store.u.ival, "startstop");
236 notes(res.store.u.ival);
237 dostop(res.store.u.ival);
240 void
241 waitstop(Node *r, Node *args)
243 Node res;
245 USED(r);
246 if(args == 0)
247 error("waitstop(pid): no pid");
248 expr(args, &res);
249 if(res.type != TINT)
250 error("waitstop(pid): arg type");
252 Bflush(bout);
253 msg(res.store.u.ival, "waitstop");
254 notes(res.store.u.ival);
255 dostop(res.store.u.ival);
258 void
259 sysstop(Node *r, Node *args)
261 Node res;
263 USED(r);
264 if(args == 0)
265 error("waitstop(pid): no pid");
266 expr(args, &res);
267 if(res.type != TINT)
268 error("waitstop(pid): arg type");
270 Bflush(bout);
271 msg(res.store.u.ival, "sysstop");
272 notes(res.store.u.ival);
273 dostop(res.store.u.ival);
276 void
277 start(Node *r, Node *args)
279 Node res;
281 USED(r);
282 if(args == 0)
283 error("start(pid): no pid");
284 expr(args, &res);
285 if(res.type != TINT)
286 error("start(pid): arg type");
288 msg(res.store.u.ival, "start");
291 void
292 stop(Node *r, Node *args)
294 Node res;
296 USED(r);
297 if(args == 0)
298 error("stop(pid): no pid");
299 expr(args, &res);
300 if(res.type != TINT)
301 error("stop(pid): arg type");
303 Bflush(bout);
304 msg(res.store.u.ival, "stop");
305 notes(res.store.u.ival);
306 dostop(res.store.u.ival);
309 void
310 xkill(Node *r, Node *args)
312 Node res;
314 USED(r);
315 if(args == 0)
316 error("kill(pid): no pid");
317 expr(args, &res);
318 if(res.type != TINT)
319 error("kill(pid): arg type");
321 msg(res.store.u.ival, "kill");
322 deinstall(res.store.u.ival);
325 void
326 xregister(Node *r, Node *args)
328 int tid;
329 Regdesc *rp;
330 Node res, resid;
331 Node *av[Maxarg];
333 na = 0;
334 flatten(av, args);
335 if(na != 1/* && na != 2 */)
336 error("register(name): arg count");
338 expr(av[0], &res);
339 if(res.type != TSTRING)
340 error("register(name): arg type: name should be string");
341 tid = 0;
342 if(na == 2){
343 expr(av[1], &resid);
344 if(resid.type != TINT)
345 error("register(name[, threadid]): arg type: threadid should be int");
346 tid = resid.store.u.ival;
348 if((rp = regdesc(res.store.u.string->string)) == nil)
349 error("no such register");
350 r->op = OCONST;
351 r->type = TREG;
352 r->store.fmt = rp->format;
353 r->store.u.reg.name = rp->name;
354 r->store.u.reg.thread = tid;
357 void
358 refconst(Node *r, Node *args)
360 Node *n;
362 if(args == 0)
363 error("refconst(expr): arg count");
365 n = an(OCONST, ZN, ZN);
366 expr(args, n);
368 r->op = OCONST;
369 r->type = TCON;
370 r->store.u.con = n;
373 void
374 dolook(Node *r, Node *args)
376 Node res;
377 Lsym *l;
379 if(args == 0)
380 error("var(string): arg count");
381 expr(args, &res);
382 if(res.type != TSTRING)
383 error("var(string): arg type");
385 r->op = OCONST;
386 if((l = look(res.store.u.string->string)) == nil || l->v->set == 0){
387 r->type = TLIST;
388 r->store.u.l = nil;
389 }else{
390 r->type = l->v->type;
391 r->store = l->v->store;
395 void
396 status(Node *r, Node *args)
398 Node res;
399 char *p;
401 USED(r);
402 if(args == 0)
403 error("status(pid): no pid");
404 expr(args, &res);
405 if(res.type != TINT)
406 error("status(pid): arg type");
408 p = getstatus(res.store.u.ival);
409 r->store.u.string = strnode(p);
410 r->op = OCONST;
411 r->store.fmt = 's';
412 r->type = TSTRING;
415 void
416 reason(Node *r, Node *args)
418 Node res;
420 if(args == 0)
421 error("reason(cause): no cause");
422 expr(args, &res);
423 if(res.type != TINT)
424 error("reason(cause): arg type");
426 r->op = OCONST;
427 r->type = TSTRING;
428 r->store.fmt = 's';
429 r->store.u.string = strnode((*mach->exc)(cormap, acidregs));
432 void
433 follow(Node *r, Node *args)
435 int n, i;
436 Node res;
437 ulong f[10];
438 List **tail, *l;
440 if(args == 0)
441 error("follow(addr): no addr");
442 expr(args, &res);
443 if(res.type != TINT)
444 error("follow(addr): arg type");
446 n = (*mach->foll)(cormap, acidregs, res.store.u.ival, f);
447 if (n < 0)
448 error("follow(addr): %r");
449 tail = &r->store.u.l;
450 for(i = 0; i < n; i++) {
451 l = al(TINT);
452 l->store.u.ival = f[i];
453 l->store.fmt = 'X';
454 *tail = l;
455 tail = &l->next;
459 void
460 funcbound(Node *r, Node *args)
462 int n;
463 Node res;
464 ulong bounds[2];
465 List *l;
467 if(args == 0)
468 error("fnbound(addr): no addr");
469 expr(args, &res);
470 if(res.type != TINT)
471 error("fnbound(addr): arg type");
473 n = fnbound(res.store.u.ival, bounds);
474 if (n != 0) {
475 r->store.u.l = al(TINT);
476 l = r->store.u.l;
477 l->store.u.ival = bounds[0];
478 l->store.fmt = 'X';
479 l->next = al(TINT);
480 l = l->next;
481 l->store.u.ival = bounds[1];
482 l->store.fmt = 'X';
486 void
487 setproc(Node *r, Node *args)
489 Node res;
491 USED(r);
492 if(args == 0)
493 error("setproc(pid): no pid");
494 expr(args, &res);
495 if(res.type != TINT)
496 error("setproc(pid): arg type");
498 sproc(res.store.u.ival);
501 void
502 filepc(Node *r, Node *args)
504 int i;
505 Node res;
506 char *p, c;
507 ulong v;
509 if(args == 0)
510 error("filepc(filename:line): arg count");
511 expr(args, &res);
512 if(res.type != TSTRING)
513 error("filepc(filename:line): arg type");
515 p = strchr(res.store.u.string->string, ':');
516 if(p == 0)
517 error("filepc(filename:line): bad arg format");
519 c = *p;
520 *p++ = '\0';
521 i = file2pc(res.store.u.string->string, atoi(p), &v);
522 p[-1] = c;
523 if(i < 0)
524 error("filepc(filename:line): can't find address");
526 r->op = OCONST;
527 r->type = TINT;
528 r->store.fmt = 'D';
529 r->store.u.ival = v;
532 void
533 interpret(Node *r, Node *args)
535 Node res;
536 int isave;
538 if(args == 0)
539 error("interpret(string): arg count");
540 expr(args, &res);
541 if(res.type != TSTRING)
542 error("interpret(string): arg type");
544 pushstr(&res);
546 isave = interactive;
547 interactive = 0;
548 r->store.u.ival = yyparse();
549 interactive = isave;
550 popio();
551 r->op = OCONST;
552 r->type = TINT;
553 r->store.fmt = 'D';
556 void
557 include(Node *r, Node *args)
559 char *file, *libfile;
560 static char buf[1024];
561 Node res;
562 int isave;
564 if(args == 0)
565 error("include(string): arg count");
566 expr(args, &res);
567 if(res.type != TSTRING)
568 error("include(string): arg type");
570 Bflush(bout);
572 libfile = nil;
573 file = res.store.u.string->string;
574 if(access(file, AREAD) < 0 && file[0] != '/'){
575 snprint(buf, sizeof buf, "#9/acid/%s", file);
576 libfile = unsharp(buf);
577 if(access(libfile, AREAD) >= 0){
578 strecpy(buf, buf+sizeof buf, libfile);
579 file = buf;
581 free(libfile);
584 pushfile(file);
585 isave = interactive;
586 interactive = 0;
587 r->store.u.ival = yyparse();
588 interactive = isave;
589 popio();
590 r->op = OCONST;
591 r->type = TINT;
592 r->store.fmt = 'D';
595 void
596 includepipe(Node *r, Node *args)
598 Node res;
599 int i, isave, pid, pip[2];
600 char *argv[4];
601 Waitmsg *w;
603 USED(r);
604 if(args == 0)
605 error("includepipe(string): arg count");
606 expr(args, &res);
607 if(res.type != TSTRING)
608 error("includepipe(string): arg type");
610 Bflush(bout);
612 argv[0] = "rc";
613 argv[1] = "-c";
614 argv[2] = res.store.u.string->string;
615 argv[3] = 0;
617 if(pipe(pip) < 0)
618 error("pipe: %r");
620 pid = fork();
621 switch(pid) {
622 case -1:
623 close(pip[0]);
624 close(pip[1]);
625 error("fork: %r");
626 case 0:
627 close(pip[0]);
628 close(0);
629 open("/dev/null", OREAD);
630 dup(pip[1], 1);
631 if(pip[1] > 1)
632 close(pip[1]);
633 for(i=3; i<100; i++)
634 close(i);
635 exec("rc", argv);
636 sysfatal("exec rc: %r");
639 close(pip[1]);
640 pushfd(pip[0]);
642 isave = interactive;
643 interactive = 0;
644 r->store.u.ival = yyparse();
645 interactive = isave;
646 popio();
648 r->op = OCONST;
649 r->type = TINT;
650 r->store.fmt = 'D';
652 w = waitfor(pid);
653 if(w->msg && w->msg[0])
654 error("includepipe(\"%s\"): %s", argv[2], w->msg); /* leaks w */
655 free(w);
658 void
659 rc(Node *r, Node *args)
661 Node res;
662 int pid;
663 char *p, *q, *argv[4];
664 Waitmsg *w;
666 USED(r);
667 if(args == 0)
668 error("rc(string): arg count");
669 expr(args, &res);
670 if(res.type != TSTRING)
671 error("rc(string): arg type");
673 argv[0] = "rc";
674 argv[1] = "-c";
675 argv[2] = res.store.u.string->string;
676 argv[3] = 0;
678 pid = fork();
679 switch(pid) {
680 case -1:
681 error("fork %r");
682 case 0:
683 exec("rc", argv);
684 exits(0);
685 default:
686 w = waitfor(pid);
687 break;
689 p = w->msg;
690 q = strrchr(p, ':');
691 if (q)
692 p = q+1;
694 r->op = OCONST;
695 r->type = TSTRING;
696 r->store.u.string = strnode(p);
697 free(w);
698 r->store.fmt = 's';
701 void
702 doerror(Node *r, Node *args)
704 Node res;
706 USED(r);
707 if(args == 0)
708 error("error(string): arg count");
709 expr(args, &res);
710 if(res.type != TSTRING)
711 error("error(string): arg type");
713 error(res.store.u.string->string);
716 void
717 doaccess(Node *r, Node *args)
719 Node res;
721 if(args == 0)
722 error("access(filename): arg count");
723 expr(args, &res);
724 if(res.type != TSTRING)
725 error("access(filename): arg type");
727 r->op = OCONST;
728 r->type = TINT;
729 r->store.fmt = 'D';
730 r->store.u.ival = 0;
731 if(access(res.store.u.string->string, 4) == 0)
732 r->store.u.ival = 1;
735 void
736 readfile(Node *r, Node *args)
738 Node res;
739 int n, fd;
740 char *buf;
741 Dir *db;
743 if(args == 0)
744 error("readfile(filename): arg count");
745 expr(args, &res);
746 if(res.type != TSTRING)
747 error("readfile(filename): arg type");
749 fd = open(res.store.u.string->string, OREAD);
750 if(fd < 0)
751 return;
753 db = dirfstat(fd);
754 if(db == nil || db->length == 0)
755 n = 8192;
756 else
757 n = db->length;
758 free(db);
760 buf = malloc(n);
761 n = read(fd, buf, n);
763 if(n > 0) {
764 r->op = OCONST;
765 r->type = TSTRING;
766 r->store.u.string = strnodlen(buf, n);
767 r->store.fmt = 's';
769 free(buf);
770 close(fd);
773 void
774 getfile(Node *r, Node *args)
776 int n;
777 char *p;
778 Node res;
779 String *s;
780 Biobuf *bp;
781 List **l, *new;
783 if(args == 0)
784 error("file(filename): arg count");
785 expr(args, &res);
786 if(res.type != TSTRING)
787 error("file(filename): arg type");
789 r->op = OCONST;
790 r->type = TLIST;
791 r->store.u.l = 0;
793 p = res.store.u.string->string;
794 bp = Bopen(p, OREAD);
795 if(bp == 0)
796 return;
798 l = &r->store.u.l;
799 for(;;) {
800 p = Brdline(bp, '\n');
801 n = Blinelen(bp);
802 if(p == 0) {
803 if(n == 0)
804 break;
805 s = strnodlen(0, n);
806 Bread(bp, s->string, n);
808 else
809 s = strnodlen(p, n-1);
811 new = al(TSTRING);
812 new->store.u.string = s;
813 new->store.fmt = 's';
814 *l = new;
815 l = &new->next;
817 Bterm(bp);
820 void
821 cvtatof(Node *r, Node *args)
823 Node res;
825 if(args == 0)
826 error("atof(string): arg count");
827 expr(args, &res);
828 if(res.type != TSTRING)
829 error("atof(string): arg type");
831 r->op = OCONST;
832 r->type = TFLOAT;
833 r->store.u.fval = atof(res.store.u.string->string);
834 r->store.fmt = 'f';
837 void
838 cvtatoi(Node *r, Node *args)
840 Node res;
842 if(args == 0)
843 error("atoi(string): arg count");
844 expr(args, &res);
845 if(res.type != TSTRING)
846 error("atoi(string): arg type");
848 r->op = OCONST;
849 r->type = TINT;
850 r->store.u.ival = strtoul(res.store.u.string->string, 0, 0);
851 r->store.fmt = 'D';
854 void
855 cvtitoa(Node *r, Node *args)
857 Node res;
858 Node *av[Maxarg];
859 int ival;
860 char buf[128], *fmt;
862 if(args == 0)
863 err:
864 error("itoa(number [, printformat]): arg count");
865 na = 0;
866 flatten(av, args);
867 if(na == 0 || na > 2)
868 goto err;
869 expr(av[0], &res);
870 if(res.type != TINT)
871 error("itoa(integer): arg type");
872 ival = (int)res.store.u.ival;
873 fmt = "%d";
874 if(na == 2){
875 expr(av[1], &res);
876 if(res.type != TSTRING)
877 error("itoa(integer, string): arg type");
878 fmt = res.store.u.string->string;
881 sprint(buf, fmt, ival);
882 r->op = OCONST;
883 r->type = TSTRING;
884 r->store.u.string = strnode(buf);
885 r->store.fmt = 's';
888 List*
889 mapent(Map *m)
891 int i;
892 List *l, *n, **t, *h;
894 h = 0;
895 t = &h;
896 for(i = 0; i < m->nseg; i++) {
897 l = al(TSTRING);
898 n = al(TLIST);
899 n->store.u.l = l;
900 *t = n;
901 t = &n->next;
902 l->store.u.string = strnode(m->seg[i].name);
903 l->store.fmt = 's';
904 l->next = al(TSTRING);
905 l = l->next;
906 l->store.u.string = strnode(m->seg[i].file ? m->seg[i].file : "");
907 l->store.fmt = 's';
908 l->next = al(TINT);
909 l = l->next;
910 l->store.u.ival = m->seg[i].base;
911 l->store.fmt = 'X';
912 l->next = al(TINT);
913 l = l->next;
914 l->store.u.ival = m->seg[i].base + m->seg[i].size;
915 l->store.fmt = 'X';
916 l->next = al(TINT);
917 l = l->next;
918 l->store.u.ival = m->seg[i].offset;
919 l->store.fmt = 'X';
921 return h;
924 void
925 map(Node *r, Node *args)
927 int i;
928 Map *m;
929 List *l;
930 char *nam, *fil;
931 Node *av[Maxarg], res;
933 na = 0;
934 flatten(av, args);
936 if(na != 0) {
937 expr(av[0], &res);
938 if(res.type != TLIST)
939 error("map(list): map needs a list");
940 if(listlen(res.store.u.l) != 5)
941 error("map(list): list must have 5 entries");
943 l = res.store.u.l;
944 if(l->type != TSTRING)
945 error("map name must be a string");
946 nam = l->store.u.string->string;
947 l = l->next;
948 if(l->type != TSTRING)
949 error("map file must be a string");
950 fil = l->store.u.string->string;
951 m = symmap;
952 i = findseg(m, nam, fil);
953 if(i < 0) {
954 m = cormap;
955 i = findseg(m, nam, fil);
957 if(i < 0)
958 error("%s %s is not a map entry", nam, fil);
959 l = l->next;
960 if(l->type != TINT)
961 error("map entry not int");
962 m->seg[i].base = l->store.u.ival;
963 /*
964 if (strcmp(ent, "text") == 0)
965 textseg(l->store.u.ival, &fhdr);
966 */
967 l = l->next;
968 if(l->type != TINT)
969 error("map entry not int");
970 m->seg[i].size = l->store.u.ival - m->seg[i].base;
971 l = l->next;
972 if(l->type != TINT)
973 error("map entry not int");
974 m->seg[i].offset = l->store.u.ival;
977 r->type = TLIST;
978 r->store.u.l = 0;
979 if(symmap)
980 r->store.u.l = mapent(symmap);
981 if(cormap) {
982 if(r->store.u.l == 0)
983 r->store.u.l = mapent(cormap);
984 else {
985 for(l = r->store.u.l; l->next; l = l->next)
987 l->next = mapent(cormap);
992 void
993 flatten(Node **av, Node *n)
995 if(n == 0)
996 return;
998 switch(n->op) {
999 case OLIST:
1000 flatten(av, n->left);
1001 flatten(av, n->right);
1002 break;
1003 default:
1004 av[na++] = n;
1005 if(na >= Maxarg)
1006 error("too many function arguments");
1007 break;
1011 static struct
1013 char *name;
1014 ulong val;
1015 } sregs[Maxarg/2];
1016 static int nsregs;
1018 static int
1019 straceregrw(Regs *regs, char *name, ulong *val, int isr)
1021 int i;
1023 if(!isr){
1024 werrstr("saved registers cannot be written");
1025 return -1;
1027 for(i=0; i<nsregs; i++)
1028 if(strcmp(sregs[i].name, name) == 0){
1029 *val = sregs[i].val;
1030 return 0;
1032 return rget(acidregs, name, val);
1035 void
1036 strace(Node *r, Node *args)
1038 Node *av[Maxarg], res;
1039 List *l;
1040 Regs regs;
1042 na = 0;
1043 flatten(av, args);
1045 if(na != 1)
1046 error("strace(list): want one arg");
1048 expr(av[0], &res);
1049 if(res.type != TLIST)
1050 error("strace(list): strace needs a list");
1051 l = res.store.u.l;
1052 if(listlen(l)%2)
1053 error("strace(list): strace needs an even-length list");
1054 for(nsregs=0; l; nsregs++){
1055 if(l->type != TSTRING)
1056 error("strace({r,v,r,v,...}): non-string name");
1057 sregs[nsregs].name = l->store.u.string->string;
1058 if(regdesc(sregs[nsregs].name) == nil)
1059 error("strace: bad register '%s'", sregs[nsregs].name);
1060 l = l->next;
1062 if(l == nil)
1063 error("cannot happen in strace");
1064 if(l->type != TINT)
1065 error("strace: non-int value for %s", sregs[nsregs].name);
1066 sregs[nsregs].val = l->store.u.ival;
1067 l = l->next;
1069 regs.rw = straceregrw;
1071 tracelist = 0;
1072 if(stacktrace(cormap, &regs, trlist) <= 0)
1073 error("no stack frame");
1074 r->type = TLIST;
1075 r->store.u.l = tracelist;
1078 void
1079 regerror(char *msg)
1081 error(msg);
1084 void
1085 regexp(Node *r, Node *args)
1087 Node res;
1088 Reprog *rp;
1089 Node *av[Maxarg];
1091 na = 0;
1092 flatten(av, args);
1093 if(na != 2)
1094 error("regexp(pattern, string): arg count");
1095 expr(av[0], &res);
1096 if(res.type != TSTRING)
1097 error("regexp(pattern, string): pattern must be string");
1098 rp = regcomp(res.store.u.string->string);
1099 if(rp == 0)
1100 return;
1102 expr(av[1], &res);
1103 if(res.type != TSTRING)
1104 error("regexp(pattern, string): bad string");
1106 r->store.fmt = 'D';
1107 r->type = TINT;
1108 r->store.u.ival = regexec(rp, res.store.u.string->string, 0, 0);
1109 free(rp);
1112 char vfmt[] = "aBbcCdDfFgGiIoOqQrRsSuUVxXYZ";
1114 void
1115 fmt(Node *r, Node *args)
1117 Node res;
1118 Node *av[Maxarg];
1120 na = 0;
1121 flatten(av, args);
1122 if(na != 2)
1123 error("fmt(obj, fmt): arg count");
1124 expr(av[1], &res);
1125 if(res.type != TINT || strchr(vfmt, res.store.u.ival) == 0)
1126 error("fmt(obj, fmt): bad format '%c'", (char)res.store.u.ival);
1127 expr(av[0], r);
1128 r->store.fmt = res.store.u.ival;
1131 void
1132 patom(char type, Store *res)
1134 int i;
1135 char buf[512];
1136 extern char *typenames[];
1137 Node *n;
1139 switch(type){
1140 case TREG:
1141 if(res->u.reg.thread)
1142 Bprint(bout, "register(\"%s\", %#ux)", res->u.reg.name, res->u.reg.thread);
1143 else
1144 Bprint(bout, "register(\"%s\")", res->u.reg.name);
1145 return;
1146 case TCON:
1147 Bprint(bout, "refconst(");
1148 n = res->u.con;
1149 patom(n->type, &n->store);
1150 Bprint(bout, ")");
1151 return;
1154 switch(res->fmt){
1155 case 'c':
1156 case 'C':
1157 case 'r':
1158 case 'B':
1159 case 'b':
1160 case 'X':
1161 case 'x':
1162 case 'W':
1163 case 'D':
1164 case 'd':
1165 case 'u':
1166 case 'U':
1167 case 'Z':
1168 case 'V':
1169 case 'Y':
1170 case 'o':
1171 case 'O':
1172 case 'q':
1173 case 'Q':
1174 case 'a':
1175 case 'A':
1176 case 'I':
1177 case 'i':
1178 if(type != TINT){
1179 badtype:
1180 Bprint(bout, "*%s\\%c*", typenames[(uchar)type], res->fmt);
1181 return;
1183 break;
1185 case 'f':
1186 case 'F':
1187 if(type != TFLOAT)
1188 goto badtype;
1189 break;
1191 case 's':
1192 case 'g':
1193 case 'G':
1194 case 'R':
1195 if(type != TSTRING)
1196 goto badtype;
1197 break;
1200 switch(res->fmt) {
1201 case 'c':
1202 Bprint(bout, "%c", (int)res->u.ival);
1203 break;
1204 case 'C':
1205 if(res->u.ival < ' ' || res->u.ival >= 0x7f)
1206 Bprint(bout, "%3d", (int)res->u.ival&0xff);
1207 else
1208 Bprint(bout, "%3c", (int)res->u.ival);
1209 break;
1210 case 'r':
1211 Bprint(bout, "%C", (int)res->u.ival);
1212 break;
1213 case 'B':
1214 memset(buf, '0', 34);
1215 buf[1] = 'b';
1216 for(i = 0; i < 32; i++) {
1217 if(res->u.ival & (1<<i))
1218 buf[33-i] = '1';
1220 buf[35] = '\0';
1221 Bprint(bout, "%s", buf);
1222 break;
1223 case 'b':
1224 Bprint(bout, "%#.2x", (int)res->u.ival&0xff);
1225 break;
1226 case 'X':
1227 Bprint(bout, "%#.8lux", (ulong)res->u.ival);
1228 break;
1229 case 'x':
1230 Bprint(bout, "%#.4lux", (ulong)res->u.ival&0xffff);
1231 break;
1232 case 'W':
1233 Bprint(bout, "%#.16llux", res->u.ival);
1234 break;
1235 case 'D':
1236 Bprint(bout, "%d", (int)res->u.ival);
1237 break;
1238 case 'd':
1239 Bprint(bout, "%d", (ushort)res->u.ival);
1240 break;
1241 case 'u':
1242 Bprint(bout, "%d", (int)res->u.ival&0xffff);
1243 break;
1244 case 'U':
1245 Bprint(bout, "%lud", (ulong)res->u.ival);
1246 break;
1247 case 'Z':
1248 Bprint(bout, "%llud", res->u.ival);
1249 break;
1250 case 'V':
1251 Bprint(bout, "%lld", res->u.ival);
1252 break;
1253 case 'Y':
1254 Bprint(bout, "%#.16llux", res->u.ival);
1255 break;
1256 case 'o':
1257 Bprint(bout, "%#.11uo", (int)res->u.ival&0xffff);
1258 break;
1259 case 'O':
1260 Bprint(bout, "%#.6uo", (int)res->u.ival);
1261 break;
1262 case 'q':
1263 Bprint(bout, "%#.11o", (short)(res->u.ival&0xffff));
1264 break;
1265 case 'Q':
1266 Bprint(bout, "%#.6o", (int)res->u.ival);
1267 break;
1268 case 'f':
1269 case 'F':
1270 Bprint(bout, "%g", res->u.fval);
1271 break;
1272 case 's':
1273 case 'g':
1274 case 'G':
1275 Bwrite(bout, res->u.string->string, res->u.string->len);
1276 break;
1277 case 'R':
1278 Bprint(bout, "%S", (Rune*)res->u.string->string);
1279 break;
1280 case 'a':
1281 case 'A':
1282 symoff(buf, sizeof(buf), res->u.ival, CANY);
1283 Bprint(bout, "%s", buf);
1284 break;
1285 case 'I':
1286 case 'i':
1287 if (symmap == nil || (*mach->das)(symmap, res->u.ival, res->fmt, buf, sizeof(buf)) < 0)
1288 Bprint(bout, "no instruction");
1289 else
1290 Bprint(bout, "%s", buf);
1291 break;
1295 void
1296 blprint(List *l)
1298 Store *res;
1300 Bprint(bout, "{");
1301 while(l) {
1302 switch(l->type) {
1303 case TINT:
1304 res = &l->store;
1305 if(res->fmt == 'c'){
1306 Bprint(bout, "\'%c\'", (int)res->u.ival);
1307 break;
1308 }else if(res->fmt == 'r'){
1309 Bprint(bout, "\'%C\'", (int)res->u.ival);
1310 break;
1312 /* fall through */
1313 default:
1314 patom(l->type, &l->store);
1315 break;
1316 case TSTRING:
1317 Bputc(bout, '"');
1318 patom(l->type, &l->store);
1319 Bputc(bout, '"');
1320 break;
1321 case TLIST:
1322 blprint(l->store.u.l);
1323 break;
1324 case TCODE:
1325 pcode(l->store.u.cc, 0);
1326 break;
1328 l = l->next;
1329 if(l)
1330 Bprint(bout, ", ");
1332 Bprint(bout, "}");
1335 int
1336 comx(Node res)
1338 Lsym *sl;
1339 Node *n, xx;
1341 if(res.store.fmt != 'a' && res.store.fmt != 'A')
1342 return 0;
1344 if(res.store.comt == 0 || res.store.comt->base == 0)
1345 return 0;
1347 sl = res.store.comt->base;
1348 if(sl->proc) {
1349 res.left = ZN;
1350 res.right = ZN;
1351 n = an(ONAME, ZN, ZN);
1352 n->sym = sl;
1353 n = an(OCALL, n, &res);
1354 n->left->sym = sl;
1355 expr(n, &xx);
1356 return 1;
1358 print("(%s)", sl->name);
1359 return 0;
1362 void
1363 bprint(Node *r, Node *args)
1365 int i, nas;
1366 Node res, *av[Maxarg];
1368 USED(r);
1369 na = 0;
1370 flatten(av, args);
1371 nas = na;
1372 for(i = 0; i < nas; i++) {
1373 expr(av[i], &res);
1374 switch(res.type) {
1375 default:
1376 if(comx(res))
1377 break;
1378 patom(res.type, &res.store);
1379 break;
1380 case TCODE:
1381 pcode(res.store.u.cc, 0);
1382 break;
1383 case TLIST:
1384 blprint(res.store.u.l);
1385 break;
1388 if(ret == 0)
1389 Bputc(bout, '\n');
1392 void
1393 printto(Node *r, Node *args)
1395 int fd;
1396 Biobuf *b;
1397 int i, nas;
1398 Node res, *av[Maxarg];
1400 USED(r);
1401 na = 0;
1402 flatten(av, args);
1403 nas = na;
1405 expr(av[0], &res);
1406 if(res.type != TSTRING)
1407 error("printto(string, ...): need string");
1409 fd = create(res.store.u.string->string, OWRITE, 0666);
1410 if(fd < 0)
1411 fd = open(res.store.u.string->string, OWRITE);
1412 if(fd < 0)
1413 error("printto: open %s: %r", res.store.u.string->string);
1415 b = gmalloc(sizeof(Biobuf));
1416 Binit(b, fd, OWRITE);
1418 Bflush(bout);
1419 io[iop++] = bout;
1420 bout = b;
1422 for(i = 1; i < nas; i++) {
1423 expr(av[i], &res);
1424 switch(res.type) {
1425 default:
1426 if(comx(res))
1427 break;
1428 patom(res.type, &res.store);
1429 break;
1430 case TLIST:
1431 blprint(res.store.u.l);
1432 break;
1435 if(ret == 0)
1436 Bputc(bout, '\n');
1438 Bterm(b);
1439 close(fd);
1440 free(b);
1441 bout = io[--iop];
1444 void
1445 pcfile(Node *r, Node *args)
1447 Node res;
1448 char *p, buf[128];
1450 if(args == 0)
1451 error("pcfile(addr): arg count");
1452 expr(args, &res);
1453 if(res.type != TINT)
1454 error("pcfile(addr): arg type");
1456 r->type = TSTRING;
1457 r->store.fmt = 's';
1458 if(fileline(res.store.u.ival, buf, sizeof(buf)) < 0) {
1459 r->store.u.string = strnode("?file?");
1460 return;
1462 p = strrchr(buf, ':');
1463 if(p == 0)
1464 error("pcfile(addr): funny file %s", buf);
1465 *p = '\0';
1466 r->store.u.string = strnode(buf);
1469 void
1470 pcline(Node *r, Node *args)
1472 Node res;
1473 char *p, buf[128];
1475 if(args == 0)
1476 error("pcline(addr): arg count");
1477 expr(args, &res);
1478 if(res.type != TINT)
1479 error("pcline(addr): arg type");
1481 r->type = TINT;
1482 r->store.fmt = 'D';
1483 if(fileline(res.store.u.ival, buf, sizeof(buf)) < 0) {
1484 r->store.u.ival = 0;
1485 return;
1488 p = strrchr(buf, ':');
1489 if(p == 0)
1490 error("pcline(addr): funny file %s", buf);
1491 r->store.u.ival = atoi(p+1);
1494 void
1495 textfile(Node *r, Node *args)
1497 char *file;
1498 long base;
1499 Fhdr *fp;
1500 Node res, *av[Maxarg];
1501 List *l, *l2, **tail, *list, *tl;
1503 na = 0;
1504 flatten(av, args);
1506 if(na != 0) {
1507 expr(av[0], &res);
1508 if(res.type != TLIST)
1509 error("textfile(list): textfile needs a list");
1510 if(listlen(res.store.u.l) != 2)
1511 error("textfile(list): list must have 2 entries");
1513 l = res.store.u.l;
1514 if(l->type != TSTRING)
1515 error("textfile name must be a string");
1516 file = l->store.u.string->string;
1518 l = l->next;
1519 if(l->type != TINT)
1520 error("textfile base must be an int");
1521 base = l->store.u.ival;
1523 if((fp = crackhdr(file, OREAD)) == nil)
1524 error("crackhdr %s: %r", file);
1525 Bflush(bout);
1526 fp->base = base;
1527 fprint(2, "%s: %s %s %s\n", file, fp->aname, fp->mname, fp->fname);
1528 if(mapfile(fp, base, symmap, nil) < 0)
1529 fprint(2, "mapping %s: %r\n", file);
1530 if(corhdr){
1531 unmapfile(corhdr, cormap);
1532 mapfile(fp, base, cormap, nil);
1533 free(correg);
1534 correg = nil;
1535 mapfile(corhdr, 0, cormap, &correg);
1537 if(symopen(fp) < 0)
1538 fprint(2, "symopen %s: %r\n", file);
1539 else
1540 addvarsym(fp);
1541 return;
1544 l2 = nil;
1545 tail = &l2;
1546 for(fp=fhdrlist; fp; fp=fp->next){
1547 if(fp->ftype == FCORE)
1548 continue;
1549 tl = al(TLIST);
1550 *tail = tl;
1551 tail = &tl->next;
1553 list = al(TSTRING);
1554 tl->store.u.l = list;
1555 list->store.u.string = strnode(fp->filename);
1556 list->store.fmt = 's';
1557 list->next = al(TINT);
1558 list = list->next;
1559 list->store.fmt = 'X';
1560 list->store.u.ival = fp->base;
1563 r->type = TLIST;
1564 r->store.u.l = l2;
1567 void
1568 deltextfile(Node *r, Node *args)
1570 int did;
1571 char *file;
1572 Fhdr *fp, *fpnext;
1573 Node res, *av[Maxarg];
1575 na = 0;
1576 flatten(av, args);
1578 if(na != 1)
1579 error("deltextfile(string): arg count");
1581 expr(av[0], &res);
1582 if(res.type != TSTRING)
1583 error("deltextfile(string): arg type");
1584 file = res.store.u.string->string;
1586 did = 0;
1587 for(fp=fhdrlist; fp; fp=fpnext){
1588 fpnext = fp->next;
1589 if(fp->ftype == FCORE)
1590 continue;
1591 if(strcmp(file, fp->filename) == 0){
1592 did = 1;
1593 if(fp == symhdr)
1594 error("cannot remove symbols from main text file");
1595 unmapfile(fp, symmap);
1596 uncrackhdr(fp);
1600 delvarsym(file);
1601 if(!did)
1602 error("symbol file %s not open", file);
1605 void
1606 stringn(Node *r, Node *args)
1608 uint addr;
1609 int i, n, ret;
1610 Node res, *av[Maxarg];
1611 char *buf;
1613 na = 0;
1614 flatten(av, args);
1615 if(na != 2)
1616 error("stringn(addr, n): arg count");
1618 expr(av[0], &res);
1619 if(res.type != TINT)
1620 error("stringn(addr, n): arg type");
1621 addr = res.store.u.ival;
1623 expr(av[1], &res);
1624 if(res.type != TINT)
1625 error("stringn(addr,n): arg type");
1626 n = res.store.u.ival;
1628 buf = malloc(n+1);
1629 if(buf == nil)
1630 error("out of memory");
1632 r->type = TSTRING;
1633 for(i=0; i<n; i++){
1634 ret = get1(cormap, addr, (uchar*)&buf[i], 1);
1635 if(ret < 0){
1636 free(buf);
1637 error("indir: %r");
1639 addr++;
1641 buf[n] = 0;
1642 r->store.u.string = strnode(buf);
1643 free(buf);