Annotation of 42BSD/ucb/dbx/object.c, revision 1.1.1.1

1.1       root        1: /* Copyright (c) 1982 Regents of the University of California */
                      2: 
                      3: static char sccsid[] = "@(#)object.c 1.14 10/22/83";
                      4: 
                      5: /*
                      6:  * Object code interface, mainly for extraction of symbolic information.
                      7:  */
                      8: 
                      9: #include "defs.h"
                     10: #include "object.h"
                     11: #include "main.h"
                     12: #include "symbols.h"
                     13: #include "names.h"
                     14: #include "languages.h"
                     15: #include "mappings.h"
                     16: #include "lists.h"
                     17: #include <a.out.h>
                     18: #include <stab.h>
                     19: #include <ctype.h>
                     20: 
                     21: #ifndef public
                     22: 
                     23: struct {
                     24:     unsigned int stringsize;   /* size of the dumped string table */
                     25:     unsigned int nsyms;                /* number of symbols */
                     26:     unsigned int nfiles;       /* number of files */
                     27:     unsigned int nlines;       /* number of lines */
                     28: } nlhdr;
                     29: 
                     30: #endif
                     31: 
                     32: public String objname = "a.out";
                     33: public Integer objsize;
                     34: public char *stringtab;
                     35: 
                     36: private String progname = nil;
                     37: private Language curlang;
                     38: private Symbol curmodule;
                     39: private Symbol curparam;
                     40: private Boolean warned;
                     41: private Symbol curcomm;
                     42: private Symbol commchain;
                     43: private Boolean strip_ = false;
                     44: 
                     45: private Filetab *filep;
                     46: private Linetab *linep, *prevlinep;
                     47: 
                     48: #define curfilename() (filep-1)->filename
                     49: 
                     50: /*
                     51:  * Blocks are figured out on the fly while reading the symbol table.
                     52:  */
                     53: 
                     54: #define MAXBLKDEPTH 25
                     55: 
                     56: private Symbol curblock;
                     57: private Symbol blkstack[MAXBLKDEPTH];
                     58: private Integer curlevel;
                     59: private Integer bnum, nesting;
                     60: private Address addrstk[MAXBLKDEPTH];
                     61: 
                     62: #define enterblock(b) { \
                     63:     blkstack[curlevel] = curblock; \
                     64:     ++curlevel; \
                     65:     b->level = curlevel; \
                     66:     b->block = curblock; \
                     67:     curblock = b; \
                     68: }
                     69: 
                     70: #define exitblock() { \
                     71:     if (curblock->class == FUNC or curblock->class == PROC) { \
                     72:        if (prevlinep != linep) { \
                     73:            curblock->symvalue.funcv.src = true; \
                     74:        } \
                     75:     } \
                     76:     --curlevel; \
                     77:     curblock = blkstack[curlevel]; \
                     78: }
                     79: 
                     80: /*
                     81:  * Enter a source line or file name reference into the appropriate table.
                     82:  * Expanded inline to reduce procedure calls.
                     83:  *
                     84:  * private enterline(linenumber, address)
                     85:  * Lineno linenumber;
                     86:  * Address address;
                     87:  *  ...
                     88:  */
                     89: 
                     90: #define enterline(linenumber, address) \
                     91: { \
                     92:     register Linetab *lp; \
                     93:  \
                     94:     lp = linep - 1; \
                     95:     if (linenumber != lp->line) { \
                     96:        if (address != lp->addr) { \
                     97:            ++lp; \
                     98:        } \
                     99:        lp->line = linenumber; \
                    100:        lp->addr = address; \
                    101:        linep = lp + 1; \
                    102:     } \
                    103: }
                    104: 
                    105: #define NTYPES 1000
                    106: 
                    107: private Symbol typetable[NTYPES];
                    108: 
                    109: /*
                    110:  * Read in the namelist from the obj file.
                    111:  *
                    112:  * Reads and seeks are used instead of fread's and fseek's
                    113:  * for efficiency sake; there's a lot of data being read here.
                    114:  */
                    115: 
                    116: public readobj(file)
                    117: String file;
                    118: {
                    119:     Fileid f;
                    120:     struct exec hdr;
                    121:     struct nlist nlist;
                    122: 
                    123:     f = open(file, 0);
                    124:     if (f < 0) {
                    125:        fatal("can't open %s", file);
                    126:     }
                    127:     read(f, &hdr, sizeof(hdr));
                    128:     objsize = hdr.a_text;
                    129:     nlhdr.nsyms = hdr.a_syms / sizeof(nlist);
                    130:     nlhdr.nfiles = nlhdr.nsyms;
                    131:     nlhdr.nlines = nlhdr.nsyms;
                    132:     if (nlhdr.nsyms > 0) {
                    133:        lseek(f, (long) N_STROFF(hdr), 0);
                    134:        read(f, &(nlhdr.stringsize), sizeof(nlhdr.stringsize));
                    135:        nlhdr.stringsize -= 4;
                    136:        stringtab = newarr(char, nlhdr.stringsize);
                    137:        read(f, stringtab, nlhdr.stringsize);
                    138:        allocmaps(nlhdr.nfiles, nlhdr.nlines);
                    139:        lseek(f, (long) N_SYMOFF(hdr), 0);
                    140:        readsyms(f);
                    141:        ordfunctab();
                    142:        setnlines();
                    143:        setnfiles();
                    144:     }
                    145:     close(f);
                    146: }
                    147: 
                    148: /*
                    149:  * Read in symbols from object file.
                    150:  */
                    151: 
                    152: private readsyms(f)
                    153: Fileid f;
                    154: {
                    155:     struct nlist *namelist;
                    156:     register struct nlist *np, *ub;
                    157:     register int index;
                    158:     register String name;
                    159:     register Boolean afterlg;
                    160: 
                    161:     initsyms();
                    162:     namelist = newarr(struct nlist, nlhdr.nsyms);
                    163:     read(f, namelist, nlhdr.nsyms * sizeof(struct nlist));
                    164:     afterlg = false;
                    165:     ub = &namelist[nlhdr.nsyms];
                    166:     for (np = &namelist[0]; np < ub; np++) {
                    167:        index = np->n_un.n_strx;
                    168:        if (index != 0) {
                    169:            name = &stringtab[index - 4];
                    170:            /*
                    171:              *  if the program contains any .f files a trailing _ is stripped
                    172:                     *  from the name on the assumption it was added by the compiler.
                    173:             *  This only affects names that follow the sdb N_SO entry with
                    174:              *  the .f name. 
                    175:              */
                    176:             if (strip_ and name[0] != '\0' ) {
                    177:                register char *p;
                    178: 
                    179:                p = name;
                    180:                while (*p != '\0') {
                    181:                    ++p;
                    182:                }
                    183:                --p;
                    184:                if (*p == '_') {
                    185:                    *p = '\0';
                    186:                }
                    187:             }
                    188: 
                    189:        } else {
                    190:            name = nil;
                    191:        } 
                    192:        /*
                    193:         * assumptions:
                    194:         *      not an N_STAB   ==> name != nil
                    195:         *      name[0] == '-'  ==> name == "-lg"
                    196:         *      name[0] != '_'  ==> filename or invisible
                    197:         *
                    198:         * The "-lg" signals the beginning of global loader symbols.
                    199:          *
                    200:         */
                    201:        if ((np->n_type&N_STAB) != 0) {
                    202:            enter_nl(name, np);
                    203:        } else if (name[0] == '-') {
                    204:            afterlg = true;
                    205:            if (curblock->class != PROG) {
                    206:                exitblock();
                    207:                if (curblock->class != PROG) {
                    208:                    exitblock();
                    209:                }
                    210:            }
                    211:            enterline(0, (linep-1)->addr + 1);
                    212:        } else if (afterlg) {
                    213:            if (name[0] == '_') {
                    214:                check_global(&name[1], np);
                    215:            }
                    216:        } else if (name[0] == '_') {
                    217:            check_local(&name[1], np);
                    218:        } else if ((np->n_type&N_TEXT) == N_TEXT) {
                    219:            check_filename(name);
                    220:        }
                    221:     }
                    222:     if (not afterlg) {
                    223:        fatal("not linked for debugging, use \"cc -g ...\"");
                    224:     }
                    225:     dispose(namelist);
                    226: }
                    227: 
                    228: /*
                    229:  * Initialize symbol information.
                    230:  */
                    231: 
                    232: private initsyms()
                    233: {
                    234:     curblock = nil;
                    235:     curlevel = 0;
                    236:     nesting = 0;
                    237:     if (progname == nil) {
                    238:        progname = strdup(objname);
                    239:        if (rindex(progname, '/') != nil) {
                    240:            progname = rindex(progname, '/') + 1;
                    241:        }
                    242:        if (index(progname, '.') != nil) {
                    243:            *(index(progname, '.')) = '\0';
                    244:        }
                    245:     }
                    246:     program = insert(identname(progname, true));
                    247:     program->class = PROG;
                    248:     program->symvalue.funcv.beginaddr = 0;
                    249:     program->symvalue.funcv.inline = false;
                    250:     newfunc(program, codeloc(program));
                    251:     findbeginning(program);
                    252:     enterblock(program);
                    253:     curmodule = program;
                    254: }
                    255: 
                    256: /*
                    257:  * Free all the object file information that's being stored.
                    258:  */
                    259: 
                    260: public objfree()
                    261: {
                    262:     symbol_free();
                    263:     keywords_free();
                    264:     names_free();
                    265:     dispose(stringtab);
                    266:     clrfunctab();
                    267: }
                    268: 
                    269: /*
                    270:  * Enter a namelist entry.
                    271:  */
                    272: 
                    273: private enter_nl(name, np)
                    274: String name;
                    275: register struct nlist *np;
                    276: {
                    277:     register Symbol s;
                    278:     register Name n, nn;
                    279:     char buf[100];
                    280: 
                    281:     s = nil;
                    282:     if (name == nil) {
                    283:        n = nil;
                    284:     } else {
                    285:        n = identname(name, true);
                    286:     }
                    287:     switch (np->n_type) {
                    288:        /*
                    289:         * Build a symbol for the FORTRAN common area.  All GSYMS that follow
                    290:         * will be chained in a list with the head kept in common.offset, and
                    291:         * the tail in common.chain.
                    292:         */
                    293:        case N_BCOMM:
                    294:            if (curcomm) {
                    295:                curcomm->symvalue.common.chain = commchain;
                    296:            }
                    297:            curcomm = lookup(n);
                    298:            if (curcomm == nil) {
                    299:                curcomm = insert(n);
                    300:                curcomm->class = COMMON;
                    301:                curcomm->block = curblock;
                    302:                curcomm->level = program->level;
                    303:                curcomm->symvalue.common.chain = nil;
                    304:            }
                    305:            commchain = curcomm->symvalue.common.chain;
                    306:            break;
                    307: 
                    308:        case N_ECOMM:
                    309:            if (curcomm) {
                    310:                curcomm->symvalue.common.chain = commchain;
                    311:                curcomm = nil;
                    312:            }
                    313:            break;
                    314: 
                    315:        case N_LBRAC:
                    316:            ++nesting;
                    317:            addrstk[nesting] = (linep - 1)->addr;
                    318:            break;
                    319: 
                    320:        case N_RBRAC:
                    321:            if (addrstk[nesting] == NOADDR) {
                    322:                exitblock();
                    323:                newfunc(curblock, (linep - 1)->addr);
                    324:            }
                    325:            --nesting;
                    326:            break;
                    327: 
                    328:        case N_SLINE:
                    329:            enterline((Lineno) np->n_desc, (Address) np->n_value);
                    330:            break;
                    331: 
                    332:        /*
                    333:         * Source files.
                    334:         */
                    335:        case N_SO:
                    336:            enterSourceModule(n, (Address) np->n_value);
                    337:            break;
                    338: 
                    339:        /*
                    340:         * Textually included files.
                    341:         */
                    342:        case N_SOL:
                    343:            enterfile(name, (Address) np->n_value);
                    344:            break;
                    345: 
                    346:        /*
                    347:         * These symbols are assumed to have non-nil names.
                    348:         */
                    349:        case N_GSYM:
                    350:        case N_FUN:
                    351:        case N_STSYM:
                    352:        case N_LCSYM:
                    353:        case N_RSYM:
                    354:        case N_PSYM:
                    355:        case N_LSYM:
                    356:        case N_SSYM:
                    357:        case N_LENG:
                    358:            if (index(name, ':') == nil) {
                    359:                if (not warned) {
                    360:                    warned = true;
                    361:                    warning("old style symbol information found in \"%s\"",
                    362:                        curfilename());
                    363:                }
                    364:            } else {
                    365:                entersym(name, np);
                    366:            }
                    367:            break;
                    368: 
                    369:        case N_PC:
                    370:            break;
                    371: 
                    372:        default:
                    373:            printf("warning:  stab entry unrecognized: ");
                    374:            if (name != nil) {
                    375:                printf("name %s,", name);
                    376:            }
                    377:            printf("ntype %2x, desc %x, value %x'\n",
                    378:                np->n_type, np->n_desc, np->n_value);
                    379:            break;
                    380:     }
                    381: }
                    382: 
                    383: /*
                    384:  * Check to see if a global _name is already in the symbol table,
                    385:  * if not then insert it.
                    386:  */
                    387: 
                    388: private check_global(name, np)
                    389: String name;
                    390: register struct nlist *np;
                    391: {
                    392:     register Name n;
                    393:     register Symbol t, u;
                    394: 
                    395:     if (not streq(name, "end")) {
                    396:        n = identname(name, true);
                    397:        if ((np->n_type&N_TYPE) == N_TEXT) {
                    398:            find(t, n) where
                    399:                t->level == program->level and
                    400:                (t->class == PROC or t->class == FUNC)
                    401:            endfind(t);
                    402:            if (t == nil) {
                    403:                t = insert(n);
                    404:                t->language = findlanguage(".s");
                    405:                t->class = FUNC;
                    406:                t->type = t_int;
                    407:                t->block = curblock;
                    408:                t->level = program->level;
                    409:                t->symvalue.funcv.src = false;
                    410:                t->symvalue.funcv.inline = false;
                    411:            }
                    412:            t->symvalue.funcv.beginaddr = np->n_value;
                    413:            newfunc(t, codeloc(t));
                    414:            findbeginning(t);
                    415:        } else if ((np->n_type&N_TYPE) == N_BSS) {
                    416:            find(t, n) where
                    417:                t->class == COMMON
                    418:            endfind(t);
                    419:            if (t != nil) {
                    420:                u = (Symbol) t->symvalue.common.offset;
                    421:                while (u != nil) {
                    422:                    u->symvalue.offset = u->symvalue.common.offset+np->n_value;
                    423:                    u = u->symvalue.common.chain;
                    424:                }
                    425:             } else {
                    426:                check_var(np, n);
                    427:            }
                    428:         } else {
                    429:            check_var(np, n);
                    430:        }
                    431:     }
                    432: }
                    433: 
                    434: /*
                    435:  * Check to see if a namelist entry refers to a variable.
                    436:  * If not, create a variable for the entry.  In any case,
                    437:  * set the offset of the variable according to the value field
                    438:  * in the entry.
                    439:  */
                    440: 
                    441: private check_var(np, n)
                    442: struct nlist *np;
                    443: register Name n;
                    444: {
                    445:     register Symbol t;
                    446: 
                    447:     find(t, n) where
                    448:        t->class == VAR and t->level == program->level
                    449:     endfind(t);
                    450:     if (t == nil) {
                    451:        t = insert(n);
                    452:        t->language = findlanguage(".s");
                    453:        t->class = VAR;
                    454:        t->type = t_int;
                    455:        t->level = program->level;
                    456:     }
                    457:     t->block = curblock;
                    458:     t->symvalue.offset = np->n_value;
                    459: }
                    460: 
                    461: /*
                    462:  * Check to see if a local _name is known in the current scope.
                    463:  * If not then enter it.
                    464:  */
                    465: 
                    466: private check_local(name, np)
                    467: String name;
                    468: register struct nlist *np;
                    469: {
                    470:     register Name n;
                    471:     register Symbol t, cur;
                    472: 
                    473:     n = identname(name, true);
                    474:     cur = ((np->n_type&N_TYPE) == N_TEXT) ? curmodule : curblock;
                    475:     find(t, n) where t->block == cur endfind(t);
                    476:     if (t == nil) {
                    477:        t = insert(n);
                    478:        t->language = findlanguage(".s");
                    479:        t->type = t_int;
                    480:        t->block = cur;
                    481:        t->level = cur->level;
                    482:        if ((np->n_type&N_TYPE) == N_TEXT) {
                    483:            t->class = FUNC;
                    484:            t->symvalue.funcv.src = false;
                    485:            t->symvalue.funcv.inline = false;
                    486:            t->symvalue.funcv.beginaddr = np->n_value;
                    487:            newfunc(t, codeloc(t));
                    488:            findbeginning(t);
                    489:        } else {
                    490:            t->class = VAR;
                    491:            t->symvalue.offset = np->n_value;
                    492:        }
                    493:     }
                    494: }
                    495: 
                    496: /*
                    497:  * Check to see if a symbol corresponds to a object file name.
                    498:  * For some reason these are listed as in the text segment.
                    499:  */
                    500: 
                    501: private check_filename(name)
                    502: String name;
                    503: {
                    504:     register String mname;
                    505:     register Integer i;
                    506:     register Symbol s;
                    507: 
                    508:     mname = strdup(name);
                    509:     i = strlen(mname) - 2;
                    510:     if (i >= 0 and mname[i] == '.' and mname[i+1] == 'o') {
                    511:        mname[i] = '\0';
                    512:        --i;
                    513:        while (mname[i] != '/' and i >= 0) {
                    514:            --i;
                    515:        }
                    516:        s = insert(identname(&mname[i+1], true));
                    517:        s->language = findlanguage(".s");
                    518:        s->class = MODULE;
                    519:        s->symvalue.funcv.beginaddr = 0;
                    520:        findbeginning(s);
                    521:        if (curblock->class != PROG) {
                    522:            exitblock();
                    523:            if (curblock->class != PROG) {
                    524:                exitblock();
                    525:            }
                    526:        }
                    527:        enterblock(s);
                    528:        curmodule = s;
                    529:     }
                    530: }
                    531: 
                    532: /*
                    533:  * Check to see if a symbol is about to be defined within an unnamed block.
                    534:  * If this happens, we create a procedure for the unnamed block, make it
                    535:  * "inline" so that tracebacks don't associate an activation record with it,
                    536:  * and enter it into the function table so that it will be detected
                    537:  * by "whatblock".
                    538:  */
                    539: 
                    540: private unnamed_block()
                    541: {
                    542:     register Symbol s;
                    543:     static int bnum = 0;
                    544:     char buf[100];
                    545: 
                    546:     ++bnum;
                    547:     sprintf(buf, "$b%d", bnum);
                    548:     s = insert(identname(buf, false));
                    549:     s->class = PROG;
                    550:     s->symvalue.funcv.src = false;
                    551:     s->symvalue.funcv.inline = true;
                    552:     s->symvalue.funcv.beginaddr = addrstk[nesting];
                    553:     enterblock(s);
                    554:     newfunc(s, addrstk[nesting]);
                    555:     addrstk[nesting] = NOADDR;
                    556: }
                    557: 
                    558: /*
                    559:  * Compilation unit.  C associates scope with filenames
                    560:  * so we treat them as "modules".  The filename without
                    561:  * the suffix is used for the module name.
                    562:  *
                    563:  * Because there is no explicit "end-of-block" mark in
                    564:  * the object file, we must exit blocks for the current
                    565:  * procedure and module.
                    566:  */
                    567: 
                    568: private enterSourceModule(n, addr)
                    569: Name n;
                    570: Address addr;
                    571: {
                    572:     register Symbol s;
                    573:     Name nn;
                    574:     String mname, suffix;
                    575: 
                    576:     mname = strdup(ident(n));
                    577:     if (rindex(mname, '/') != nil) {
                    578:        mname = rindex(mname, '/') + 1;
                    579:     }
                    580:     suffix = rindex(mname, '.');
                    581:     curlang = findlanguage(suffix);
                    582:     if (curlang == findlanguage(".f")) {
                    583:        strip_ = true;
                    584:     } 
                    585:     if (suffix != nil) {
                    586:        *suffix = '\0';
                    587:     }
                    588:     if (curblock->class != PROG) {
                    589:        exitblock();
                    590:        if (curblock->class != PROG) {
                    591:            exitblock();
                    592:        }
                    593:     }
                    594:     nn = identname(mname, true);
                    595:     if (curmodule == nil or curmodule->name != nn) {
                    596:        s = insert(nn);
                    597:        s->class = MODULE;
                    598:        s->symvalue.funcv.beginaddr = 0;
                    599:        findbeginning(s);
                    600:     } else {
                    601:        s = curmodule;
                    602:     }
                    603:     s->language = curlang;
                    604:     enterblock(s);
                    605:     curmodule = s;
                    606:     if (program->language == nil) {
                    607:        program->language = curlang;
                    608:     }
                    609:     warned = false;
                    610:     enterfile(ident(n), addr);
                    611:     bzero(typetable, sizeof(typetable));
                    612: }
                    613: 
                    614: /*
                    615:  * Put an nlist into the symbol table.
                    616:  * If it's already there just add the associated information.
                    617:  *
                    618:  * Type information is encoded in the name following a ":".
                    619:  */
                    620: 
                    621: private Symbol constype();
                    622: private Char *curchar;
                    623: 
                    624: #define skipchar(ptr, ch) { \
                    625:     if (*ptr != ch) { \
                    626:        panic("expected char '%c', found char '%c'", ch, *ptr); \
                    627:     } \
                    628:     ++ptr; \
                    629: }
                    630: 
                    631: private entersym(str, np)
                    632: String str;
                    633: struct nlist *np;
                    634: {
                    635:     register Symbol s;
                    636:     register char *p;
                    637:     register int c;
                    638:     register Name n;
                    639:     register Integer i;
                    640:     Boolean knowtype, isnew;
                    641:     Symclass class;
                    642:     Integer level;
                    643: 
                    644:     p = index(str, ':');
                    645:     *p = '\0';
                    646:     c = *(p+1);
                    647:     n = identname(str, true);
                    648:     if (index("FfGV", c) != nil) {
                    649:        if (c == 'F' or c == 'f') {
                    650:            class = FUNC;
                    651:        } else {
                    652:            class = VAR;
                    653:        }
                    654:        level = (c == 'f' ? curmodule->level : program->level);
                    655:        find(s, n) where s->level == level and s->class == class endfind(s);
                    656:        if (s == nil) {
                    657:            isnew = true;
                    658:            s = insert(n);
                    659:        } else {
                    660:            isnew = false;
                    661:        }
                    662:     } else {
                    663:        isnew = true;
                    664:        s = insert(n);
                    665:     }
                    666: 
                    667:     if (nesting > 0 and addrstk[nesting] != NOADDR) {
                    668:        unnamed_block();
                    669:     }
                    670: 
                    671:     /*
                    672:      * Default attributes.
                    673:      */
                    674:     s->language = curlang;
                    675:     s->class = VAR;
                    676:     s->block = curblock;
                    677:     s->level = curlevel;
                    678:     s->symvalue.offset = np->n_value;
                    679:     curchar = p + 2;
                    680:     knowtype = false;
                    681:     switch (c) {
                    682:        case 't':       /* type name */
                    683:            s->class = TYPE;
                    684:            i = getint();
                    685:            if (i == 0) {
                    686:                panic("bad input on type \"%s\" at \"%s\"", symname(s),
                    687:                    curchar);
                    688:            } else if (i >= NTYPES) {
                    689:                panic("too many types in file \"%s\"", curfilename());
                    690:            }
                    691:            /*
                    692:             * A hack for C typedefs that don't create new types,
                    693:             * e.g. typedef unsigned int Hashvalue;
                    694:             *  or  typedef struct blah BLAH;
                    695:             */
                    696:            if (*curchar == '\0') {
                    697:                s->type = typetable[i];
                    698:                if (s->type == nil) {
                    699:                    s->type = symbol_alloc();
                    700:                    typetable[i] = s->type;
                    701:                }
                    702:                knowtype = true;
                    703:            } else {
                    704:                typetable[i] = s;
                    705:                skipchar(curchar, '=');
                    706:            }
                    707:            break;
                    708: 
                    709:        case 'T':       /* tag */
                    710:            s->class = TAG;
                    711:            i = getint();
                    712:            if (i == 0) {
                    713:                panic("bad input on tag \"%s\" at \"%s\"", symname(s),
                    714:                    curchar);
                    715:            } else if (i >= NTYPES) {
                    716:                panic("too many types in file \"%s\"", curfilename());
                    717:            }
                    718:            if (typetable[i] != nil) {
                    719:                typetable[i]->language = curlang;
                    720:                typetable[i]->class = TYPE;
                    721:                typetable[i]->type = s;
                    722:            } else {
                    723:                typetable[i] = s;
                    724:            }
                    725:            skipchar(curchar, '=');
                    726:            break;
                    727: 
                    728:        case 'F':       /* public function */
                    729:        case 'f':       /* private function */
                    730:            s->class = FUNC;
                    731:            if (curblock->class == FUNC or curblock->class == PROC) {
                    732:                exitblock();
                    733:            }
                    734:            enterblock(s);
                    735:            if (c == 'F') {
                    736:                s->level = program->level;
                    737:                isnew = false;
                    738:            }
                    739:            curparam = s;
                    740:            if (isnew) {
                    741:                s->symvalue.funcv.src = false;
                    742:                s->symvalue.funcv.inline = false;
                    743:                s->symvalue.funcv.beginaddr = np->n_value;
                    744:                newfunc(s, codeloc(s));
                    745:                findbeginning(s);
                    746:            }
                    747:            break;
                    748: 
                    749:        case 'G':       /* public variable */
                    750:            s->level = program->level;
                    751:            break;
                    752: 
                    753:        case 'S':       /* private variable */
                    754:            s->level = curmodule->level;
                    755:            s->block = curmodule;
                    756:            break;
                    757: 
                    758: /*
                    759:  *  keep global BSS variables chained so can resolve when get the start
                    760:  *  of common; keep the list in order so f77 can display all vars in a COMMON
                    761: */
                    762:        case 'V':       /* own variable */
                    763:            s->level = 2;
                    764:            if (curcomm) {
                    765:              if (commchain != nil) {
                    766:                  commchain->symvalue.common.chain = s;
                    767:              }                   
                    768:              else {
                    769:                  curcomm->symvalue.common.offset = (int) s;
                    770:              }                   
                    771:               commchain = s;
                    772:               s->symvalue.common.offset = np->n_value;
                    773:               s->symvalue.common.chain = nil;
                    774:            }
                    775:            break;
                    776: 
                    777:        case 'r':       /* register variable */
                    778:            s->level = -(s->level);
                    779:            break;
                    780: 
                    781:        case 'p':       /* parameter variable */
                    782:            curparam->chain = s;
                    783:            curparam = s;
                    784:            break;
                    785: 
                    786:        case 'v':       /* varies parameter */
                    787:            s->class = REF;
                    788:            s->symvalue.offset = np->n_value;
                    789:            curparam->chain = s;
                    790:            curparam = s;
                    791:            break;
                    792: 
                    793:        default:        /* local variable */
                    794:            --curchar;
                    795:            break;
                    796:     }
                    797:     if (not knowtype) {
                    798:        s->type = constype(nil);
                    799:        if (s->class == TAG) {
                    800:            addtag(s);
                    801:        }
                    802:     }
                    803:     if (tracesyms) {
                    804:        printdecl(s);
                    805:        fflush(stdout);
                    806:     }
                    807: }
                    808: 
                    809: /*
                    810:  * Construct a type out of a string encoding.
                    811:  *
                    812:  * The forms of the string are
                    813:  *
                    814:  *     <number>
                    815:  *     <number>=<type>
                    816:  *     r<type>;<number>;<number>               $ subrange
                    817:  *     a<type>;<type>                          $ array[index] of element
                    818:  *     s{<name>:<type>;<number>;<number>}      $ record
                    819:  *     S<type>                                 $ set
                    820:  *     *<type>                                 $ pointer
                    821:  */
                    822: 
                    823: private Rangetype getrangetype();
                    824: 
                    825: private Symbol constype(type)
                    826: Symbol type;
                    827: {
                    828:     register Symbol t, u;
                    829:     register Char *p, *cur;
                    830:     register Integer n;
                    831:     Integer b;
                    832:     Name name;
                    833:     Char class;
                    834: 
                    835:     b = curlevel;
                    836:     if (isdigit(*curchar)) {
                    837:        n = getint();
                    838:        if (n == 0) {
                    839:            panic("bad type number at \"%s\"", curchar);
                    840:        } else if (n >= NTYPES) {
                    841:            panic("too many types in file \"%s\"", curfilename());
                    842:        }
                    843:        if (*curchar == '=') {
                    844:            if (typetable[n] != nil) {
                    845:                t = typetable[n];
                    846:            } else {
                    847:                t = symbol_alloc();
                    848:                typetable[n] = t;
                    849:            }
                    850:            ++curchar;
                    851:            constype(t);
                    852:        } else {
                    853:            t = typetable[n];
                    854:            if (t == nil) {
                    855:                t = symbol_alloc();
                    856:                typetable[n] = t;
                    857:            }
                    858:        }
                    859:     } else {
                    860:        if (type == nil) {
                    861:            t = symbol_alloc();
                    862:        } else {
                    863:            t = type;
                    864:        }
                    865:        t->language = curlang;
                    866:        t->level = b;
                    867:        t->block = curblock;
                    868:        class = *curchar++;
                    869:        switch (class) {
                    870:            case 'r':
                    871:                t->class = RANGE;
                    872:                t->type = constype(nil);
                    873:                skipchar(curchar, ';');
                    874:                t->symvalue.rangev.lowertype = getrangetype();
                    875:                t->symvalue.rangev.lower = getint();
                    876:                skipchar(curchar, ';');
                    877:                t->symvalue.rangev.uppertype = getrangetype();
                    878:                t->symvalue.rangev.upper = getint();
                    879:                break;
                    880: 
                    881:            case 'a':
                    882:                t->class = ARRAY;
                    883:                t->chain = constype(nil);
                    884:                skipchar(curchar, ';');
                    885:                t->type = constype(nil);
                    886:                break;
                    887: 
                    888:            case 'S':
                    889:                t->class = SET;
                    890:                t->type = constype(nil);
                    891:                break;
                    892: 
                    893:            case 's':
                    894:            case 'u':
                    895:                t->class = (class == 's') ? RECORD : VARNT;
                    896:                t->symvalue.offset = getint();
                    897:                u = t;
                    898:                cur = curchar;
                    899:                while (*cur != ';' and *cur != '\0') {
                    900:                    p = index(cur, ':');
                    901:                    if (p == nil) {
                    902:                        panic("index(\"%s\", ':') failed", curchar);
                    903:                    }
                    904:                    *p = '\0';
                    905:                    name = identname(cur, true);
                    906:                    u->chain = newSymbol(name, b, FIELD, nil, nil);
                    907:                    cur = p + 1;
                    908:                    u = u->chain;
                    909:                    u->language = curlang;
                    910:                    curchar = cur;
                    911:                    u->type = constype(nil);
                    912:                    skipchar(curchar, ',');
                    913:                    u->symvalue.field.offset = getint();
                    914:                    skipchar(curchar, ',');
                    915:                    u->symvalue.field.length = getint();
                    916:                    skipchar(curchar, ';');
                    917:                    cur = curchar;
                    918:                }
                    919:                if (*cur == ';') {
                    920:                    ++cur;
                    921:                }
                    922:                curchar = cur;
                    923:                break;
                    924: 
                    925:            case 'e':
                    926:                t->class = SCAL;
                    927:                u = t;
                    928:                while (*curchar != ';' and *curchar != '\0') {
                    929:                    p = index(curchar, ':');
                    930:                    assert(p != nil);
                    931:                    *p = '\0';
                    932:                    u->chain = insert(identname(curchar, true));
                    933:                    curchar = p + 1;
                    934:                    u = u->chain;
                    935:                    u->language = curlang;
                    936:                    u->class = CONST;
                    937:                    u->level = b;
                    938:                    u->block = curblock;
                    939:                    u->type = t;
                    940:                    u->symvalue.iconval = getint();
                    941:                    skipchar(curchar, ',');
                    942:                }
                    943:                if (*curchar == ';')
                    944:                        curchar++;
                    945:                break;
                    946: 
                    947:            case '*':
                    948:                t->class = PTR;
                    949:                t->type = constype(nil);
                    950:                break;
                    951: 
                    952:            case 'f':
                    953:                t->class = FUNC;
                    954:                t->type = constype(nil);
                    955:                break;
                    956: 
                    957:            default:
                    958:                badcaseval(class);
                    959:        }
                    960:     }
                    961:     return t;
                    962: }
                    963: 
                    964: /*
                    965:  * Get a range type.
                    966:  *
                    967:  * Special letters indicate a dynamic bound, i.e. what follows
                    968:  * is the offset from the fp which contains the bound.
                    969:  * J is a special flag to handle fortran a(*) bounds.
                    970:  */
                    971: 
                    972: private Rangetype getrangetype()
                    973: {
                    974:     Rangetype t;
                    975: 
                    976:     switch (*curchar) {
                    977:        case 'A':
                    978:            t = R_ARG;
                    979:            curchar++;
                    980:            break;
                    981: 
                    982:        case 'T':
                    983:            t = R_TEMP;
                    984:            curchar++;
                    985:            break;
                    986: 
                    987:        case 'J': 
                    988:            t = R_ADJUST;
                    989:            curchar++;
                    990:            break;
                    991: 
                    992:        default:
                    993:            t = R_CONST;
                    994:            break;
                    995:     }
                    996:     return t;
                    997: }
                    998: 
                    999: /*
                   1000:  * Read an integer from the current position in the type string.
                   1001:  */
                   1002: 
                   1003: private Integer getint()
                   1004: {
                   1005:     register Integer n;
                   1006:     register char *p;
                   1007:     register Boolean isneg;
                   1008: 
                   1009:     n = 0;
                   1010:     p = curchar;
                   1011:     if (*p == '-') {
                   1012:        isneg = true;
                   1013:        ++p;
                   1014:     } else {
                   1015:        isneg = false;
                   1016:     }
                   1017:     while (isdigit(*p)) {
                   1018:        n = 10*n + (*p - '0');
                   1019:        ++p;
                   1020:     }
                   1021:     curchar = p;
                   1022:     return isneg ? (-n) : n;
                   1023: }
                   1024: 
                   1025: /*
                   1026:  * Add a tag name.  This is a kludge to be able to refer
                   1027:  * to tags that have the same name as some other symbol
                   1028:  * in the same block.
                   1029:  */
                   1030: 
                   1031: private addtag(s)
                   1032: register Symbol s;
                   1033: {
                   1034:     register Symbol t;
                   1035:     char buf[100];
                   1036: 
                   1037:     sprintf(buf, "$$%.90s", ident(s->name));
                   1038:     t = insert(identname(buf, false));
                   1039:     t->language = s->language;
                   1040:     t->class = TAG;
                   1041:     t->type = s->type;
                   1042:     t->block = s->block;
                   1043: }
                   1044: 
                   1045: /*
                   1046:  * Allocate file and line tables and initialize indices.
                   1047:  */
                   1048: 
                   1049: private allocmaps(nf, nl)
                   1050: Integer nf, nl;
                   1051: {
                   1052:     if (filetab != nil) {
                   1053:        dispose(filetab);
                   1054:     }
                   1055:     if (linetab != nil) {
                   1056:        dispose(linetab);
                   1057:     }
                   1058:     filetab = newarr(Filetab, nf);
                   1059:     linetab = newarr(Linetab, nl);
                   1060:     filep = filetab;
                   1061:     linep = linetab;
                   1062: }
                   1063: 
                   1064: /*
                   1065:  * Add a file to the file table.
                   1066:  *
                   1067:  * If the new address is the same as the previous file address
                   1068:  * this routine used to not enter the file, but this caused some
                   1069:  * problems so it has been removed.  It's not clear that this in
                   1070:  * turn may not also cause a problem.
                   1071:  */
                   1072: 
                   1073: private enterfile(filename, addr)
                   1074: String filename;
                   1075: Address addr;
                   1076: {
                   1077:     filep->addr = addr;
                   1078:     filep->filename = filename;
                   1079:     filep->lineindex = linep - linetab;
                   1080:     ++filep;
                   1081: }
                   1082: 
                   1083: /*
                   1084:  * Since we only estimated the number of lines (and it was a poor
                   1085:  * estimation) and since we need to know the exact number of lines
                   1086:  * to do a binary search, we set it when we're done.
                   1087:  */
                   1088: 
                   1089: private setnlines()
                   1090: {
                   1091:     nlhdr.nlines = linep - linetab;
                   1092: }
                   1093: 
                   1094: /*
                   1095:  * Similarly for nfiles ...
                   1096:  */
                   1097: 
                   1098: private setnfiles()
                   1099: {
                   1100:     nlhdr.nfiles = filep - filetab;
                   1101:     setsource(filetab[0].filename);
                   1102: }

unix.superglobalmegacorp.com

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