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*);
47 typedef struct Btab Btab;
48 struct Btab
49 {
50 char *name;
51 void (*fn)(Node*, Node*);
52 } tab[] =
53 {
54 "atof", cvtatof,
55 "atoi", cvtatoi,
56 "deltextfile", deltextfile,
57 "error", doerror,
58 "file", getfile,
59 "readfile", readfile,
60 "access", doaccess,
61 "filepc", filepc,
62 "fnbound", funcbound,
63 "fmt", fmt,
64 "follow", follow,
65 "include", include,
66 "includepipe", includepipe,
67 "interpret", interpret,
68 "itoa", cvtitoa,
69 "kill", xkill,
70 "map", map,
71 "match", match,
72 "newproc", newproc,
73 "pcfile", pcfile,
74 "pcline", pcline,
75 "print", bprint,
76 "printto", printto,
77 "rc", rc,
78 "reason", reason,
79 "regexp", regexp,
80 "setproc", setproc,
81 "start", start,
82 "startstop", startstop,
83 "status", status,
84 "stop", stop,
85 "strace", strace,
86 "sysstop", sysstop,
87 "textfile", textfile,
88 "waitstop", waitstop,
89 0
90 };
92 void
93 mkprint(Lsym *s)
94 {
95 prnt = malloc(sizeof(Node));
96 memset(prnt, 0, sizeof(Node));
97 prnt->op = OCALL;
98 prnt->left = malloc(sizeof(Node));
99 memset(prnt->left, 0, sizeof(Node));
100 prnt->left->sym = s;
103 void
104 installbuiltin(void)
106 Btab *b;
107 Lsym *s;
109 b = tab;
110 while(b->name) {
111 s = look(b->name);
112 if(s == 0)
113 s = enter(b->name, Tid);
115 s->builtin = b->fn;
116 if(b->fn == bprint)
117 mkprint(s);
118 b++;
122 void
123 match(Node *r, Node *args)
125 int i;
126 List *f;
127 Node *av[Maxarg];
128 Node resi, resl;
130 na = 0;
131 flatten(av, args);
132 if(na != 2)
133 error("match(obj, list): arg count");
135 expr(av[1], &resl);
136 if(resl.type != TLIST)
137 error("match(obj, list): need list");
138 expr(av[0], &resi);
140 r->op = OCONST;
141 r->type = TINT;
142 r->store.fmt = 'D';
143 r->store.u.ival = -1;
145 i = 0;
146 for(f = resl.store.u.l; f; f = f->next) {
147 if(resi.type == f->type) {
148 switch(resi.type) {
149 case TINT:
150 if(resi.store.u.ival == f->store.u.ival) {
151 r->store.u.ival = i;
152 return;
154 break;
155 case TFLOAT:
156 if(resi.store.u.fval == f->store.u.fval) {
157 r->store.u.ival = i;
158 return;
160 break;
161 case TSTRING:
162 if(scmp(resi.store.u.string, f->store.u.string)) {
163 r->store.u.ival = i;
164 return;
166 break;
167 case TLIST:
168 error("match(obj, list): not defined for list");
171 i++;
175 void
176 newproc(Node *r, Node *args)
178 int i;
179 Node res;
180 char *p, *e;
181 char *argv[Maxarg], buf[Strsize];
183 i = 1;
184 argv[0] = symfil;
186 if(args) {
187 expr(args, &res);
188 if(res.type != TSTRING)
189 error("newproc(): arg not string");
190 if(res.store.u.string->len >= sizeof(buf))
191 error("newproc(): too many arguments");
192 memmove(buf, res.store.u.string->string, res.store.u.string->len);
193 buf[res.store.u.string->len] = '\0';
194 p = buf;
195 e = buf+res.store.u.string->len;
196 for(;;) {
197 while(p < e && (*p == '\t' || *p == ' '))
198 *p++ = '\0';
199 if(p >= e)
200 break;
201 argv[i++] = p;
202 if(i >= Maxarg)
203 error("newproc: too many arguments");
204 while(p < e && *p != '\t' && *p != ' ')
205 p++;
208 argv[i] = 0;
209 r->op = OCONST;
210 r->type = TINT;
211 r->store.fmt = 'D';
212 r->store.u.ival = nproc(argv);
215 void
216 startstop(Node *r, Node *args)
218 Node res;
220 USED(r);
221 if(args == 0)
222 error("startstop(pid): no pid");
223 expr(args, &res);
224 if(res.type != TINT)
225 error("startstop(pid): arg type");
227 msg(res.store.u.ival, "startstop");
228 notes(res.store.u.ival);
229 dostop(res.store.u.ival);
232 void
233 waitstop(Node *r, Node *args)
235 Node res;
237 USED(r);
238 if(args == 0)
239 error("waitstop(pid): no pid");
240 expr(args, &res);
241 if(res.type != TINT)
242 error("waitstop(pid): arg type");
244 Bflush(bout);
245 msg(res.store.u.ival, "waitstop");
246 notes(res.store.u.ival);
247 dostop(res.store.u.ival);
250 void
251 sysstop(Node *r, Node *args)
253 Node res;
255 USED(r);
256 if(args == 0)
257 error("waitstop(pid): no pid");
258 expr(args, &res);
259 if(res.type != TINT)
260 error("waitstop(pid): arg type");
262 Bflush(bout);
263 msg(res.store.u.ival, "sysstop");
264 notes(res.store.u.ival);
265 dostop(res.store.u.ival);
268 void
269 start(Node *r, Node *args)
271 Node res;
273 USED(r);
274 if(args == 0)
275 error("start(pid): no pid");
276 expr(args, &res);
277 if(res.type != TINT)
278 error("start(pid): arg type");
280 msg(res.store.u.ival, "start");
283 void
284 stop(Node *r, Node *args)
286 Node res;
288 USED(r);
289 if(args == 0)
290 error("stop(pid): no pid");
291 expr(args, &res);
292 if(res.type != TINT)
293 error("stop(pid): arg type");
295 Bflush(bout);
296 msg(res.store.u.ival, "stop");
297 notes(res.store.u.ival);
298 dostop(res.store.u.ival);
301 void
302 xkill(Node *r, Node *args)
304 Node res;
306 USED(r);
307 if(args == 0)
308 error("kill(pid): no pid");
309 expr(args, &res);
310 if(res.type != TINT)
311 error("kill(pid): arg type");
313 msg(res.store.u.ival, "kill");
314 deinstall(res.store.u.ival);
317 void
318 status(Node *r, Node *args)
320 Node res;
321 char *p;
323 USED(r);
324 if(args == 0)
325 error("status(pid): no pid");
326 expr(args, &res);
327 if(res.type != TINT)
328 error("status(pid): arg type");
330 p = getstatus(res.store.u.ival);
331 r->store.u.string = strnode(p);
332 r->op = OCONST;
333 r->store.fmt = 's';
334 r->type = TSTRING;
337 void
338 reason(Node *r, Node *args)
340 Node res;
342 if(args == 0)
343 error("reason(cause): no cause");
344 expr(args, &res);
345 if(res.type != TINT)
346 error("reason(cause): arg type");
348 r->op = OCONST;
349 r->type = TSTRING;
350 r->store.fmt = 's';
351 r->store.u.string = strnode((*mach->exc)(cormap, correg));
354 void
355 follow(Node *r, Node *args)
357 int n, i;
358 Node res;
359 ulong f[10];
360 List **tail, *l;
362 if(args == 0)
363 error("follow(addr): no addr");
364 expr(args, &res);
365 if(res.type != TINT)
366 error("follow(addr): arg type");
368 n = (*mach->foll)(cormap, correg, res.store.u.ival, f);
369 if (n < 0)
370 error("follow(addr): %r");
371 tail = &r->store.u.l;
372 for(i = 0; i < n; i++) {
373 l = al(TINT);
374 l->store.u.ival = f[i];
375 l->store.fmt = 'X';
376 *tail = l;
377 tail = &l->next;
381 void
382 funcbound(Node *r, Node *args)
384 int n;
385 Node res;
386 ulong bounds[2];
387 List *l;
389 if(args == 0)
390 error("fnbound(addr): no addr");
391 expr(args, &res);
392 if(res.type != TINT)
393 error("fnbound(addr): arg type");
395 n = fnbound(res.store.u.ival, bounds);
396 if (n != 0) {
397 r->store.u.l = al(TINT);
398 l = r->store.u.l;
399 l->store.u.ival = bounds[0];
400 l->store.fmt = 'X';
401 l->next = al(TINT);
402 l = l->next;
403 l->store.u.ival = bounds[1];
404 l->store.fmt = 'X';
408 void
409 setproc(Node *r, Node *args)
411 Node res;
413 USED(r);
414 if(args == 0)
415 error("setproc(pid): no pid");
416 expr(args, &res);
417 if(res.type != TINT)
418 error("setproc(pid): arg type");
420 sproc(res.store.u.ival);
423 void
424 filepc(Node *r, Node *args)
426 int i;
427 Node res;
428 char *p, c;
429 ulong v;
431 if(args == 0)
432 error("filepc(filename:line): arg count");
433 expr(args, &res);
434 if(res.type != TSTRING)
435 error("filepc(filename:line): arg type");
437 p = strchr(res.store.u.string->string, ':');
438 if(p == 0)
439 error("filepc(filename:line): bad arg format");
441 c = *p;
442 *p++ = '\0';
443 i = file2pc(res.store.u.string->string, atoi(p), &v);
444 p[-1] = c;
445 if(i < 0)
446 error("filepc(filename:line): can't find address");
448 r->op = OCONST;
449 r->type = TINT;
450 r->store.fmt = 'D';
451 r->store.u.ival = v;
454 void
455 interpret(Node *r, Node *args)
457 Node res;
458 int isave;
460 if(args == 0)
461 error("interpret(string): arg count");
462 expr(args, &res);
463 if(res.type != TSTRING)
464 error("interpret(string): arg type");
466 pushstr(&res);
468 isave = interactive;
469 interactive = 0;
470 r->store.u.ival = yyparse();
471 interactive = isave;
472 popio();
473 r->op = OCONST;
474 r->type = TINT;
475 r->store.fmt = 'D';
478 void
479 include(Node *r, Node *args)
481 char *file, *libfile;
482 static char buf[1024];
483 Node res;
484 int isave;
486 if(args == 0)
487 error("include(string): arg count");
488 expr(args, &res);
489 if(res.type != TSTRING)
490 error("include(string): arg type");
492 Bflush(bout);
494 libfile = nil;
495 file = res.store.u.string->string;
496 if(access(file, AREAD) < 0 && file[0] != '/'){
497 snprint(buf, sizeof buf, "#9/acid/%s", file);
498 libfile = unsharp(buf);
499 if(access(libfile, AREAD) >= 0){
500 strecpy(buf, buf+sizeof buf, libfile);
501 file = buf;
503 free(libfile);
506 pushfile(file);
507 isave = interactive;
508 interactive = 0;
509 r->store.u.ival = yyparse();
510 interactive = isave;
511 popio();
512 r->op = OCONST;
513 r->type = TINT;
514 r->store.fmt = 'D';
517 void
518 includepipe(Node *r, Node *args)
520 Node res;
521 int i, isave, pid, pip[2];
522 char *argv[4];
523 Waitmsg *w;
525 USED(r);
526 if(args == 0)
527 error("includepipe(string): arg count");
528 expr(args, &res);
529 if(res.type != TSTRING)
530 error("includepipe(string): arg type");
532 Bflush(bout);
534 argv[0] = "rc";
535 argv[1] = "-c";
536 argv[2] = res.store.u.string->string;
537 argv[3] = 0;
539 if(pipe(pip) < 0)
540 error("pipe: %r");
542 pid = fork();
543 switch(pid) {
544 case -1:
545 close(pip[0]);
546 close(pip[1]);
547 error("fork: %r");
548 case 0:
549 close(pip[0]);
550 close(0);
551 open("/dev/null", OREAD);
552 dup(pip[1], 1);
553 if(pip[1] > 1)
554 close(pip[1]);
555 for(i=3; i<100; i++)
556 close(i);
557 exec("rc", argv);
558 sysfatal("exec rc: %r");
561 close(pip[1]);
562 pushfd(pip[0]);
564 isave = interactive;
565 interactive = 0;
566 r->store.u.ival = yyparse();
567 interactive = isave;
568 popio();
570 r->op = OCONST;
571 r->type = TINT;
572 r->store.fmt = 'D';
574 w = waitfor(pid);
575 if(w->msg && w->msg[0])
576 error("includepipe(\"%s\"): %s", argv[2], w->msg); /* leaks w */
577 free(w);
580 void
581 rc(Node *r, Node *args)
583 Node res;
584 int pid;
585 char *p, *q, *argv[4];
586 Waitmsg *w;
588 USED(r);
589 if(args == 0)
590 error("rc(string): arg count");
591 expr(args, &res);
592 if(res.type != TSTRING)
593 error("rc(string): arg type");
595 argv[0] = "rc";
596 argv[1] = "-c";
597 argv[2] = res.store.u.string->string;
598 argv[3] = 0;
600 pid = fork();
601 switch(pid) {
602 case -1:
603 error("fork %r");
604 case 0:
605 exec("rc", argv);
606 exits(0);
607 default:
608 w = waitfor(pid);
609 break;
611 p = w->msg;
612 q = strrchr(p, ':');
613 if (q)
614 p = q+1;
616 r->op = OCONST;
617 r->type = TSTRING;
618 r->store.u.string = strnode(p);
619 free(w);
620 r->store.fmt = 's';
623 void
624 doerror(Node *r, Node *args)
626 Node res;
628 USED(r);
629 if(args == 0)
630 error("error(string): arg count");
631 expr(args, &res);
632 if(res.type != TSTRING)
633 error("error(string): arg type");
635 error(res.store.u.string->string);
638 void
639 doaccess(Node *r, Node *args)
641 Node res;
643 if(args == 0)
644 error("access(filename): arg count");
645 expr(args, &res);
646 if(res.type != TSTRING)
647 error("access(filename): arg type");
649 r->op = OCONST;
650 r->type = TINT;
651 r->store.fmt = 'D';
652 r->store.u.ival = 0;
653 if(access(res.store.u.string->string, 4) == 0)
654 r->store.u.ival = 1;
657 void
658 readfile(Node *r, Node *args)
660 Node res;
661 int n, fd;
662 char *buf;
663 Dir *db;
665 if(args == 0)
666 error("readfile(filename): arg count");
667 expr(args, &res);
668 if(res.type != TSTRING)
669 error("readfile(filename): arg type");
671 fd = open(res.store.u.string->string, OREAD);
672 if(fd < 0)
673 return;
675 db = dirfstat(fd);
676 if(db == nil || db->length == 0)
677 n = 8192;
678 else
679 n = db->length;
680 free(db);
682 buf = malloc(n);
683 n = read(fd, buf, n);
685 if(n > 0) {
686 r->op = OCONST;
687 r->type = TSTRING;
688 r->store.u.string = strnodlen(buf, n);
689 r->store.fmt = 's';
691 free(buf);
692 close(fd);
695 void
696 getfile(Node *r, Node *args)
698 int n;
699 char *p;
700 Node res;
701 String *s;
702 Biobuf *bp;
703 List **l, *new;
705 if(args == 0)
706 error("file(filename): arg count");
707 expr(args, &res);
708 if(res.type != TSTRING)
709 error("file(filename): arg type");
711 r->op = OCONST;
712 r->type = TLIST;
713 r->store.u.l = 0;
715 p = res.store.u.string->string;
716 bp = Bopen(p, OREAD);
717 if(bp == 0)
718 return;
720 l = &r->store.u.l;
721 for(;;) {
722 p = Brdline(bp, '\n');
723 n = Blinelen(bp);
724 if(p == 0) {
725 if(n == 0)
726 break;
727 s = strnodlen(0, n);
728 Bread(bp, s->string, n);
730 else
731 s = strnodlen(p, n-1);
733 new = al(TSTRING);
734 new->store.u.string = s;
735 new->store.fmt = 's';
736 *l = new;
737 l = &new->next;
739 Bterm(bp);
742 void
743 cvtatof(Node *r, Node *args)
745 Node res;
747 if(args == 0)
748 error("atof(string): arg count");
749 expr(args, &res);
750 if(res.type != TSTRING)
751 error("atof(string): arg type");
753 r->op = OCONST;
754 r->type = TFLOAT;
755 r->store.u.fval = atof(res.store.u.string->string);
756 r->store.fmt = 'f';
759 void
760 cvtatoi(Node *r, Node *args)
762 Node res;
764 if(args == 0)
765 error("atoi(string): arg count");
766 expr(args, &res);
767 if(res.type != TSTRING)
768 error("atoi(string): arg type");
770 r->op = OCONST;
771 r->type = TINT;
772 r->store.u.ival = strtoul(res.store.u.string->string, 0, 0);
773 r->store.fmt = 'D';
776 void
777 cvtitoa(Node *r, Node *args)
779 Node res;
780 Node *av[Maxarg];
781 int ival;
782 char buf[128], *fmt;
784 if(args == 0)
785 err:
786 error("itoa(number [, printformat]): arg count");
787 na = 0;
788 flatten(av, args);
789 if(na == 0 || na > 2)
790 goto err;
791 expr(av[0], &res);
792 if(res.type != TINT)
793 error("itoa(integer): arg type");
794 ival = (int)res.store.u.ival;
795 fmt = "%d";
796 if(na == 2){
797 expr(av[1], &res);
798 if(res.type != TSTRING)
799 error("itoa(integer, string): arg type");
800 fmt = res.store.u.string->string;
803 sprint(buf, fmt, ival);
804 r->op = OCONST;
805 r->type = TSTRING;
806 r->store.u.string = strnode(buf);
807 r->store.fmt = 's';
810 List*
811 mapent(Map *m)
813 int i;
814 List *l, *n, **t, *h;
816 h = 0;
817 t = &h;
818 for(i = 0; i < m->nseg; i++) {
819 l = al(TSTRING);
820 n = al(TLIST);
821 n->store.u.l = l;
822 *t = n;
823 t = &n->next;
824 l->store.u.string = strnode(m->seg[i].name);
825 l->store.fmt = 's';
826 l->next = al(TSTRING);
827 l = l->next;
828 l->store.u.string = strnode(m->seg[i].file ? m->seg[i].file : "");
829 l->store.fmt = 's';
830 l->next = al(TINT);
831 l = l->next;
832 l->store.u.ival = m->seg[i].base;
833 l->store.fmt = 'X';
834 l->next = al(TINT);
835 l = l->next;
836 l->store.u.ival = m->seg[i].base + m->seg[i].size;
837 l->store.fmt = 'X';
838 l->next = al(TINT);
839 l = l->next;
840 l->store.u.ival = m->seg[i].offset;
841 l->store.fmt = 'X';
843 return h;
846 void
847 map(Node *r, Node *args)
849 int i;
850 Map *m;
851 List *l;
852 char *nam, *fil;
853 Node *av[Maxarg], res;
855 na = 0;
856 flatten(av, args);
858 if(na != 0) {
859 expr(av[0], &res);
860 if(res.type != TLIST)
861 error("map(list): map needs a list");
862 if(listlen(res.store.u.l) != 5)
863 error("map(list): list must have 5 entries");
865 l = res.store.u.l;
866 if(l->type != TSTRING)
867 error("map name must be a string");
868 nam = l->store.u.string->string;
869 l = l->next;
870 if(l->type != TSTRING)
871 error("map file must be a string");
872 fil = l->store.u.string->string;
873 m = symmap;
874 i = findseg(m, nam, fil);
875 if(i < 0) {
876 m = cormap;
877 i = findseg(m, nam, fil);
879 if(i < 0)
880 error("%s %s is not a map entry", nam, fil);
881 l = l->next;
882 if(l->type != TINT)
883 error("map entry not int");
884 m->seg[i].base = l->store.u.ival;
885 /*
886 if (strcmp(ent, "text") == 0)
887 textseg(l->store.u.ival, &fhdr);
888 */
889 l = l->next;
890 if(l->type != TINT)
891 error("map entry not int");
892 m->seg[i].size = l->store.u.ival - m->seg[i].base;
893 l = l->next;
894 if(l->type != TINT)
895 error("map entry not int");
896 m->seg[i].offset = l->store.u.ival;
899 r->type = TLIST;
900 r->store.u.l = 0;
901 if(symmap)
902 r->store.u.l = mapent(symmap);
903 if(cormap) {
904 if(r->store.u.l == 0)
905 r->store.u.l = mapent(cormap);
906 else {
907 for(l = r->store.u.l; l->next; l = l->next)
909 l->next = mapent(cormap);
914 void
915 flatten(Node **av, Node *n)
917 if(n == 0)
918 return;
920 switch(n->op) {
921 case OLIST:
922 flatten(av, n->left);
923 flatten(av, n->right);
924 break;
925 default:
926 av[na++] = n;
927 if(na >= Maxarg)
928 error("too many function arguments");
929 break;
933 static struct
935 char *name;
936 ulong val;
937 } sregs[Maxarg/2];
938 static int nsregs;
940 static int
941 straceregrw(Regs *regs, char *name, ulong *val, int isr)
943 int i;
945 if(!isr){
946 werrstr("saved registers cannot be written");
947 return -1;
949 for(i=0; i<nsregs; i++)
950 if(strcmp(sregs[i].name, name) == 0){
951 *val = sregs[i].val;
952 return 0;
954 return rget(correg, name, val);
957 void
958 strace(Node *r, Node *args)
960 Node *av[Maxarg], res;
961 List *l;
962 Regs regs;
964 na = 0;
965 flatten(av, args);
967 if(na != 1)
968 error("strace(list): want one arg");
970 expr(av[0], &res);
971 if(res.type != TLIST)
972 error("strace(list): strace needs a list");
973 l = res.store.u.l;
974 if(listlen(l)%2)
975 error("strace(list): strace needs an even-length list");
976 for(nsregs=0; l; nsregs++){
977 if(l->type != TSTRING)
978 error("strace({r,v,r,v,...}): non-string name");
979 sregs[nsregs].name = l->store.u.string->string;
980 if(regdesc(sregs[nsregs].name) == nil)
981 error("strace: bad register '%s'", sregs[nsregs].name);
982 l = l->next;
984 if(l == nil)
985 error("cannot happen in strace");
986 if(l->type != TINT)
987 error("strace: non-int value for %s", sregs[nsregs].name);
988 sregs[nsregs].val = l->store.u.ival;
989 l = l->next;
991 regs.rw = straceregrw;
993 tracelist = 0;
994 if(stacktrace(cormap, &regs, trlist) <= 0)
995 error("no stack frame");
996 r->type = TLIST;
997 r->store.u.l = tracelist;
1000 void
1001 regerror(char *msg)
1003 error(msg);
1006 void
1007 regexp(Node *r, Node *args)
1009 Node res;
1010 Reprog *rp;
1011 Node *av[Maxarg];
1013 na = 0;
1014 flatten(av, args);
1015 if(na != 2)
1016 error("regexp(pattern, string): arg count");
1017 expr(av[0], &res);
1018 if(res.type != TSTRING)
1019 error("regexp(pattern, string): pattern must be string");
1020 rp = regcomp(res.store.u.string->string);
1021 if(rp == 0)
1022 return;
1024 expr(av[1], &res);
1025 if(res.type != TSTRING)
1026 error("regexp(pattern, string): bad string");
1028 r->store.fmt = 'D';
1029 r->type = TINT;
1030 r->store.u.ival = regexec(rp, res.store.u.string->string, 0, 0);
1031 free(rp);
1034 char vfmt[] = "aBbcCdDfFgGiIoOqQrRsSuUVxXYZ";
1036 void
1037 fmt(Node *r, Node *args)
1039 Node res;
1040 Node *av[Maxarg];
1042 na = 0;
1043 flatten(av, args);
1044 if(na != 2)
1045 error("fmt(obj, fmt): arg count");
1046 expr(av[1], &res);
1047 if(res.type != TINT || strchr(vfmt, res.store.u.ival) == 0)
1048 error("fmt(obj, fmt): bad format '%c'", (char)res.store.u.ival);
1049 expr(av[0], r);
1050 r->store.fmt = res.store.u.ival;
1053 void
1054 patom(char type, Store *res)
1056 int i;
1057 char buf[512];
1058 extern char *typenames[];
1060 switch(res->fmt) {
1061 case 'c':
1062 Bprint(bout, "%c", (int)res->u.ival);
1063 break;
1064 case 'C':
1065 if(res->u.ival < ' ' || res->u.ival >= 0x7f)
1066 Bprint(bout, "%3d", (int)res->u.ival&0xff);
1067 else
1068 Bprint(bout, "%3c", (int)res->u.ival);
1069 break;
1070 case 'r':
1071 Bprint(bout, "%C", (int)res->u.ival);
1072 break;
1073 case 'B':
1074 memset(buf, '0', 34);
1075 buf[1] = 'b';
1076 for(i = 0; i < 32; i++) {
1077 if(res->u.ival & (1<<i))
1078 buf[33-i] = '1';
1080 buf[35] = '\0';
1081 Bprint(bout, "%s", buf);
1082 break;
1083 case 'b':
1084 Bprint(bout, "%.2x", (int)res->u.ival&0xff);
1085 break;
1086 case 'X':
1087 Bprint(bout, "%.8lux", (ulong)res->u.ival);
1088 break;
1089 case 'x':
1090 Bprint(bout, "%.4lux", (ulong)res->u.ival&0xffff);
1091 break;
1092 case 'W':
1093 Bprint(bout, "%.16llux", res->u.ival);
1094 break;
1095 case 'D':
1096 Bprint(bout, "%d", (int)res->u.ival);
1097 break;
1098 case 'd':
1099 Bprint(bout, "%d", (ushort)res->u.ival);
1100 break;
1101 case 'u':
1102 Bprint(bout, "%d", (int)res->u.ival&0xffff);
1103 break;
1104 case 'U':
1105 Bprint(bout, "%lud", (ulong)res->u.ival);
1106 break;
1107 case 'Z':
1108 Bprint(bout, "%llud", res->u.ival);
1109 break;
1110 case 'V':
1111 Bprint(bout, "%lld", res->u.ival);
1112 break;
1113 case 'Y':
1114 Bprint(bout, "%.16llux", res->u.ival);
1115 break;
1116 case 'o':
1117 Bprint(bout, "0%.11uo", (int)res->u.ival&0xffff);
1118 break;
1119 case 'O':
1120 Bprint(bout, "0%.6uo", (int)res->u.ival);
1121 break;
1122 case 'q':
1123 Bprint(bout, "0%.11o", (short)(res->u.ival&0xffff));
1124 break;
1125 case 'Q':
1126 Bprint(bout, "0%.6o", (int)res->u.ival);
1127 break;
1128 case 'f':
1129 case 'F':
1130 if(type != TFLOAT)
1131 Bprint(bout, "*%c<%s>*", res->fmt, typenames[(uchar)type]);
1132 else
1133 Bprint(bout, "%g", res->u.fval);
1134 break;
1135 case 's':
1136 case 'g':
1137 case 'G':
1138 if(type != TSTRING)
1139 Bprint(bout, "*%c<%s>*", res->fmt, typenames[(uchar)type]);
1140 else
1141 Bwrite(bout, res->u.string->string, res->u.string->len);
1142 break;
1143 case 'R':
1144 if(type != TSTRING)
1145 Bprint(bout, "*%c<%s>*", res->fmt, typenames[(uchar)type]);
1146 else
1147 Bprint(bout, "%S", (Rune*)res->u.string->string);
1148 break;
1149 case 'a':
1150 case 'A':
1151 symoff(buf, sizeof(buf), res->u.ival, CANY);
1152 Bprint(bout, "%s", buf);
1153 break;
1154 case 'I':
1155 case 'i':
1156 if(type != TINT)
1157 Bprint(bout, "*%c<%s>*", res->fmt, typenames[(uchar)type]);
1158 else {
1159 if (symmap == nil || (*mach->das)(symmap, res->u.ival, res->fmt, buf, sizeof(buf)) < 0)
1160 Bprint(bout, "no instruction");
1161 else
1162 Bprint(bout, "%s", buf);
1164 break;
1168 void
1169 blprint(List *l)
1171 Store *res;
1173 Bprint(bout, "{");
1174 while(l) {
1175 switch(l->type) {
1176 case TINT:
1177 res = &l->store;
1178 if(res->fmt == 'c'){
1179 Bprint(bout, "\'%c\'", (int)res->u.ival);
1180 break;
1181 }else if(res->fmt == 'r'){
1182 Bprint(bout, "\'%C\'", (int)res->u.ival);
1183 break;
1185 /* fall through */
1186 default:
1187 patom(l->type, &l->store);
1188 break;
1189 case TSTRING:
1190 Bputc(bout, '"');
1191 patom(l->type, &l->store);
1192 Bputc(bout, '"');
1193 break;
1194 case TLIST:
1195 blprint(l->store.u.l);
1196 break;
1197 case TCODE:
1198 pcode(l->store.u.cc, 0);
1199 break;
1201 l = l->next;
1202 if(l)
1203 Bprint(bout, ", ");
1205 Bprint(bout, "}");
1208 int
1209 comx(Node res)
1211 Lsym *sl;
1212 Node *n, xx;
1214 if(res.store.fmt != 'a' && res.store.fmt != 'A')
1215 return 0;
1217 if(res.store.comt == 0 || res.store.comt->base == 0)
1218 return 0;
1220 sl = res.store.comt->base;
1221 if(sl->proc) {
1222 res.left = ZN;
1223 res.right = ZN;
1224 n = an(ONAME, ZN, ZN);
1225 n->sym = sl;
1226 n = an(OCALL, n, &res);
1227 n->left->sym = sl;
1228 expr(n, &xx);
1229 return 1;
1231 print("(%s)", sl->name);
1232 return 0;
1235 void
1236 bprint(Node *r, Node *args)
1238 int i, nas;
1239 Node res, *av[Maxarg];
1241 USED(r);
1242 na = 0;
1243 flatten(av, args);
1244 nas = na;
1245 for(i = 0; i < nas; i++) {
1246 expr(av[i], &res);
1247 switch(res.type) {
1248 default:
1249 if(comx(res))
1250 break;
1251 patom(res.type, &res.store);
1252 break;
1253 case TCODE:
1254 pcode(res.store.u.cc, 0);
1255 break;
1256 case TLIST:
1257 blprint(res.store.u.l);
1258 break;
1261 if(ret == 0)
1262 Bputc(bout, '\n');
1265 void
1266 printto(Node *r, Node *args)
1268 int fd;
1269 Biobuf *b;
1270 int i, nas;
1271 Node res, *av[Maxarg];
1273 USED(r);
1274 na = 0;
1275 flatten(av, args);
1276 nas = na;
1278 expr(av[0], &res);
1279 if(res.type != TSTRING)
1280 error("printto(string, ...): need string");
1282 fd = create(res.store.u.string->string, OWRITE, 0666);
1283 if(fd < 0)
1284 fd = open(res.store.u.string->string, OWRITE);
1285 if(fd < 0)
1286 error("printto: open %s: %r", res.store.u.string->string);
1288 b = gmalloc(sizeof(Biobuf));
1289 Binit(b, fd, OWRITE);
1291 Bflush(bout);
1292 io[iop++] = bout;
1293 bout = b;
1295 for(i = 1; i < nas; i++) {
1296 expr(av[i], &res);
1297 switch(res.type) {
1298 default:
1299 if(comx(res))
1300 break;
1301 patom(res.type, &res.store);
1302 break;
1303 case TLIST:
1304 blprint(res.store.u.l);
1305 break;
1308 if(ret == 0)
1309 Bputc(bout, '\n');
1311 Bterm(b);
1312 close(fd);
1313 free(b);
1314 bout = io[--iop];
1317 void
1318 pcfile(Node *r, Node *args)
1320 Node res;
1321 char *p, buf[128];
1323 if(args == 0)
1324 error("pcfile(addr): arg count");
1325 expr(args, &res);
1326 if(res.type != TINT)
1327 error("pcfile(addr): arg type");
1329 r->type = TSTRING;
1330 r->store.fmt = 's';
1331 if(fileline(res.store.u.ival, buf, sizeof(buf)) < 0) {
1332 r->store.u.string = strnode("?file?");
1333 return;
1335 p = strrchr(buf, ':');
1336 if(p == 0)
1337 error("pcfile(addr): funny file %s", buf);
1338 *p = '\0';
1339 r->store.u.string = strnode(buf);
1342 void
1343 pcline(Node *r, Node *args)
1345 Node res;
1346 char *p, buf[128];
1348 if(args == 0)
1349 error("pcline(addr): arg count");
1350 expr(args, &res);
1351 if(res.type != TINT)
1352 error("pcline(addr): arg type");
1354 r->type = TINT;
1355 r->store.fmt = 'D';
1356 if(fileline(res.store.u.ival, buf, sizeof(buf)) < 0) {
1357 r->store.u.ival = 0;
1358 return;
1361 p = strrchr(buf, ':');
1362 if(p == 0)
1363 error("pcline(addr): funny file %s", buf);
1364 r->store.u.ival = atoi(p+1);
1367 void
1368 textfile(Node *r, Node *args)
1370 char *file;
1371 long base;
1372 Fhdr *fp;
1373 Node res, *av[Maxarg];
1374 List *l, *l2, **tail, *list, *tl;
1376 na = 0;
1377 flatten(av, args);
1379 if(na != 0) {
1380 expr(av[0], &res);
1381 if(res.type != TLIST)
1382 error("textfile(list): textfile needs a list");
1383 if(listlen(res.store.u.l) != 2)
1384 error("textfile(list): list must have 2 entries");
1386 l = res.store.u.l;
1387 if(l->type != TSTRING)
1388 error("textfile name must be a string");
1389 file = l->store.u.string->string;
1391 l = l->next;
1392 if(l->type != TINT)
1393 error("textfile base must be an int");
1394 base = l->store.u.ival;
1396 if((fp = crackhdr(file, OREAD)) == nil)
1397 error("crackhdr %s: %r", file);
1398 Bflush(bout);
1399 fp->base = base;
1400 fprint(2, "%s: %s %s %s\n", file, fp->aname, fp->mname, fp->fname);
1401 if(mapfile(fp, base, symmap, nil) < 0)
1402 fprint(2, "mapping %s: %r\n", file);
1403 if(corhdr){
1404 unmapfile(corhdr, cormap);
1405 mapfile(fp, base, cormap, nil);
1406 free(correg);
1407 mapfile(corhdr, 0, cormap, &correg);
1409 if(syminit(fp) < 0)
1410 fprint(2, "syminit %s: %r\n", file);
1411 else
1412 addvarsym(fp);
1413 return;
1416 l2 = nil;
1417 tail = &l2;
1418 for(fp=fhdrlist; fp; fp=fp->next){
1419 if(fp->ftype == FCORE)
1420 continue;
1421 tl = al(TLIST);
1422 *tail = tl;
1423 tail = &tl->next;
1425 list = al(TSTRING);
1426 tl->store.u.l = list;
1427 list->store.u.string = strnode(fp->filename);
1428 list->store.fmt = 's';
1429 list->next = al(TINT);
1430 list = list->next;
1431 list->store.fmt = 'X';
1432 list->store.u.ival = fp->base;
1435 r->type = TLIST;
1436 r->store.u.l = l2;
1439 void
1440 deltextfile(Node *r, Node *args)
1442 int did;
1443 char *file;
1444 Fhdr *fp, *fpnext;
1445 Node res, *av[Maxarg];
1447 na = 0;
1448 flatten(av, args);
1450 if(na != 1)
1451 error("deltextfile(string): arg count");
1453 expr(av[0], &res);
1454 if(res.type != TSTRING)
1455 error("deltextfile(string): arg type");
1456 file = res.store.u.string->string;
1458 did = 0;
1459 for(fp=fhdrlist; fp; fp=fpnext){
1460 fpnext = fp->next;
1461 if(fp->ftype == FCORE)
1462 continue;
1463 if(strcmp(file, fp->filename) == 0){
1464 did = 1;
1465 if(fp == symhdr)
1466 error("cannot remove symbols from main text file");
1467 unmapfile(fp, symmap);
1468 uncrackhdr(fp);
1472 delvarsym(file);
1473 if(!did)
1474 error("symbol file %s not open", file);