1 /* Copyright (c) 1982 Regents of the University of California */ 2 3 static char sccsid[] = "@(#)symbols.c 1.3 02/20/83"; 4 5 /* 6 * Symbol management. 7 */ 8 9 #include "defs.h" 10 #include "symbols.h" 11 #include "languages.h" 12 #include "printsym.h" 13 #include "tree.h" 14 #include "operators.h" 15 #include "eval.h" 16 #include "mappings.h" 17 #include "events.h" 18 #include "process.h" 19 #include "runtime.h" 20 #include "machine.h" 21 #include "names.h" 22 23 #ifndef public 24 typedef struct Symbol *Symbol; 25 26 #include "machine.h" 27 #include "names.h" 28 #include "languages.h" 29 30 /* 31 * Symbol classes 32 */ 33 34 typedef enum { 35 BADUSE, CONST, TYPE, VAR, ARRAY, PTRFILE, RECORD, FIELD, 36 PROC, FUNC, FVAR, REF, PTR, FILET, SET, RANGE, 37 LABEL, WITHPTR, SCAL, STR, PROG, IMPROPER, VARNT, 38 FPROC, FFUNC, MODULE, TYPEREF, TAG 39 } Symclass; 40 41 struct Symbol { 42 Name name; 43 Language language; 44 Symclass class : 8; 45 Integer level : 8; 46 Symbol type; 47 Symbol chain; 48 union { 49 int offset; /* variable address */ 50 long iconval; /* integer constant value */ 51 double fconval; /* floating constant value */ 52 struct { /* field offset and size (both in bits) */ 53 int offset; 54 int length; 55 } field; 56 struct { /* range bounds */ 57 long lower; 58 long upper; 59 } rangev; 60 struct { /* address of function value, code */ 61 int offset; 62 Address beginaddr; 63 } funcv; 64 struct { /* variant record info */ 65 int size; 66 Symbol vtorec; 67 Symbol vtag; 68 } varnt; 69 } symvalue; 70 Symbol block; /* symbol containing this symbol */ 71 Symbol next_sym; /* hash chain */ 72 }; 73 74 /* 75 * Basic types. 76 */ 77 78 Symbol t_boolean; 79 Symbol t_char; 80 Symbol t_int; 81 Symbol t_real; 82 Symbol t_nil; 83 84 Symbol program; 85 Symbol curfunc; 86 87 #define symname(s) ident(s->name) 88 #define codeloc(f) ((f)->symvalue.funcv.beginaddr) 89 #define isblock(s) (Boolean) ( \ 90 s->class == FUNC or s->class == PROC or \ 91 s->class == MODULE or s->class == PROG \ 92 ) 93 94 #include "tree.h" 95 96 /* 97 * Some macros to make finding a symbol with certain attributes. 98 */ 99 100 #define find(s, withname) \ 101 { \ 102 s = lookup(withname); \ 103 while (s != nil and not (s->name == (withname) and 104 105 #define where /* qualification */ 106 107 #define endfind(s) )) { \ 108 s = s->next_sym; \ 109 } \ 110 } 111 112 #endif 113 114 /* 115 * Symbol table structure currently does not support deletions. 116 */ 117 118 #define HASHTABLESIZE 2003 119 120 private Symbol hashtab[HASHTABLESIZE]; 121 122 #define hash(name) ((((unsigned) name) >> 2) mod HASHTABLESIZE) 123 124 /* 125 * Allocate a new symbol. 126 */ 127 128 #define SYMBLOCKSIZE 100 129 130 typedef struct Sympool { 131 struct Symbol sym[SYMBLOCKSIZE]; 132 struct Sympool *prevpool; 133 } *Sympool; 134 135 private Sympool sympool = nil; 136 private Integer nleft = 0; 137 138 public Symbol symbol_alloc() 139 { 140 register Sympool newpool; 141 142 if (nleft <= 0) { 143 newpool = new(Sympool); 144 bzero(newpool, sizeof(newpool)); 145 newpool->prevpool = sympool; 146 sympool = newpool; 147 nleft = SYMBLOCKSIZE; 148 } 149 --nleft; 150 return &(sympool->sym[nleft]); 151 } 152 153 /* 154 * Free all the symbols currently allocated. 155 */ 156 157 public symbol_free() 158 { 159 Sympool s, t; 160 register Integer i; 161 162 s = sympool; 163 while (s != nil) { 164 t = s->prevpool; 165 dispose(s); 166 s = t; 167 } 168 for (i = 0; i < HASHTABLESIZE; i++) { 169 hashtab[i] = nil; 170 } 171 sympool = nil; 172 nleft = 0; 173 } 174 175 /* 176 * Create a new symbol with the given attributes. 177 */ 178 179 public Symbol newSymbol(name, blevel, class, type, chain) 180 Name name; 181 Integer blevel; 182 Symclass class; 183 Symbol type; 184 Symbol chain; 185 { 186 register Symbol s; 187 188 s = symbol_alloc(); 189 s->name = name; 190 s->level = blevel; 191 s->class = class; 192 s->type = type; 193 s->chain = chain; 194 return s; 195 } 196 197 /* 198 * Insert a symbol into the hash table. 199 */ 200 201 public Symbol insert(name) 202 Name name; 203 { 204 register Symbol s; 205 register unsigned int h; 206 207 h = hash(name); 208 s = symbol_alloc(); 209 s->name = name; 210 s->next_sym = hashtab[h]; 211 hashtab[h] = s; 212 return s; 213 } 214 215 /* 216 * Symbol lookup. 217 */ 218 219 public Symbol lookup(name) 220 Name name; 221 { 222 register Symbol s; 223 register unsigned int h; 224 225 h = hash(name); 226 s = hashtab[h]; 227 while (s != nil and s->name != name) { 228 s = s->next_sym; 229 } 230 return s; 231 } 232 233 /* 234 * Dump out all the variables associated with the given 235 * procedure, function, or program at the given recursive level. 236 * 237 * This is quite inefficient. We traverse the entire symbol table 238 * each time we're called. The assumption is that this routine 239 * won't be called frequently enough to merit improved performance. 240 */ 241 242 public dumpvars(f, frame) 243 Symbol f; 244 Frame frame; 245 { 246 register Integer i; 247 register Symbol s; 248 249 for (i = 0; i < HASHTABLESIZE; i++) { 250 for (s = hashtab[i]; s != nil; s = s->next_sym) { 251 if (container(s) == f) { 252 if (should_print(s)) { 253 printv(s, frame); 254 putchar('\n'); 255 } else if (s->class == MODULE) { 256 dumpvars(s, frame); 257 } 258 } 259 } 260 } 261 } 262 263 /* 264 * Create a builtin type. 265 * Builtin types are circular in that btype->type->type = btype. 266 */ 267 268 public Symbol maketype(name, lower, upper) 269 String name; 270 long lower; 271 long upper; 272 { 273 register Symbol s; 274 275 s = newSymbol(identname(name, true), 0, TYPE, nil, nil); 276 s->language = findlanguage(".c"); 277 s->type = newSymbol(nil, 0, RANGE, s, nil); 278 s->type->symvalue.rangev.lower = lower; 279 s->type->symvalue.rangev.upper = upper; 280 return s; 281 } 282 283 /* 284 * These functions are now compiled inline. 285 * 286 * public String symname(s) 287 Symbol s; 288 { 289 checkref(s); 290 return ident(s->name); 291 } 292 293 * 294 * public Address codeloc(f) 295 Symbol f; 296 { 297 checkref(f); 298 if (not isblock(f)) { 299 panic("codeloc: \"%s\" is not a block", ident(f->name)); 300 } 301 return f->symvalue.funcv.beginaddr; 302 } 303 * 304 */ 305 306 /* 307 * Reduce type to avoid worrying about type names. 308 */ 309 310 public Symbol rtype(type) 311 Symbol type; 312 { 313 register Symbol t; 314 315 t = type; 316 if (t != nil) { 317 if (t->class == VAR or t->class == FIELD) { 318 t = t->type; 319 } 320 while (t->class == TYPE or t->class == TAG) { 321 t = t->type; 322 } 323 } 324 return t; 325 } 326 327 public Integer level(s) 328 Symbol s; 329 { 330 checkref(s); 331 return s->level; 332 } 333 334 public Symbol container(s) 335 Symbol s; 336 { 337 checkref(s); 338 return s->block; 339 } 340 341 /* 342 * Return the object address of the given symbol. 343 * 344 * There are the following possibilities: 345 * 346 * globals - just take offset 347 * locals - take offset from locals base 348 * arguments - take offset from argument base 349 * register - offset is register number 350 */ 351 352 #define isglobal(s) (s->level == 1 or s->level == 2) 353 #define islocaloff(s) (s->level >= 3 and s->symvalue.offset < 0) 354 #define isparamoff(s) (s->level >= 3 and s->symvalue.offset >= 0) 355 #define isreg(s) (s->level < 0) 356 357 public Address address(s, frame) 358 Symbol s; 359 Frame frame; 360 { 361 register Frame frp; 362 register Address addr; 363 register Symbol cur; 364 365 checkref(s); 366 if (not isactive(s->block)) { 367 error("\"%s\" is not currently defined", symname(s)); 368 } else if (isglobal(s)) { 369 addr = s->symvalue.offset; 370 } else { 371 frp = frame; 372 if (frp == nil) { 373 cur = s->block; 374 while (cur != nil and cur->class == MODULE) { 375 cur = cur->block; 376 } 377 if (cur == nil) { 378 cur = whatblock(pc); 379 } 380 frp = findframe(cur); 381 if (frp == nil) { 382 panic("unexpected nil frame for \"%s\"", symname(s)); 383 } 384 } 385 if (islocaloff(s)) { 386 addr = locals_base(frp) + s->symvalue.offset; 387 } else if (isparamoff(s)) { 388 addr = args_base(frp) + s->symvalue.offset; 389 } else if (isreg(s)) { 390 addr = savereg(s->symvalue.offset, frp); 391 } else { 392 panic("address: bad symbol \"%s\"", symname(s)); 393 } 394 } 395 return addr; 396 } 397 398 /* 399 * Define a symbol used to access register values. 400 */ 401 402 public defregname(n, r) 403 Name n; 404 Integer r; 405 { 406 register Symbol s, t; 407 408 s = insert(n); 409 t = newSymbol(nil, 0, PTR, t_int, nil); 410 t->language = findlanguage(".s"); 411 s->language = t->language; 412 s->class = VAR; 413 s->level = -3; 414 s->type = t; 415 s->block = program; 416 s->symvalue.offset = r; 417 } 418 419 /* 420 * Resolve an "abstract" type reference. 421 * 422 * It is possible in C to define a pointer to a type, but never define 423 * the type in a particular source file. Here we try to resolve 424 * the type definition. This is problematic, it is possible to 425 * have multiple, different definitions for the same name type. 426 */ 427 428 public findtype(s) 429 Symbol s; 430 { 431 register Symbol t, u, prev; 432 433 u = s; 434 prev = nil; 435 while (u != nil and u->class != BADUSE) { 436 if (u->name != nil) { 437 prev = u; 438 } 439 u = u->type; 440 } 441 if (prev == nil) { 442 error("couldn't find link to type reference"); 443 } 444 find(t, prev->name) where 445 t->type != nil and t->class == prev->class and 446 t->type->class != BADUSE and t->block->class == MODULE 447 endfind(t); 448 if (t == nil) { 449 error("couldn't resolve reference"); 450 } else { 451 prev->type = t->type; 452 } 453 } 454 455 /* 456 * Find the size in bytes of the given type. 457 * 458 * This is probably the WRONG thing to do. The size should be kept 459 * as an attribute in the symbol information as is done for structures 460 * and fields. I haven't gotten around to cleaning this up yet. 461 */ 462 463 #define MINCHAR -128 464 #define MAXCHAR 127 465 #define MINSHORT -32768 466 #define MAXSHORT 32767 467 468 public Integer size(sym) 469 Symbol sym; 470 { 471 register Symbol s, t; 472 register int nel, elsize; 473 long lower, upper; 474 int r; 475 476 t = sym; 477 checkref(t); 478 switch (t->class) { 479 case RANGE: 480 lower = t->symvalue.rangev.lower; 481 upper = t->symvalue.rangev.upper; 482 if (upper == 0 and lower > 0) { /* real */ 483 r = lower; 484 } else if (lower >= MINCHAR and upper <= MAXCHAR) { 485 r = sizeof(char); 486 } else if (lower >= MINSHORT and upper <= MAXSHORT) { 487 r = sizeof(short); 488 } else { 489 r = sizeof(long); 490 } 491 break; 492 493 case ARRAY: 494 elsize = size(t->type); 495 nel = 1; 496 for (t = t->chain; t != nil; t = t->chain) { 497 s = rtype(t); 498 lower = s->symvalue.rangev.lower; 499 upper = s->symvalue.rangev.upper; 500 nel *= (upper-lower+1); 501 } 502 r = nel*elsize; 503 break; 504 505 case VAR: 506 case FVAR: 507 r = size(t->type); 508 if (r < sizeof(Word)) { 509 r = sizeof(Word); 510 } 511 break; 512 513 case CONST: 514 r = size(t->type); 515 break; 516 517 case TYPE: 518 if (t->type->class == PTR and t->type->type->class == BADUSE) { 519 findtype(t); 520 } 521 r = size(t->type); 522 break; 523 524 case TAG: 525 r = size(t->type); 526 break; 527 528 case FIELD: 529 r = (t->symvalue.field.length + 7) div 8; 530 break; 531 532 case RECORD: 533 case VARNT: 534 r = t->symvalue.offset; 535 if (r == 0 and t->chain != nil) { 536 panic("missing size information for record"); 537 } 538 break; 539 540 case PTR: 541 case REF: 542 case FILET: 543 r = sizeof(Word); 544 break; 545 546 case SCAL: 547 if (t->symvalue.iconval > 255) { 548 r = sizeof(short); 549 } else { 550 r = sizeof(char); 551 } 552 break; 553 554 case FPROC: 555 case FFUNC: 556 r = sizeof(Word); 557 break; 558 559 case PROC: 560 case FUNC: 561 case MODULE: 562 case PROG: 563 r = sizeof(Symbol); 564 break; 565 566 default: 567 if (ord(t->class) > ord(TYPEREF)) { 568 panic("size: bad class (%d)", ord(t->class)); 569 } else { 570 error("improper operation on a %s", classname(t)); 571 } 572 /* NOTREACHED */ 573 } 574 if (r < sizeof(Word) and isparam(sym)) { 575 r = sizeof(Word); 576 } 577 return r; 578 } 579 580 /* 581 * Test if a symbol is a parameter. This is true if there 582 * is a cycle from s->block to s via chain pointers. 583 */ 584 585 public Boolean isparam(s) 586 Symbol s; 587 { 588 register Symbol t; 589 590 t = s->block; 591 while (t != nil and t != s) { 592 t = t->chain; 593 } 594 return (Boolean) (t != nil); 595 } 596 597 /* 598 * Test if a symbol is a var parameter, i.e. has class REF. 599 */ 600 601 public Boolean isvarparam(s) 602 Symbol s; 603 { 604 return (Boolean) (s->class == REF); 605 } 606 607 /* 608 * Test if a symbol is a variable (actually any addressible quantity 609 * with do). 610 */ 611 612 public Boolean isvariable(s) 613 register Symbol s; 614 { 615 return (Boolean) (s->class == VAR or s->class == FVAR or s->class == REF); 616 } 617 618 /* 619 * Test if a symbol is a block, e.g. function, procedure, or the 620 * main program. 621 * 622 * This function is now expanded inline for efficiency. 623 * 624 * public Boolean isblock(s) 625 register Symbol s; 626 { 627 return (Boolean) ( 628 s->class == FUNC or s->class == PROC or 629 s->class == MODULE or s->class == PROG 630 ); 631 } 632 * 633 */ 634 635 /* 636 * Test if a symbol is a module. 637 */ 638 639 public Boolean ismodule(s) 640 register Symbol s; 641 { 642 return (Boolean) (s->class == MODULE); 643 } 644 645 /* 646 * Test if a symbol is builtin, that is, a predefined type or 647 * reserved word. 648 */ 649 650 public Boolean isbuiltin(s) 651 register Symbol s; 652 { 653 return (Boolean) (s->level == 0 and s->class != PROG and s->class != VAR); 654 } 655 656 /* 657 * Test if two types match. 658 * Equivalent names implies a match in any language. 659 * 660 * Special symbols must be handled with care. 661 */ 662 663 public Boolean compatible(t1, t2) 664 register Symbol t1, t2; 665 { 666 Boolean b; 667 668 if (t1 == t2) { 669 b = true; 670 } else if (t1 == nil or t2 == nil) { 671 b = false; 672 } else if (t1 == procsym) { 673 b = isblock(t2); 674 } else if (t2 == procsym) { 675 b = isblock(t1); 676 } else if (t1->language == nil) { 677 b = (Boolean) (t2->language == nil or 678 (*language_op(t2->language, L_TYPEMATCH))(t1, t2)); 679 } else { 680 b = (Boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2); 681 } 682 return b; 683 } 684 685 /* 686 * Check for a type of the given name. 687 */ 688 689 public Boolean istypename(type, name) 690 Symbol type; 691 String name; 692 { 693 Symbol t; 694 Boolean b; 695 696 t = type; 697 checkref(t); 698 b = (Boolean) ( 699 t->class == TYPE and t->name == identname(name, true) 700 ); 701 return b; 702 } 703 704 /* 705 * Test if the name of a symbol is uniquely defined or not. 706 */ 707 708 public Boolean isambiguous(s) 709 register Symbol s; 710 { 711 register Symbol t; 712 713 find(t, s->name) where t != s endfind(t); 714 return (Boolean) (t != nil); 715 } 716 717 typedef char *Arglist; 718 719 #define nextarg(type) ((type *) (ap += sizeof(type)))[-1] 720 721 private Symbol mkstring(); 722 private Symbol namenode(); 723 724 /* 725 * Determine the type of a parse tree. 726 * Also make some symbol-dependent changes to the tree such as 727 * changing removing RVAL nodes for constant symbols. 728 */ 729 730 public assigntypes(p) 731 register Node p; 732 { 733 register Node p1; 734 register Symbol s; 735 736 switch (p->op) { 737 case O_SYM: 738 p->nodetype = namenode(p); 739 break; 740 741 case O_LCON: 742 p->nodetype = t_int; 743 break; 744 745 case O_FCON: 746 p->nodetype = t_real; 747 break; 748 749 case O_SCON: 750 p->value.scon = strdup(p->value.scon); 751 s = mkstring(p->value.scon); 752 if (s == t_char) { 753 p->op = O_LCON; 754 p->value.lcon = p->value.scon[0]; 755 } 756 p->nodetype = s; 757 break; 758 759 case O_INDIR: 760 p1 = p->value.arg[0]; 761 chkclass(p1, PTR); 762 p->nodetype = rtype(p1->nodetype)->type; 763 break; 764 765 case O_DOT: 766 p->nodetype = p->value.arg[1]->value.sym; 767 break; 768 769 case O_RVAL: 770 p1 = p->value.arg[0]; 771 p->nodetype = p1->nodetype; 772 if (p1->op == O_SYM) { 773 if (p1->nodetype->class == FUNC) { 774 p->op = O_CALL; 775 p->value.arg[1] = nil; 776 } else if (p1->value.sym->class == CONST) { 777 if (compatible(p1->value.sym->type, t_real)) { 778 p->op = O_FCON; 779 p->value.fcon = p1->value.sym->symvalue.fconval; 780 p->nodetype = t_real; 781 dispose(p1); 782 } else { 783 p->op = O_LCON; 784 p->value.lcon = p1->value.sym->symvalue.iconval; 785 p->nodetype = p1->value.sym->type; 786 dispose(p1); 787 } 788 } else if (isreg(p1->value.sym)) { 789 p->op = O_SYM; 790 p->value.sym = p1->value.sym; 791 dispose(p1); 792 } 793 } else if (p1->op == O_INDIR and p1->value.arg[0]->op == O_SYM) { 794 s = p1->value.arg[0]->value.sym; 795 if (isreg(s)) { 796 p1->op = O_SYM; 797 dispose(p1->value.arg[0]); 798 p1->value.sym = s; 799 p1->nodetype = s; 800 } 801 } 802 break; 803 804 /* 805 * Perform a cast if the call is of the form "type(expr)". 806 */ 807 case O_CALL: 808 p1 = p->value.arg[0]; 809 p->nodetype = rtype(p1->nodetype)->type; 810 break; 811 812 case O_TYPERENAME: 813 p->nodetype = p->value.arg[1]->nodetype; 814 break; 815 816 case O_ITOF: 817 p->nodetype = t_real; 818 break; 819 820 case O_NEG: 821 s = p->value.arg[0]->nodetype; 822 if (not compatible(s, t_int)) { 823 if (not compatible(s, t_real)) { 824 beginerrmsg(); 825 prtree(stderr, p->value.arg[0]); 826 fprintf(stderr, "is improper type"); 827 enderrmsg(); 828 } else { 829 p->op = O_NEGF; 830 } 831 } 832 p->nodetype = s; 833 break; 834 835 case O_ADD: 836 case O_SUB: 837 case O_MUL: 838 case O_LT: 839 case O_LE: 840 case O_GT: 841 case O_GE: 842 case O_EQ: 843 case O_NE: 844 { 845 Boolean t1real, t2real; 846 Symbol t1, t2; 847 848 t1 = rtype(p->value.arg[0]->nodetype); 849 t2 = rtype(p->value.arg[1]->nodetype); 850 t1real = compatible(t1, t_real); 851 t2real = compatible(t2, t_real); 852 if (t1real or t2real) { 853 p->op = (Operator) (ord(p->op) + 1); 854 if (not t1real) { 855 p->value.arg[0] = build(O_ITOF, p->value.arg[0]); 856 } else if (not t2real) { 857 p->value.arg[1] = build(O_ITOF, p->value.arg[1]); 858 } 859 } else { 860 if (t1real) { 861 convert(&(p->value.arg[0]), t_int, O_NOP); 862 } 863 if (t2real) { 864 convert(&(p->value.arg[1]), t_int, O_NOP); 865 } 866 } 867 if (ord(p->op) >= ord(O_LT)) { 868 p->nodetype = t_boolean; 869 } else { 870 if (t1real or t2real) { 871 p->nodetype = t_real; 872 } else { 873 p->nodetype = t_int; 874 } 875 } 876 break; 877 } 878 879 case O_DIVF: 880 convert(&(p->value.arg[0]), t_real, O_ITOF); 881 convert(&(p->value.arg[1]), t_real, O_ITOF); 882 p->nodetype = t_real; 883 break; 884 885 case O_DIV: 886 case O_MOD: 887 convert(&(p->value.arg[0]), t_int, O_NOP); 888 convert(&(p->value.arg[1]), t_int, O_NOP); 889 p->nodetype = t_int; 890 break; 891 892 case O_AND: 893 case O_OR: 894 chkboolean(p->value.arg[0]); 895 chkboolean(p->value.arg[1]); 896 p->nodetype = t_boolean; 897 break; 898 899 case O_QLINE: 900 p->nodetype = t_int; 901 break; 902 903 default: 904 p->nodetype = nil; 905 break; 906 } 907 } 908 909 /* 910 * Create a node for a name. The symbol for the name has already 911 * been chosen, either implicitly with "which" or explicitly from 912 * the dot routine. 913 */ 914 915 private Symbol namenode(p) 916 Node p; 917 { 918 register Symbol r, s; 919 register Node np; 920 921 s = p->value.sym; 922 if (s->class == REF) { 923 np = new(Node); 924 np->op = p->op; 925 np->nodetype = s; 926 np->value.sym = s; 927 p->op = O_INDIR; 928 p->value.arg[0] = np; 929 } 930 /* 931 * Old way 932 * 933 if (s->class == CONST or s->class == VAR or s->class == FVAR) { 934 r = s->type; 935 } else { 936 r = s; 937 } 938 * 939 */ 940 return s; 941 } 942 943 /* 944 * Convert a tree to a type via a conversion operator; 945 * if this isn't possible generate an error. 946 * 947 * Note the tree is call by address, hence the #define below. 948 */ 949 950 private convert(tp, typeto, op) 951 Node *tp; 952 Symbol typeto; 953 Operator op; 954 { 955 #define tree (*tp) 956 957 Symbol s; 958 959 s = rtype(tree->nodetype); 960 typeto = rtype(typeto); 961 if (compatible(typeto, t_real) and compatible(s, t_int)) { 962 tree = build(op, tree); 963 } else if (not compatible(s, typeto)) { 964 beginerrmsg(); 965 prtree(stderr, s); 966 fprintf(stderr, " is improper type"); 967 enderrmsg(); 968 } else if (op != O_NOP and s != typeto) { 969 tree = build(op, tree); 970 } 971 972 #undef tree 973 } 974 975 /* 976 * Construct a node for the dot operator. 977 * 978 * If the left operand is not a record, but rather a procedure 979 * or function, then we interpret the "." as referencing an 980 * "invisible" variable; i.e. a variable within a dynamically 981 * active block but not within the static scope of the current procedure. 982 */ 983 984 public Node dot(record, fieldname) 985 Node record; 986 Name fieldname; 987 { 988 register Node p; 989 register Symbol s, t; 990 991 if (isblock(record->nodetype)) { 992 find(s, fieldname) where 993 s->block == record->nodetype and 994 s->class != FIELD and s->class != TAG 995 endfind(s); 996 if (s == nil) { 997 beginerrmsg(); 998 fprintf(stderr, "\"%s\" is not defined in ", ident(fieldname)); 999 printname(stderr, record->nodetype); 1000 enderrmsg(); 1001 } 1002 p = new(Node); 1003 p->op = O_SYM; 1004 p->value.sym = s; 1005 p->nodetype = namenode(p); 1006 } else { 1007 p = record; 1008 t = rtype(p->nodetype); 1009 if (t->class == PTR) { 1010 s = findfield(fieldname, t->type); 1011 } else { 1012 s = findfield(fieldname, t); 1013 } 1014 if (s == nil) { 1015 beginerrmsg(); 1016 fprintf(stderr, "\"%s\" is not a field in ", ident(fieldname)); 1017 prtree(stderr, record); 1018 enderrmsg(); 1019 } 1020 if (t->class == PTR and not isreg(record->nodetype)) { 1021 p = build(O_INDIR, record); 1022 } 1023 p = build(O_DOT, p, build(O_SYM, s)); 1024 } 1025 return p; 1026 } 1027 1028 /* 1029 * Return a tree corresponding to an array reference and do the 1030 * error checking. 1031 */ 1032 1033 public Node subscript(a, slist) 1034 Node a, slist; 1035 { 1036 register Symbol t; 1037 register Node p; 1038 Symbol etype, atype, eltype; 1039 Node esub, olda; 1040 1041 olda = a; 1042 t = rtype(a->nodetype); 1043 if (t->class != ARRAY) { 1044 beginerrmsg(); 1045 prtree(stderr, a); 1046 fprintf(stderr, " is not an array"); 1047 enderrmsg(); 1048 } 1049 eltype = t->type; 1050 p = slist; 1051 t = t->chain; 1052 for (; p != nil and t != nil; p = p->value.arg[1], t = t->chain) { 1053 esub = p->value.arg[0]; 1054 etype = rtype(esub->nodetype); 1055 atype = rtype(t); 1056 if (not compatible(atype, etype)) { 1057 beginerrmsg(); 1058 fprintf(stderr, "subscript "); 1059 prtree(stderr, esub); 1060 fprintf(stderr, " is the wrong type"); 1061 enderrmsg(); 1062 } 1063 a = build(O_INDEX, a, esub); 1064 a->nodetype = eltype; 1065 } 1066 if (p != nil or t != nil) { 1067 beginerrmsg(); 1068 if (p != nil) { 1069 fprintf(stderr, "too many subscripts for "); 1070 } else { 1071 fprintf(stderr, "not enough subscripts for "); 1072 } 1073 prtree(stderr, olda); 1074 enderrmsg(); 1075 } 1076 return a; 1077 } 1078 1079 /* 1080 * Evaluate a subscript index. 1081 */ 1082 1083 public int evalindex(s, i) 1084 Symbol s; 1085 long i; 1086 { 1087 long lb, ub; 1088 1089 s = rtype(s)->chain; 1090 lb = s->symvalue.rangev.lower; 1091 ub = s->symvalue.rangev.upper; 1092 if (i < lb or i > ub) { 1093 error("subscript out of range"); 1094 } 1095 return (i - lb); 1096 } 1097 1098 /* 1099 * Check to see if a tree is boolean-valued, if not it's an error. 1100 */ 1101 1102 public chkboolean(p) 1103 register Node p; 1104 { 1105 if (p->nodetype != t_boolean) { 1106 beginerrmsg(); 1107 fprintf(stderr, "found "); 1108 prtree(stderr, p); 1109 fprintf(stderr, ", expected boolean expression"); 1110 enderrmsg(); 1111 } 1112 } 1113 1114 /* 1115 * Check to make sure the given tree has a type of the given class. 1116 */ 1117 1118 private chkclass(p, class) 1119 Node p; 1120 Symclass class; 1121 { 1122 struct Symbol tmpsym; 1123 1124 tmpsym.class = class; 1125 if (rtype(p->nodetype)->class != class) { 1126 beginerrmsg(); 1127 fprintf(stderr, "\""); 1128 prtree(stderr, p); 1129 fprintf(stderr, "\" is not a %s", classname(&tmpsym)); 1130 enderrmsg(); 1131 } 1132 } 1133 1134 /* 1135 * Construct a node for the type of a string. While we're at it, 1136 * scan the string for '' that collapse to ', and chop off the ends. 1137 */ 1138 1139 private Symbol mkstring(str) 1140 String str; 1141 { 1142 register char *p, *q; 1143 register Symbol s; 1144 1145 p = str; 1146 q = str; 1147 while (*p != '\0') { 1148 if (*p == '\\') { 1149 ++p; 1150 } 1151 *q = *p; 1152 ++p; 1153 ++q; 1154 } 1155 *q = '\0'; 1156 s = newSymbol(nil, 0, ARRAY, t_char, nil); 1157 s->language = findlanguage(".s"); 1158 s->chain = newSymbol(nil, 0, RANGE, t_int, nil); 1159 s->chain->language = s->language; 1160 s->chain->symvalue.rangev.lower = 1; 1161 s->chain->symvalue.rangev.upper = p - str + 1; 1162 return s; 1163 } 1164 1165 /* 1166 * Free up the space allocated for a string type. 1167 */ 1168 1169 public unmkstring(s) 1170 Symbol s; 1171 { 1172 dispose(s->chain); 1173 } 1174 1175 /* 1176 * Figure out the "current" variable or function being referred to, 1177 * this is either the active one or the most visible from the 1178 * current scope. 1179 */ 1180 1181 public Symbol which(n) 1182 Name n; 1183 { 1184 register Symbol s, p, t, f; 1185 1186 find(s, n) where s->class != FIELD and s->class != TAG endfind(s); 1187 if (s == nil) { 1188 s = lookup(n); 1189 } 1190 if (s == nil) { 1191 error("\"%s\" is not defined", ident(n)); 1192 } else if (s == program or isbuiltin(s)) { 1193 t = s; 1194 } else { 1195 /* 1196 * Old way 1197 * 1198 if (not isactive(program)) { 1199 f = program; 1200 } else { 1201 f = whatblock(pc); 1202 if (f == nil) { 1203 panic("no block for addr 0x%x", pc); 1204 } 1205 } 1206 * 1207 * Now start with curfunc. 1208 */ 1209 p = curfunc; 1210 do { 1211 find(t, n) where 1212 t->block == p and t->class != FIELD and t->class != TAG 1213 endfind(t); 1214 p = p->block; 1215 } while (t == nil and p != nil); 1216 if (t == nil) { 1217 t = s; 1218 } 1219 } 1220 return t; 1221 } 1222 1223 /* 1224 * Find the symbol which is has the same name and scope as the 1225 * given symbol but is of the given field. Return nil if there is none. 1226 */ 1227 1228 public Symbol findfield(fieldname, record) 1229 Name fieldname; 1230 Symbol record; 1231 { 1232 register Symbol t; 1233 1234 t = rtype(record)->chain; 1235 while (t != nil and t->name != fieldname) { 1236 t = t->chain; 1237 } 1238 return t; 1239 } 1240