Annotation of 43BSD/ucb/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.1 (Berkeley) 5/31/85";
        !             9: #endif not lint
        !            10: 
        !            11: static char rcsid[] = "$Header: object.c,v 1.6 84/12/26 10:40:51 linton 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:     register Boolean afterlg;
        !           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:     ub = &namelist[nlhdr.nsyms];
        !           246:     curnp = &namelist[0];
        !           247:     np = curnp;
        !           248:     while (np < ub) {
        !           249:        index = np->n_un.n_strx;
        !           250:        if (index != 0) {
        !           251:            name = &stringtab[index - 4];
        !           252:            /*
        !           253:              *  If the program contains any .f files a trailing _ is stripped
        !           254:                     *  from the name on the assumption it was added by the compiler.
        !           255:             *  This only affects names that follow the sdb N_SO entry with
        !           256:              *  the .f name. 
        !           257:              */
        !           258:             if (strip_ and name[0] != '\0' ) {
        !           259:                lastchar = &name[strlen(name) - 1];
        !           260:                if (*lastchar == '_') {
        !           261:                    *lastchar = '\0';
        !           262:                }
        !           263:             }
        !           264:        } else {
        !           265:            name = nil;
        !           266:        } 
        !           267: 
        !           268:        /*
        !           269:         * Assumptions:
        !           270:         *      not an N_STAB   ==> name != nil
        !           271:         *      name[0] == '-'  ==> name == "-lg"
        !           272:         *      name[0] != '_'  ==> filename or invisible
        !           273:         *
        !           274:         * The "-lg" signals the beginning of global loader symbols.
        !           275:          *
        !           276:         */
        !           277:        if ((np->n_type&N_STAB) != 0) {
        !           278:            enter_nl(name, np);
        !           279:        } else if (name[0] == '-') {
        !           280:            afterlg = true;
        !           281:            foundglobals();
        !           282:        } else if (afterlg) {
        !           283:            check_global(name, np);
        !           284:        } else if ((np->n_type&N_EXT) == N_EXT) {
        !           285:            afterlg = true;
        !           286:            foundglobals();
        !           287:            check_global(name, np);
        !           288:        } else if (name[0] == '_') {
        !           289:            check_local(&name[1], np);
        !           290:        } else if ((np->n_type&N_TEXT) == N_TEXT) {
        !           291:            check_filename(name);
        !           292:        }
        !           293:        ++curnp;
        !           294:        np = curnp;
        !           295:     }
        !           296:     dispose(namelist);
        !           297: }
        !           298: 
        !           299: /*
        !           300:  * Get a continuation entry from the name list.
        !           301:  * Return the beginning of the name.
        !           302:  */
        !           303: 
        !           304: public String getcont ()
        !           305: {
        !           306:     register integer index;
        !           307:     register String name;
        !           308: 
        !           309:     ++curnp;
        !           310:     index = curnp->n_un.n_strx;
        !           311:     if (index == 0) {
        !           312:        panic("continuation followed by empty stab");
        !           313:     }
        !           314:     name = &stringtab[index - 4];
        !           315:     return name;
        !           316: }
        !           317: 
        !           318: /*
        !           319:  * Initialize symbol information.
        !           320:  */
        !           321: 
        !           322: private initsyms ()
        !           323: {
        !           324:     curblock = nil;
        !           325:     curlevel = 0;
        !           326:     nesting = 0;
        !           327:     program = insert(identname("", true));
        !           328:     program->class = PROG;
        !           329:     program->symvalue.funcv.beginaddr = 0;
        !           330:     program->symvalue.funcv.inline = false;
        !           331:     newfunc(program, codeloc(program));
        !           332:     findbeginning(program);
        !           333:     enterblock(program);
        !           334:     curmodule = program;
        !           335: }
        !           336: 
        !           337: /*
        !           338:  * Free all the object file information that's being stored.
        !           339:  */
        !           340: 
        !           341: public objfree ()
        !           342: {
        !           343:     symbol_free();
        !           344:     /* keywords_free(); */
        !           345:     /* names_free(); */
        !           346:     /* dispose(stringtab); */
        !           347:     clrfunctab();
        !           348: }
        !           349: 
        !           350: /*
        !           351:  * Enter a namelist entry.
        !           352:  */
        !           353: 
        !           354: private enter_nl (name, np)
        !           355: String name;
        !           356: register struct nlist *np;
        !           357: {
        !           358:     register Symbol s;
        !           359:     register Name n;
        !           360: 
        !           361:     s = nil;
        !           362:     switch (np->n_type) {
        !           363:        /*
        !           364:         * Build a symbol for the FORTRAN common area.  All GSYMS that follow
        !           365:         * will be chained in a list with the head kept in common.offset, and
        !           366:         * the tail in common.chain.
        !           367:         */
        !           368:        case N_BCOMM:
        !           369:            if (curcomm) {
        !           370:                curcomm->symvalue.common.chain = commchain;
        !           371:            }
        !           372:            n = identname(name, true);
        !           373:            curcomm = lookup(n);
        !           374:            if (curcomm == nil) {
        !           375:                curcomm = insert(n);
        !           376:                curcomm->class = COMMON;
        !           377:                curcomm->block = curblock;
        !           378:                curcomm->level = program->level;
        !           379:                curcomm->symvalue.common.chain = nil;
        !           380:            }
        !           381:            commchain = curcomm->symvalue.common.chain;
        !           382:            break;
        !           383: 
        !           384:        case N_ECOMM:
        !           385:            if (curcomm) {
        !           386:                curcomm->symvalue.common.chain = commchain;
        !           387:                curcomm = nil;
        !           388:            }
        !           389:            break;
        !           390: 
        !           391:        case N_LBRAC:
        !           392:            ++nesting;
        !           393:            addrstk[nesting] = (linep - 1)->addr;
        !           394:            break;
        !           395: 
        !           396:        case N_RBRAC:
        !           397:            --nesting;
        !           398:            if (addrstk[nesting] == NOADDR) {
        !           399:                exitblock();
        !           400:                newfunc(curblock, (linep - 1)->addr);
        !           401:                addrstk[nesting] = (linep - 1)->addr;
        !           402:            }
        !           403:            break;
        !           404: 
        !           405:        case N_SLINE:
        !           406:            enterline((Lineno) np->n_desc, (Address) np->n_value);
        !           407:            break;
        !           408: 
        !           409:        /*
        !           410:         * Source files.
        !           411:         */
        !           412:        case N_SO:
        !           413:            n = identname(name, true);
        !           414:            enterSourceModule(n, (Address) np->n_value);
        !           415:            break;
        !           416: 
        !           417:        /*
        !           418:         * Textually included files.
        !           419:         */
        !           420:        case N_SOL:
        !           421:            enterfile(name, (Address) np->n_value);
        !           422:            break;
        !           423: 
        !           424:        /*
        !           425:         * These symbols are assumed to have non-nil names.
        !           426:         */
        !           427:        case N_GSYM:
        !           428:        case N_FUN:
        !           429:        case N_STSYM:
        !           430:        case N_LCSYM:
        !           431:        case N_RSYM:
        !           432:        case N_PSYM:
        !           433:        case N_LSYM:
        !           434:        case N_SSYM:
        !           435:        case N_LENG:
        !           436:            if (index(name, ':') == nil) {
        !           437:                if (not warned) {
        !           438:                    warned = true;
        !           439:                    warning("old style symbol information found in \"%s\"",
        !           440:                        curfilename());
        !           441:                }
        !           442:            } else {
        !           443:                entersym(name, np);
        !           444:            }
        !           445:            break;
        !           446: 
        !           447:        case N_PC:
        !           448:        case N_MOD2:
        !           449:            break;
        !           450: 
        !           451:        default:
        !           452:            printf("warning:  stab entry unrecognized: ");
        !           453:            if (name != nil) {
        !           454:                printf("name %s,", name);
        !           455:            }
        !           456:            printf("ntype %2x, desc %x, value %x'\n",
        !           457:                np->n_type, np->n_desc, np->n_value);
        !           458:            break;
        !           459:     }
        !           460: }
        !           461: 
        !           462: /*
        !           463:  * Try to find the symbol that is referred to by the given name.  Since it's
        !           464:  * an external, we need to follow a level or two of indirection.
        !           465:  */
        !           466: 
        !           467: private Symbol findsym (n, var_isextref)
        !           468: Name n;
        !           469: boolean *var_isextref;
        !           470: {
        !           471:     register Symbol r, s;
        !           472: 
        !           473:     *var_isextref = false;
        !           474:     find(s, n) where
        !           475:        (
        !           476:            s->level == program->level and (
        !           477:                s->class == EXTREF or s->class == VAR or
        !           478:                s->class == PROC or s->class == FUNC
        !           479:            )
        !           480:        ) or (
        !           481:            s->block == program and s->class == MODULE
        !           482:        )
        !           483:     endfind(s);
        !           484:     if (s == nil) {
        !           485:        r = nil;
        !           486:     } else if (s->class == EXTREF) {
        !           487:        *var_isextref = true;
        !           488:        r = s->symvalue.extref;
        !           489:        delete(s);
        !           490: 
        !           491:        /*
        !           492:         * Now check for another level of indirection that could come from
        !           493:         * a forward reference in procedure nesting information.  In this case
        !           494:         * the symbol has already been deleted.
        !           495:         */
        !           496:        if (r != nil and r->class == EXTREF) {
        !           497:            r = r->symvalue.extref;
        !           498:        }
        !           499: /*
        !           500:     } else if (s->class == MODULE) {
        !           501:        s->class = FUNC;
        !           502:        s->level = program->level;
        !           503:        r = s;
        !           504:  */
        !           505:     } else {
        !           506:        r = s;
        !           507:     }
        !           508:     return r;
        !           509: }
        !           510: 
        !           511: /*
        !           512:  * Create a symbol for a text symbol with no source information.
        !           513:  * We treat it as an assembly language function.
        !           514:  */
        !           515: 
        !           516: private Symbol deffunc (n)
        !           517: Name n;
        !           518: {
        !           519:     Symbol f;
        !           520: 
        !           521:     f = insert(n);
        !           522:     f->language = findlanguage(".s");
        !           523:     f->class = FUNC;
        !           524:     f->type = t_int;
        !           525:     f->block = curblock;
        !           526:     f->level = program->level;
        !           527:     f->symvalue.funcv.src = false;
        !           528:     f->symvalue.funcv.inline = false;
        !           529:     return f;
        !           530: }
        !           531: 
        !           532: /*
        !           533:  * Create a symbol for a data or bss symbol with no source information.
        !           534:  * We treat it as an assembly language variable.
        !           535:  */
        !           536: 
        !           537: private Symbol defvar (n)
        !           538: Name n;
        !           539: {
        !           540:     Symbol v;
        !           541: 
        !           542:     v = insert(n);
        !           543:     v->language = findlanguage(".s");
        !           544:     v->class = VAR;
        !           545:     v->type = t_int;
        !           546:     v->level = program->level;
        !           547:     v->block = curblock;
        !           548:     return v;
        !           549: }
        !           550: 
        !           551: /*
        !           552:  * Update a symbol entry with a text address.
        !           553:  */
        !           554: 
        !           555: private updateTextSym (s, name, addr)
        !           556: Symbol s;
        !           557: char *name;
        !           558: Address addr;
        !           559: {
        !           560:     if (s->class == VAR) {
        !           561:        s->symvalue.offset = addr;
        !           562:     } else {
        !           563:        s->symvalue.funcv.beginaddr = addr;
        !           564:        if (name[0] == '_') {
        !           565:            newfunc(s, codeloc(s));
        !           566:            findbeginning(s);
        !           567:        }
        !           568:     }
        !           569: }
        !           570: 
        !           571: /*
        !           572:  * Check to see if a global _name is already in the symbol table,
        !           573:  * if not then insert it.
        !           574:  */
        !           575: 
        !           576: private check_global (name, np)
        !           577: String name;
        !           578: register struct nlist *np;
        !           579: {
        !           580:     register Name n;
        !           581:     register Symbol t, u;
        !           582:     char buf[4096];
        !           583:     boolean isextref;
        !           584:     integer count;
        !           585: 
        !           586:     if (not streq(name, "_end")) {
        !           587:        if (name[0] == '_') {
        !           588:            n = identname(&name[1], true);
        !           589:        } else {
        !           590:            n = identname(name, true);
        !           591:            if (lookup(n) != nil) {
        !           592:                sprintf(buf, "$%s", name);
        !           593:                n = identname(buf, false);
        !           594:            }
        !           595:        }
        !           596:        if ((np->n_type&N_TYPE) == N_TEXT) {
        !           597:            count = 0;
        !           598:            t = findsym(n, &isextref);
        !           599:            while (isextref) {
        !           600:                ++count;
        !           601:                updateTextSym(t, name, np->n_value);
        !           602:                t = findsym(n, &isextref);
        !           603:            }
        !           604:            if (count == 0) {
        !           605:                if (t == nil) {
        !           606:                    t = deffunc(n);
        !           607:                    updateTextSym(t, name, np->n_value);
        !           608:                    if (tracesyms) {
        !           609:                        printdecl(t);
        !           610:                    }
        !           611:                } else {
        !           612:                    if (t->class == MODULE) {
        !           613:                        u = t;
        !           614:                        t = deffunc(n);
        !           615:                        t->block = u;
        !           616:                        if (tracesyms) {
        !           617:                            printdecl(t);
        !           618:                        }
        !           619:                    }
        !           620:                    updateTextSym(t, name, np->n_value);
        !           621:                }
        !           622:            }
        !           623:        } else if ((np->n_type&N_TYPE) == N_BSS) {
        !           624:            find(t, n) where
        !           625:                t->class == COMMON
        !           626:            endfind(t);
        !           627:            if (t != nil) {
        !           628:                u = (Symbol) t->symvalue.common.offset;
        !           629:                while (u != nil) {
        !           630:                    u->symvalue.offset = u->symvalue.common.offset+np->n_value;
        !           631:                    u = u->symvalue.common.chain;
        !           632:                }
        !           633:             } else {
        !           634:                check_var(np, n);
        !           635:            }
        !           636:         } else {
        !           637:            check_var(np, n);
        !           638:        }
        !           639:     }
        !           640: }
        !           641: 
        !           642: /*
        !           643:  * Check to see if a namelist entry refers to a variable.
        !           644:  * If not, create a variable for the entry.  In any case,
        !           645:  * set the offset of the variable according to the value field
        !           646:  * in the entry.
        !           647:  *
        !           648:  * If the external name has been referred to by several other symbols,
        !           649:  * we must update each of them.
        !           650:  */
        !           651: 
        !           652: private check_var (np, n)
        !           653: struct nlist *np;
        !           654: register Name n;
        !           655: {
        !           656:     register Symbol t, u, next;
        !           657:     Symbol conflict;
        !           658: 
        !           659:     t = lookup(n);
        !           660:     if (t == nil) {
        !           661:        t = defvar(n);
        !           662:        t->symvalue.offset = np->n_value;
        !           663:        if (tracesyms) {
        !           664:            printdecl(t);
        !           665:        }
        !           666:     } else {
        !           667:        conflict = nil;
        !           668:        do {
        !           669:            next = t->next_sym;
        !           670:            if (t->name == n) {
        !           671:                if (t->class == MODULE and t->block == program) {
        !           672:                    conflict = t;
        !           673:                } else if (t->class == EXTREF and t->level == program->level) {
        !           674:                    u = t->symvalue.extref;
        !           675:                    while (u != nil and u->class == EXTREF) {
        !           676:                        u = u->symvalue.extref;
        !           677:                    }
        !           678:                    u->symvalue.offset = np->n_value;
        !           679:                    delete(t);
        !           680:                } else if (t->level == program->level and
        !           681:                    (t->class == VAR or t->class == PROC or t->class == FUNC)
        !           682:                ) {
        !           683:                    conflict = nil;
        !           684:                    t->symvalue.offset = np->n_value;
        !           685:                }
        !           686:            }
        !           687:            t = next;
        !           688:        } while (t != nil);
        !           689:        if (conflict != nil) {
        !           690:            u = defvar(n);
        !           691:            u->block = conflict;
        !           692:            u->symvalue.offset = np->n_value;
        !           693:        }
        !           694:     }
        !           695: }
        !           696: 
        !           697: /*
        !           698:  * Check to see if a local _name is known in the current scope.
        !           699:  * If not then enter it.
        !           700:  */
        !           701: 
        !           702: private check_local (name, np)
        !           703: String name;
        !           704: register struct nlist *np;
        !           705: {
        !           706:     register Name n;
        !           707:     register Symbol t, cur;
        !           708: 
        !           709:     n = identname(name, true);
        !           710:     cur = ((np->n_type&N_TYPE) == N_TEXT) ? curmodule : curblock;
        !           711:     find(t, n) where t->block == cur endfind(t);
        !           712:     if (t == nil) {
        !           713:        t = insert(n);
        !           714:        t->language = findlanguage(".s");
        !           715:        t->type = t_int;
        !           716:        t->block = cur;
        !           717:        t->level = cur->level;
        !           718:        if ((np->n_type&N_TYPE) == N_TEXT) {
        !           719:            t->class = FUNC;
        !           720:            t->symvalue.funcv.src = false;
        !           721:            t->symvalue.funcv.inline = false;
        !           722:            t->symvalue.funcv.beginaddr = np->n_value;
        !           723:            newfunc(t, codeloc(t));
        !           724:            findbeginning(t);
        !           725:        } else {
        !           726:            t->class = VAR;
        !           727:            t->symvalue.offset = np->n_value;
        !           728:        }
        !           729:     }
        !           730: }
        !           731: 
        !           732: /*
        !           733:  * Check to see if a symbol corresponds to a object file name.
        !           734:  * For some reason these are listed as in the text segment.
        !           735:  */
        !           736: 
        !           737: private check_filename (name)
        !           738: String name;
        !           739: {
        !           740:     register String mname;
        !           741:     register integer i;
        !           742:     Name n;
        !           743:     Symbol s;
        !           744: 
        !           745:     mname = strdup(name);
        !           746:     i = strlen(mname) - 2;
        !           747:     if (i >= 0 and mname[i] == '.' and mname[i+1] == 'o') {
        !           748:        mname[i] = '\0';
        !           749:        --i;
        !           750:        while (mname[i] != '/' and i >= 0) {
        !           751:            --i;
        !           752:        }
        !           753:        n = identname(&mname[i+1], true);
        !           754:        find(s, n) where s->block == program and s->class == MODULE endfind(s);
        !           755:        if (s == nil) {
        !           756:            s = insert(n);
        !           757:            s->language = findlanguage(".s");
        !           758:            s->class = MODULE;
        !           759:            s->symvalue.funcv.beginaddr = 0;
        !           760:            findbeginning(s);
        !           761:        }
        !           762:        if (curblock->class != PROG) {
        !           763:            exitblock();
        !           764:            if (curblock->class != PROG) {
        !           765:                exitblock();
        !           766:            }
        !           767:        }
        !           768:        enterblock(s);
        !           769:        curmodule = s;
        !           770:     }
        !           771: }
        !           772: 
        !           773: /*
        !           774:  * Check to see if a symbol is about to be defined within an unnamed block.
        !           775:  * If this happens, we create a procedure for the unnamed block, make it
        !           776:  * "inline" so that tracebacks don't associate an activation record with it,
        !           777:  * and enter it into the function table so that it will be detected
        !           778:  * by "whatblock".
        !           779:  */
        !           780: 
        !           781: public chkUnnamedBlock ()
        !           782: {
        !           783:     register Symbol s;
        !           784:     static int bnum = 0;
        !           785:     char buf[100];
        !           786:     Address startaddr;
        !           787: 
        !           788:     if (nesting > 0 and addrstk[nesting] != NOADDR) {
        !           789:        startaddr = (linep - 1)->addr;
        !           790:        ++bnum;
        !           791:        sprintf(buf, "$b%d", bnum);
        !           792:        s = insert(identname(buf, false));
        !           793:        s->language = curlang;
        !           794:        s->class = PROC;
        !           795:        s->symvalue.funcv.src = false;
        !           796:        s->symvalue.funcv.inline = true;
        !           797:        s->symvalue.funcv.beginaddr = startaddr;
        !           798:        enterblock(s);
        !           799:        newfunc(s, startaddr);
        !           800:        addrstk[nesting] = NOADDR;
        !           801:     }
        !           802: }
        !           803: 
        !           804: /*
        !           805:  * Compilation unit.  C associates scope with filenames
        !           806:  * so we treat them as "modules".  The filename without
        !           807:  * the suffix is used for the module name.
        !           808:  *
        !           809:  * Because there is no explicit "end-of-block" mark in
        !           810:  * the object file, we must exit blocks for the current
        !           811:  * procedure and module.
        !           812:  */
        !           813: 
        !           814: private enterSourceModule (n, addr)
        !           815: Name n;
        !           816: Address addr;
        !           817: {
        !           818:     register Symbol s;
        !           819:     Name nn;
        !           820:     String mname, suffix;
        !           821: 
        !           822:     mname = strdup(ident(n));
        !           823:     if (rindex(mname, '/') != nil) {
        !           824:        mname = rindex(mname, '/') + 1;
        !           825:     }
        !           826:     suffix = rindex(mname, '.');
        !           827:     curlang = findlanguage(suffix);
        !           828:     if (curlang == findlanguage(".f")) {
        !           829:        strip_ = true;
        !           830:     } 
        !           831:     if (suffix != nil) {
        !           832:        *suffix = '\0';
        !           833:     }
        !           834:     if (not (*language_op(curlang, L_HASMODULES))()) {
        !           835:        if (curblock->class != PROG) {
        !           836:            exitblock();
        !           837:            if (curblock->class != PROG) {
        !           838:                exitblock();
        !           839:            }
        !           840:        }
        !           841:        nn = identname(mname, true);
        !           842:        if (curmodule == nil or curmodule->name != nn) {
        !           843:            s = insert(nn);
        !           844:            s->class = MODULE;
        !           845:            s->symvalue.funcv.beginaddr = 0;
        !           846:            findbeginning(s);
        !           847:        } else {
        !           848:            s = curmodule;
        !           849:        }
        !           850:        s->language = curlang;
        !           851:        enterblock(s);
        !           852:        curmodule = s;
        !           853:     }
        !           854:     if (program->language == nil) {
        !           855:        program->language = curlang;
        !           856:     }
        !           857:     warned = false;
        !           858:     enterfile(ident(n), addr);
        !           859:     initTypeTable();
        !           860: }
        !           861: 
        !           862: /*
        !           863:  * Allocate file and line tables and initialize indices.
        !           864:  */
        !           865: 
        !           866: private allocmaps (nf, nl)
        !           867: integer nf, nl;
        !           868: {
        !           869:     if (filetab != nil) {
        !           870:        dispose(filetab);
        !           871:     }
        !           872:     if (linetab != nil) {
        !           873:        dispose(linetab);
        !           874:     }
        !           875:     filetab = newarr(Filetab, nf);
        !           876:     linetab = newarr(Linetab, nl);
        !           877:     filep = filetab;
        !           878:     linep = linetab;
        !           879: }
        !           880: 
        !           881: /*
        !           882:  * Add a file to the file table.
        !           883:  *
        !           884:  * If the new address is the same as the previous file address
        !           885:  * this routine used to not enter the file, but this caused some
        !           886:  * problems so it has been removed.  It's not clear that this in
        !           887:  * turn may not also cause a problem.
        !           888:  */
        !           889: 
        !           890: private enterfile (filename, addr)
        !           891: String filename;
        !           892: Address addr;
        !           893: {
        !           894:     filep->addr = addr;
        !           895:     filep->filename = filename;
        !           896:     filep->lineindex = linep - linetab;
        !           897:     ++filep;
        !           898: }
        !           899: 
        !           900: /*
        !           901:  * Since we only estimated the number of lines (and it was a poor
        !           902:  * estimation) and since we need to know the exact number of lines
        !           903:  * to do a binary search, we set it when we're done.
        !           904:  */
        !           905: 
        !           906: private setnlines ()
        !           907: {
        !           908:     nlhdr.nlines = linep - linetab;
        !           909: }
        !           910: 
        !           911: /*
        !           912:  * Similarly for nfiles ...
        !           913:  */
        !           914: 
        !           915: private setnfiles ()
        !           916: {
        !           917:     nlhdr.nfiles = filep - filetab;
        !           918:     setsource(filetab[0].filename);
        !           919: }

unix.superglobalmegacorp.com

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