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