|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1983 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #ifndef lint ! 8: static char sccsid[] = "@(#)symbols.c 5.2 (Berkeley) 9/5/85"; ! 9: #endif not lint ! 10: ! 11: static char rcsid[] = "$Header: symbols.c,v 1.6 84/12/26 10:42:31 linton Exp $"; ! 12: ! 13: /* ! 14: * Symbol management. ! 15: */ ! 16: ! 17: #include "defs.h" ! 18: #include "symbols.h" ! 19: #include "languages.h" ! 20: #include "printsym.h" ! 21: #include "tree.h" ! 22: #include "operators.h" ! 23: #include "eval.h" ! 24: #include "mappings.h" ! 25: #include "events.h" ! 26: #include "process.h" ! 27: #include "runtime.h" ! 28: #include "machine.h" ! 29: #include "names.h" ! 30: ! 31: #ifndef public ! 32: typedef struct Symbol *Symbol; ! 33: ! 34: #include "machine.h" ! 35: #include "names.h" ! 36: #include "languages.h" ! 37: #include "tree.h" ! 38: ! 39: /* ! 40: * Symbol classes ! 41: */ ! 42: ! 43: typedef enum { ! 44: BADUSE, CONST, TYPE, VAR, ARRAY, DYNARRAY, SUBARRAY, PTRFILE, RECORD, FIELD, ! 45: PROC, FUNC, FVAR, REF, PTR, FILET, SET, RANGE, ! 46: LABEL, WITHPTR, SCAL, STR, PROG, IMPROPER, VARNT, ! 47: FPROC, FFUNC, MODULE, TAG, COMMON, EXTREF, TYPEREF ! 48: } Symclass; ! 49: ! 50: typedef enum { R_CONST, R_TEMP, R_ARG, R_ADJUST } Rangetype; ! 51: ! 52: struct Symbol { ! 53: Name name; ! 54: Language language; ! 55: Symclass class : 8; ! 56: Integer level : 8; ! 57: Symbol type; ! 58: Symbol chain; ! 59: union { ! 60: Node constval; /* value of constant symbol */ ! 61: int offset; /* variable address */ ! 62: long iconval; /* integer constant value */ ! 63: double fconval; /* floating constant value */ ! 64: int ndims; /* no. of dimensions for dynamic/sub-arrays */ ! 65: struct { /* field offset and size (both in bits) */ ! 66: int offset; ! 67: int length; ! 68: } field; ! 69: struct { /* common offset and chain; used to relocate */ ! 70: int offset; /* vars in global BSS */ ! 71: Symbol chain; ! 72: } common; ! 73: struct { /* range bounds */ ! 74: Rangetype lowertype : 16; ! 75: Rangetype uppertype : 16; ! 76: long lower; ! 77: long upper; ! 78: } rangev; ! 79: struct { ! 80: int offset : 16; /* offset for of function value */ ! 81: Boolean src : 1; /* true if there is source line info */ ! 82: Boolean inline : 1; /* true if no separate act. rec. */ ! 83: Boolean intern : 1; /* internal calling sequence */ ! 84: int unused : 13; ! 85: Address beginaddr; /* address of function code */ ! 86: } funcv; ! 87: struct { /* variant record info */ ! 88: int size; ! 89: Symbol vtorec; ! 90: Symbol vtag; ! 91: } varnt; ! 92: String typeref; /* type defined by "<module>:<type>" */ ! 93: Symbol extref; /* indirect symbol for external reference */ ! 94: } symvalue; ! 95: Symbol block; /* symbol containing this symbol */ ! 96: Symbol next_sym; /* hash chain */ ! 97: }; ! 98: ! 99: /* ! 100: * Basic types. ! 101: */ ! 102: ! 103: Symbol t_boolean; ! 104: Symbol t_char; ! 105: Symbol t_int; ! 106: Symbol t_real; ! 107: Symbol t_nil; ! 108: Symbol t_addr; ! 109: ! 110: Symbol program; ! 111: Symbol curfunc; ! 112: ! 113: boolean showaggrs; ! 114: ! 115: #define symname(s) ident(s->name) ! 116: #define codeloc(f) ((f)->symvalue.funcv.beginaddr) ! 117: #define isblock(s) (Boolean) ( \ ! 118: s->class == FUNC or s->class == PROC or \ ! 119: s->class == MODULE or s->class == PROG \ ! 120: ) ! 121: #define isroutine(s) (Boolean) ( \ ! 122: s->class == FUNC or s->class == PROC \ ! 123: ) ! 124: ! 125: #define nosource(f) (not (f)->symvalue.funcv.src) ! 126: #define isinline(f) ((f)->symvalue.funcv.inline) ! 127: ! 128: #define isreg(s) (s->level < 0) ! 129: ! 130: #include "tree.h" ! 131: ! 132: /* ! 133: * Some macros to make finding a symbol with certain attributes. ! 134: */ ! 135: ! 136: #define find(s, withname) \ ! 137: { \ ! 138: s = lookup(withname); \ ! 139: while (s != nil and not (s->name == (withname) and ! 140: ! 141: #define where /* qualification */ ! 142: ! 143: #define endfind(s) )) { \ ! 144: s = s->next_sym; \ ! 145: } \ ! 146: } ! 147: ! 148: #endif ! 149: ! 150: /* ! 151: * Symbol table structure currently does not support deletions. ! 152: */ ! 153: ! 154: #define HASHTABLESIZE 2003 ! 155: ! 156: private Symbol hashtab[HASHTABLESIZE]; ! 157: ! 158: #define hash(name) ((((unsigned) name) >> 2) mod HASHTABLESIZE) ! 159: ! 160: /* ! 161: * Allocate a new symbol. ! 162: */ ! 163: ! 164: #define SYMBLOCKSIZE 100 ! 165: ! 166: typedef struct Sympool { ! 167: struct Symbol sym[SYMBLOCKSIZE]; ! 168: struct Sympool *prevpool; ! 169: } *Sympool; ! 170: ! 171: private Sympool sympool = nil; ! 172: private Integer nleft = 0; ! 173: ! 174: public Symbol symbol_alloc() ! 175: { ! 176: register Sympool newpool; ! 177: ! 178: if (nleft <= 0) { ! 179: newpool = new(Sympool); ! 180: bzero(newpool, sizeof(newpool)); ! 181: newpool->prevpool = sympool; ! 182: sympool = newpool; ! 183: nleft = SYMBLOCKSIZE; ! 184: } ! 185: --nleft; ! 186: return &(sympool->sym[nleft]); ! 187: } ! 188: ! 189: public symbol_dump (func) ! 190: Symbol func; ! 191: { ! 192: register Symbol s; ! 193: register integer i; ! 194: ! 195: printf(" symbols in %s \n",symname(func)); ! 196: for (i = 0; i < HASHTABLESIZE; i++) { ! 197: for (s = hashtab[i]; s != nil; s = s->next_sym) { ! 198: if (s->block == func) { ! 199: psym(s); ! 200: } ! 201: } ! 202: } ! 203: } ! 204: ! 205: /* ! 206: * Free all the symbols currently allocated. ! 207: */ ! 208: ! 209: public symbol_free() ! 210: { ! 211: Sympool s, t; ! 212: register Integer i; ! 213: ! 214: s = sympool; ! 215: while (s != nil) { ! 216: t = s->prevpool; ! 217: dispose(s); ! 218: s = t; ! 219: } ! 220: for (i = 0; i < HASHTABLESIZE; i++) { ! 221: hashtab[i] = nil; ! 222: } ! 223: sympool = nil; ! 224: nleft = 0; ! 225: } ! 226: ! 227: /* ! 228: * Create a new symbol with the given attributes. ! 229: */ ! 230: ! 231: public Symbol newSymbol(name, blevel, class, type, chain) ! 232: Name name; ! 233: Integer blevel; ! 234: Symclass class; ! 235: Symbol type; ! 236: Symbol chain; ! 237: { ! 238: register Symbol s; ! 239: ! 240: s = symbol_alloc(); ! 241: s->name = name; ! 242: s->language = primlang; ! 243: s->level = blevel; ! 244: s->class = class; ! 245: s->type = type; ! 246: s->chain = chain; ! 247: return s; ! 248: } ! 249: ! 250: /* ! 251: * Insert a symbol into the hash table. ! 252: */ ! 253: ! 254: public Symbol insert(name) ! 255: Name name; ! 256: { ! 257: register Symbol s; ! 258: register unsigned int h; ! 259: ! 260: h = hash(name); ! 261: s = symbol_alloc(); ! 262: s->name = name; ! 263: s->next_sym = hashtab[h]; ! 264: hashtab[h] = s; ! 265: return s; ! 266: } ! 267: ! 268: /* ! 269: * Symbol lookup. ! 270: */ ! 271: ! 272: public Symbol lookup(name) ! 273: Name name; ! 274: { ! 275: register Symbol s; ! 276: register unsigned int h; ! 277: ! 278: h = hash(name); ! 279: s = hashtab[h]; ! 280: while (s != nil and s->name != name) { ! 281: s = s->next_sym; ! 282: } ! 283: return s; ! 284: } ! 285: ! 286: /* ! 287: * Delete a symbol from the symbol table. ! 288: */ ! 289: ! 290: public delete (s) ! 291: Symbol s; ! 292: { ! 293: register Symbol t; ! 294: register unsigned int h; ! 295: ! 296: h = hash(s->name); ! 297: t = hashtab[h]; ! 298: if (t == nil) { ! 299: panic("delete of non-symbol '%s'", symname(s)); ! 300: } else if (t == s) { ! 301: hashtab[h] = s->next_sym; ! 302: } else { ! 303: while (t->next_sym != s) { ! 304: t = t->next_sym; ! 305: if (t == nil) { ! 306: panic("delete of non-symbol '%s'", symname(s)); ! 307: } ! 308: } ! 309: t->next_sym = s->next_sym; ! 310: } ! 311: } ! 312: ! 313: /* ! 314: * Dump out all the variables associated with the given ! 315: * procedure, function, or program associated with the given stack frame. ! 316: * ! 317: * This is quite inefficient. We traverse the entire symbol table ! 318: * each time we're called. The assumption is that this routine ! 319: * won't be called frequently enough to merit improved performance. ! 320: */ ! 321: ! 322: public dumpvars(f, frame) ! 323: Symbol f; ! 324: Frame frame; ! 325: { ! 326: register Integer i; ! 327: register Symbol s; ! 328: ! 329: for (i = 0; i < HASHTABLESIZE; i++) { ! 330: for (s = hashtab[i]; s != nil; s = s->next_sym) { ! 331: if (container(s) == f) { ! 332: if (should_print(s)) { ! 333: printv(s, frame); ! 334: putchar('\n'); ! 335: } else if (s->class == MODULE) { ! 336: dumpvars(s, frame); ! 337: } ! 338: } ! 339: } ! 340: } ! 341: } ! 342: ! 343: /* ! 344: * Create a builtin type. ! 345: * Builtin types are circular in that btype->type->type = btype. ! 346: */ ! 347: ! 348: private Symbol maketype(name, lower, upper) ! 349: String name; ! 350: long lower; ! 351: long upper; ! 352: { ! 353: register Symbol s; ! 354: Name n; ! 355: ! 356: if (name == nil) { ! 357: n = nil; ! 358: } else { ! 359: n = identname(name, true); ! 360: } ! 361: s = insert(n); ! 362: s->language = primlang; ! 363: s->level = 0; ! 364: s->class = TYPE; ! 365: s->type = nil; ! 366: s->chain = nil; ! 367: s->type = newSymbol(nil, 0, RANGE, s, nil); ! 368: s->type->symvalue.rangev.lower = lower; ! 369: s->type->symvalue.rangev.upper = upper; ! 370: return s; ! 371: } ! 372: ! 373: /* ! 374: * Create the builtin symbols. ! 375: */ ! 376: ! 377: public symbols_init () ! 378: { ! 379: Symbol s; ! 380: ! 381: t_boolean = maketype("$boolean", 0L, 1L); ! 382: t_int = maketype("$integer", 0x80000000L, 0x7fffffffL); ! 383: t_char = maketype("$char", 0L, 255L); ! 384: t_real = maketype("$real", 8L, 0L); ! 385: t_nil = maketype("$nil", 0L, 0L); ! 386: t_addr = insert(identname("$address", true)); ! 387: t_addr->language = primlang; ! 388: t_addr->level = 0; ! 389: t_addr->class = TYPE; ! 390: t_addr->type = newSymbol(nil, 1, PTR, t_int, nil); ! 391: s = insert(identname("true", true)); ! 392: s->class = CONST; ! 393: s->type = t_boolean; ! 394: s->symvalue.constval = build(O_LCON, 1L); ! 395: s->symvalue.constval->nodetype = t_boolean; ! 396: s = insert(identname("false", true)); ! 397: s->class = CONST; ! 398: s->type = t_boolean; ! 399: s->symvalue.constval = build(O_LCON, 0L); ! 400: s->symvalue.constval->nodetype = t_boolean; ! 401: } ! 402: ! 403: /* ! 404: * Reduce type to avoid worrying about type names. ! 405: */ ! 406: ! 407: public Symbol rtype(type) ! 408: Symbol type; ! 409: { ! 410: register Symbol t; ! 411: ! 412: t = type; ! 413: if (t != nil) { ! 414: if (t->class == VAR or t->class == CONST or ! 415: t->class == FIELD or t->class == REF ! 416: ) { ! 417: t = t->type; ! 418: } ! 419: if (t->class == TYPEREF) { ! 420: resolveRef(t); ! 421: } ! 422: while (t->class == TYPE or t->class == TAG) { ! 423: t = t->type; ! 424: if (t->class == TYPEREF) { ! 425: resolveRef(t); ! 426: } ! 427: } ! 428: } ! 429: return t; ! 430: } ! 431: ! 432: /* ! 433: * Find the end of a module name. Return nil if there is none ! 434: * in the given string. ! 435: */ ! 436: ! 437: private String findModuleMark (s) ! 438: String s; ! 439: { ! 440: register char *p, *r; ! 441: register boolean done; ! 442: ! 443: p = s; ! 444: done = false; ! 445: do { ! 446: if (*p == ':') { ! 447: done = true; ! 448: r = p; ! 449: } else if (*p == '\0') { ! 450: done = true; ! 451: r = nil; ! 452: } else { ! 453: ++p; ! 454: } ! 455: } while (not done); ! 456: return r; ! 457: } ! 458: ! 459: /* ! 460: * Resolve a type reference by modifying to be the appropriate type. ! 461: * ! 462: * If the reference has a name, then it refers to an opaque type and ! 463: * the actual type is directly accessible. Otherwise, we must use ! 464: * the type reference string, which is of the form "module:{module:}name". ! 465: */ ! 466: ! 467: public resolveRef (t) ! 468: Symbol t; ! 469: { ! 470: register char *p; ! 471: char *start; ! 472: Symbol s, m, outer; ! 473: Name n; ! 474: ! 475: if (t->name != nil) { ! 476: s = t; ! 477: } else { ! 478: start = t->symvalue.typeref; ! 479: outer = program; ! 480: p = findModuleMark(start); ! 481: while (p != nil) { ! 482: *p = '\0'; ! 483: n = identname(start, true); ! 484: find(m, n) where m->block == outer endfind(m); ! 485: if (m == nil) { ! 486: p = nil; ! 487: outer = nil; ! 488: s = nil; ! 489: } else { ! 490: outer = m; ! 491: start = p + 1; ! 492: p = findModuleMark(start); ! 493: } ! 494: } ! 495: if (outer != nil) { ! 496: n = identname(start, true); ! 497: find(s, n) where s->block == outer endfind(s); ! 498: } ! 499: } ! 500: if (s != nil and s->type != nil) { ! 501: t->name = s->type->name; ! 502: t->class = s->type->class; ! 503: t->type = s->type->type; ! 504: t->chain = s->type->chain; ! 505: t->symvalue = s->type->symvalue; ! 506: t->block = s->type->block; ! 507: } ! 508: } ! 509: ! 510: public integer regnum (s) ! 511: Symbol s; ! 512: { ! 513: integer r; ! 514: ! 515: checkref(s); ! 516: if (s->level < 0) { ! 517: r = s->symvalue.offset; ! 518: } else { ! 519: r = -1; ! 520: } ! 521: return r; ! 522: } ! 523: ! 524: public Symbol container(s) ! 525: Symbol s; ! 526: { ! 527: checkref(s); ! 528: return s->block; ! 529: } ! 530: ! 531: public Node constval(s) ! 532: Symbol s; ! 533: { ! 534: checkref(s); ! 535: if (s->class != CONST) { ! 536: error("[internal error: constval(non-CONST)]"); ! 537: } ! 538: return s->symvalue.constval; ! 539: } ! 540: ! 541: /* ! 542: * Return the object address of the given symbol. ! 543: * ! 544: * There are the following possibilities: ! 545: * ! 546: * globals - just take offset ! 547: * locals - take offset from locals base ! 548: * arguments - take offset from argument base ! 549: * register - offset is register number ! 550: */ ! 551: ! 552: #define isglobal(s) (s->level == 1) ! 553: #define islocaloff(s) (s->level >= 2 and s->symvalue.offset < 0) ! 554: #define isparamoff(s) (s->level >= 2 and s->symvalue.offset >= 0) ! 555: ! 556: public Address address (s, frame) ! 557: Symbol s; ! 558: Frame frame; ! 559: { ! 560: register Frame frp; ! 561: register Address addr; ! 562: register Symbol cur; ! 563: ! 564: checkref(s); ! 565: if (not isactive(s->block)) { ! 566: error("\"%s\" is not currently defined", symname(s)); ! 567: } else if (isglobal(s)) { ! 568: addr = s->symvalue.offset; ! 569: } else { ! 570: frp = frame; ! 571: if (frp == nil) { ! 572: cur = s->block; ! 573: while (cur != nil and cur->class == MODULE) { ! 574: cur = cur->block; ! 575: } ! 576: if (cur == nil) { ! 577: frp = nil; ! 578: } else { ! 579: frp = findframe(cur); ! 580: if (frp == nil) { ! 581: error("[internal error: unexpected nil frame for \"%s\"]", ! 582: symname(s) ! 583: ); ! 584: } ! 585: } ! 586: } ! 587: if (islocaloff(s)) { ! 588: addr = locals_base(frp) + s->symvalue.offset; ! 589: } else if (isparamoff(s)) { ! 590: addr = args_base(frp) + s->symvalue.offset; ! 591: } else if (isreg(s)) { ! 592: addr = savereg(s->symvalue.offset, frp); ! 593: } else { ! 594: panic("address: bad symbol \"%s\"", symname(s)); ! 595: } ! 596: } ! 597: return addr; ! 598: } ! 599: ! 600: /* ! 601: * Define a symbol used to access register values. ! 602: */ ! 603: ! 604: public defregname (n, r) ! 605: Name n; ! 606: integer r; ! 607: { ! 608: Symbol s; ! 609: ! 610: s = insert(n); ! 611: s->language = t_addr->language; ! 612: s->class = VAR; ! 613: s->level = -3; ! 614: s->type = t_addr; ! 615: s->symvalue.offset = r; ! 616: } ! 617: ! 618: /* ! 619: * Resolve an "abstract" type reference. ! 620: * ! 621: * It is possible in C to define a pointer to a type, but never define ! 622: * the type in a particular source file. Here we try to resolve ! 623: * the type definition. This is problematic, it is possible to ! 624: * have multiple, different definitions for the same name type. ! 625: */ ! 626: ! 627: public findtype(s) ! 628: Symbol s; ! 629: { ! 630: register Symbol t, u, prev; ! 631: ! 632: u = s; ! 633: prev = nil; ! 634: while (u != nil and u->class != BADUSE) { ! 635: if (u->name != nil) { ! 636: prev = u; ! 637: } ! 638: u = u->type; ! 639: } ! 640: if (prev == nil) { ! 641: error("couldn't find link to type reference"); ! 642: } ! 643: t = lookup(prev->name); ! 644: while (t != nil and ! 645: not ( ! 646: t != prev and t->name == prev->name and ! 647: t->block->class == MODULE and t->class == prev->class and ! 648: t->type != nil and t->type->type != nil and ! 649: t->type->type->class != BADUSE ! 650: ) ! 651: ) { ! 652: t = t->next_sym; ! 653: } ! 654: if (t == nil) { ! 655: error("couldn't resolve reference"); ! 656: } else { ! 657: prev->type = t->type; ! 658: } ! 659: } ! 660: ! 661: /* ! 662: * Find the size in bytes of the given type. ! 663: * ! 664: * This is probably the WRONG thing to do. The size should be kept ! 665: * as an attribute in the symbol information as is done for structures ! 666: * and fields. I haven't gotten around to cleaning this up yet. ! 667: */ ! 668: ! 669: #define MAXUCHAR 255 ! 670: #define MAXUSHORT 65535L ! 671: #define MINCHAR -128 ! 672: #define MAXCHAR 127 ! 673: #define MINSHORT -32768 ! 674: #define MAXSHORT 32767 ! 675: ! 676: public findbounds (u, lower, upper) ! 677: Symbol u; ! 678: long *lower, *upper; ! 679: { ! 680: Rangetype lbt, ubt; ! 681: long lb, ub; ! 682: ! 683: if (u->class == RANGE) { ! 684: lbt = u->symvalue.rangev.lowertype; ! 685: ubt = u->symvalue.rangev.uppertype; ! 686: lb = u->symvalue.rangev.lower; ! 687: ub = u->symvalue.rangev.upper; ! 688: if (lbt == R_ARG or lbt == R_TEMP) { ! 689: if (not getbound(u, lb, lbt, lower)) { ! 690: error("dynamic bounds not currently available"); ! 691: } ! 692: } else { ! 693: *lower = lb; ! 694: } ! 695: if (ubt == R_ARG or ubt == R_TEMP) { ! 696: if (not getbound(u, ub, ubt, upper)) { ! 697: error("dynamic bounds not currently available"); ! 698: } ! 699: } else { ! 700: *upper = ub; ! 701: } ! 702: } else if (u->class == SCAL) { ! 703: *lower = 0; ! 704: *upper = u->symvalue.iconval - 1; ! 705: } else { ! 706: error("[internal error: unexpected array bound type]"); ! 707: } ! 708: } ! 709: ! 710: public integer size(sym) ! 711: Symbol sym; ! 712: { ! 713: register Symbol s, t, u; ! 714: register integer nel, elsize; ! 715: long lower, upper; ! 716: integer r, off, len; ! 717: ! 718: t = sym; ! 719: checkref(t); ! 720: if (t->class == TYPEREF) { ! 721: resolveRef(t); ! 722: } ! 723: switch (t->class) { ! 724: case RANGE: ! 725: lower = t->symvalue.rangev.lower; ! 726: upper = t->symvalue.rangev.upper; ! 727: if (upper == 0 and lower > 0) { ! 728: /* real */ ! 729: r = lower; ! 730: } else if (lower > upper) { ! 731: /* unsigned long */ ! 732: r = sizeof(long); ! 733: } else if ( ! 734: (lower >= MINCHAR and upper <= MAXCHAR) or ! 735: (lower >= 0 and upper <= MAXUCHAR) ! 736: ) { ! 737: r = sizeof(char); ! 738: } else if ( ! 739: (lower >= MINSHORT and upper <= MAXSHORT) or ! 740: (lower >= 0 and upper <= MAXUSHORT) ! 741: ) { ! 742: r = sizeof(short); ! 743: } else { ! 744: r = sizeof(long); ! 745: } ! 746: break; ! 747: ! 748: case ARRAY: ! 749: elsize = size(t->type); ! 750: nel = 1; ! 751: for (t = t->chain; t != nil; t = t->chain) { ! 752: u = rtype(t); ! 753: findbounds(u, &lower, &upper); ! 754: nel *= (upper-lower+1); ! 755: } ! 756: r = nel*elsize; ! 757: break; ! 758: ! 759: case DYNARRAY: ! 760: r = (t->symvalue.ndims + 1) * sizeof(Word); ! 761: break; ! 762: ! 763: case SUBARRAY: ! 764: r = (2 * t->symvalue.ndims + 1) * sizeof(Word); ! 765: break; ! 766: ! 767: case REF: ! 768: case VAR: ! 769: r = size(t->type); ! 770: /* ! 771: * ! 772: if (r < sizeof(Word) and isparam(t)) { ! 773: r = sizeof(Word); ! 774: } ! 775: */ ! 776: break; ! 777: ! 778: case FVAR: ! 779: case CONST: ! 780: case TAG: ! 781: r = size(t->type); ! 782: break; ! 783: ! 784: case TYPE: ! 785: if (t->type->class == PTR and t->type->type->class == BADUSE) { ! 786: findtype(t); ! 787: } ! 788: r = size(t->type); ! 789: break; ! 790: ! 791: case FIELD: ! 792: off = t->symvalue.field.offset; ! 793: len = t->symvalue.field.length; ! 794: r = (off + len + 7) div 8 - (off div 8); ! 795: break; ! 796: ! 797: case RECORD: ! 798: case VARNT: ! 799: r = t->symvalue.offset; ! 800: if (r == 0 and t->chain != nil) { ! 801: panic("missing size information for record"); ! 802: } ! 803: break; ! 804: ! 805: case PTR: ! 806: case TYPEREF: ! 807: case FILET: ! 808: r = sizeof(Word); ! 809: break; ! 810: ! 811: case SCAL: ! 812: r = sizeof(Word); ! 813: /* ! 814: * ! 815: if (t->symvalue.iconval > 255) { ! 816: r = sizeof(short); ! 817: } else { ! 818: r = sizeof(char); ! 819: } ! 820: * ! 821: */ ! 822: break; ! 823: ! 824: case FPROC: ! 825: case FFUNC: ! 826: r = sizeof(Word); ! 827: break; ! 828: ! 829: case PROC: ! 830: case FUNC: ! 831: case MODULE: ! 832: case PROG: ! 833: r = sizeof(Symbol); ! 834: break; ! 835: ! 836: case SET: ! 837: u = rtype(t->type); ! 838: switch (u->class) { ! 839: case RANGE: ! 840: r = u->symvalue.rangev.upper - u->symvalue.rangev.lower + 1; ! 841: break; ! 842: ! 843: case SCAL: ! 844: r = u->symvalue.iconval; ! 845: break; ! 846: ! 847: default: ! 848: error("expected range for set base type"); ! 849: break; ! 850: } ! 851: r = (r + BITSPERBYTE - 1) div BITSPERBYTE; ! 852: break; ! 853: ! 854: /* ! 855: * These can happen in C (unfortunately) for unresolved type references ! 856: * Assume they are pointers. ! 857: */ ! 858: case BADUSE: ! 859: r = sizeof(Address); ! 860: break; ! 861: ! 862: default: ! 863: if (ord(t->class) > ord(TYPEREF)) { ! 864: panic("size: bad class (%d)", ord(t->class)); ! 865: } else { ! 866: fprintf(stderr, "can't compute size of a %s\n", classname(t)); ! 867: } ! 868: r = 0; ! 869: break; ! 870: } ! 871: return r; ! 872: } ! 873: ! 874: /* ! 875: * Return the size associated with a symbol that takes into account ! 876: * reference parameters. This might be better as the normal size function, but ! 877: * too many places already depend on it working the way it does. ! 878: */ ! 879: ! 880: public integer psize (s) ! 881: Symbol s; ! 882: { ! 883: integer r; ! 884: Symbol t; ! 885: ! 886: if (s->class == REF) { ! 887: t = rtype(s->type); ! 888: if (t->class == DYNARRAY) { ! 889: r = (t->symvalue.ndims + 1) * sizeof(Word); ! 890: } else if (t->class == SUBARRAY) { ! 891: r = (2 * t->symvalue.ndims + 1) * sizeof(Word); ! 892: } else { ! 893: r = sizeof(Word); ! 894: } ! 895: } else { ! 896: r = size(s); ! 897: } ! 898: return r; ! 899: } ! 900: ! 901: /* ! 902: * Test if a symbol is a parameter. This is true if there ! 903: * is a cycle from s->block to s via chain pointers. ! 904: */ ! 905: ! 906: public Boolean isparam(s) ! 907: Symbol s; ! 908: { ! 909: register Symbol t; ! 910: ! 911: t = s->block; ! 912: while (t != nil and t != s) { ! 913: t = t->chain; ! 914: } ! 915: return (Boolean) (t != nil); ! 916: } ! 917: ! 918: /* ! 919: * Test if a type is an open array parameter type. ! 920: */ ! 921: ! 922: public boolean isopenarray (type) ! 923: Symbol type; ! 924: { ! 925: Symbol t; ! 926: ! 927: t = rtype(type); ! 928: return (boolean) (t->class == DYNARRAY); ! 929: } ! 930: ! 931: /* ! 932: * Test if a symbol is a var parameter, i.e. has class REF. ! 933: */ ! 934: ! 935: public Boolean isvarparam(s) ! 936: Symbol s; ! 937: { ! 938: return (Boolean) (s->class == REF); ! 939: } ! 940: ! 941: /* ! 942: * Test if a symbol is a variable (actually any addressible quantity ! 943: * with do). ! 944: */ ! 945: ! 946: public Boolean isvariable(s) ! 947: Symbol s; ! 948: { ! 949: return (Boolean) (s->class == VAR or s->class == FVAR or s->class == REF); ! 950: } ! 951: ! 952: /* ! 953: * Test if a symbol is a constant. ! 954: */ ! 955: ! 956: public Boolean isconst(s) ! 957: Symbol s; ! 958: { ! 959: return (Boolean) (s->class == CONST); ! 960: } ! 961: ! 962: /* ! 963: * Test if a symbol is a module. ! 964: */ ! 965: ! 966: public Boolean ismodule(s) ! 967: register Symbol s; ! 968: { ! 969: return (Boolean) (s->class == MODULE); ! 970: } ! 971: ! 972: /* ! 973: * Mark a procedure or function as internal, meaning that it is called ! 974: * with a different calling sequence. ! 975: */ ! 976: ! 977: public markInternal (s) ! 978: Symbol s; ! 979: { ! 980: s->symvalue.funcv.intern = true; ! 981: } ! 982: ! 983: public boolean isinternal (s) ! 984: Symbol s; ! 985: { ! 986: return s->symvalue.funcv.intern; ! 987: } ! 988: ! 989: /* ! 990: * Decide if a field begins or ends on a bit rather than byte boundary. ! 991: */ ! 992: ! 993: public Boolean isbitfield(s) ! 994: register Symbol s; ! 995: { ! 996: boolean b; ! 997: register integer off, len; ! 998: register Symbol t; ! 999: ! 1000: off = s->symvalue.field.offset; ! 1001: len = s->symvalue.field.length; ! 1002: if ((off mod BITSPERBYTE) != 0 or (len mod BITSPERBYTE) != 0) { ! 1003: b = true; ! 1004: } else { ! 1005: t = rtype(s->type); ! 1006: b = (Boolean) ( ! 1007: (t->class == SCAL and len != (sizeof(int)*BITSPERBYTE)) or ! 1008: len != (size(t)*BITSPERBYTE) ! 1009: ); ! 1010: } ! 1011: return b; ! 1012: } ! 1013: ! 1014: private boolean primlang_typematch (t1, t2) ! 1015: Symbol t1, t2; ! 1016: { ! 1017: return (boolean) ( ! 1018: (t1 == t2) or ! 1019: ( ! 1020: t1->class == RANGE and t2->class == RANGE and ! 1021: t1->symvalue.rangev.lower == t2->symvalue.rangev.lower and ! 1022: t1->symvalue.rangev.upper == t2->symvalue.rangev.upper ! 1023: ) or ( ! 1024: t1->class == PTR and t2->class == RANGE and ! 1025: t2->symvalue.rangev.upper >= t2->symvalue.rangev.lower ! 1026: ) or ( ! 1027: t2->class == PTR and t1->class == RANGE and ! 1028: t1->symvalue.rangev.upper >= t1->symvalue.rangev.lower ! 1029: ) ! 1030: ); ! 1031: } ! 1032: ! 1033: /* ! 1034: * Test if two types match. ! 1035: * Equivalent names implies a match in any language. ! 1036: * ! 1037: * Special symbols must be handled with care. ! 1038: */ ! 1039: ! 1040: public Boolean compatible(t1, t2) ! 1041: register Symbol t1, t2; ! 1042: { ! 1043: Boolean b; ! 1044: Symbol rt1, rt2; ! 1045: ! 1046: if (t1 == t2) { ! 1047: b = true; ! 1048: } else if (t1 == nil or t2 == nil) { ! 1049: b = false; ! 1050: } else if (t1 == procsym) { ! 1051: b = isblock(t2); ! 1052: } else if (t2 == procsym) { ! 1053: b = isblock(t1); ! 1054: } else if (t1->language == primlang) { ! 1055: if (t2->language == primlang) { ! 1056: b = primlang_typematch(rtype(t1), rtype(t2)); ! 1057: } else { ! 1058: b = (boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2); ! 1059: } ! 1060: } else if (t2->language == primlang) { ! 1061: b = (boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2); ! 1062: } else if (t1->language == nil) { ! 1063: if (t2->language == nil) { ! 1064: b = false; ! 1065: } else { ! 1066: b = (boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2); ! 1067: } ! 1068: } else { ! 1069: b = (boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2); ! 1070: } ! 1071: return b; ! 1072: } ! 1073: ! 1074: /* ! 1075: * Check for a type of the given name. ! 1076: */ ! 1077: ! 1078: public Boolean istypename(type, name) ! 1079: Symbol type; ! 1080: String name; ! 1081: { ! 1082: register Symbol t; ! 1083: Boolean b; ! 1084: ! 1085: t = type; ! 1086: if (t == nil) { ! 1087: b = false; ! 1088: } else { ! 1089: b = (Boolean) ( ! 1090: t->class == TYPE and streq(ident(t->name), name) ! 1091: ); ! 1092: } ! 1093: return b; ! 1094: } ! 1095: ! 1096: /* ! 1097: * Determine if a (value) parameter should actually be passed by address. ! 1098: */ ! 1099: ! 1100: public boolean passaddr (p, exprtype) ! 1101: Symbol p, exprtype; ! 1102: { ! 1103: boolean b; ! 1104: Language def; ! 1105: ! 1106: if (p == nil) { ! 1107: def = findlanguage(".c"); ! 1108: b = (boolean) (*language_op(def, L_PASSADDR))(p, exprtype); ! 1109: } else if (p->language == nil or p->language == primlang) { ! 1110: b = false; ! 1111: } else if (isopenarray(p->type)) { ! 1112: b = true; ! 1113: } else { ! 1114: b = (boolean) (*language_op(p->language, L_PASSADDR))(p, exprtype); ! 1115: } ! 1116: return b; ! 1117: } ! 1118: ! 1119: /* ! 1120: * Test if the name of a symbol is uniquely defined or not. ! 1121: */ ! 1122: ! 1123: public Boolean isambiguous(s) ! 1124: register Symbol s; ! 1125: { ! 1126: register Symbol t; ! 1127: ! 1128: find(t, s->name) where t != s endfind(t); ! 1129: return (Boolean) (t != nil); ! 1130: } ! 1131: ! 1132: typedef char *Arglist; ! 1133: ! 1134: #define nextarg(type) ((type *) (ap += sizeof(type)))[-1] ! 1135: ! 1136: private Symbol mkstring(); ! 1137: ! 1138: /* ! 1139: * Determine the type of a parse tree. ! 1140: * ! 1141: * Also make some symbol-dependent changes to the tree such as ! 1142: * removing indirection for constant or register symbols. ! 1143: */ ! 1144: ! 1145: public assigntypes (p) ! 1146: register Node p; ! 1147: { ! 1148: register Node p1; ! 1149: register Symbol s; ! 1150: ! 1151: switch (p->op) { ! 1152: case O_SYM: ! 1153: p->nodetype = p->value.sym; ! 1154: break; ! 1155: ! 1156: case O_LCON: ! 1157: p->nodetype = t_int; ! 1158: break; ! 1159: ! 1160: case O_CCON: ! 1161: p->nodetype = t_char; ! 1162: break; ! 1163: ! 1164: case O_FCON: ! 1165: p->nodetype = t_real; ! 1166: break; ! 1167: ! 1168: case O_SCON: ! 1169: p->nodetype = mkstring(p->value.scon); ! 1170: break; ! 1171: ! 1172: case O_INDIR: ! 1173: p1 = p->value.arg[0]; ! 1174: s = rtype(p1->nodetype); ! 1175: if (s->class != PTR) { ! 1176: beginerrmsg(); ! 1177: fprintf(stderr, "\""); ! 1178: prtree(stderr, p1); ! 1179: fprintf(stderr, "\" is not a pointer"); ! 1180: enderrmsg(); ! 1181: } ! 1182: p->nodetype = rtype(p1->nodetype)->type; ! 1183: break; ! 1184: ! 1185: case O_DOT: ! 1186: p->nodetype = p->value.arg[1]->value.sym; ! 1187: break; ! 1188: ! 1189: case O_RVAL: ! 1190: p1 = p->value.arg[0]; ! 1191: p->nodetype = p1->nodetype; ! 1192: if (p1->op == O_SYM) { ! 1193: if (p1->nodetype->class == PROC or p->nodetype->class == FUNC) { ! 1194: p->op = p1->op; ! 1195: p->value.sym = p1->value.sym; ! 1196: p->nodetype = p1->nodetype; ! 1197: dispose(p1); ! 1198: } else if (p1->value.sym->class == CONST) { ! 1199: p->op = p1->op; ! 1200: p->value = p1->value; ! 1201: p->nodetype = p1->nodetype; ! 1202: dispose(p1); ! 1203: } else if (isreg(p1->value.sym)) { ! 1204: p->op = O_SYM; ! 1205: p->value.sym = p1->value.sym; ! 1206: dispose(p1); ! 1207: } ! 1208: } else if (p1->op == O_INDIR and p1->value.arg[0]->op == O_SYM) { ! 1209: s = p1->value.arg[0]->value.sym; ! 1210: if (isreg(s)) { ! 1211: p1->op = O_SYM; ! 1212: dispose(p1->value.arg[0]); ! 1213: p1->value.sym = s; ! 1214: p1->nodetype = s; ! 1215: } ! 1216: } ! 1217: break; ! 1218: ! 1219: case O_COMMA: ! 1220: p->nodetype = p->value.arg[0]->nodetype; ! 1221: break; ! 1222: ! 1223: case O_CALLPROC: ! 1224: case O_CALL: ! 1225: p1 = p->value.arg[0]; ! 1226: p->nodetype = rtype(p1->nodetype)->type; ! 1227: break; ! 1228: ! 1229: case O_TYPERENAME: ! 1230: p->nodetype = p->value.arg[1]->nodetype; ! 1231: break; ! 1232: ! 1233: case O_ITOF: ! 1234: p->nodetype = t_real; ! 1235: break; ! 1236: ! 1237: case O_NEG: ! 1238: s = p->value.arg[0]->nodetype; ! 1239: if (not compatible(s, t_int)) { ! 1240: if (not compatible(s, t_real)) { ! 1241: beginerrmsg(); ! 1242: fprintf(stderr, "\""); ! 1243: prtree(stderr, p->value.arg[0]); ! 1244: fprintf(stderr, "\" is improper type"); ! 1245: enderrmsg(); ! 1246: } else { ! 1247: p->op = O_NEGF; ! 1248: } ! 1249: } ! 1250: p->nodetype = s; ! 1251: break; ! 1252: ! 1253: case O_ADD: ! 1254: case O_SUB: ! 1255: case O_MUL: ! 1256: binaryop(p, nil); ! 1257: break; ! 1258: ! 1259: case O_LT: ! 1260: case O_LE: ! 1261: case O_GT: ! 1262: case O_GE: ! 1263: case O_EQ: ! 1264: case O_NE: ! 1265: binaryop(p, t_boolean); ! 1266: break; ! 1267: ! 1268: case O_DIVF: ! 1269: convert(&(p->value.arg[0]), t_real, O_ITOF); ! 1270: convert(&(p->value.arg[1]), t_real, O_ITOF); ! 1271: p->nodetype = t_real; ! 1272: break; ! 1273: ! 1274: case O_DIV: ! 1275: case O_MOD: ! 1276: convert(&(p->value.arg[0]), t_int, O_NOP); ! 1277: convert(&(p->value.arg[1]), t_int, O_NOP); ! 1278: p->nodetype = t_int; ! 1279: break; ! 1280: ! 1281: case O_AND: ! 1282: case O_OR: ! 1283: chkboolean(p->value.arg[0]); ! 1284: chkboolean(p->value.arg[1]); ! 1285: p->nodetype = t_boolean; ! 1286: break; ! 1287: ! 1288: case O_QLINE: ! 1289: p->nodetype = t_int; ! 1290: break; ! 1291: ! 1292: default: ! 1293: p->nodetype = nil; ! 1294: break; ! 1295: } ! 1296: } ! 1297: ! 1298: /* ! 1299: * Process a binary arithmetic or relational operator. ! 1300: * Convert from integer to real if necessary. ! 1301: */ ! 1302: ! 1303: private binaryop (p, t) ! 1304: Node p; ! 1305: Symbol t; ! 1306: { ! 1307: Node p1, p2; ! 1308: Boolean t1real, t2real; ! 1309: Symbol t1, t2; ! 1310: ! 1311: p1 = p->value.arg[0]; ! 1312: p2 = p->value.arg[1]; ! 1313: t1 = rtype(p1->nodetype); ! 1314: t2 = rtype(p2->nodetype); ! 1315: t1real = compatible(t1, t_real); ! 1316: t2real = compatible(t2, t_real); ! 1317: if (t1real or t2real) { ! 1318: p->op = (Operator) (ord(p->op) + 1); ! 1319: if (not t1real) { ! 1320: p->value.arg[0] = build(O_ITOF, p1); ! 1321: } else if (not t2real) { ! 1322: p->value.arg[1] = build(O_ITOF, p2); ! 1323: } ! 1324: p->nodetype = t_real; ! 1325: } else { ! 1326: if (size(p1->nodetype) > sizeof(integer)) { ! 1327: beginerrmsg(); ! 1328: fprintf(stderr, "operation not defined on \""); ! 1329: prtree(stderr, p1); ! 1330: fprintf(stderr, "\""); ! 1331: enderrmsg(); ! 1332: } else if (size(p2->nodetype) > sizeof(integer)) { ! 1333: beginerrmsg(); ! 1334: fprintf(stderr, "operation not defined on \""); ! 1335: prtree(stderr, p2); ! 1336: fprintf(stderr, "\""); ! 1337: enderrmsg(); ! 1338: } ! 1339: p->nodetype = t_int; ! 1340: } ! 1341: if (t != nil) { ! 1342: p->nodetype = t; ! 1343: } ! 1344: } ! 1345: ! 1346: /* ! 1347: * Convert a tree to a type via a conversion operator; ! 1348: * if this isn't possible generate an error. ! 1349: * ! 1350: * Note the tree is call by address, hence the #define below. ! 1351: */ ! 1352: ! 1353: private convert(tp, typeto, op) ! 1354: Node *tp; ! 1355: Symbol typeto; ! 1356: Operator op; ! 1357: { ! 1358: Node tree; ! 1359: Symbol s, t; ! 1360: ! 1361: tree = *tp; ! 1362: s = rtype(tree->nodetype); ! 1363: t = rtype(typeto); ! 1364: if (compatible(t, t_real) and compatible(s, t_int)) { ! 1365: tree = build(op, tree); ! 1366: } else if (not compatible(s, t)) { ! 1367: beginerrmsg(); ! 1368: fprintf(stderr, "expected integer or real, found \""); ! 1369: prtree(stderr, tree); ! 1370: fprintf(stderr, "\""); ! 1371: enderrmsg(); ! 1372: } else if (op != O_NOP and s != t) { ! 1373: tree = build(op, tree); ! 1374: } ! 1375: *tp = tree; ! 1376: } ! 1377: ! 1378: /* ! 1379: * Construct a node for the dot operator. ! 1380: * ! 1381: * If the left operand is not a record, but rather a procedure ! 1382: * or function, then we interpret the "." as referencing an ! 1383: * "invisible" variable; i.e. a variable within a dynamically ! 1384: * active block but not within the static scope of the current procedure. ! 1385: */ ! 1386: ! 1387: public Node dot(record, fieldname) ! 1388: Node record; ! 1389: Name fieldname; ! 1390: { ! 1391: register Node rec, p; ! 1392: register Symbol s, t; ! 1393: ! 1394: rec = record; ! 1395: if (isblock(rec->nodetype)) { ! 1396: find(s, fieldname) where ! 1397: s->block == rec->nodetype and ! 1398: s->class != FIELD ! 1399: endfind(s); ! 1400: if (s == nil) { ! 1401: beginerrmsg(); ! 1402: fprintf(stderr, "\"%s\" is not defined in ", ident(fieldname)); ! 1403: printname(stderr, rec->nodetype); ! 1404: enderrmsg(); ! 1405: } ! 1406: p = new(Node); ! 1407: p->op = O_SYM; ! 1408: p->value.sym = s; ! 1409: p->nodetype = s; ! 1410: } else { ! 1411: p = rec; ! 1412: t = rtype(p->nodetype); ! 1413: if (t->class == PTR) { ! 1414: s = findfield(fieldname, t->type); ! 1415: } else { ! 1416: s = findfield(fieldname, t); ! 1417: } ! 1418: if (s == nil) { ! 1419: beginerrmsg(); ! 1420: fprintf(stderr, "\"%s\" is not a field in ", ident(fieldname)); ! 1421: prtree(stderr, rec); ! 1422: enderrmsg(); ! 1423: } ! 1424: if (t->class != PTR or isreg(rec->nodetype)) { ! 1425: p = unrval(p); ! 1426: } ! 1427: p->nodetype = t_addr; ! 1428: p = build(O_DOT, p, build(O_SYM, s)); ! 1429: } ! 1430: return build(O_RVAL, p); ! 1431: } ! 1432: ! 1433: /* ! 1434: * Return a tree corresponding to an array reference and do the ! 1435: * error checking. ! 1436: */ ! 1437: ! 1438: public Node subscript(a, slist) ! 1439: Node a, slist; ! 1440: { ! 1441: Symbol t; ! 1442: Node p; ! 1443: ! 1444: t = rtype(a->nodetype); ! 1445: if (t->language == nil or t->language == primlang) { ! 1446: p = (Node) (*language_op(findlanguage(".s"), L_BUILDAREF))(a, slist); ! 1447: } else { ! 1448: p = (Node) (*language_op(t->language, L_BUILDAREF))(a, slist); ! 1449: } ! 1450: return build(O_RVAL, p); ! 1451: } ! 1452: ! 1453: /* ! 1454: * Evaluate a subscript index. ! 1455: */ ! 1456: ! 1457: public int evalindex(s, base, i) ! 1458: Symbol s; ! 1459: Address base; ! 1460: long i; ! 1461: { ! 1462: Symbol t; ! 1463: int r; ! 1464: ! 1465: t = rtype(s); ! 1466: if (t->language == nil or t->language == primlang) { ! 1467: r = ((*language_op(findlanguage(".s"), L_EVALAREF)) (s, base, i)); ! 1468: } else { ! 1469: r = ((*language_op(t->language, L_EVALAREF)) (s, base, i)); ! 1470: } ! 1471: return r; ! 1472: } ! 1473: ! 1474: /* ! 1475: * Check to see if a tree is boolean-valued, if not it's an error. ! 1476: */ ! 1477: ! 1478: public chkboolean(p) ! 1479: register Node p; ! 1480: { ! 1481: if (p->nodetype != t_boolean) { ! 1482: beginerrmsg(); ! 1483: fprintf(stderr, "found "); ! 1484: prtree(stderr, p); ! 1485: fprintf(stderr, ", expected boolean expression"); ! 1486: enderrmsg(); ! 1487: } ! 1488: } ! 1489: ! 1490: /* ! 1491: * Construct a node for the type of a string. ! 1492: */ ! 1493: ! 1494: private Symbol mkstring(str) ! 1495: String str; ! 1496: { ! 1497: register Symbol s; ! 1498: ! 1499: s = newSymbol(nil, 0, ARRAY, t_char, nil); ! 1500: s->chain = newSymbol(nil, 0, RANGE, t_int, nil); ! 1501: s->chain->language = s->language; ! 1502: s->chain->symvalue.rangev.lower = 1; ! 1503: s->chain->symvalue.rangev.upper = strlen(str) + 1; ! 1504: return s; ! 1505: } ! 1506: ! 1507: /* ! 1508: * Free up the space allocated for a string type. ! 1509: */ ! 1510: ! 1511: public unmkstring(s) ! 1512: Symbol s; ! 1513: { ! 1514: dispose(s->chain); ! 1515: } ! 1516: ! 1517: /* ! 1518: * Figure out the "current" variable or function being referred to ! 1519: * by the name n. ! 1520: */ ! 1521: ! 1522: private boolean stwhich(), dynwhich(); ! 1523: ! 1524: public Symbol which (n) ! 1525: Name n; ! 1526: { ! 1527: Symbol s; ! 1528: ! 1529: s = lookup(n); ! 1530: if (s == nil) { ! 1531: error("\"%s\" is not defined", ident(n)); ! 1532: } else if (not stwhich(&s) and isambiguous(s) and not dynwhich(&s)) { ! 1533: printf("[using "); ! 1534: printname(stdout, s); ! 1535: printf("]\n"); ! 1536: } ! 1537: return s; ! 1538: } ! 1539: ! 1540: /* ! 1541: * Static search. ! 1542: */ ! 1543: ! 1544: private boolean stwhich (var_s) ! 1545: Symbol *var_s; ! 1546: { ! 1547: Name n; /* name of desired symbol */ ! 1548: Symbol s; /* iteration variable for symbols with name n */ ! 1549: Symbol f; /* iteration variable for blocks containing s */ ! 1550: integer count; /* number of levels from s->block to curfunc */ ! 1551: Symbol t; /* current best answer for stwhich(n) */ ! 1552: integer mincount; /* relative level for current best answer (t) */ ! 1553: boolean b; /* return value, true if symbol found */ ! 1554: ! 1555: s = *var_s; ! 1556: n = s->name; ! 1557: t = s; ! 1558: mincount = 10000; /* force first match to set mincount */ ! 1559: do { ! 1560: if (s->name == n and s->class != FIELD and s->class != TAG) { ! 1561: f = curfunc; ! 1562: count = 0; ! 1563: while (f != nil and f != s->block) { ! 1564: ++count; ! 1565: f = f->block; ! 1566: } ! 1567: if (f != nil and count < mincount) { ! 1568: t = s; ! 1569: mincount = count; ! 1570: b = true; ! 1571: } ! 1572: } ! 1573: s = s->next_sym; ! 1574: } while (s != nil); ! 1575: if (mincount != 10000) { ! 1576: *var_s = t; ! 1577: b = true; ! 1578: } else { ! 1579: b = false; ! 1580: } ! 1581: return b; ! 1582: } ! 1583: ! 1584: /* ! 1585: * Dynamic search. ! 1586: */ ! 1587: ! 1588: private boolean dynwhich (var_s) ! 1589: Symbol *var_s; ! 1590: { ! 1591: Name n; /* name of desired symbol */ ! 1592: Symbol s; /* iteration variable for possible symbols */ ! 1593: Symbol f; /* iteration variable for active functions */ ! 1594: Frame frp; /* frame associated with stack walk */ ! 1595: boolean b; /* return value */ ! 1596: ! 1597: f = curfunc; ! 1598: frp = curfuncframe(); ! 1599: n = (*var_s)->name; ! 1600: b = false; ! 1601: if (frp != nil) { ! 1602: frp = nextfunc(frp, &f); ! 1603: while (frp != nil) { ! 1604: s = *var_s; ! 1605: while (s != nil and ! 1606: ( ! 1607: s->name != n or s->block != f or ! 1608: s->class == FIELD or s->class == TAG ! 1609: ) ! 1610: ) { ! 1611: s = s->next_sym; ! 1612: } ! 1613: if (s != nil) { ! 1614: *var_s = s; ! 1615: b = true; ! 1616: break; ! 1617: } ! 1618: if (f == program) { ! 1619: break; ! 1620: } ! 1621: frp = nextfunc(frp, &f); ! 1622: } ! 1623: } ! 1624: return b; ! 1625: } ! 1626: ! 1627: /* ! 1628: * Find the symbol that has the same name and scope as the ! 1629: * given symbol but is of the given field. Return nil if there is none. ! 1630: */ ! 1631: ! 1632: public Symbol findfield (fieldname, record) ! 1633: Name fieldname; ! 1634: Symbol record; ! 1635: { ! 1636: register Symbol t; ! 1637: ! 1638: t = rtype(record)->chain; ! 1639: while (t != nil and t->name != fieldname) { ! 1640: t = t->chain; ! 1641: } ! 1642: return t; ! 1643: } ! 1644: ! 1645: public Boolean getbound(s,off,type,valp) ! 1646: Symbol s; ! 1647: int off; ! 1648: Rangetype type; ! 1649: int *valp; ! 1650: { ! 1651: Frame frp; ! 1652: Address addr; ! 1653: Symbol cur; ! 1654: ! 1655: if (not isactive(s->block)) { ! 1656: return(false); ! 1657: } ! 1658: cur = s->block; ! 1659: while (cur != nil and cur->class == MODULE) { /* WHY*/ ! 1660: cur = cur->block; ! 1661: } ! 1662: if(cur == nil) { ! 1663: cur = whatblock(pc); ! 1664: } ! 1665: frp = findframe(cur); ! 1666: if (frp == nil) { ! 1667: return(false); ! 1668: } ! 1669: if(type == R_TEMP) addr = locals_base(frp) + off; ! 1670: else if (type == R_ARG) addr = args_base(frp) + off; ! 1671: else return(false); ! 1672: dread(valp,addr,sizeof(long)); ! 1673: return(true); ! 1674: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.