Annotation of 43BSDReno/pgrm/dbx/symbols.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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