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