Annotation of 43BSD/ucb/dbx/object.c, revision 1.1.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.