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

1.1     ! root        1: /* Copyright (c) 1982 Regents of the University of California */
        !             2: 
        !             3: static char sccsid[] = "@(#)symbols.c 1.11 8/16/83";
        !             4: 
        !             5: /*
        !             6:  * Symbol management.
        !             7:  */
        !             8: 
        !             9: #include "defs.h"
        !            10: #include "symbols.h"
        !            11: #include "languages.h"
        !            12: #include "printsym.h"
        !            13: #include "tree.h"
        !            14: #include "operators.h"
        !            15: #include "eval.h"
        !            16: #include "mappings.h"
        !            17: #include "events.h"
        !            18: #include "process.h"
        !            19: #include "runtime.h"
        !            20: #include "machine.h"
        !            21: #include "names.h"
        !            22: 
        !            23: #ifndef public
        !            24: typedef struct Symbol *Symbol;
        !            25: 
        !            26: #include "machine.h"
        !            27: #include "names.h"
        !            28: #include "languages.h"
        !            29: 
        !            30: /*
        !            31:  * Symbol classes
        !            32:  */
        !            33: 
        !            34: typedef enum {
        !            35:     BADUSE, CONST, TYPE, VAR, ARRAY, PTRFILE, RECORD, FIELD,
        !            36:     PROC, FUNC, FVAR, REF, PTR, FILET, SET, RANGE, 
        !            37:     LABEL, WITHPTR, SCAL, STR, PROG, IMPROPER, VARNT,
        !            38:     FPROC, FFUNC, MODULE, TAG, COMMON, TYPEREF
        !            39: } Symclass;
        !            40: 
        !            41: typedef enum { R_CONST, R_TEMP, R_ARG, R_ADJUST } Rangetype; 
        !            42: 
        !            43: struct Symbol {
        !            44:     Name name;
        !            45:     Language language;
        !            46:     Symclass class : 8;
        !            47:     Integer level : 8;
        !            48:     Symbol type;
        !            49:     Symbol chain;
        !            50:     union {
        !            51:        int offset;             /* variable address */
        !            52:        long iconval;           /* integer constant value */
        !            53:        double fconval;         /* floating constant value */
        !            54:        struct {                /* field offset and size (both in bits) */
        !            55:            int offset;
        !            56:            int length;
        !            57:        } field;
        !            58:        struct {                /* common offset and chain; used to relocate */
        !            59:            int offset;         /* vars in global BSS */
        !            60:            Symbol chain;
        !            61:        } common;
        !            62:        struct {                /* range bounds */
        !            63:             Rangetype lowertype : 16; 
        !            64:             Rangetype uppertype : 16;  
        !            65:            long lower;
        !            66:            long upper;
        !            67:        } rangev;
        !            68:        struct {
        !            69:            int offset : 16;    /* offset for of function value */
        !            70:            Boolean src : 8;    /* true if there is source line info */
        !            71:            Boolean inline : 8; /* true if no separate act. rec. */
        !            72:            Address beginaddr;  /* address of function code */
        !            73:        } funcv;
        !            74:        struct {                /* variant record info */
        !            75:            int size;
        !            76:            Symbol vtorec;
        !            77:            Symbol vtag;
        !            78:        } varnt;
        !            79:     } symvalue;
        !            80:     Symbol block;              /* symbol containing this symbol */
        !            81:     Symbol next_sym;           /* hash chain */
        !            82: };
        !            83: 
        !            84: /*
        !            85:  * Basic types.
        !            86:  */
        !            87: 
        !            88: Symbol t_boolean;
        !            89: Symbol t_char;
        !            90: Symbol t_int;
        !            91: Symbol t_real;
        !            92: Symbol t_nil;
        !            93: 
        !            94: Symbol program;
        !            95: Symbol curfunc;
        !            96: 
        !            97: #define symname(s) ident(s->name)
        !            98: #define codeloc(f) ((f)->symvalue.funcv.beginaddr)
        !            99: #define isblock(s) (Boolean) ( \
        !           100:     s->class == FUNC or s->class == PROC or \
        !           101:     s->class == MODULE or s->class == PROG \
        !           102: )
        !           103: 
        !           104: #define nosource(f) (not (f)->symvalue.funcv.src)
        !           105: #define isinline(f) ((f)->symvalue.funcv.inline)
        !           106: 
        !           107: #include "tree.h"
        !           108: 
        !           109: /*
        !           110:  * Some macros to make finding a symbol with certain attributes.
        !           111:  */
        !           112: 
        !           113: #define find(s, withname) \
        !           114: { \
        !           115:     s = lookup(withname); \
        !           116:     while (s != nil and not (s->name == (withname) and
        !           117: 
        !           118: #define where /* qualification */
        !           119: 
        !           120: #define endfind(s) )) { \
        !           121:        s = s->next_sym; \
        !           122:     } \
        !           123: }
        !           124: 
        !           125: #endif
        !           126: 
        !           127: /*
        !           128:  * Symbol table structure currently does not support deletions.
        !           129:  */
        !           130: 
        !           131: #define HASHTABLESIZE 2003
        !           132: 
        !           133: private Symbol hashtab[HASHTABLESIZE];
        !           134: 
        !           135: #define hash(name) ((((unsigned) name) >> 2) mod HASHTABLESIZE)
        !           136: 
        !           137: /*
        !           138:  * Allocate a new symbol.
        !           139:  */
        !           140: 
        !           141: #define SYMBLOCKSIZE 100
        !           142: 
        !           143: typedef struct Sympool {
        !           144:     struct Symbol sym[SYMBLOCKSIZE];
        !           145:     struct Sympool *prevpool;
        !           146: } *Sympool;
        !           147: 
        !           148: private Sympool sympool = nil;
        !           149: private Integer nleft = 0;
        !           150: 
        !           151: public Symbol symbol_alloc()
        !           152: {
        !           153:     register Sympool newpool;
        !           154: 
        !           155:     if (nleft <= 0) {
        !           156:        newpool = new(Sympool);
        !           157:        bzero(newpool, sizeof(newpool));
        !           158:        newpool->prevpool = sympool;
        !           159:        sympool = newpool;
        !           160:        nleft = SYMBLOCKSIZE;
        !           161:     }
        !           162:     --nleft;
        !           163:     return &(sympool->sym[nleft]);
        !           164: }
        !           165: 
        !           166: 
        !           167: public symbol_dump(func)
        !           168: Symbol func;
        !           169: {
        !           170:     register Symbol s;
        !           171:     register Integer i;
        !           172: 
        !           173:     printf(" symbols in %s \n",symname(func));
        !           174:     for (i = 0; i< HASHTABLESIZE; i++) {
        !           175:        for (s = hashtab[i]; s != nil; s = s->next_sym) {
        !           176:            if (s->block == func) {
        !           177:                psym(s);
        !           178:            }
        !           179:        }
        !           180:     }
        !           181: }
        !           182: 
        !           183: /*
        !           184:  * Free all the symbols currently allocated.
        !           185:  */
        !           186: 
        !           187: public symbol_free()
        !           188: {
        !           189:     Sympool s, t;
        !           190:     register Integer i;
        !           191: 
        !           192:     s = sympool;
        !           193:     while (s != nil) {
        !           194:        t = s->prevpool;
        !           195:        dispose(s);
        !           196:        s = t;
        !           197:     }
        !           198:     for (i = 0; i < HASHTABLESIZE; i++) {
        !           199:        hashtab[i] = nil;
        !           200:     }
        !           201:     sympool = nil;
        !           202:     nleft = 0;
        !           203: }
        !           204: 
        !           205: /*
        !           206:  * Create a new symbol with the given attributes.
        !           207:  */
        !           208: 
        !           209: public Symbol newSymbol(name, blevel, class, type, chain)
        !           210: Name name;
        !           211: Integer blevel;
        !           212: Symclass class;
        !           213: Symbol type;
        !           214: Symbol chain;
        !           215: {
        !           216:     register Symbol s;
        !           217: 
        !           218:     s = symbol_alloc();
        !           219:     s->name = name;
        !           220:     s->level = blevel;
        !           221:     s->class = class;
        !           222:     s->type = type;
        !           223:     s->chain = chain;
        !           224:     return s;
        !           225: }
        !           226: 
        !           227: /*
        !           228:  * Insert a symbol into the hash table.
        !           229:  */
        !           230: 
        !           231: public Symbol insert(name)
        !           232: Name name;
        !           233: {
        !           234:     register Symbol s;
        !           235:     register unsigned int h;
        !           236: 
        !           237:     h = hash(name);
        !           238:     s = symbol_alloc();
        !           239:     s->name = name;
        !           240:     s->next_sym = hashtab[h];
        !           241:     hashtab[h] = s;
        !           242:     return s;
        !           243: }
        !           244: 
        !           245: /*
        !           246:  * Symbol lookup.
        !           247:  */
        !           248: 
        !           249: public Symbol lookup(name)
        !           250: Name name;
        !           251: {
        !           252:     register Symbol s;
        !           253:     register unsigned int h;
        !           254: 
        !           255:     h = hash(name);
        !           256:     s = hashtab[h];
        !           257:     while (s != nil and s->name != name) {
        !           258:        s = s->next_sym;
        !           259:     }
        !           260:     return s;
        !           261: }
        !           262: 
        !           263: /*
        !           264:  * Dump out all the variables associated with the given
        !           265:  * procedure, function, or program at the given recursive level.
        !           266:  *
        !           267:  * This is quite inefficient.  We traverse the entire symbol table
        !           268:  * each time we're called.  The assumption is that this routine
        !           269:  * won't be called frequently enough to merit improved performance.
        !           270:  */
        !           271: 
        !           272: public dumpvars(f, frame)
        !           273: Symbol f;
        !           274: Frame frame;
        !           275: {
        !           276:     register Integer i;
        !           277:     register Symbol s;
        !           278: 
        !           279:     for (i = 0; i < HASHTABLESIZE; i++) {
        !           280:        for (s = hashtab[i]; s != nil; s = s->next_sym) {
        !           281:            if (container(s) == f) {
        !           282:                if (should_print(s)) {
        !           283:                    printv(s, frame);
        !           284:                    putchar('\n');
        !           285:                } else if (s->class == MODULE) {
        !           286:                    dumpvars(s, frame);
        !           287:                }
        !           288:            }
        !           289:        }
        !           290:     }
        !           291: }
        !           292: 
        !           293: /*
        !           294:  * Create base types.
        !           295:  */
        !           296: 
        !           297: public symbols_init()
        !           298: {
        !           299:     t_boolean = maketype("$boolean", 0L, 1L);
        !           300:     t_int = maketype("$integer", 0x80000000L, 0x7fffffffL);
        !           301:     t_char = maketype("$char", 0L, 127L);
        !           302:     t_real = maketype("$real", 8L, 0L);
        !           303:     t_nil = maketype("$nil", 0L, 0L);
        !           304: }
        !           305: 
        !           306: /*
        !           307:  * Create a builtin type.
        !           308:  * Builtin types are circular in that btype->type->type = btype.
        !           309:  */
        !           310: 
        !           311: public Symbol maketype(name, lower, upper)
        !           312: String name;
        !           313: long lower;
        !           314: long upper;
        !           315: {
        !           316:     register Symbol s;
        !           317: 
        !           318:     s = newSymbol(identname(name, true), 0, TYPE, nil, nil);
        !           319:     s->language = findlanguage(".c");
        !           320:     s->type = newSymbol(nil, 0, RANGE, s, nil);
        !           321:     s->type->symvalue.rangev.lower = lower;
        !           322:     s->type->symvalue.rangev.upper = upper;
        !           323:     return s;
        !           324: }
        !           325: 
        !           326: /*
        !           327:  * These functions are now compiled inline.
        !           328:  *
        !           329:  * public String symname(s)
        !           330: Symbol s;
        !           331: {
        !           332:     checkref(s);
        !           333:     return ident(s->name);
        !           334: }
        !           335: 
        !           336:  *
        !           337:  * public Address codeloc(f)
        !           338: Symbol f;
        !           339: {
        !           340:     checkref(f);
        !           341:     if (not isblock(f)) {
        !           342:        panic("codeloc: \"%s\" is not a block", ident(f->name));
        !           343:     }
        !           344:     return f->symvalue.funcv.beginaddr;
        !           345: }
        !           346:  *
        !           347:  */
        !           348: 
        !           349: /*
        !           350:  * Reduce type to avoid worrying about type names.
        !           351:  */
        !           352: 
        !           353: public Symbol rtype(type)
        !           354: Symbol type;
        !           355: {
        !           356:     register Symbol t;
        !           357: 
        !           358:     t = type;
        !           359:     if (t != nil) {
        !           360:        if (t->class == VAR or t->class == FIELD or t->class == REF ) {
        !           361:            t = t->type;
        !           362:        }
        !           363:        while (t->class == TYPE or t->class == TAG) {
        !           364:            t = t->type;
        !           365:        }
        !           366:     }
        !           367:     return t;
        !           368: }
        !           369: 
        !           370: public Integer level(s)
        !           371: Symbol s;
        !           372: {
        !           373:     checkref(s);
        !           374:     return s->level;
        !           375: }
        !           376: 
        !           377: public Symbol container(s)
        !           378: Symbol s;
        !           379: {
        !           380:     checkref(s);
        !           381:     return s->block;
        !           382: }
        !           383: 
        !           384: /*
        !           385:  * Return the object address of the given symbol.
        !           386:  *
        !           387:  * There are the following possibilities:
        !           388:  *
        !           389:  *     globals         - just take offset
        !           390:  *     locals          - take offset from locals base
        !           391:  *     arguments       - take offset from argument base
        !           392:  *     register        - offset is register number
        !           393:  */
        !           394: 
        !           395: #define isglobal(s)            (s->level == 1 or s->level == 2)
        !           396: #define islocaloff(s)          (s->level >= 3 and s->symvalue.offset < 0)
        !           397: #define isparamoff(s)          (s->level >= 3 and s->symvalue.offset >= 0)
        !           398: #define isreg(s)               (s->level < 0)
        !           399: 
        !           400: public Address address(s, frame)
        !           401: Symbol s;
        !           402: Frame frame;
        !           403: {
        !           404:     register Frame frp;
        !           405:     register Address addr;
        !           406:     register Symbol cur;
        !           407: 
        !           408:     checkref(s);
        !           409:     if (not isactive(s->block)) {
        !           410:        error("\"%s\" is not currently defined", symname(s));
        !           411:     } else if (isglobal(s)) {
        !           412:        addr = s->symvalue.offset;
        !           413:     } else {
        !           414:        frp = frame;
        !           415:        if (frp == nil) {
        !           416:            cur = s->block;
        !           417:            while (cur != nil and cur->class == MODULE) {
        !           418:                cur = cur->block;
        !           419:            }
        !           420:            if (cur == nil) {
        !           421:                cur = whatblock(pc);
        !           422:            }
        !           423:            frp = findframe(cur);
        !           424:            if (frp == nil) {
        !           425:                panic("unexpected nil frame for \"%s\"", symname(s));
        !           426:            }
        !           427:        }
        !           428:        if (islocaloff(s)) {
        !           429:            addr = locals_base(frp) + s->symvalue.offset;
        !           430:        } else if (isparamoff(s)) {
        !           431:            addr = args_base(frp) + s->symvalue.offset;
        !           432:        } else if (isreg(s)) {
        !           433:            addr = savereg(s->symvalue.offset, frp);
        !           434:        } else {
        !           435:            panic("address: bad symbol \"%s\"", symname(s));
        !           436:        }
        !           437:     }
        !           438:     return addr;
        !           439: }
        !           440: 
        !           441: /*
        !           442:  * Define a symbol used to access register values.
        !           443:  */
        !           444: 
        !           445: public defregname(n, r)
        !           446: Name n;
        !           447: Integer r;
        !           448: {
        !           449:     register Symbol s, t;
        !           450: 
        !           451:     s = insert(n);
        !           452:     t = newSymbol(nil, 0, PTR, t_int, nil);
        !           453:     t->language = findlanguage(".s");
        !           454:     s->language = t->language;
        !           455:     s->class = VAR;
        !           456:     s->level = -3;
        !           457:     s->type = t;
        !           458:     s->block = program;
        !           459:     s->symvalue.offset = r;
        !           460: }
        !           461: 
        !           462: /*
        !           463:  * Resolve an "abstract" type reference.
        !           464:  *
        !           465:  * It is possible in C to define a pointer to a type, but never define
        !           466:  * the type in a particular source file.  Here we try to resolve
        !           467:  * the type definition.  This is problematic, it is possible to
        !           468:  * have multiple, different definitions for the same name type.
        !           469:  */
        !           470: 
        !           471: public findtype(s)
        !           472: Symbol s;
        !           473: {
        !           474:     register Symbol t, u, prev;
        !           475: 
        !           476:     u = s;
        !           477:     prev = nil;
        !           478:     while (u != nil and u->class != BADUSE) {
        !           479:        if (u->name != nil) {
        !           480:            prev = u;
        !           481:        }
        !           482:        u = u->type;
        !           483:     }
        !           484:     if (prev == nil) {
        !           485:        error("couldn't find link to type reference");
        !           486:     }
        !           487:     find(t, prev->name) where
        !           488:        t->type != nil and t->class == prev->class and
        !           489:        t->type->class != BADUSE and t->block->class == MODULE
        !           490:     endfind(t);
        !           491:     if (t == nil) {
        !           492:        error("couldn't resolve reference");
        !           493:     } else {
        !           494:        prev->type = t->type;
        !           495:     }
        !           496: }
        !           497: 
        !           498: /*
        !           499:  * Find the size in bytes of the given type.
        !           500:  *
        !           501:  * This is probably the WRONG thing to do.  The size should be kept
        !           502:  * as an attribute in the symbol information as is done for structures
        !           503:  * and fields.  I haven't gotten around to cleaning this up yet.
        !           504:  */
        !           505: 
        !           506: #define MAXUCHAR 255
        !           507: #define MAXUSHORT 65535L
        !           508: #define MINCHAR -128
        !           509: #define MAXCHAR 127
        !           510: #define MINSHORT -32768
        !           511: #define MAXSHORT 32767
        !           512: 
        !           513: public Integer size(sym)
        !           514: Symbol sym;
        !           515: {
        !           516:     register Symbol s, t;
        !           517:     register int nel, elsize;
        !           518:     long lower, upper;
        !           519:     int r;
        !           520: 
        !           521:     t = sym;
        !           522:     checkref(t);
        !           523:     switch (t->class) {
        !           524:        case RANGE:
        !           525:            lower = t->symvalue.rangev.lower;
        !           526:            upper = t->symvalue.rangev.upper;
        !           527:            if (upper == 0 and lower > 0) {             /* real */
        !           528:                r = lower;
        !           529:            } else if (
        !           530:                (lower >= MINCHAR and upper <= MAXCHAR) or
        !           531:                (lower >= 0 and upper <= MAXUCHAR)
        !           532:              ) {
        !           533:                r = sizeof(char);
        !           534:            } else if (
        !           535:                (lower >= MINSHORT and upper <= MAXSHORT) or
        !           536:                (lower >= 0 and upper <= MAXUSHORT)
        !           537:              ) {
        !           538:                r = sizeof(short);
        !           539:            } else {
        !           540:                r = sizeof(long);
        !           541:            }
        !           542:            break;
        !           543: 
        !           544:        case ARRAY:
        !           545:            elsize = size(t->type);
        !           546:            nel = 1;
        !           547:            for (t = t->chain; t != nil; t = t->chain) {
        !           548:                if (t->symvalue.rangev.lowertype == R_ARG or
        !           549:                  t->symvalue.rangev.lowertype == R_TEMP)  {
        !           550:                    if (not getbound(t, t->symvalue.rangev.lower,
        !           551:                      t->symvalue.rangev.lowertype, &lower)) {
        !           552:                        error("dynamic bounds not currently available");
        !           553:                    }
        !           554:                } else {
        !           555:                    lower = t->symvalue.rangev.lower;
        !           556:                }
        !           557:                if (t->symvalue.rangev.uppertype == R_ARG or
        !           558:                  t->symvalue.rangev.uppertype == R_TEMP) {
        !           559:                    if (not getbound(t, t->symvalue.rangev.upper,
        !           560:                      t->symvalue.rangev.uppertype, &upper)) {
        !           561:                        error("dynamic bounds nor currently available");
        !           562:                    }
        !           563:                } else {
        !           564:                    upper = t->symvalue.rangev.upper;
        !           565:                }
        !           566:                nel *= (upper-lower+1);
        !           567:            }
        !           568:            r = nel*elsize;
        !           569:            break;
        !           570: 
        !           571:        case REF:
        !           572:        case VAR:
        !           573:        case FVAR:
        !           574:            r = size(t->type);
        !           575:            /*
        !           576:             *
        !           577:            if (r < sizeof(Word) and isparam(t)) {
        !           578:                r = sizeof(Word);
        !           579:            }
        !           580:            */
        !           581:            break;
        !           582: 
        !           583:        case CONST:
        !           584:            r = size(t->type);
        !           585:            break;
        !           586: 
        !           587:        case TYPE:
        !           588:            if (t->type->class == PTR and t->type->type->class == BADUSE) {
        !           589:                findtype(t);
        !           590:            }
        !           591:            r = size(t->type);
        !           592:            break;
        !           593: 
        !           594:        case TAG:
        !           595:            r = size(t->type);
        !           596:            break;
        !           597: 
        !           598:        case FIELD:
        !           599:            r = (t->symvalue.field.length + 7) div 8;
        !           600:            break;
        !           601: 
        !           602:        case RECORD:
        !           603:        case VARNT:
        !           604:            r = t->symvalue.offset;
        !           605:            if (r == 0 and t->chain != nil) {
        !           606:                panic("missing size information for record");
        !           607:            }
        !           608:            break;
        !           609: 
        !           610:        case PTR:
        !           611:        case FILET:
        !           612:            r = sizeof(Word);
        !           613:            break;
        !           614: 
        !           615:        case SCAL:
        !           616:            r = sizeof(Word);
        !           617:            /*
        !           618:             *
        !           619:            if (t->symvalue.iconval > 255) {
        !           620:                r = sizeof(short);
        !           621:            } else {
        !           622:                r = sizeof(char);
        !           623:            }
        !           624:             *
        !           625:             */
        !           626:            break;
        !           627: 
        !           628:        case FPROC:
        !           629:        case FFUNC:
        !           630:            r = sizeof(Word);
        !           631:            break;
        !           632: 
        !           633:        case PROC:
        !           634:        case FUNC:
        !           635:        case MODULE:
        !           636:        case PROG:
        !           637:            r = sizeof(Symbol);
        !           638:            break;
        !           639: 
        !           640:        default:
        !           641:            if (ord(t->class) > ord(TYPEREF)) {
        !           642:                panic("size: bad class (%d)", ord(t->class));
        !           643:            } else {
        !           644:                error("improper operation on a %s", classname(t));
        !           645:            }
        !           646:            /* NOTREACHED */
        !           647:     }
        !           648:     return r;
        !           649: }
        !           650: 
        !           651: /*
        !           652:  * Test if a symbol is a parameter.  This is true if there
        !           653:  * is a cycle from s->block to s via chain pointers.
        !           654:  */
        !           655: 
        !           656: public Boolean isparam(s)
        !           657: Symbol s;
        !           658: {
        !           659:     register Symbol t;
        !           660: 
        !           661:     t = s->block;
        !           662:     while (t != nil and t != s) {
        !           663:        t = t->chain;
        !           664:     }
        !           665:     return (Boolean) (t != nil);
        !           666: }
        !           667: 
        !           668: /*
        !           669:  * Test if a symbol is a var parameter, i.e. has class REF.
        !           670:  */
        !           671: 
        !           672: public Boolean isvarparam(s)
        !           673: Symbol s;
        !           674: {
        !           675:     return (Boolean) (s->class == REF);
        !           676: }
        !           677: 
        !           678: /*
        !           679:  * Test if a symbol is a variable (actually any addressible quantity
        !           680:  * with do).
        !           681:  */
        !           682: 
        !           683: public Boolean isvariable(s)
        !           684: register Symbol s;
        !           685: {
        !           686:     return (Boolean) (s->class == VAR or s->class == FVAR or s->class == REF);
        !           687: }
        !           688: 
        !           689: /*
        !           690:  * Test if a symbol is a block, e.g. function, procedure, or the
        !           691:  * main program.
        !           692:  *
        !           693:  * This function is now expanded inline for efficiency.
        !           694:  *
        !           695:  * public Boolean isblock(s)
        !           696: register Symbol s;
        !           697: {
        !           698:     return (Boolean) (
        !           699:        s->class == FUNC or s->class == PROC or
        !           700:        s->class == MODULE or s->class == PROG
        !           701:     );
        !           702: }
        !           703:  *
        !           704:  */
        !           705: 
        !           706: /*
        !           707:  * Test if a symbol is a module.
        !           708:  */
        !           709: 
        !           710: public Boolean ismodule(s)
        !           711: register Symbol s;
        !           712: {
        !           713:     return (Boolean) (s->class == MODULE);
        !           714: }
        !           715: 
        !           716: /*
        !           717:  * Test if a symbol is builtin, that is, a predefined type or
        !           718:  * reserved word.
        !           719:  */
        !           720: 
        !           721: public Boolean isbuiltin(s)
        !           722: register Symbol s;
        !           723: {
        !           724:     return (Boolean) (s->level == 0 and s->class != PROG and s->class != VAR);
        !           725: }
        !           726: 
        !           727: /*
        !           728:  * Test if two types match.
        !           729:  * Equivalent names implies a match in any language.
        !           730:  *
        !           731:  * Special symbols must be handled with care.
        !           732:  */
        !           733: 
        !           734: public Boolean compatible(t1, t2)
        !           735: register Symbol t1, t2;
        !           736: {
        !           737:     Boolean b;
        !           738: 
        !           739:     if (t1 == t2) {
        !           740:        b = true;
        !           741:     } else if (t1 == nil or t2 == nil) {
        !           742:        b = false;
        !           743:     } else if (t1 == procsym) {
        !           744:        b = isblock(t2);
        !           745:     } else if (t2 == procsym) {
        !           746:        b = isblock(t1);
        !           747:     } else if (t1->language == nil) {
        !           748:        b = (Boolean) (t2->language == nil or
        !           749:            (*language_op(t2->language, L_TYPEMATCH))(t1, t2));
        !           750:     } else if (t2->language == nil) {
        !           751:        b = (Boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2);
        !           752:     } else if ( isbuiltin(t1) or isbuiltin(t1->type) ) {
        !           753:        b = (Boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2);
        !           754:     } else {
        !           755:        b = (Boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2);
        !           756:     }
        !           757:     return b;
        !           758: }
        !           759: 
        !           760: /*
        !           761:  * Check for a type of the given name.
        !           762:  */
        !           763: 
        !           764: public Boolean istypename(type, name)
        !           765: Symbol type;
        !           766: String name;
        !           767: {
        !           768:     Symbol t;
        !           769:     Boolean b;
        !           770: 
        !           771:     t = type;
        !           772:     checkref(t);
        !           773:     b = (Boolean) (
        !           774:        t->class == TYPE and t->name == identname(name, true)
        !           775:     );
        !           776:     return b;
        !           777: }
        !           778: 
        !           779: /*
        !           780:  * Test if the name of a symbol is uniquely defined or not.
        !           781:  */
        !           782: 
        !           783: public Boolean isambiguous(s)
        !           784: register Symbol s;
        !           785: {
        !           786:     register Symbol t;
        !           787: 
        !           788:     find(t, s->name) where t != s endfind(t);
        !           789:     return (Boolean) (t != nil);
        !           790: }
        !           791: 
        !           792: typedef char *Arglist;
        !           793: 
        !           794: #define nextarg(type)  ((type *) (ap += sizeof(type)))[-1]
        !           795: 
        !           796: private Symbol mkstring();
        !           797: private Symbol namenode();
        !           798: 
        !           799: /*
        !           800:  * Determine the type of a parse tree.
        !           801:  * Also make some symbol-dependent changes to the tree such as
        !           802:  * changing removing RVAL nodes for constant symbols.
        !           803:  */
        !           804: 
        !           805: public assigntypes(p)
        !           806: register Node p;
        !           807: {
        !           808:     register Node p1;
        !           809:     register Symbol s;
        !           810: 
        !           811:     switch (p->op) {
        !           812:        case O_SYM:
        !           813:            p->nodetype = namenode(p);
        !           814:            break;
        !           815: 
        !           816:        case O_LCON:
        !           817:            p->nodetype = t_int;
        !           818:            break;
        !           819: 
        !           820:        case O_FCON:
        !           821:            p->nodetype = t_real;
        !           822:            break;
        !           823: 
        !           824:        case O_SCON:
        !           825:            p->value.scon = strdup(p->value.scon);
        !           826:            s = mkstring(p->value.scon);
        !           827:            if (s == t_char) {
        !           828:                p->op = O_LCON;
        !           829:                p->value.lcon = p->value.scon[0];
        !           830:            }
        !           831:            p->nodetype = s;
        !           832:            break;
        !           833: 
        !           834:        case O_INDIR:
        !           835:            p1 = p->value.arg[0];
        !           836:            chkclass(p1, PTR);
        !           837:            p->nodetype = rtype(p1->nodetype)->type;
        !           838:            break;
        !           839: 
        !           840:        case O_DOT:
        !           841:            p->nodetype = p->value.arg[1]->value.sym;
        !           842:            break;
        !           843: 
        !           844:        case O_RVAL:
        !           845:            p1 = p->value.arg[0];
        !           846:            p->nodetype = p1->nodetype;
        !           847:            if (p1->op == O_SYM) {
        !           848:                if (p1->nodetype->class == FUNC) {
        !           849:                    p->op = O_CALL;
        !           850:                    p->value.arg[1] = nil;
        !           851:                } else if (p1->value.sym->class == CONST) {
        !           852:                    if (compatible(p1->value.sym->type, t_real)) {
        !           853:                        p->op = O_FCON;
        !           854:                        p->value.fcon = p1->value.sym->symvalue.fconval;
        !           855:                        p->nodetype = t_real;
        !           856:                        dispose(p1);
        !           857:                    } else {
        !           858:                        p->op = O_LCON;
        !           859:                        p->value.lcon = p1->value.sym->symvalue.iconval;
        !           860:                        p->nodetype = p1->value.sym->type;
        !           861:                        dispose(p1);
        !           862:                    }
        !           863:                } else if (isreg(p1->value.sym)) {
        !           864:                    p->op = O_SYM;
        !           865:                    p->value.sym = p1->value.sym;
        !           866:                    dispose(p1);
        !           867:                }
        !           868:            } else if (p1->op == O_INDIR and p1->value.arg[0]->op == O_SYM) {
        !           869:                s = p1->value.arg[0]->value.sym;
        !           870:                if (isreg(s)) {
        !           871:                    p1->op = O_SYM;
        !           872:                    dispose(p1->value.arg[0]);
        !           873:                    p1->value.sym = s;
        !           874:                    p1->nodetype = s;
        !           875:                }
        !           876:            }
        !           877:            break;
        !           878: 
        !           879:        case O_CALL:
        !           880:            p1 = p->value.arg[0];
        !           881:            p->nodetype = rtype(p1->nodetype)->type;
        !           882:            break;
        !           883: 
        !           884:        case O_TYPERENAME:
        !           885:            p->nodetype = p->value.arg[1]->nodetype;
        !           886:            break;
        !           887: 
        !           888:        case O_ITOF:
        !           889:            p->nodetype = t_real;
        !           890:            break;
        !           891: 
        !           892:        case O_NEG:
        !           893:            s = p->value.arg[0]->nodetype;
        !           894:            if (not compatible(s, t_int)) {
        !           895:                if (not compatible(s, t_real)) {
        !           896:                    beginerrmsg();
        !           897:                    prtree(stderr, p->value.arg[0]);
        !           898:                    fprintf(stderr, "is improper type");
        !           899:                    enderrmsg();
        !           900:                } else {
        !           901:                    p->op = O_NEGF;
        !           902:                }
        !           903:            }
        !           904:            p->nodetype = s;
        !           905:            break;
        !           906: 
        !           907:        case O_ADD:
        !           908:        case O_SUB:
        !           909:        case O_MUL:
        !           910:        case O_LT:
        !           911:        case O_LE:
        !           912:        case O_GT:
        !           913:        case O_GE:
        !           914:        case O_EQ:
        !           915:        case O_NE:
        !           916:        {
        !           917:            Boolean t1real, t2real;
        !           918:            Symbol t1, t2;
        !           919: 
        !           920:            t1 = rtype(p->value.arg[0]->nodetype);
        !           921:            t2 = rtype(p->value.arg[1]->nodetype);
        !           922:            t1real = compatible(t1, t_real);
        !           923:            t2real = compatible(t2, t_real);
        !           924:            if (t1real or t2real) {
        !           925:                p->op = (Operator) (ord(p->op) + 1);
        !           926:                if (not t1real) {
        !           927:                    p->value.arg[0] = build(O_ITOF, p->value.arg[0]);
        !           928:                } else if (not t2real) {
        !           929:                    p->value.arg[1] = build(O_ITOF, p->value.arg[1]);
        !           930:                }
        !           931:            } else {
        !           932:                if (t1real) {
        !           933:                    convert(&(p->value.arg[0]), t_int, O_NOP);
        !           934:                }
        !           935:                if (t2real) {
        !           936:                    convert(&(p->value.arg[1]), t_int, O_NOP);
        !           937:                }
        !           938:            }
        !           939:            if (ord(p->op) >= ord(O_LT)) {
        !           940:                p->nodetype = t_boolean;
        !           941:            } else {
        !           942:                if (t1real or t2real) {
        !           943:                    p->nodetype = t_real;
        !           944:                } else {
        !           945:                    p->nodetype = t_int;
        !           946:                }
        !           947:            }
        !           948:            break;
        !           949:        }
        !           950: 
        !           951:        case O_DIVF:
        !           952:            convert(&(p->value.arg[0]), t_real, O_ITOF);
        !           953:            convert(&(p->value.arg[1]), t_real, O_ITOF);
        !           954:            p->nodetype = t_real;
        !           955:            break;
        !           956: 
        !           957:        case O_DIV:
        !           958:        case O_MOD:
        !           959:            convert(&(p->value.arg[0]), t_int, O_NOP);
        !           960:            convert(&(p->value.arg[1]), t_int, O_NOP);
        !           961:            p->nodetype = t_int;
        !           962:            break;
        !           963: 
        !           964:        case O_AND:
        !           965:        case O_OR:
        !           966:            chkboolean(p->value.arg[0]);
        !           967:            chkboolean(p->value.arg[1]);
        !           968:            p->nodetype = t_boolean;
        !           969:            break;
        !           970: 
        !           971:        case O_QLINE:
        !           972:            p->nodetype = t_int;
        !           973:            break;
        !           974: 
        !           975:        default:
        !           976:            p->nodetype = nil;
        !           977:            break;
        !           978:     }
        !           979: }
        !           980: 
        !           981: /*
        !           982:  * Create a node for a name.  The symbol for the name has already
        !           983:  * been chosen, either implicitly with "which" or explicitly from
        !           984:  * the dot routine.
        !           985:  */
        !           986: 
        !           987: private Symbol namenode(p)
        !           988: Node p;
        !           989: {
        !           990:     register Symbol r, s;
        !           991:     register Node np;
        !           992: 
        !           993:     s = p->value.sym;
        !           994:     if (s->class == REF) {
        !           995:        np = new(Node);
        !           996:        np->op = p->op;
        !           997:        np->nodetype = s;
        !           998:        np->value.sym = s;
        !           999:        p->op = O_INDIR;
        !          1000:        p->value.arg[0] = np;
        !          1001:     }
        !          1002: /*
        !          1003:  * Old way
        !          1004:  *
        !          1005:     if (s->class == CONST or s->class == VAR or s->class == FVAR) {
        !          1006:        r = s->type;
        !          1007:     } else {
        !          1008:        r = s;
        !          1009:     }
        !          1010:  *
        !          1011:  */
        !          1012:     return s;
        !          1013: }
        !          1014: 
        !          1015: /*
        !          1016:  * Convert a tree to a type via a conversion operator;
        !          1017:  * if this isn't possible generate an error.
        !          1018:  *
        !          1019:  * Note the tree is call by address, hence the #define below.
        !          1020:  */
        !          1021: 
        !          1022: private convert(tp, typeto, op)
        !          1023: Node *tp;
        !          1024: Symbol typeto;
        !          1025: Operator op;
        !          1026: {
        !          1027: #define tree    (*tp)
        !          1028: 
        !          1029:     Symbol s;
        !          1030: 
        !          1031:     s = rtype(tree->nodetype);
        !          1032:     typeto = rtype(typeto);
        !          1033:     if (compatible(typeto, t_real) and compatible(s, t_int)) {
        !          1034:        tree = build(op, tree);
        !          1035:     } else if (not compatible(s, typeto)) {
        !          1036:        beginerrmsg();
        !          1037:        prtree(stderr, s);
        !          1038:        fprintf(stderr, " is improper type");
        !          1039:        enderrmsg();
        !          1040:     } else if (op != O_NOP and s != typeto) {
        !          1041:        tree = build(op, tree);
        !          1042:     }
        !          1043: 
        !          1044: #undef tree
        !          1045: }
        !          1046: 
        !          1047: /*
        !          1048:  * Construct a node for the dot operator.
        !          1049:  *
        !          1050:  * If the left operand is not a record, but rather a procedure
        !          1051:  * or function, then we interpret the "." as referencing an
        !          1052:  * "invisible" variable; i.e. a variable within a dynamically
        !          1053:  * active block but not within the static scope of the current procedure.
        !          1054:  */
        !          1055: 
        !          1056: public Node dot(record, fieldname)
        !          1057: Node record;
        !          1058: Name fieldname;
        !          1059: {
        !          1060:     register Node p;
        !          1061:     register Symbol s, t;
        !          1062: 
        !          1063:     if (isblock(record->nodetype)) {
        !          1064:        find(s, fieldname) where
        !          1065:            s->block == record->nodetype and
        !          1066:            s->class != FIELD and s->class != TAG
        !          1067:        endfind(s);
        !          1068:        if (s == nil) {
        !          1069:            beginerrmsg();
        !          1070:            fprintf(stderr, "\"%s\" is not defined in ", ident(fieldname));
        !          1071:            printname(stderr, record->nodetype);
        !          1072:            enderrmsg();
        !          1073:        }
        !          1074:        p = new(Node);
        !          1075:        p->op = O_SYM;
        !          1076:        p->value.sym = s;
        !          1077:        p->nodetype = namenode(p);
        !          1078:     } else {
        !          1079:        p = record;
        !          1080:        t = rtype(p->nodetype);
        !          1081:        if (t->class == PTR) {
        !          1082:            s = findfield(fieldname, t->type);
        !          1083:        } else {
        !          1084:            s = findfield(fieldname, t);
        !          1085:        }
        !          1086:        if (s == nil) {
        !          1087:            beginerrmsg();
        !          1088:            fprintf(stderr, "\"%s\" is not a field in ", ident(fieldname));
        !          1089:            prtree(stderr, record);
        !          1090:            enderrmsg();
        !          1091:        }
        !          1092:        if (t->class == PTR and not isreg(record->nodetype)) {
        !          1093:            p = build(O_INDIR, record);
        !          1094:        }
        !          1095:        p = build(O_DOT, p, build(O_SYM, s));
        !          1096:     }
        !          1097:     return p;
        !          1098: }
        !          1099: 
        !          1100: /*
        !          1101:  * Return a tree corresponding to an array reference and do the
        !          1102:  * error checking.
        !          1103:  */
        !          1104: 
        !          1105: public Node subscript(a, slist)
        !          1106: Node a, slist;
        !          1107: {
        !          1108: Symbol t;
        !          1109: 
        !          1110:    t = rtype(a->nodetype);
        !          1111:    if(t->language == nil) {
        !          1112:        error("unknown language");
        !          1113:    }
        !          1114:    else {
        !          1115:         return ( (Node)
        !          1116:         (*language_op(t->language, L_BUILDAREF)) (a,slist)
        !          1117:                );
        !          1118:    }
        !          1119: }
        !          1120: 
        !          1121: /*
        !          1122:  * Evaluate a subscript index.
        !          1123:  */
        !          1124: 
        !          1125: public int evalindex(s, i)
        !          1126: Symbol s;
        !          1127: long i;
        !          1128: {
        !          1129: Symbol t;
        !          1130: 
        !          1131:    t = rtype(s);
        !          1132:    if(t->language == nil) {
        !          1133:        error("unknown language");
        !          1134:    }
        !          1135:    else {
        !          1136:         return (
        !          1137:              (*language_op(t->language, L_EVALAREF)) (s,i)
        !          1138:                );
        !          1139:    }
        !          1140: }
        !          1141: 
        !          1142: /*
        !          1143:  * Check to see if a tree is boolean-valued, if not it's an error.
        !          1144:  */
        !          1145: 
        !          1146: public chkboolean(p)
        !          1147: register Node p;
        !          1148: {
        !          1149:     if (p->nodetype != t_boolean) {
        !          1150:        beginerrmsg();
        !          1151:        fprintf(stderr, "found ");
        !          1152:        prtree(stderr, p);
        !          1153:        fprintf(stderr, ", expected boolean expression");
        !          1154:        enderrmsg();
        !          1155:     }
        !          1156: }
        !          1157: 
        !          1158: /*
        !          1159:  * Check to make sure the given tree has a type of the given class.
        !          1160:  */
        !          1161: 
        !          1162: private chkclass(p, class)
        !          1163: Node p;
        !          1164: Symclass class;
        !          1165: {
        !          1166:     struct Symbol tmpsym;
        !          1167: 
        !          1168:     tmpsym.class = class;
        !          1169:     if (rtype(p->nodetype)->class != class) {
        !          1170:        beginerrmsg();
        !          1171:        fprintf(stderr, "\"");
        !          1172:        prtree(stderr, p);
        !          1173:        fprintf(stderr, "\" is not a %s", classname(&tmpsym));
        !          1174:        enderrmsg();
        !          1175:     }
        !          1176: }
        !          1177: 
        !          1178: /*
        !          1179:  * Construct a node for the type of a string.  While we're at it,
        !          1180:  * scan the string for '' that collapse to ', and chop off the ends.
        !          1181:  */
        !          1182: 
        !          1183: private Symbol mkstring(str)
        !          1184: String str;
        !          1185: {
        !          1186:     register char *p, *q;
        !          1187:     register Symbol s;
        !          1188: 
        !          1189:     p = str;
        !          1190:     q = str;
        !          1191:     while (*p != '\0') {
        !          1192:        if (*p == '\\') {
        !          1193:            ++p;
        !          1194:        }
        !          1195:        *q = *p;
        !          1196:        ++p;
        !          1197:        ++q;
        !          1198:     }
        !          1199:     *q = '\0';
        !          1200:     s = newSymbol(nil, 0, ARRAY, t_char, nil);
        !          1201:     s->language = findlanguage(".s");
        !          1202:     s->chain = newSymbol(nil, 0, RANGE, t_int, nil);
        !          1203:     s->chain->language = s->language;
        !          1204:     s->chain->symvalue.rangev.lower = 1;
        !          1205:     s->chain->symvalue.rangev.upper = p - str + 1;
        !          1206:     return s;
        !          1207: }
        !          1208: 
        !          1209: /*
        !          1210:  * Free up the space allocated for a string type.
        !          1211:  */
        !          1212: 
        !          1213: public unmkstring(s)
        !          1214: Symbol s;
        !          1215: {
        !          1216:     dispose(s->chain);
        !          1217: }
        !          1218: 
        !          1219: /*
        !          1220:  * Figure out the "current" variable or function being referred to,
        !          1221:  * this is either the active one or the most visible from the
        !          1222:  * current scope.
        !          1223:  */
        !          1224: 
        !          1225: public Symbol which(n)
        !          1226: Name n;
        !          1227: {
        !          1228:     register Symbol s, p, t, f;
        !          1229: 
        !          1230:     find(s, n) where s->class != FIELD and s->class != TAG endfind(s);
        !          1231:     if (s == nil) {
        !          1232:        s = lookup(n);
        !          1233:     }
        !          1234:     if (s == nil) {
        !          1235:        error("\"%s\" is not defined", ident(n));
        !          1236:     } else if (s == program or isbuiltin(s)) {
        !          1237:        t = s;
        !          1238:     } else {
        !          1239:     /*
        !          1240:      * Old way
        !          1241:      *
        !          1242:        if (not isactive(program)) {
        !          1243:            f = program;
        !          1244:        } else {
        !          1245:            f = whatblock(pc);
        !          1246:            if (f == nil) {
        !          1247:                panic("no block for addr 0x%x", pc);
        !          1248:            }
        !          1249:        }
        !          1250:      *
        !          1251:      * Now start with curfunc.
        !          1252:      */
        !          1253:        p = curfunc;
        !          1254:        do {
        !          1255:            find(t, n) where
        !          1256:                t->block == p and t->class != FIELD and t->class != TAG
        !          1257:            endfind(t);
        !          1258:            p = p->block;
        !          1259:        } while (t == nil and p != nil);
        !          1260:        if (t == nil) {
        !          1261:            t = s;
        !          1262:        }
        !          1263:     }
        !          1264:     return t;
        !          1265: }
        !          1266: 
        !          1267: /*
        !          1268:  * Find the symbol which is has the same name and scope as the
        !          1269:  * given symbol but is of the given field.  Return nil if there is none.
        !          1270:  */
        !          1271: 
        !          1272: public Symbol findfield(fieldname, record)
        !          1273: Name fieldname;
        !          1274: Symbol record;
        !          1275: {
        !          1276:     register Symbol t;
        !          1277: 
        !          1278:     t = rtype(record)->chain;
        !          1279:     while (t != nil and t->name != fieldname) {
        !          1280:        t = t->chain;
        !          1281:     }
        !          1282:     return t;
        !          1283: }
        !          1284: 
        !          1285: public Boolean getbound(s,off,type,valp)
        !          1286: Symbol s;
        !          1287: int off;
        !          1288: Rangetype type;
        !          1289: int *valp;
        !          1290: {
        !          1291:     Frame frp;
        !          1292:     Address addr;
        !          1293:     Symbol cur;
        !          1294: 
        !          1295:     if (not isactive(s->block)) {
        !          1296:        return(false);
        !          1297:     }
        !          1298:     cur = s->block;
        !          1299:     while (cur != nil and cur->class == MODULE) {  /* WHY*/
        !          1300:                cur = cur->block;
        !          1301:     }
        !          1302:     if(cur == nil) {
        !          1303:                cur = whatblock(pc);
        !          1304:     }
        !          1305:     frp = findframe(cur);
        !          1306:     if (frp == nil) {
        !          1307:        return(false);
        !          1308:     }
        !          1309:     if(type == R_TEMP) addr = locals_base(frp) + off;
        !          1310:     else if (type == R_ARG) addr = args_base(frp) + off;
        !          1311:     else return(false);
        !          1312:     dread(valp,addr,sizeof(long));
        !          1313:     return(true);
        !          1314: }

unix.superglobalmegacorp.com

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