Annotation of 43BSDTahoe/lib/old_compiler/dbx/object.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1983 Regents of the University of California.
        !             3:  * All rights reserved.  The Berkeley software License Agreement
        !             4:  * specifies the terms and conditions for redistribution.
        !             5:  */
        !             6: 
        !             7: #ifndef lint
        !             8: static char sccsid[] = "@(#)object.c   5.2 (Berkeley) 1/12/88";
        !             9: #endif not lint
        !            10: 
        !            11: static char rcsid[] = "$Header: object.c,v 1.5 87/03/26 20:24:58 donn Exp $";
        !            12: 
        !            13: /*
        !            14:  * Object code interface, mainly for extraction of symbolic information.
        !            15:  */
        !            16: 
        !            17: #include "defs.h"
        !            18: #include "object.h"
        !            19: #include "stabstring.h"
        !            20: #include "main.h"
        !            21: #include "symbols.h"
        !            22: #include "names.h"
        !            23: #include "languages.h"
        !            24: #include "mappings.h"
        !            25: #include "lists.h"
        !            26: #include <a.out.h>
        !            27: #include <stab.h>
        !            28: #include <ctype.h>
        !            29: 
        !            30: #ifndef public
        !            31: 
        !            32: struct {
        !            33:     unsigned int stringsize;   /* size of the dumped string table */
        !            34:     unsigned int nsyms;                /* number of symbols */
        !            35:     unsigned int nfiles;       /* number of files */
        !            36:     unsigned int nlines;       /* number of lines */
        !            37: } nlhdr;
        !            38: 
        !            39: #include "languages.h"
        !            40: #include "symbols.h"
        !            41: 
        !            42: #endif
        !            43: 
        !            44: #ifndef N_MOD2
        !            45: #    define N_MOD2 0x50
        !            46: #endif
        !            47: 
        !            48: public String objname = "a.out";
        !            49: public integer objsize;
        !            50: 
        !            51: public Language curlang;
        !            52: public Symbol curmodule;
        !            53: public Symbol curparam;
        !            54: public Symbol curcomm;
        !            55: public Symbol commchain;
        !            56: 
        !            57: private char *stringtab;
        !            58: private struct nlist *curnp;
        !            59: private Boolean warned;
        !            60: private Boolean strip_ = false;
        !            61: 
        !            62: private Filetab *filep;
        !            63: private Linetab *linep, *prevlinep;
        !            64: 
        !            65: public String curfilename ()
        !            66: {
        !            67:     return ((filep-1)->filename);
        !            68: }
        !            69: 
        !            70: /*
        !            71:  * Blocks are figured out on the fly while reading the symbol table.
        !            72:  */
        !            73: 
        !            74: #define MAXBLKDEPTH 25
        !            75: 
        !            76: public Symbol curblock;
        !            77: 
        !            78: private Symbol blkstack[MAXBLKDEPTH];
        !            79: private integer curlevel;
        !            80: private integer bnum, nesting;
        !            81: private Address addrstk[MAXBLKDEPTH];
        !            82: 
        !            83: public pushBlock (b)
        !            84: Symbol b;
        !            85: {
        !            86:     if (curlevel >= MAXBLKDEPTH) {
        !            87:        fatal("nesting depth too large (%d)", curlevel);
        !            88:     }
        !            89:     blkstack[curlevel] = curblock;
        !            90:     ++curlevel;
        !            91:     curblock = b;
        !            92:     if (traceblocks) {
        !            93:        printf("entering block %s\n", symname(b));
        !            94:     }
        !            95: }
        !            96: 
        !            97: /*
        !            98:  * Change the current block with saving the previous one,
        !            99:  * since it is assumed that the symbol for the current one is to be deleted.
        !           100:  */
        !           101: 
        !           102: public changeBlock (b)
        !           103: Symbol b;
        !           104: {
        !           105:     curblock = b;
        !           106: }
        !           107: 
        !           108: public enterblock (b)
        !           109: Symbol b;
        !           110: {
        !           111:     if (curblock == nil) {
        !           112:        b->level = 1;
        !           113:     } else {
        !           114:        b->level = curblock->level + 1;
        !           115:     }
        !           116:     b->block = curblock;
        !           117:     pushBlock(b);
        !           118: }
        !           119: 
        !           120: public exitblock ()
        !           121: {
        !           122:     if (curblock->class == FUNC or curblock->class == PROC) {
        !           123:        if (prevlinep != linep) {
        !           124:            curblock->symvalue.funcv.src = true;
        !           125:        }
        !           126:     }
        !           127:     if (curlevel <= 0) {
        !           128:        panic("nesting depth underflow (%d)", curlevel);
        !           129:     }
        !           130:     --curlevel;
        !           131:     if (traceblocks) {
        !           132:        printf("exiting block %s\n", symname(curblock));
        !           133:     }
        !           134:     curblock = blkstack[curlevel];
        !           135: }
        !           136: 
        !           137: /*
        !           138:  * Enter a source line or file name reference into the appropriate table.
        !           139:  * Expanded inline to reduce procedure calls.
        !           140:  *
        !           141:  * private enterline (linenumber, address)
        !           142:  * Lineno linenumber;
        !           143:  * Address address;
        !           144:  *  ...
        !           145:  */
        !           146: 
        !           147: #define enterline(linenumber, address) \
        !           148: { \
        !           149:     register Linetab *lp; \
        !           150:  \
        !           151:     lp = linep - 1; \
        !           152:     if (linenumber != lp->line) { \
        !           153:        if (address != lp->addr) { \
        !           154:            ++lp; \
        !           155:        } \
        !           156:        lp->line = linenumber; \
        !           157:        lp->addr = address; \
        !           158:        linep = lp + 1; \
        !           159:     } \
        !           160: }
        !           161: 
        !           162: /*
        !           163:  * Read in the namelist from the obj file.
        !           164:  *
        !           165:  * Reads and seeks are used instead of fread's and fseek's
        !           166:  * for efficiency sake; there's a lot of data being read here.
        !           167:  */
        !           168: 
        !           169: public readobj (file)
        !           170: String file;
        !           171: {
        !           172:     Fileid f;
        !           173:     struct exec hdr;
        !           174:     struct nlist nlist;
        !           175: 
        !           176:     f = open(file, 0);
        !           177:     if (f < 0) {
        !           178:        fatal("can't open %s", file);
        !           179:     }
        !           180:     read(f, &hdr, sizeof(hdr));
        !           181:     if (N_BADMAG(hdr)) {
        !           182:        objsize = 0;
        !           183:        nlhdr.nsyms = 0;
        !           184:        nlhdr.nfiles = 0;
        !           185:        nlhdr.nlines = 0;
        !           186:     } else {
        !           187:        objsize = hdr.a_text;
        !           188:        nlhdr.nsyms = hdr.a_syms / sizeof(nlist);
        !           189:        nlhdr.nfiles = nlhdr.nsyms;
        !           190:        nlhdr.nlines = nlhdr.nsyms;
        !           191:     }
        !           192:     if (nlhdr.nsyms > 0) {
        !           193:        lseek(f, (long) N_STROFF(hdr), 0);
        !           194:        read(f, &(nlhdr.stringsize), sizeof(nlhdr.stringsize));
        !           195:        nlhdr.stringsize -= 4;
        !           196:        stringtab = newarr(char, nlhdr.stringsize);
        !           197:        read(f, stringtab, nlhdr.stringsize);
        !           198:        allocmaps(nlhdr.nfiles, nlhdr.nlines);
        !           199:        lseek(f, (long) N_SYMOFF(hdr), 0);
        !           200:        readsyms(f);
        !           201:        ordfunctab();
        !           202:        setnlines();
        !           203:        setnfiles();
        !           204:     } else {
        !           205:        initsyms();
        !           206:     }
        !           207:     close(f);
        !           208: }
        !           209: 
        !           210: /*
        !           211:  * Found the beginning of the externals in the object file
        !           212:  * (signified by the "-lg" or find an external), close the
        !           213:  * block for the last procedure.
        !           214:  */
        !           215: 
        !           216: private foundglobals ()
        !           217: {
        !           218:     if (curblock->class != PROG) {
        !           219:        exitblock();
        !           220:        if (curblock->class != PROG) {
        !           221:            exitblock();
        !           222:        }
        !           223:     }
        !           224:     enterline(0, (linep-1)->addr + 1);
        !           225: }
        !           226: 
        !           227: /*
        !           228:  * Read in symbols from object file.
        !           229:  */
        !           230: 
        !           231: private readsyms (f)
        !           232: Fileid f;
        !           233: {
        !           234:     struct nlist *namelist;
        !           235:     register struct nlist *np, *ub;
        !           236:     register String name;
        !           237:     boolean afterlg, foundstab;
        !           238:     integer index;
        !           239:     char *lastchar;
        !           240: 
        !           241:     initsyms();
        !           242:     namelist = newarr(struct nlist, nlhdr.nsyms);
        !           243:     read(f, namelist, nlhdr.nsyms * sizeof(struct nlist));
        !           244:     afterlg = false;
        !           245:     foundstab = false;
        !           246:     ub = &namelist[nlhdr.nsyms];
        !           247:     curnp = &namelist[0];
        !           248:     np = curnp;
        !           249:     while (np < ub) {
        !           250:        index = np->n_un.n_strx;
        !           251:        if (index != 0) {
        !           252:            name = &stringtab[index - 4];
        !           253:            /*
        !           254:              *  If the program contains any .f files a trailing _ is stripped
        !           255:                     *  from the name on the assumption it was added by the compiler.
        !           256:             *  This only affects names that follow the sdb N_SO entry with
        !           257:              *  the .f name. 
        !           258:              */
        !           259:             if (strip_ and name[0] != '\0' ) {
        !           260:                lastchar = &name[strlen(name) - 1];
        !           261:                if (*lastchar == '_') {
        !           262:                    *lastchar = '\0';
        !           263:                }
        !           264:             }
        !           265:        } else {
        !           266:            name = nil;
        !           267:        } 
        !           268: 
        !           269:        /*
        !           270:         * Assumptions:
        !           271:         *      not an N_STAB   ==> name != nil
        !           272:         *      name[0] == '-'  ==> name == "-lg"
        !           273:         *      name[0] != '_'  ==> filename or invisible
        !           274:         *
        !           275:         * The "-lg" signals the beginning of global loader symbols.
        !           276:          *
        !           277:         */
        !           278:        if ((np->n_type&N_STAB) != 0) {
        !           279:            foundstab = true;
        !           280:            enter_nl(name, np);
        !           281:        } else if (name[0] == '-') {
        !           282:            afterlg = true;
        !           283:            foundglobals();
        !           284:        } else if (afterlg) {
        !           285:            check_global(name, np);
        !           286:        } else if ((np->n_type&N_EXT) == N_EXT) {
        !           287:            afterlg = true;
        !           288:            foundglobals();
        !           289:            check_global(name, np);
        !           290:        } else if (name[0] == '_') {
        !           291:            check_local(&name[1], np);
        !           292:        } else if ((np->n_type&N_TEXT) == N_TEXT) {
        !           293:            check_filename(name);
        !           294:        }
        !           295:        ++curnp;
        !           296:        np = curnp;
        !           297:     }
        !           298:     if (not foundstab) {
        !           299:        warning("no source compiled with -g");
        !           300:     }
        !           301:     dispose(namelist);
        !           302: }
        !           303: 
        !           304: /*
        !           305:  * Get a continuation entry from the name list.
        !           306:  * Return the beginning of the name.
        !           307:  */
        !           308: 
        !           309: public String getcont ()
        !           310: {
        !           311:     register integer index;
        !           312:     register String name;
        !           313: 
        !           314:     ++curnp;
        !           315:     index = curnp->n_un.n_strx;
        !           316:     if (index == 0) {
        !           317:        name = "";
        !           318:     } else {
        !           319:        name = &stringtab[index - 4];
        !           320:     }
        !           321:     return name;
        !           322: }
        !           323: 
        !           324: /*
        !           325:  * Initialize symbol information.
        !           326:  */
        !           327: 
        !           328: private initsyms ()
        !           329: {
        !           330:     curblock = nil;
        !           331:     curlevel = 0;
        !           332:     nesting = 0;
        !           333:     program = insert(identname("", true));
        !           334:     program->class = PROG;
        !           335:     program->language = primlang;
        !           336:     program->symvalue.funcv.beginaddr = CODESTART;
        !           337:     program->symvalue.funcv.inline = false;
        !           338:     newfunc(program, codeloc(program));
        !           339:     findbeginning(program);
        !           340:     enterblock(program);
        !           341:     curmodule = program;
        !           342: }
        !           343: 
        !           344: /*
        !           345:  * Free all the object file information that's being stored.
        !           346:  */
        !           347: 
        !           348: public objfree ()
        !           349: {
        !           350:     symbol_free();
        !           351:     /* keywords_free(); */
        !           352:     /* names_free(); */
        !           353:     /* dispose(stringtab); */
        !           354:     clrfunctab();
        !           355: }
        !           356: 
        !           357: /*
        !           358:  * Enter a namelist entry.
        !           359:  */
        !           360: 
        !           361: private enter_nl (name, np)
        !           362: String name;
        !           363: register struct nlist *np;
        !           364: {
        !           365:     register Symbol s;
        !           366:     register Name n;
        !           367: 
        !           368:     s = nil;
        !           369:     switch (np->n_type) {
        !           370:        /*
        !           371:         * Build a symbol for the FORTRAN common area.  All GSYMS that follow
        !           372:         * will be chained in a list with the head kept in common.offset, and
        !           373:         * the tail in common.chain.
        !           374:         */
        !           375:        case N_BCOMM:
        !           376:            if (curcomm) {
        !           377:                curcomm->symvalue.common.chain = commchain;
        !           378:            }
        !           379:            n = identname(name, true);
        !           380:            curcomm = lookup(n);
        !           381:            if (curcomm == nil) {
        !           382:                curcomm = insert(n);
        !           383:                curcomm->class = COMMON;
        !           384:                curcomm->block = curblock;
        !           385:                curcomm->level = program->level;
        !           386:                curcomm->symvalue.common.chain = nil;
        !           387:            }
        !           388:            commchain = curcomm->symvalue.common.chain;
        !           389:            break;
        !           390: 
        !           391:        case N_ECOMM:
        !           392:            if (curcomm) {
        !           393:                curcomm->symvalue.common.chain = commchain;
        !           394:                curcomm = nil;
        !           395:            }
        !           396:            break;
        !           397: 
        !           398:        case N_LBRAC:
        !           399:            ++nesting;
        !           400:            addrstk[nesting] = (linep - 1)->addr;
        !           401:            break;
        !           402: 
        !           403:        case N_RBRAC:
        !           404:            --nesting;
        !           405:            if (addrstk[nesting] == NOADDR) {
        !           406:                exitblock();
        !           407:                newfunc(curblock, (linep - 1)->addr);
        !           408:                addrstk[nesting] = (linep - 1)->addr;
        !           409:            }
        !           410:            break;
        !           411: 
        !           412:        case N_SLINE:
        !           413:            enterline((Lineno) np->n_desc, (Address) np->n_value);
        !           414:            break;
        !           415: 
        !           416:        /*
        !           417:         * Source files.
        !           418:         */
        !           419:        case N_SO:
        !           420:            n = identname(name, true);
        !           421:            enterSourceModule(n, (Address) np->n_value);
        !           422:            break;
        !           423: 
        !           424:        /*
        !           425:         * Textually included files.
        !           426:         */
        !           427:        case N_SOL:
        !           428:            enterfile(name, (Address) np->n_value);
        !           429:            break;
        !           430: 
        !           431:        /*
        !           432:         * These symbols are assumed to have non-nil names.
        !           433:         */
        !           434:        case N_GSYM:
        !           435:        case N_FUN:
        !           436:        case N_STSYM:
        !           437:        case N_LCSYM:
        !           438:        case N_RSYM:
        !           439:        case N_PSYM:
        !           440:        case N_LSYM:
        !           441:        case N_SSYM:
        !           442:        case N_LENG:
        !           443:            if (index(name, ':') == nil) {
        !           444:                if (not warned) {
        !           445:                    warned = true;
        !           446:                    printf("warning: old style symbol information ");
        !           447:                    printf("found in \"%s\"\n", curfilename());
        !           448:                }
        !           449:            } else {
        !           450:                entersym(name, np);
        !           451:            }
        !           452:            break;
        !           453: 
        !           454:        case N_PC:
        !           455:        case N_MOD2:
        !           456:            break;
        !           457: 
        !           458:        default:
        !           459:            printf("warning:  stab entry unrecognized: ");
        !           460:            if (name != nil) {
        !           461:                printf("name %s,", name);
        !           462:            }
        !           463:            printf("ntype %2x, desc %x, value %x'\n",
        !           464:                np->n_type, np->n_desc, np->n_value);
        !           465:            break;
        !           466:     }
        !           467: }
        !           468: 
        !           469: /*
        !           470:  * Try to find the symbol that is referred to by the given name.  Since it's
        !           471:  * an external, we need to follow a level or two of indirection.
        !           472:  */
        !           473: 
        !           474: private Symbol findsym (n, var_isextref)
        !           475: Name n;
        !           476: boolean *var_isextref;
        !           477: {
        !           478:     register Symbol r, s;
        !           479: 
        !           480:     *var_isextref = false;
        !           481:     find(s, n) where
        !           482:        (
        !           483:            s->level == program->level and (
        !           484:                s->class == EXTREF or s->class == VAR or
        !           485:                s->class == PROC or s->class == FUNC
        !           486:            )
        !           487:        ) or (
        !           488:            s->block == program and s->class == MODULE
        !           489:        )
        !           490:     endfind(s);
        !           491:     if (s == nil) {
        !           492:        r = nil;
        !           493:     } else if (s->class == EXTREF) {
        !           494:        *var_isextref = true;
        !           495:        r = s->symvalue.extref;
        !           496:        delete(s);
        !           497: 
        !           498:        /*
        !           499:         * Now check for another level of indirection that could come from
        !           500:         * a forward reference in procedure nesting information.  In this case
        !           501:         * the symbol has already been deleted.
        !           502:         */
        !           503:        if (r != nil and r->class == EXTREF) {
        !           504:            r = r->symvalue.extref;
        !           505:        }
        !           506: /*
        !           507:     } else if (s->class == MODULE) {
        !           508:        s->class = FUNC;
        !           509:        s->level = program->level;
        !           510:        r = s;
        !           511:  */
        !           512:     } else {
        !           513:        r = s;
        !           514:     }
        !           515:     return r;
        !           516: }
        !           517: 
        !           518: /*
        !           519:  * Create a symbol for a text symbol with no source information.
        !           520:  * We treat it as an assembly language function.
        !           521:  */
        !           522: 
        !           523: private Symbol deffunc (n)
        !           524: Name n;
        !           525: {
        !           526:     Symbol f;
        !           527: 
        !           528:     f = insert(n);
        !           529:     f->language = findlanguage(".s");
        !           530:     f->class = FUNC;
        !           531:     f->type = t_int;
        !           532:     f->block = curblock;
        !           533:     f->level = program->level;
        !           534:     f->symvalue.funcv.src = false;
        !           535:     f->symvalue.funcv.inline = false;
        !           536:     if (f->chain != nil) {
        !           537:        panic("chain not nil in deffunc");
        !           538:     }
        !           539:     return f;
        !           540: }
        !           541: 
        !           542: /*
        !           543:  * Create a symbol for a data or bss symbol with no source information.
        !           544:  * We treat it as an assembly language variable.
        !           545:  */
        !           546: 
        !           547: private Symbol defvar (n)
        !           548: Name n;
        !           549: {
        !           550:     Symbol v;
        !           551: 
        !           552:     v = insert(n);
        !           553:     v->language = findlanguage(".s");
        !           554:     v->storage = EXT;
        !           555:     v->class = VAR;
        !           556:     v->type = t_int;
        !           557:     v->level = program->level;
        !           558:     v->block = curblock;
        !           559:     return v;
        !           560: }
        !           561: 
        !           562: /*
        !           563:  * Update a symbol entry with a text address.
        !           564:  */
        !           565: 
        !           566: private updateTextSym (s, name, addr)
        !           567: Symbol s;
        !           568: char *name;
        !           569: Address addr;
        !           570: {
        !           571:     if (s->class == VAR) {
        !           572:        s->symvalue.offset = addr;
        !           573:     } else {
        !           574:        s->symvalue.funcv.beginaddr = addr;
        !           575:        if (name[0] == '_') {
        !           576:            newfunc(s, codeloc(s));
        !           577:            findbeginning(s);
        !           578:        }
        !           579:     }
        !           580: }
        !           581: 
        !           582: /*
        !           583:  * Avoid seeing Pascal labels as text symbols.
        !           584:  */
        !           585: 
        !           586: private boolean PascalLabel (n)
        !           587: Name n;
        !           588: {
        !           589:     boolean b;
        !           590:     register char *p;
        !           591: 
        !           592:     b = false;
        !           593:     if (curlang == findlanguage(".p")) {
        !           594:        p = ident(n);
        !           595:        while (*p != '\0') {
        !           596:            if (*p == '_' and *(p+1) == '$') {
        !           597:                b = true;
        !           598:                break;
        !           599:            }
        !           600:            ++p;
        !           601:        }
        !           602:     }
        !           603:     return b;
        !           604: }
        !           605: 
        !           606: /*
        !           607:  * Check to see if a global _name is already in the symbol table,
        !           608:  * if not then insert it.
        !           609:  */
        !           610: 
        !           611: private check_global (name, np)
        !           612: String name;
        !           613: register struct nlist *np;
        !           614: {
        !           615:     register Name n;
        !           616:     register Symbol t, u;
        !           617:     char buf[4096];
        !           618:     boolean isextref;
        !           619:     integer count;
        !           620: 
        !           621:     if (not streq(name, "_end")) {
        !           622:        if (name[0] == '_') {
        !           623:            n = identname(&name[1], true);
        !           624:        } else {
        !           625:            n = identname(name, true);
        !           626:            if (lookup(n) != nil) {
        !           627:                sprintf(buf, "$%s", name);
        !           628:                n = identname(buf, false);
        !           629:            }
        !           630:        }
        !           631:        if ((np->n_type&N_TYPE) == N_TEXT) {
        !           632:            count = 0;
        !           633:            t = findsym(n, &isextref);
        !           634:            while (isextref) {
        !           635:                ++count;
        !           636:                updateTextSym(t, name, np->n_value);
        !           637:                t = findsym(n, &isextref);
        !           638:            }
        !           639:            if (count == 0) {
        !           640:                if (t == nil) {
        !           641:                    if (not PascalLabel(n)) {
        !           642:                        t = deffunc(n);
        !           643:                        updateTextSym(t, name, np->n_value);
        !           644:                        if (tracesyms) {
        !           645:                            printdecl(t);
        !           646:                        }
        !           647:                    }
        !           648:                } else {
        !           649:                    if (t->class == MODULE) {
        !           650:                        u = t;
        !           651:                        t = deffunc(n);
        !           652:                        t->block = u;
        !           653:                        if (tracesyms) {
        !           654:                            printdecl(t);
        !           655:                        }
        !           656:                    }
        !           657:                    updateTextSym(t, name, np->n_value);
        !           658:                }
        !           659:            }
        !           660:        } else if ((np->n_type&N_TYPE) == N_BSS or (np->n_type&N_TYPE) == N_DATA) {
        !           661:            find(t, n) where
        !           662:                t->class == COMMON
        !           663:            endfind(t);
        !           664:            if (t != nil) {
        !           665:                u = (Symbol) t->symvalue.common.offset;
        !           666:                while (u != nil) {
        !           667:                    u->symvalue.offset = u->symvalue.common.offset+np->n_value;
        !           668:                    u = u->symvalue.common.chain;
        !           669:                }
        !           670:             } else {
        !           671:                check_var(np, n);
        !           672:            }
        !           673:         } else {
        !           674:            check_var(np, n);
        !           675:        }
        !           676:     }
        !           677: }
        !           678: 
        !           679: /*
        !           680:  * Check to see if a namelist entry refers to a variable.
        !           681:  * If not, create a variable for the entry.  In any case,
        !           682:  * set the offset of the variable according to the value field
        !           683:  * in the entry.
        !           684:  *
        !           685:  * If the external name has been referred to by several other symbols,
        !           686:  * we must update each of them.
        !           687:  */
        !           688: 
        !           689: private check_var (np, n)
        !           690: struct nlist *np;
        !           691: register Name n;
        !           692: {
        !           693:     register Symbol t, u, next;
        !           694:     Symbol conflict;
        !           695: 
        !           696:     t = lookup(n);
        !           697:     if (t == nil) {
        !           698:        t = defvar(n);
        !           699:        t->symvalue.offset = np->n_value;
        !           700:        if (tracesyms) {
        !           701:            printdecl(t);
        !           702:        }
        !           703:     } else {
        !           704:        conflict = nil;
        !           705:        do {
        !           706:            next = t->next_sym;
        !           707:            if (t->name == n) {
        !           708:                if (t->class == MODULE and t->block == program) {
        !           709:                    conflict = t;
        !           710:                } else if (t->class == EXTREF and t->level == program->level) {
        !           711:                    u = t->symvalue.extref;
        !           712:                    while (u != nil and u->class == EXTREF) {
        !           713:                        u = u->symvalue.extref;
        !           714:                    }
        !           715:                    u->symvalue.offset = np->n_value;
        !           716:                    delete(t);
        !           717:                } else if (t->level == program->level and
        !           718:                    (t->class == VAR or t->class == PROC or t->class == FUNC)
        !           719:                ) {
        !           720:                    conflict = nil;
        !           721:                    t->symvalue.offset = np->n_value;
        !           722:                }
        !           723:            }
        !           724:            t = next;
        !           725:        } while (t != nil);
        !           726:        if (conflict != nil) {
        !           727:            u = defvar(n);
        !           728:            u->block = conflict;
        !           729:            u->symvalue.offset = np->n_value;
        !           730:        }
        !           731:     }
        !           732: }
        !           733: 
        !           734: /*
        !           735:  * Check to see if a local _name is known in the current scope.
        !           736:  * If not then enter it.
        !           737:  */
        !           738: 
        !           739: private check_local (name, np)
        !           740: String name;
        !           741: register struct nlist *np;
        !           742: {
        !           743:     register Name n;
        !           744:     register Symbol t, cur;
        !           745: 
        !           746:     n = identname(name, true);
        !           747:     cur = ((np->n_type&N_TYPE) == N_TEXT) ? curmodule : curblock;
        !           748:     find(t, n) where t->block == cur endfind(t);
        !           749:     if (t == nil) {
        !           750:        t = insert(n);
        !           751:        t->language = findlanguage(".s");
        !           752:        t->type = t_int;
        !           753:        t->block = cur;
        !           754:        t->storage = EXT;
        !           755:        t->level = cur->level;
        !           756:        if ((np->n_type&N_TYPE) == N_TEXT) {
        !           757:            t->class = FUNC;
        !           758:            t->symvalue.funcv.src = false;
        !           759:            t->symvalue.funcv.inline = false;
        !           760:            t->symvalue.funcv.beginaddr = np->n_value;
        !           761:            newfunc(t, codeloc(t));
        !           762:            findbeginning(t);
        !           763:        } else {
        !           764:            t->class = VAR;
        !           765:            t->symvalue.offset = np->n_value;
        !           766:        }
        !           767:     }
        !           768: }
        !           769: 
        !           770: /*
        !           771:  * Check to see if a symbol corresponds to a object file name.
        !           772:  * For some reason these are listed as in the text segment.
        !           773:  */
        !           774: 
        !           775: private check_filename (name)
        !           776: String name;
        !           777: {
        !           778:     register String mname;
        !           779:     register integer i;
        !           780:     Name n;
        !           781:     Symbol s;
        !           782: 
        !           783:     mname = strdup(name);
        !           784:     i = strlen(mname) - 2;
        !           785:     if (i >= 0 and mname[i] == '.' and mname[i+1] == 'o') {
        !           786:        mname[i] = '\0';
        !           787:        --i;
        !           788:        while (mname[i] != '/' and i >= 0) {
        !           789:            --i;
        !           790:        }
        !           791:        n = identname(&mname[i+1], true);
        !           792:        find(s, n) where s->block == program and s->class == MODULE endfind(s);
        !           793:        if (s == nil) {
        !           794:            s = insert(n);
        !           795:            s->language = findlanguage(".s");
        !           796:            s->class = MODULE;
        !           797:            s->symvalue.funcv.beginaddr = 0;
        !           798:            findbeginning(s);
        !           799:        }
        !           800:        if (curblock->class != PROG) {
        !           801:            exitblock();
        !           802:            if (curblock->class != PROG) {
        !           803:                exitblock();
        !           804:            }
        !           805:        }
        !           806:        enterblock(s);
        !           807:        curmodule = s;
        !           808:     }
        !           809: }
        !           810: 
        !           811: /*
        !           812:  * Check to see if a symbol is about to be defined within an unnamed block.
        !           813:  * If this happens, we create a procedure for the unnamed block, make it
        !           814:  * "inline" so that tracebacks don't associate an activation record with it,
        !           815:  * and enter it into the function table so that it will be detected
        !           816:  * by "whatblock".
        !           817:  */
        !           818: 
        !           819: public chkUnnamedBlock ()
        !           820: {
        !           821:     register Symbol s;
        !           822:     static int bnum = 0;
        !           823:     char buf[100];
        !           824:     Address startaddr;
        !           825: 
        !           826:     if (nesting > 0 and addrstk[nesting] != NOADDR) {
        !           827:        startaddr = (linep - 1)->addr;
        !           828:        ++bnum;
        !           829:        sprintf(buf, "$b%d", bnum);
        !           830:        s = insert(identname(buf, false));
        !           831:        s->language = curlang;
        !           832:        s->class = PROC;
        !           833:        s->symvalue.funcv.src = false;
        !           834:        s->symvalue.funcv.inline = true;
        !           835:        s->symvalue.funcv.beginaddr = startaddr;
        !           836:        enterblock(s);
        !           837:        newfunc(s, startaddr);
        !           838:        addrstk[nesting] = NOADDR;
        !           839:     }
        !           840: }
        !           841: 
        !           842: /*
        !           843:  * Compilation unit.  C associates scope with filenames
        !           844:  * so we treat them as "modules".  The filename without
        !           845:  * the suffix is used for the module name.
        !           846:  *
        !           847:  * Because there is no explicit "end-of-block" mark in
        !           848:  * the object file, we must exit blocks for the current
        !           849:  * procedure and module.
        !           850:  */
        !           851: 
        !           852: private enterSourceModule (n, addr)
        !           853: Name n;
        !           854: Address addr;
        !           855: {
        !           856:     register Symbol s;
        !           857:     Name nn;
        !           858:     String mname, suffix;
        !           859: 
        !           860:     mname = strdup(ident(n));
        !           861:     if (rindex(mname, '/') != nil) {
        !           862:        mname = rindex(mname, '/') + 1;
        !           863:     }
        !           864:     suffix = rindex(mname, '.');
        !           865:     if (suffix > mname && *(suffix-1) == '.') {
        !           866:        /* special hack for C++ */
        !           867:        --suffix;
        !           868:     }
        !           869:     curlang = findlanguage(suffix);
        !           870:     if (curlang == findlanguage(".f")) {
        !           871:        strip_ = true;
        !           872:     } 
        !           873:     if (suffix != nil) {
        !           874:        *suffix = '\0';
        !           875:     }
        !           876:     if (not (*language_op(curlang, L_HASMODULES))()) {
        !           877:        if (curblock->class != PROG) {
        !           878:            exitblock();
        !           879:            if (curblock->class != PROG) {
        !           880:                exitblock();
        !           881:            }
        !           882:        }
        !           883:        nn = identname(mname, true);
        !           884:        if (curmodule == nil or curmodule->name != nn) {
        !           885:            s = insert(nn);
        !           886:            s->class = MODULE;
        !           887:            s->symvalue.funcv.beginaddr = 0;
        !           888:            findbeginning(s);
        !           889:        } else {
        !           890:            s = curmodule;
        !           891:        }
        !           892:        s->language = curlang;
        !           893:        enterblock(s);
        !           894:        curmodule = s;
        !           895:     }
        !           896:     if (program->language == nil) {
        !           897:        program->language = curlang;
        !           898:     }
        !           899:     warned = false;
        !           900:     enterfile(ident(n), addr);
        !           901:     initTypeTable();
        !           902: }
        !           903: 
        !           904: /*
        !           905:  * Allocate file and line tables and initialize indices.
        !           906:  */
        !           907: 
        !           908: private allocmaps (nf, nl)
        !           909: integer nf, nl;
        !           910: {
        !           911:     if (filetab != nil) {
        !           912:        dispose(filetab);
        !           913:     }
        !           914:     if (linetab != nil) {
        !           915:        dispose(linetab);
        !           916:     }
        !           917:     filetab = newarr(Filetab, nf);
        !           918:     linetab = newarr(Linetab, nl);
        !           919:     filep = filetab;
        !           920:     linep = linetab;
        !           921: }
        !           922: 
        !           923: /*
        !           924:  * Add a file to the file table.
        !           925:  *
        !           926:  * If the new address is the same as the previous file address
        !           927:  * this routine used to not enter the file, but this caused some
        !           928:  * problems so it has been removed.  It's not clear that this in
        !           929:  * turn may not also cause a problem.
        !           930:  */
        !           931: 
        !           932: private enterfile (filename, addr)
        !           933: String filename;
        !           934: Address addr;
        !           935: {
        !           936:     filep->addr = addr;
        !           937:     filep->filename = filename;
        !           938:     filep->lineindex = linep - linetab;
        !           939:     ++filep;
        !           940: }
        !           941: 
        !           942: /*
        !           943:  * Since we only estimated the number of lines (and it was a poor
        !           944:  * estimation) and since we need to know the exact number of lines
        !           945:  * to do a binary search, we set it when we're done.
        !           946:  */
        !           947: 
        !           948: private setnlines ()
        !           949: {
        !           950:     nlhdr.nlines = linep - linetab;
        !           951: }
        !           952: 
        !           953: /*
        !           954:  * Similarly for nfiles ...
        !           955:  */
        !           956: 
        !           957: private setnfiles ()
        !           958: {
        !           959:     nlhdr.nfiles = filep - filetab;
        !           960:     setsource(filetab[0].filename);
        !           961: }

unix.superglobalmegacorp.com

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