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