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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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* 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 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 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 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 919 regerror(char *msg) 920 { 921 error(msg); 922 } 923 924 void 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 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 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 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 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 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 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 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 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 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 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