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*);
48 typedef struct Btab Btab;
49 struct Btab
50 {
51 char *name;
52 void (*fn)(Node*, Node*);
53 } tab[] =
54 {
55 "atof", cvtatof,
56 "atoi", cvtatoi,
57 "deltextfile", deltextfile,
58 "error", doerror,
59 "file", getfile,
60 "readfile", readfile,
61 "access", doaccess,
62 "filepc", filepc,
63 "fnbound", funcbound,
64 "fmt", fmt,
65 "follow", follow,
66 "include", include,
67 "includepipe", includepipe,
68 "interpret", interpret,
69 "itoa", cvtitoa,
70 "kill", xkill,
71 "map", map,
72 "match", match,
73 "newproc", newproc,
74 "pcfile", pcfile,
75 "pcline", pcline,
76 "print", bprint,
77 "printto", printto,
78 "rc", rc,
79 "reason", reason,
80 "regexp", regexp,
81 "setproc", setproc,
82 "start", start,
83 "startstop", startstop,
84 "status", status,
85 "stop", stop,
86 "strace", strace,
87 "stringn", stringn,
88 "sysstop", sysstop,
89 "textfile", textfile,
90 "waitstop", waitstop,
91 0
92 };
94 void
95 mkprint(Lsym *s)
96 {
97 prnt = malloc(sizeof(Node));
98 memset(prnt, 0, sizeof(Node));
99 prnt->op = OCALL;
100 prnt->left = malloc(sizeof(Node));
101 memset(prnt->left, 0, sizeof(Node));
102 prnt->left->sym = s;
105 void
106 installbuiltin(void)
108 Btab *b;
109 Lsym *s;
111 b = tab;
112 while(b->name) {
113 s = look(b->name);
114 if(s == 0)
115 s = enter(b->name, Tid);
117 s->builtin = b->fn;
118 if(b->fn == bprint)
119 mkprint(s);
120 b++;
124 void
125 match(Node *r, Node *args)
127 int i;
128 List *f;
129 Node *av[Maxarg];
130 Node resi, resl;
132 na = 0;
133 flatten(av, args);
134 if(na != 2)
135 error("match(obj, list): arg count");
137 expr(av[1], &resl);
138 if(resl.type != TLIST)
139 error("match(obj, list): need list");
140 expr(av[0], &resi);
142 r->op = OCONST;
143 r->type = TINT;
144 r->store.fmt = 'D';
145 r->store.u.ival = -1;
147 i = 0;
148 for(f = resl.store.u.l; f; f = f->next) {
149 if(resi.type == f->type) {
150 switch(resi.type) {
151 case TINT:
152 if(resi.store.u.ival == f->store.u.ival) {
153 r->store.u.ival = i;
154 return;
156 break;
157 case TFLOAT:
158 if(resi.store.u.fval == f->store.u.fval) {
159 r->store.u.ival = i;
160 return;
162 break;
163 case TSTRING:
164 if(scmp(resi.store.u.string, f->store.u.string)) {
165 r->store.u.ival = i;
166 return;
168 break;
169 case TLIST:
170 error("match(obj, list): not defined for list");
173 i++;
177 void
178 newproc(Node *r, Node *args)
180 int i;
181 Node res;
182 char *p, *e;
183 char *argv[Maxarg], buf[Strsize];
185 i = 1;
186 argv[0] = symfil;
188 if(args) {
189 expr(args, &res);
190 if(res.type != TSTRING)
191 error("newproc(): arg not string");
192 if(res.store.u.string->len >= sizeof(buf))
193 error("newproc(): too many arguments");
194 memmove(buf, res.store.u.string->string, res.store.u.string->len);
195 buf[res.store.u.string->len] = '\0';
196 p = buf;
197 e = buf+res.store.u.string->len;
198 for(;;) {
199 while(p < e && (*p == '\t' || *p == ' '))
200 *p++ = '\0';
201 if(p >= e)
202 break;
203 argv[i++] = p;
204 if(i >= Maxarg)
205 error("newproc: too many arguments");
206 while(p < e && *p != '\t' && *p != ' ')
207 p++;
210 argv[i] = 0;
211 r->op = OCONST;
212 r->type = TINT;
213 r->store.fmt = 'D';
214 r->store.u.ival = nproc(argv);
217 void
218 startstop(Node *r, Node *args)
220 Node res;
222 USED(r);
223 if(args == 0)
224 error("startstop(pid): no pid");
225 expr(args, &res);
226 if(res.type != TINT)
227 error("startstop(pid): arg type");
229 msg(res.store.u.ival, "startstop");
230 notes(res.store.u.ival);
231 dostop(res.store.u.ival);
234 void
235 waitstop(Node *r, Node *args)
237 Node res;
239 USED(r);
240 if(args == 0)
241 error("waitstop(pid): no pid");
242 expr(args, &res);
243 if(res.type != TINT)
244 error("waitstop(pid): arg type");
246 Bflush(bout);
247 msg(res.store.u.ival, "waitstop");
248 notes(res.store.u.ival);
249 dostop(res.store.u.ival);
252 void
253 sysstop(Node *r, Node *args)
255 Node res;
257 USED(r);
258 if(args == 0)
259 error("waitstop(pid): no pid");
260 expr(args, &res);
261 if(res.type != TINT)
262 error("waitstop(pid): arg type");
264 Bflush(bout);
265 msg(res.store.u.ival, "sysstop");
266 notes(res.store.u.ival);
267 dostop(res.store.u.ival);
270 void
271 start(Node *r, Node *args)
273 Node res;
275 USED(r);
276 if(args == 0)
277 error("start(pid): no pid");
278 expr(args, &res);
279 if(res.type != TINT)
280 error("start(pid): arg type");
282 msg(res.store.u.ival, "start");
285 void
286 stop(Node *r, Node *args)
288 Node res;
290 USED(r);
291 if(args == 0)
292 error("stop(pid): no pid");
293 expr(args, &res);
294 if(res.type != TINT)
295 error("stop(pid): arg type");
297 Bflush(bout);
298 msg(res.store.u.ival, "stop");
299 notes(res.store.u.ival);
300 dostop(res.store.u.ival);
303 void
304 xkill(Node *r, Node *args)
306 Node res;
308 USED(r);
309 if(args == 0)
310 error("kill(pid): no pid");
311 expr(args, &res);
312 if(res.type != TINT)
313 error("kill(pid): arg type");
315 msg(res.store.u.ival, "kill");
316 deinstall(res.store.u.ival);
319 void
320 status(Node *r, Node *args)
322 Node res;
323 char *p;
325 USED(r);
326 if(args == 0)
327 error("status(pid): no pid");
328 expr(args, &res);
329 if(res.type != TINT)
330 error("status(pid): arg type");
332 p = getstatus(res.store.u.ival);
333 r->store.u.string = strnode(p);
334 r->op = OCONST;
335 r->store.fmt = 's';
336 r->type = TSTRING;
339 void
340 reason(Node *r, Node *args)
342 Node res;
344 if(args == 0)
345 error("reason(cause): no cause");
346 expr(args, &res);
347 if(res.type != TINT)
348 error("reason(cause): arg type");
350 r->op = OCONST;
351 r->type = TSTRING;
352 r->store.fmt = 's';
353 r->store.u.string = strnode((*mach->exc)(cormap, correg));
356 void
357 follow(Node *r, Node *args)
359 int n, i;
360 Node res;
361 ulong f[10];
362 List **tail, *l;
364 if(args == 0)
365 error("follow(addr): no addr");
366 expr(args, &res);
367 if(res.type != TINT)
368 error("follow(addr): arg type");
370 n = (*mach->foll)(cormap, correg, res.store.u.ival, f);
371 if (n < 0)
372 error("follow(addr): %r");
373 tail = &r->store.u.l;
374 for(i = 0; i < n; i++) {
375 l = al(TINT);
376 l->store.u.ival = f[i];
377 l->store.fmt = 'X';
378 *tail = l;
379 tail = &l->next;
383 void
384 funcbound(Node *r, Node *args)
386 int n;
387 Node res;
388 ulong bounds[2];
389 List *l;
391 if(args == 0)
392 error("fnbound(addr): no addr");
393 expr(args, &res);
394 if(res.type != TINT)
395 error("fnbound(addr): arg type");
397 n = fnbound(res.store.u.ival, bounds);
398 if (n != 0) {
399 r->store.u.l = al(TINT);
400 l = r->store.u.l;
401 l->store.u.ival = bounds[0];
402 l->store.fmt = 'X';
403 l->next = al(TINT);
404 l = l->next;
405 l->store.u.ival = bounds[1];
406 l->store.fmt = 'X';
410 void
411 setproc(Node *r, Node *args)
413 Node res;
415 USED(r);
416 if(args == 0)
417 error("setproc(pid): no pid");
418 expr(args, &res);
419 if(res.type != TINT)
420 error("setproc(pid): arg type");
422 sproc(res.store.u.ival);
425 void
426 filepc(Node *r, Node *args)
428 int i;
429 Node res;
430 char *p, c;
431 ulong v;
433 if(args == 0)
434 error("filepc(filename:line): arg count");
435 expr(args, &res);
436 if(res.type != TSTRING)
437 error("filepc(filename:line): arg type");
439 p = strchr(res.store.u.string->string, ':');
440 if(p == 0)
441 error("filepc(filename:line): bad arg format");
443 c = *p;
444 *p++ = '\0';
445 i = file2pc(res.store.u.string->string, atoi(p), &v);
446 p[-1] = c;
447 if(i < 0)
448 error("filepc(filename:line): can't find address");
450 r->op = OCONST;
451 r->type = TINT;
452 r->store.fmt = 'D';
453 r->store.u.ival = v;
456 void
457 interpret(Node *r, Node *args)
459 Node res;
460 int isave;
462 if(args == 0)
463 error("interpret(string): arg count");
464 expr(args, &res);
465 if(res.type != TSTRING)
466 error("interpret(string): arg type");
468 pushstr(&res);
470 isave = interactive;
471 interactive = 0;
472 r->store.u.ival = yyparse();
473 interactive = isave;
474 popio();
475 r->op = OCONST;
476 r->type = TINT;
477 r->store.fmt = 'D';
480 void
481 include(Node *r, Node *args)
483 char *file, *libfile;
484 static char buf[1024];
485 Node res;
486 int isave;
488 if(args == 0)
489 error("include(string): arg count");
490 expr(args, &res);
491 if(res.type != TSTRING)
492 error("include(string): arg type");
494 Bflush(bout);
496 libfile = nil;
497 file = res.store.u.string->string;
498 if(access(file, AREAD) < 0 && file[0] != '/'){
499 snprint(buf, sizeof buf, "#9/acid/%s", file);
500 libfile = unsharp(buf);
501 if(access(libfile, AREAD) >= 0){
502 strecpy(buf, buf+sizeof buf, libfile);
503 file = buf;
505 free(libfile);
508 pushfile(file);
509 isave = interactive;
510 interactive = 0;
511 r->store.u.ival = yyparse();
512 interactive = isave;
513 popio();
514 r->op = OCONST;
515 r->type = TINT;
516 r->store.fmt = 'D';
519 void
520 includepipe(Node *r, Node *args)
522 Node res;
523 int i, isave, pid, pip[2];
524 char *argv[4];
525 Waitmsg *w;
527 USED(r);
528 if(args == 0)
529 error("includepipe(string): arg count");
530 expr(args, &res);
531 if(res.type != TSTRING)
532 error("includepipe(string): arg type");
534 Bflush(bout);
536 argv[0] = "rc";
537 argv[1] = "-c";
538 argv[2] = res.store.u.string->string;
539 argv[3] = 0;
541 if(pipe(pip) < 0)
542 error("pipe: %r");
544 pid = fork();
545 switch(pid) {
546 case -1:
547 close(pip[0]);
548 close(pip[1]);
549 error("fork: %r");
550 case 0:
551 close(pip[0]);
552 close(0);
553 open("/dev/null", OREAD);
554 dup(pip[1], 1);
555 if(pip[1] > 1)
556 close(pip[1]);
557 for(i=3; i<100; i++)
558 close(i);
559 exec("rc", argv);
560 sysfatal("exec rc: %r");
563 close(pip[1]);
564 pushfd(pip[0]);
566 isave = interactive;
567 interactive = 0;
568 r->store.u.ival = yyparse();
569 interactive = isave;
570 popio();
572 r->op = OCONST;
573 r->type = TINT;
574 r->store.fmt = 'D';
576 w = waitfor(pid);
577 if(w->msg && w->msg[0])
578 error("includepipe(\"%s\"): %s", argv[2], w->msg); /* leaks w */
579 free(w);
582 void
583 rc(Node *r, Node *args)
585 Node res;
586 int pid;
587 char *p, *q, *argv[4];
588 Waitmsg *w;
590 USED(r);
591 if(args == 0)
592 error("rc(string): arg count");
593 expr(args, &res);
594 if(res.type != TSTRING)
595 error("rc(string): arg type");
597 argv[0] = "rc";
598 argv[1] = "-c";
599 argv[2] = res.store.u.string->string;
600 argv[3] = 0;
602 pid = fork();
603 switch(pid) {
604 case -1:
605 error("fork %r");
606 case 0:
607 exec("rc", argv);
608 exits(0);
609 default:
610 w = waitfor(pid);
611 break;
613 p = w->msg;
614 q = strrchr(p, ':');
615 if (q)
616 p = q+1;
618 r->op = OCONST;
619 r->type = TSTRING;
620 r->store.u.string = strnode(p);
621 free(w);
622 r->store.fmt = 's';
625 void
626 doerror(Node *r, Node *args)
628 Node res;
630 USED(r);
631 if(args == 0)
632 error("error(string): arg count");
633 expr(args, &res);
634 if(res.type != TSTRING)
635 error("error(string): arg type");
637 error(res.store.u.string->string);
640 void
641 doaccess(Node *r, Node *args)
643 Node res;
645 if(args == 0)
646 error("access(filename): arg count");
647 expr(args, &res);
648 if(res.type != TSTRING)
649 error("access(filename): arg type");
651 r->op = OCONST;
652 r->type = TINT;
653 r->store.fmt = 'D';
654 r->store.u.ival = 0;
655 if(access(res.store.u.string->string, 4) == 0)
656 r->store.u.ival = 1;
659 void
660 readfile(Node *r, Node *args)
662 Node res;
663 int n, fd;
664 char *buf;
665 Dir *db;
667 if(args == 0)
668 error("readfile(filename): arg count");
669 expr(args, &res);
670 if(res.type != TSTRING)
671 error("readfile(filename): arg type");
673 fd = open(res.store.u.string->string, OREAD);
674 if(fd < 0)
675 return;
677 db = dirfstat(fd);
678 if(db == nil || db->length == 0)
679 n = 8192;
680 else
681 n = db->length;
682 free(db);
684 buf = malloc(n);
685 n = read(fd, buf, n);
687 if(n > 0) {
688 r->op = OCONST;
689 r->type = TSTRING;
690 r->store.u.string = strnodlen(buf, n);
691 r->store.fmt = 's';
693 free(buf);
694 close(fd);
697 void
698 getfile(Node *r, Node *args)
700 int n;
701 char *p;
702 Node res;
703 String *s;
704 Biobuf *bp;
705 List **l, *new;
707 if(args == 0)
708 error("file(filename): arg count");
709 expr(args, &res);
710 if(res.type != TSTRING)
711 error("file(filename): arg type");
713 r->op = OCONST;
714 r->type = TLIST;
715 r->store.u.l = 0;
717 p = res.store.u.string->string;
718 bp = Bopen(p, OREAD);
719 if(bp == 0)
720 return;
722 l = &r->store.u.l;
723 for(;;) {
724 p = Brdline(bp, '\n');
725 n = Blinelen(bp);
726 if(p == 0) {
727 if(n == 0)
728 break;
729 s = strnodlen(0, n);
730 Bread(bp, s->string, n);
732 else
733 s = strnodlen(p, n-1);
735 new = al(TSTRING);
736 new->store.u.string = s;
737 new->store.fmt = 's';
738 *l = new;
739 l = &new->next;
741 Bterm(bp);
744 void
745 cvtatof(Node *r, Node *args)
747 Node res;
749 if(args == 0)
750 error("atof(string): arg count");
751 expr(args, &res);
752 if(res.type != TSTRING)
753 error("atof(string): arg type");
755 r->op = OCONST;
756 r->type = TFLOAT;
757 r->store.u.fval = atof(res.store.u.string->string);
758 r->store.fmt = 'f';
761 void
762 cvtatoi(Node *r, Node *args)
764 Node res;
766 if(args == 0)
767 error("atoi(string): arg count");
768 expr(args, &res);
769 if(res.type != TSTRING)
770 error("atoi(string): arg type");
772 r->op = OCONST;
773 r->type = TINT;
774 r->store.u.ival = strtoul(res.store.u.string->string, 0, 0);
775 r->store.fmt = 'D';
778 void
779 cvtitoa(Node *r, Node *args)
781 Node res;
782 Node *av[Maxarg];
783 int ival;
784 char buf[128], *fmt;
786 if(args == 0)
787 err:
788 error("itoa(number [, printformat]): arg count");
789 na = 0;
790 flatten(av, args);
791 if(na == 0 || na > 2)
792 goto err;
793 expr(av[0], &res);
794 if(res.type != TINT)
795 error("itoa(integer): arg type");
796 ival = (int)res.store.u.ival;
797 fmt = "%d";
798 if(na == 2){
799 expr(av[1], &res);
800 if(res.type != TSTRING)
801 error("itoa(integer, string): arg type");
802 fmt = res.store.u.string->string;
805 sprint(buf, fmt, ival);
806 r->op = OCONST;
807 r->type = TSTRING;
808 r->store.u.string = strnode(buf);
809 r->store.fmt = 's';
812 List*
813 mapent(Map *m)
815 int i;
816 List *l, *n, **t, *h;
818 h = 0;
819 t = &h;
820 for(i = 0; i < m->nseg; i++) {
821 l = al(TSTRING);
822 n = al(TLIST);
823 n->store.u.l = l;
824 *t = n;
825 t = &n->next;
826 l->store.u.string = strnode(m->seg[i].name);
827 l->store.fmt = 's';
828 l->next = al(TSTRING);
829 l = l->next;
830 l->store.u.string = strnode(m->seg[i].file ? m->seg[i].file : "");
831 l->store.fmt = 's';
832 l->next = al(TINT);
833 l = l->next;
834 l->store.u.ival = m->seg[i].base;
835 l->store.fmt = 'X';
836 l->next = al(TINT);
837 l = l->next;
838 l->store.u.ival = m->seg[i].base + m->seg[i].size;
839 l->store.fmt = 'X';
840 l->next = al(TINT);
841 l = l->next;
842 l->store.u.ival = m->seg[i].offset;
843 l->store.fmt = 'X';
845 return h;
848 void
849 map(Node *r, Node *args)
851 int i;
852 Map *m;
853 List *l;
854 char *nam, *fil;
855 Node *av[Maxarg], res;
857 na = 0;
858 flatten(av, args);
860 if(na != 0) {
861 expr(av[0], &res);
862 if(res.type != TLIST)
863 error("map(list): map needs a list");
864 if(listlen(res.store.u.l) != 5)
865 error("map(list): list must have 5 entries");
867 l = res.store.u.l;
868 if(l->type != TSTRING)
869 error("map name must be a string");
870 nam = l->store.u.string->string;
871 l = l->next;
872 if(l->type != TSTRING)
873 error("map file must be a string");
874 fil = l->store.u.string->string;
875 m = symmap;
876 i = findseg(m, nam, fil);
877 if(i < 0) {
878 m = cormap;
879 i = findseg(m, nam, fil);
881 if(i < 0)
882 error("%s %s is not a map entry", nam, fil);
883 l = l->next;
884 if(l->type != TINT)
885 error("map entry not int");
886 m->seg[i].base = l->store.u.ival;
887 /*
888 if (strcmp(ent, "text") == 0)
889 textseg(l->store.u.ival, &fhdr);
890 */
891 l = l->next;
892 if(l->type != TINT)
893 error("map entry not int");
894 m->seg[i].size = l->store.u.ival - m->seg[i].base;
895 l = l->next;
896 if(l->type != TINT)
897 error("map entry not int");
898 m->seg[i].offset = l->store.u.ival;
901 r->type = TLIST;
902 r->store.u.l = 0;
903 if(symmap)
904 r->store.u.l = mapent(symmap);
905 if(cormap) {
906 if(r->store.u.l == 0)
907 r->store.u.l = mapent(cormap);
908 else {
909 for(l = r->store.u.l; l->next; l = l->next)
911 l->next = mapent(cormap);
916 void
917 flatten(Node **av, Node *n)
919 if(n == 0)
920 return;
922 switch(n->op) {
923 case OLIST:
924 flatten(av, n->left);
925 flatten(av, n->right);
926 break;
927 default:
928 av[na++] = n;
929 if(na >= Maxarg)
930 error("too many function arguments");
931 break;
935 static struct
937 char *name;
938 ulong val;
939 } sregs[Maxarg/2];
940 static int nsregs;
942 static int
943 straceregrw(Regs *regs, char *name, ulong *val, int isr)
945 int i;
947 if(!isr){
948 werrstr("saved registers cannot be written");
949 return -1;
951 for(i=0; i<nsregs; i++)
952 if(strcmp(sregs[i].name, name) == 0){
953 *val = sregs[i].val;
954 return 0;
956 return rget(correg, name, val);
959 void
960 strace(Node *r, Node *args)
962 Node *av[Maxarg], res;
963 List *l;
964 Regs regs;
966 na = 0;
967 flatten(av, args);
969 if(na != 1)
970 error("strace(list): want one arg");
972 expr(av[0], &res);
973 if(res.type != TLIST)
974 error("strace(list): strace needs a list");
975 l = res.store.u.l;
976 if(listlen(l)%2)
977 error("strace(list): strace needs an even-length list");
978 for(nsregs=0; l; nsregs++){
979 if(l->type != TSTRING)
980 error("strace({r,v,r,v,...}): non-string name");
981 sregs[nsregs].name = l->store.u.string->string;
982 if(regdesc(sregs[nsregs].name) == nil)
983 error("strace: bad register '%s'", sregs[nsregs].name);
984 l = l->next;
986 if(l == nil)
987 error("cannot happen in strace");
988 if(l->type != TINT)
989 error("strace: non-int value for %s", sregs[nsregs].name);
990 sregs[nsregs].val = l->store.u.ival;
991 l = l->next;
993 regs.rw = straceregrw;
995 tracelist = 0;
996 if(stacktrace(cormap, &regs, trlist) <= 0)
997 error("no stack frame");
998 r->type = TLIST;
999 r->store.u.l = tracelist;
1002 void
1003 regerror(char *msg)
1005 error(msg);
1008 void
1009 regexp(Node *r, Node *args)
1011 Node res;
1012 Reprog *rp;
1013 Node *av[Maxarg];
1015 na = 0;
1016 flatten(av, args);
1017 if(na != 2)
1018 error("regexp(pattern, string): arg count");
1019 expr(av[0], &res);
1020 if(res.type != TSTRING)
1021 error("regexp(pattern, string): pattern must be string");
1022 rp = regcomp(res.store.u.string->string);
1023 if(rp == 0)
1024 return;
1026 expr(av[1], &res);
1027 if(res.type != TSTRING)
1028 error("regexp(pattern, string): bad string");
1030 r->store.fmt = 'D';
1031 r->type = TINT;
1032 r->store.u.ival = regexec(rp, res.store.u.string->string, 0, 0);
1033 free(rp);
1036 char vfmt[] = "aBbcCdDfFgGiIoOqQrRsSuUVxXYZ";
1038 void
1039 fmt(Node *r, Node *args)
1041 Node res;
1042 Node *av[Maxarg];
1044 na = 0;
1045 flatten(av, args);
1046 if(na != 2)
1047 error("fmt(obj, fmt): arg count");
1048 expr(av[1], &res);
1049 if(res.type != TINT || strchr(vfmt, res.store.u.ival) == 0)
1050 error("fmt(obj, fmt): bad format '%c'", (char)res.store.u.ival);
1051 expr(av[0], r);
1052 r->store.fmt = res.store.u.ival;
1055 void
1056 patom(char type, Store *res)
1058 int i;
1059 char buf[512];
1060 extern char *typenames[];
1062 switch(res->fmt) {
1063 case 'c':
1064 Bprint(bout, "%c", (int)res->u.ival);
1065 break;
1066 case 'C':
1067 if(res->u.ival < ' ' || res->u.ival >= 0x7f)
1068 Bprint(bout, "%3d", (int)res->u.ival&0xff);
1069 else
1070 Bprint(bout, "%3c", (int)res->u.ival);
1071 break;
1072 case 'r':
1073 Bprint(bout, "%C", (int)res->u.ival);
1074 break;
1075 case 'B':
1076 memset(buf, '0', 34);
1077 buf[1] = 'b';
1078 for(i = 0; i < 32; i++) {
1079 if(res->u.ival & (1<<i))
1080 buf[33-i] = '1';
1082 buf[35] = '\0';
1083 Bprint(bout, "%s", buf);
1084 break;
1085 case 'b':
1086 Bprint(bout, "%.2x", (int)res->u.ival&0xff);
1087 break;
1088 case 'X':
1089 Bprint(bout, "%.8lux", (ulong)res->u.ival);
1090 break;
1091 case 'x':
1092 Bprint(bout, "%.4lux", (ulong)res->u.ival&0xffff);
1093 break;
1094 case 'W':
1095 Bprint(bout, "%.16llux", res->u.ival);
1096 break;
1097 case 'D':
1098 Bprint(bout, "%d", (int)res->u.ival);
1099 break;
1100 case 'd':
1101 Bprint(bout, "%d", (ushort)res->u.ival);
1102 break;
1103 case 'u':
1104 Bprint(bout, "%d", (int)res->u.ival&0xffff);
1105 break;
1106 case 'U':
1107 Bprint(bout, "%lud", (ulong)res->u.ival);
1108 break;
1109 case 'Z':
1110 Bprint(bout, "%llud", res->u.ival);
1111 break;
1112 case 'V':
1113 Bprint(bout, "%lld", res->u.ival);
1114 break;
1115 case 'Y':
1116 Bprint(bout, "%.16llux", res->u.ival);
1117 break;
1118 case 'o':
1119 Bprint(bout, "0%.11uo", (int)res->u.ival&0xffff);
1120 break;
1121 case 'O':
1122 Bprint(bout, "0%.6uo", (int)res->u.ival);
1123 break;
1124 case 'q':
1125 Bprint(bout, "0%.11o", (short)(res->u.ival&0xffff));
1126 break;
1127 case 'Q':
1128 Bprint(bout, "0%.6o", (int)res->u.ival);
1129 break;
1130 case 'f':
1131 case 'F':
1132 if(type != TFLOAT)
1133 Bprint(bout, "*%c<%s>*", res->fmt, typenames[(uchar)type]);
1134 else
1135 Bprint(bout, "%g", res->u.fval);
1136 break;
1137 case 's':
1138 case 'g':
1139 case 'G':
1140 if(type != TSTRING)
1141 Bprint(bout, "*%c<%s>*", res->fmt, typenames[(uchar)type]);
1142 else
1143 Bwrite(bout, res->u.string->string, res->u.string->len);
1144 break;
1145 case 'R':
1146 if(type != TSTRING)
1147 Bprint(bout, "*%c<%s>*", res->fmt, typenames[(uchar)type]);
1148 else
1149 Bprint(bout, "%S", (Rune*)res->u.string->string);
1150 break;
1151 case 'a':
1152 case 'A':
1153 symoff(buf, sizeof(buf), res->u.ival, CANY);
1154 Bprint(bout, "%s", buf);
1155 break;
1156 case 'I':
1157 case 'i':
1158 if(type != TINT)
1159 Bprint(bout, "*%c<%s>*", res->fmt, typenames[(uchar)type]);
1160 else {
1161 if (symmap == nil || (*mach->das)(symmap, res->u.ival, res->fmt, buf, sizeof(buf)) < 0)
1162 Bprint(bout, "no instruction");
1163 else
1164 Bprint(bout, "%s", buf);
1166 break;
1170 void
1171 blprint(List *l)
1173 Store *res;
1175 Bprint(bout, "{");
1176 while(l) {
1177 switch(l->type) {
1178 case TINT:
1179 res = &l->store;
1180 if(res->fmt == 'c'){
1181 Bprint(bout, "\'%c\'", (int)res->u.ival);
1182 break;
1183 }else if(res->fmt == 'r'){
1184 Bprint(bout, "\'%C\'", (int)res->u.ival);
1185 break;
1187 /* fall through */
1188 default:
1189 patom(l->type, &l->store);
1190 break;
1191 case TSTRING:
1192 Bputc(bout, '"');
1193 patom(l->type, &l->store);
1194 Bputc(bout, '"');
1195 break;
1196 case TLIST:
1197 blprint(l->store.u.l);
1198 break;
1199 case TCODE:
1200 pcode(l->store.u.cc, 0);
1201 break;
1203 l = l->next;
1204 if(l)
1205 Bprint(bout, ", ");
1207 Bprint(bout, "}");
1210 int
1211 comx(Node res)
1213 Lsym *sl;
1214 Node *n, xx;
1216 if(res.store.fmt != 'a' && res.store.fmt != 'A')
1217 return 0;
1219 if(res.store.comt == 0 || res.store.comt->base == 0)
1220 return 0;
1222 sl = res.store.comt->base;
1223 if(sl->proc) {
1224 res.left = ZN;
1225 res.right = ZN;
1226 n = an(ONAME, ZN, ZN);
1227 n->sym = sl;
1228 n = an(OCALL, n, &res);
1229 n->left->sym = sl;
1230 expr(n, &xx);
1231 return 1;
1233 print("(%s)", sl->name);
1234 return 0;
1237 void
1238 bprint(Node *r, Node *args)
1240 int i, nas;
1241 Node res, *av[Maxarg];
1243 USED(r);
1244 na = 0;
1245 flatten(av, args);
1246 nas = na;
1247 for(i = 0; i < nas; i++) {
1248 expr(av[i], &res);
1249 switch(res.type) {
1250 default:
1251 if(comx(res))
1252 break;
1253 patom(res.type, &res.store);
1254 break;
1255 case TCODE:
1256 pcode(res.store.u.cc, 0);
1257 break;
1258 case TLIST:
1259 blprint(res.store.u.l);
1260 break;
1263 if(ret == 0)
1264 Bputc(bout, '\n');
1267 void
1268 printto(Node *r, Node *args)
1270 int fd;
1271 Biobuf *b;
1272 int i, nas;
1273 Node res, *av[Maxarg];
1275 USED(r);
1276 na = 0;
1277 flatten(av, args);
1278 nas = na;
1280 expr(av[0], &res);
1281 if(res.type != TSTRING)
1282 error("printto(string, ...): need string");
1284 fd = create(res.store.u.string->string, OWRITE, 0666);
1285 if(fd < 0)
1286 fd = open(res.store.u.string->string, OWRITE);
1287 if(fd < 0)
1288 error("printto: open %s: %r", res.store.u.string->string);
1290 b = gmalloc(sizeof(Biobuf));
1291 Binit(b, fd, OWRITE);
1293 Bflush(bout);
1294 io[iop++] = bout;
1295 bout = b;
1297 for(i = 1; i < nas; i++) {
1298 expr(av[i], &res);
1299 switch(res.type) {
1300 default:
1301 if(comx(res))
1302 break;
1303 patom(res.type, &res.store);
1304 break;
1305 case TLIST:
1306 blprint(res.store.u.l);
1307 break;
1310 if(ret == 0)
1311 Bputc(bout, '\n');
1313 Bterm(b);
1314 close(fd);
1315 free(b);
1316 bout = io[--iop];
1319 void
1320 pcfile(Node *r, Node *args)
1322 Node res;
1323 char *p, buf[128];
1325 if(args == 0)
1326 error("pcfile(addr): arg count");
1327 expr(args, &res);
1328 if(res.type != TINT)
1329 error("pcfile(addr): arg type");
1331 r->type = TSTRING;
1332 r->store.fmt = 's';
1333 if(fileline(res.store.u.ival, buf, sizeof(buf)) < 0) {
1334 r->store.u.string = strnode("?file?");
1335 return;
1337 p = strrchr(buf, ':');
1338 if(p == 0)
1339 error("pcfile(addr): funny file %s", buf);
1340 *p = '\0';
1341 r->store.u.string = strnode(buf);
1344 void
1345 pcline(Node *r, Node *args)
1347 Node res;
1348 char *p, buf[128];
1350 if(args == 0)
1351 error("pcline(addr): arg count");
1352 expr(args, &res);
1353 if(res.type != TINT)
1354 error("pcline(addr): arg type");
1356 r->type = TINT;
1357 r->store.fmt = 'D';
1358 if(fileline(res.store.u.ival, buf, sizeof(buf)) < 0) {
1359 r->store.u.ival = 0;
1360 return;
1363 p = strrchr(buf, ':');
1364 if(p == 0)
1365 error("pcline(addr): funny file %s", buf);
1366 r->store.u.ival = atoi(p+1);
1369 void
1370 textfile(Node *r, Node *args)
1372 char *file;
1373 long base;
1374 Fhdr *fp;
1375 Node res, *av[Maxarg];
1376 List *l, *l2, **tail, *list, *tl;
1378 na = 0;
1379 flatten(av, args);
1381 if(na != 0) {
1382 expr(av[0], &res);
1383 if(res.type != TLIST)
1384 error("textfile(list): textfile needs a list");
1385 if(listlen(res.store.u.l) != 2)
1386 error("textfile(list): list must have 2 entries");
1388 l = res.store.u.l;
1389 if(l->type != TSTRING)
1390 error("textfile name must be a string");
1391 file = l->store.u.string->string;
1393 l = l->next;
1394 if(l->type != TINT)
1395 error("textfile base must be an int");
1396 base = l->store.u.ival;
1398 if((fp = crackhdr(file, OREAD)) == nil)
1399 error("crackhdr %s: %r", file);
1400 Bflush(bout);
1401 fp->base = base;
1402 fprint(2, "%s: %s %s %s\n", file, fp->aname, fp->mname, fp->fname);
1403 if(mapfile(fp, base, symmap, nil) < 0)
1404 fprint(2, "mapping %s: %r\n", file);
1405 if(corhdr){
1406 unmapfile(corhdr, cormap);
1407 mapfile(fp, base, cormap, nil);
1408 free(correg);
1409 mapfile(corhdr, 0, cormap, &correg);
1411 if(symopen(fp) < 0)
1412 fprint(2, "symopen %s: %r\n", file);
1413 else
1414 addvarsym(fp);
1415 return;
1418 l2 = nil;
1419 tail = &l2;
1420 for(fp=fhdrlist; fp; fp=fp->next){
1421 if(fp->ftype == FCORE)
1422 continue;
1423 tl = al(TLIST);
1424 *tail = tl;
1425 tail = &tl->next;
1427 list = al(TSTRING);
1428 tl->store.u.l = list;
1429 list->store.u.string = strnode(fp->filename);
1430 list->store.fmt = 's';
1431 list->next = al(TINT);
1432 list = list->next;
1433 list->store.fmt = 'X';
1434 list->store.u.ival = fp->base;
1437 r->type = TLIST;
1438 r->store.u.l = l2;
1441 void
1442 deltextfile(Node *r, Node *args)
1444 int did;
1445 char *file;
1446 Fhdr *fp, *fpnext;
1447 Node res, *av[Maxarg];
1449 na = 0;
1450 flatten(av, args);
1452 if(na != 1)
1453 error("deltextfile(string): arg count");
1455 expr(av[0], &res);
1456 if(res.type != TSTRING)
1457 error("deltextfile(string): arg type");
1458 file = res.store.u.string->string;
1460 did = 0;
1461 for(fp=fhdrlist; fp; fp=fpnext){
1462 fpnext = fp->next;
1463 if(fp->ftype == FCORE)
1464 continue;
1465 if(strcmp(file, fp->filename) == 0){
1466 did = 1;
1467 if(fp == symhdr)
1468 error("cannot remove symbols from main text file");
1469 unmapfile(fp, symmap);
1470 uncrackhdr(fp);
1474 delvarsym(file);
1475 if(!did)
1476 error("symbol file %s not open", file);
1479 int xget1(Map *m, ulong addr, u8int *a, int n);
1481 void
1482 stringn(Node *r, Node *args)
1484 uint addr;
1485 int i, n, ret;
1486 Node res, *av[Maxarg];
1487 char *buf;
1489 na = 0;
1490 flatten(av, args);
1491 if(na != 2)
1492 error("stringn(addr, n): arg count");
1494 expr(av[0], &res);
1495 if(res.type != TINT)
1496 error("stringn(addr, n): arg type");
1497 addr = res.store.u.ival;
1499 expr(av[1], &res);
1500 if(res.type != TINT)
1501 error("stringn(addr,n): arg type");
1502 n = res.store.u.ival;
1504 buf = malloc(n+1);
1505 if(buf == nil)
1506 error("out of memory");
1508 r->type = TSTRING;
1509 for(i=0; i<n; i++){
1510 ret = xget1(cormap, addr, (uchar*)&buf[i], 1);
1511 if(ret < 0){
1512 free(buf);
1513 error("indir: %r");
1515 addr++;
1517 buf[n] = 0;
1518 r->store.u.string = strnode(buf);
1519 free(buf);