Annotation of 43BSDReno/pgrm/dbx/symbols.c, revision 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.