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