|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.