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