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: }

Defined functions

allocmaps defined in line 866; used 1 times
changeBlock defined in line 102; used 1 times
check_filename defined in line 737; used 1 times
check_global defined in line 576; used 2 times
check_local defined in line 702; used 1 times
check_var defined in line 652; used 2 times
chkUnnamedBlock defined in line 781; used 1 times
curfilename defined in line 65; used 4 times
deffunc defined in line 516; used 2 times
defvar defined in line 537; used 2 times
enterSourceModule defined in line 814; used 1 times
enter_nl defined in line 354; used 1 times
enterblock defined in line 108; used 5 times
enterfile defined in line 890; used 2 times
exitblock defined in line 120; used 11 times
findsym defined in line 467; used 2 times
foundglobals defined in line 216; used 2 times
getcont defined in line 304; used 1 times
initsyms defined in line 322; used 2 times
objfree defined in line 341; used 1 times
pushBlock defined in line 83; used 2 times
readobj defined in line 169; used 2 times
readsyms defined in line 231; used 1 times
setnfiles defined in line 915; used 1 times
setnlines defined in line 906; used 1 times
updateTextSym defined in line 555; used 3 times

Defined variables

Symbol defined in line 76; used 24 times
bnum defined in line 80; used 3 times
curblock defined in line 76; used 23 times
curlevel defined in line 79; used 9 times
curnp defined in line 58; used 6 times
nesting defined in line 80; used 9 times
objname defined in line 48; never used
objsize defined in line 49; used 2 times
private defined in line 354; never used
public defined in line 341; never used
rcsid defined in line 11; never used
sccsid defined in line 8; never used
stringtab defined in line 57; used 4 times

Defined macros

MAXBLKDEPTH defined in line 74; used 3 times
N_MOD2 defined in line 45; used 1 times
  • in line 44
enterline defined in line 147; used 2 times
Last modified: 1985-05-31
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2221
Valid CSS Valid XHTML 1.0 Strict