Annotation of 43BSDReno/pgrm/dbx/object.c, revision 1.1

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

unix.superglobalmegacorp.com

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