Annotation of 43BSD/ucb/dbx/symbols.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.