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: }

Defined functions

assigntypes defined in line 1145; used 1 times
binaryop defined in line 1303; used 2 times
chkboolean defined in line 1478; used 3 times
constval defined in line 531; used 7 times
convert defined in line 1353; used 4 times
defregname defined in line 604; used 5 times
delete defined in line 290; used 3 times
dot defined in line 1387; used 6 times
dumpvars defined in line 322; used 4 times
dynwhich defined in line 1588; used 2 times
evalindex defined in line 1457; used 1 times
findModuleMark defined in line 437; used 2 times
findbounds defined in line 676; used 3 times
findfield defined in line 1632; used 2 times
findtype defined in line 627; used 3 times
getbound defined in line 1645; used 9 times
isambiguous defined in line 1123; used 3 times
isbitfield defined in line 993; used 3 times
isconst defined in line 956; used 1 times
isinternal defined in line 983; used 2 times
isopenarray defined in line 922; used 6 times
isvariable defined in line 946; used 1 times
maketype defined in line 348; used 5 times
markInternal defined in line 977; used 1 times
mkstring defined in line 1494; used 2 times
passaddr defined in line 1100; used 1 times
primlang_typematch defined in line 1014; used 1 times
psize defined in line 880; used 1 times
regnum defined in line 510; used 2 times
resolveRef defined in line 467; used 10 times
rtype defined in line 407; used 73 times
stwhich defined in line 1544; used 2 times
subscript defined in line 1438; used 2 times
symbol_alloc defined in line 174; used 7 times
symbol_dump defined in line 189; never used
symbol_free defined in line 209; used 1 times
symbols_init defined in line 377; used 2 times
unmkstring defined in line 1511; used 1 times
which defined in line 1524; used 2 times

Defined variables

curfunc defined in line 111; used 2 times
hashtab defined in line 156; used 8 times
nleft defined in line 172; used 5 times
program defined in line 110; used 2 times
public defined in line 189; never used
rcsid defined in line 11; never used
sccsid defined in line 8; never used
sympool defined in line 171; used 5 times
t_addr defined in line 108; used 8 times
t_boolean defined in line 103; used 8 times
t_char defined in line 104; used 3 times
t_int defined in line 105; used 11 times
t_nil defined in line 107; used 1 times
t_real defined in line 106; used 11 times

Defined struct's

Symbol defined in line 52; used 3 times
Sympool defined in line 166; used 2 times
  • in line 168(2)

Defined typedef's

Arglist defined in line 1132; never used
Symbol defined in line 32; used 102 times
Sympool defined in line 169; used 4 times

Defined macros

HASHTABLESIZE defined in line 154; used 5 times
MAXCHAR defined in line 672; used 1 times
MAXSHORT defined in line 674; used 1 times
MAXUCHAR defined in line 669; used 1 times
MAXUSHORT defined in line 670; used 1 times
MINCHAR defined in line 671; used 1 times
MINSHORT defined in line 673; used 1 times
SYMBLOCKSIZE defined in line 164; used 2 times
codeloc defined in line 116; never used
endfind defined in line 143; used 4 times
find defined in line 136; used 4 times
hash defined in line 158; used 3 times
isblock defined in line 117; used 3 times
isglobal defined in line 552; used 1 times
isinline defined in line 126; never used
islocaloff defined in line 553; used 1 times
isparamoff defined in line 554; used 1 times
isreg defined in line 128; used 4 times
isroutine defined in line 121; never used
nextarg defined in line 1134; never used
nosource defined in line 125; never used
symname defined in line 115; used 6 times
where defined in line 141; used 4 times
Last modified: 1985-09-06
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4520
Valid CSS Valid XHTML 1.0 Strict