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

unix.superglobalmegacorp.com

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