19673Slinton /* Copyright (c) 1982 Regents of the University of California */ 29673Slinton 3*13938Slinton static char sccsid[] = "@(#)object.c 1.10 07/15/83"; 49673Slinton 59673Slinton /* 69673Slinton * Object code interface, mainly for extraction of symbolic information. 79673Slinton */ 89673Slinton 99673Slinton #include "defs.h" 109673Slinton #include "object.h" 119673Slinton #include "main.h" 129673Slinton #include "symbols.h" 139673Slinton #include "names.h" 149673Slinton #include "languages.h" 159673Slinton #include "mappings.h" 169673Slinton #include "lists.h" 179673Slinton #include <a.out.h> 189673Slinton #include <stab.h> 199673Slinton #include <ctype.h> 209673Slinton 219673Slinton #ifndef public 229673Slinton 239673Slinton struct { 249673Slinton unsigned int stringsize; /* size of the dumped string table */ 259673Slinton unsigned int nsyms; /* number of symbols */ 269673Slinton unsigned int nfiles; /* number of files */ 279673Slinton unsigned int nlines; /* number of lines */ 289673Slinton } nlhdr; 299673Slinton 309673Slinton #endif 319673Slinton 329673Slinton public String objname = "a.out"; 339673Slinton public Integer objsize; 349673Slinton public char *stringtab; 359673Slinton 369673Slinton private String progname = nil; 379673Slinton private Language curlang; 389673Slinton private Symbol curmodule; 399673Slinton private Symbol curparam; 409673Slinton private Boolean warned; 4112542Scsvaf private Symbol curcomm; 4212542Scsvaf private Symbol commchain; 4312542Scsvaf private Boolean strip_ = false; 449673Slinton 459673Slinton private Filetab *filep; 4611875Slinton private Linetab *linep, *prevlinep; 479673Slinton 489673Slinton #define curfilename() (filep-1)->filename 499673Slinton 509673Slinton /* 519673Slinton * Blocks are figured out on the fly while reading the symbol table. 529673Slinton */ 539673Slinton 549673Slinton #define MAXBLKDEPTH 25 559673Slinton 569673Slinton private Symbol curblock; 579673Slinton private Symbol blkstack[MAXBLKDEPTH]; 589673Slinton private Integer curlevel; 599673Slinton 609673Slinton #define enterblock(b) { \ 619673Slinton blkstack[curlevel] = curblock; \ 629673Slinton ++curlevel; \ 639673Slinton b->level = curlevel; \ 649673Slinton b->block = curblock; \ 659673Slinton curblock = b; \ 669673Slinton } 679673Slinton 689673Slinton #define exitblock() { \ 6911875Slinton if (curblock->class == FUNC or curblock->class == PROC) { \ 7011875Slinton if (prevlinep != linep) { \ 7111875Slinton curblock->symvalue.funcv.src = true; \ 7211875Slinton } \ 7311875Slinton } \ 749673Slinton --curlevel; \ 759673Slinton curblock = blkstack[curlevel]; \ 769673Slinton } 779673Slinton 789673Slinton /* 799673Slinton * Enter a source line or file name reference into the appropriate table. 809673Slinton * Expanded inline to reduce procedure calls. 819673Slinton * 829673Slinton * private enterline(linenumber, address) 839673Slinton * Lineno linenumber; 849673Slinton * Address address; 859673Slinton * ... 869673Slinton */ 879673Slinton 889673Slinton #define enterline(linenumber, address) \ 899673Slinton { \ 909673Slinton register Linetab *lp; \ 919673Slinton \ 929673Slinton lp = linep - 1; \ 939673Slinton if (linenumber != lp->line) { \ 949673Slinton if (address != lp->addr) { \ 959673Slinton ++lp; \ 969673Slinton } \ 979673Slinton lp->line = linenumber; \ 989673Slinton lp->addr = address; \ 999673Slinton linep = lp + 1; \ 1009673Slinton } \ 1019673Slinton } 1029673Slinton 1039673Slinton #define NTYPES 1000 1049673Slinton 1059673Slinton private Symbol typetable[NTYPES]; 1069673Slinton 1079673Slinton /* 1089673Slinton * Read in the namelist from the obj file. 1099673Slinton * 1109673Slinton * Reads and seeks are used instead of fread's and fseek's 1119673Slinton * for efficiency sake; there's a lot of data being read here. 1129673Slinton */ 1139673Slinton 1149673Slinton public readobj(file) 1159673Slinton String file; 1169673Slinton { 1179673Slinton Fileid f; 1189673Slinton struct exec hdr; 1199673Slinton struct nlist nlist; 1209673Slinton 1219673Slinton f = open(file, 0); 1229673Slinton if (f < 0) { 1239673Slinton fatal("can't open %s", file); 1249673Slinton } 1259673Slinton read(f, &hdr, sizeof(hdr)); 1269673Slinton objsize = hdr.a_text; 1279673Slinton nlhdr.nsyms = hdr.a_syms / sizeof(nlist); 1289673Slinton nlhdr.nfiles = nlhdr.nsyms; 1299673Slinton nlhdr.nlines = nlhdr.nsyms; 1309673Slinton lseek(f, (long) N_STROFF(hdr), 0); 1319673Slinton read(f, &(nlhdr.stringsize), sizeof(nlhdr.stringsize)); 1329673Slinton nlhdr.stringsize -= 4; 1339673Slinton stringtab = newarr(char, nlhdr.stringsize); 1349673Slinton read(f, stringtab, nlhdr.stringsize); 1359673Slinton allocmaps(nlhdr.nfiles, nlhdr.nlines); 1369673Slinton lseek(f, (long) N_SYMOFF(hdr), 0); 1379673Slinton readsyms(f); 1389673Slinton ordfunctab(); 1399673Slinton setnlines(); 1409673Slinton setnfiles(); 1419673Slinton close(f); 1429673Slinton } 1439673Slinton 1449673Slinton /* 1459673Slinton * Read in symbols from object file. 1469673Slinton */ 1479673Slinton 1489673Slinton private readsyms(f) 1499673Slinton Fileid f; 1509673Slinton { 1519673Slinton struct nlist *namelist; 1529673Slinton register struct nlist *np, *ub; 1539673Slinton register int index; 1549673Slinton register String name; 1559673Slinton register Boolean afterlg; 1569673Slinton 1579673Slinton initsyms(); 1589673Slinton namelist = newarr(struct nlist, nlhdr.nsyms); 1599673Slinton read(f, namelist, nlhdr.nsyms * sizeof(struct nlist)); 1609673Slinton afterlg = false; 1619673Slinton ub = &namelist[nlhdr.nsyms]; 1629673Slinton for (np = &namelist[0]; np < ub; np++) { 1639673Slinton index = np->n_un.n_strx; 1649673Slinton if (index != 0) { 1659673Slinton name = &stringtab[index - 4]; 16612542Scsvaf /* 16712542Scsvaf * if the program contains any .f files a trailing _ is stripped 16812542Scsvaf * from the name on the assumption it was added by the compiler. 16912542Scsvaf * This only affects names that follow the sdb N_SO entry with 17012542Scsvaf * the .f name. 17112542Scsvaf */ 17212542Scsvaf if(strip_ && *name != '\0' ) { 17312542Scsvaf register char *p, *q; 17412542Scsvaf for(p=name,q=(name+1); *q != '\0'; p=q++); 17512542Scsvaf if (*p == '_') *p = '\0'; 17612542Scsvaf } 17712542Scsvaf 1789673Slinton } else { 1799673Slinton name = nil; 18012542Scsvaf } 1819673Slinton /* 1829673Slinton * assumptions: 1839673Slinton * not an N_STAB ==> name != nil 1849673Slinton * name[0] == '-' ==> name == "-lg" 1859673Slinton * name[0] != '_' ==> filename or invisible 1869673Slinton * 1879673Slinton * The "-lg" signals the beginning of global loader symbols. 18812542Scsvaf * 1899673Slinton */ 1909673Slinton if ((np->n_type&N_STAB) != 0) { 1919673Slinton enter_nl(name, np); 1929673Slinton } else if (name[0] == '-') { 1939673Slinton afterlg = true; 1949673Slinton if (curblock->class != PROG) { 1959673Slinton exitblock(); 1969673Slinton if (curblock->class != PROG) { 1979673Slinton exitblock(); 1989673Slinton } 1999673Slinton } 2009673Slinton enterline(0, (linep-1)->addr + 1); 20111104Slinton } else if (afterlg) { 20211104Slinton if (name[0] == '_') { 2039673Slinton check_global(&name[1], np); 2049673Slinton } 20511104Slinton } else if (name[0] == '_') { 20611104Slinton check_local(&name[1], np); 2079673Slinton } else if ((np->n_type&N_TEXT) == N_TEXT) { 2089673Slinton check_filename(name); 2099673Slinton } 2109673Slinton } 2119673Slinton dispose(namelist); 2129673Slinton } 2139673Slinton 2149673Slinton /* 2159673Slinton * Initialize symbol information. 2169673Slinton */ 2179673Slinton 2189673Slinton private initsyms() 2199673Slinton { 2209673Slinton curblock = nil; 2219673Slinton curlevel = 0; 2229673Slinton if (progname == nil) { 2239673Slinton progname = strdup(objname); 2249673Slinton if (rindex(progname, '/') != nil) { 2259673Slinton progname = rindex(progname, '/') + 1; 2269673Slinton } 2279673Slinton if (index(progname, '.') != nil) { 2289673Slinton *(index(progname, '.')) = '\0'; 2299673Slinton } 2309673Slinton } 2319673Slinton program = insert(identname(progname, true)); 2329673Slinton program->class = PROG; 23311769Slinton program->symvalue.funcv.beginaddr = 0; 23411769Slinton findbeginning(program); 2359673Slinton newfunc(program); 2369673Slinton enterblock(program); 2379673Slinton curmodule = program; 2389673Slinton t_boolean = maketype("$boolean", 0L, 1L); 2399673Slinton t_int = maketype("$integer", 0x80000000L, 0x7fffffffL); 2409673Slinton t_char = maketype("$char", 0L, 127L); 24113838Slinton t_real = maketype("$real", 8L, 0L); 2429673Slinton t_nil = maketype("$nil", 0L, 0L); 2439673Slinton } 2449673Slinton 2459673Slinton /* 2469673Slinton * Free all the object file information that's being stored. 2479673Slinton */ 2489673Slinton 2499673Slinton public objfree() 2509673Slinton { 2519673Slinton symbol_free(); 2529673Slinton keywords_free(); 2539673Slinton names_free(); 2549673Slinton dispose(stringtab); 2559673Slinton clrfunctab(); 2569673Slinton } 2579673Slinton 2589673Slinton /* 2599673Slinton * Enter a namelist entry. 2609673Slinton */ 2619673Slinton 2629673Slinton private enter_nl(name, np) 2639673Slinton String name; 2649673Slinton register struct nlist *np; 2659673Slinton { 2669673Slinton register Symbol s; 2679673Slinton String mname, suffix; 26811875Slinton register Name n, nn; 2699673Slinton 2709673Slinton s = nil; 2719673Slinton if (name == nil) { 2729673Slinton n = nil; 2739673Slinton } else { 2749673Slinton n = identname(name, true); 2759673Slinton } 2769673Slinton switch (np->n_type) { 27712542Scsvaf 278*13938Slinton /* 279*13938Slinton * Build a symbol for the common; all GSYMS that follow will be chained; 280*13938Slinton * the head of this list is kept in common.offset, the tail in common.chain 281*13938Slinton */ 282*13938Slinton case N_BCOMM: 283*13938Slinton if (curcomm) { 284*13938Slinton curcomm->symvalue.common.chain = commchain; 28512542Scsvaf } 28612542Scsvaf curcomm = lookup(n); 287*13938Slinton if (curcomm == nil) { 288*13938Slinton curcomm = insert(n); 289*13938Slinton curcomm->class = COMMON; 290*13938Slinton curcomm->block = curblock; 291*13938Slinton curcomm->level = program->level; 292*13938Slinton curcomm->symvalue.common.chain = nil; 29312542Scsvaf } 29412542Scsvaf commchain = curcomm->symvalue.common.chain; 295*13938Slinton break; 29612542Scsvaf 29712542Scsvaf case N_ECOMM: 298*13938Slinton if (curcomm) { 299*13938Slinton curcomm->symvalue.common.chain = commchain; 300*13938Slinton curcomm = nil; 30112542Scsvaf } 30212542Scsvaf break; 30312542Scsvaf 3049673Slinton case N_LBRAC: 3059673Slinton s = symbol_alloc(); 3069673Slinton s->class = PROC; 3079673Slinton enterblock(s); 3089673Slinton break; 3099673Slinton 3109673Slinton case N_RBRAC: 3119673Slinton exitblock(); 3129673Slinton break; 3139673Slinton 3149673Slinton case N_SLINE: 3159673Slinton enterline((Lineno) np->n_desc, (Address) np->n_value); 3169673Slinton break; 3179673Slinton 3189673Slinton /* 3199673Slinton * Compilation unit. C associates scope with filenames 3209673Slinton * so we treat them as "modules". The filename without 3219673Slinton * the suffix is used for the module name. 3229673Slinton * 3239673Slinton * Because there is no explicit "end-of-block" mark in 3249673Slinton * the object file, we must exit blocks for the current 3259673Slinton * procedure and module. 3269673Slinton */ 3279673Slinton case N_SO: 3289673Slinton mname = strdup(ident(n)); 3299673Slinton if (rindex(mname, '/') != nil) { 3309673Slinton mname = rindex(mname, '/') + 1; 3319673Slinton } 3329673Slinton suffix = rindex(mname, '.'); 3339673Slinton curlang = findlanguage(suffix); 33412542Scsvaf if(curlang == findlanguage(".f")) { 33512542Scsvaf strip_ = true; 33612542Scsvaf } 3379673Slinton if (suffix != nil) { 3389673Slinton *suffix = '\0'; 3399673Slinton } 3409673Slinton if (curblock->class != PROG) { 3419673Slinton exitblock(); 3429673Slinton if (curblock->class != PROG) { 3439673Slinton exitblock(); 3449673Slinton } 3459673Slinton } 34611875Slinton nn = identname(mname, true); 34711875Slinton if (curmodule == nil or curmodule->name != nn) { 34811875Slinton s = insert(nn); 34911875Slinton s->class = MODULE; 35011875Slinton s->symvalue.funcv.beginaddr = 0; 35111875Slinton findbeginning(s); 35211875Slinton } else { 35311875Slinton s = curmodule; 35411875Slinton } 3559673Slinton s->language = curlang; 3569673Slinton enterblock(s); 3579673Slinton curmodule = s; 3589673Slinton if (program->language == nil) { 3599673Slinton program->language = curlang; 3609673Slinton } 3619673Slinton warned = false; 3629673Slinton enterfile(ident(n), (Address) np->n_value); 36311769Slinton bzero(typetable, sizeof(typetable)); 3649673Slinton break; 3659673Slinton 3669673Slinton /* 3679673Slinton * Textually included files. 3689673Slinton */ 3699673Slinton case N_SOL: 3709673Slinton enterfile(name, (Address) np->n_value); 3719673Slinton break; 3729673Slinton 3739673Slinton /* 3749673Slinton * These symbols are assumed to have non-nil names. 3759673Slinton */ 3769673Slinton case N_GSYM: 3779673Slinton case N_FUN: 3789673Slinton case N_STSYM: 3799673Slinton case N_LCSYM: 3809673Slinton case N_RSYM: 3819673Slinton case N_PSYM: 3829673Slinton case N_LSYM: 3839673Slinton case N_SSYM: 3849673Slinton if (index(name, ':') == nil) { 3859673Slinton if (not warned) { 3869673Slinton warned = true; 3879673Slinton /* 3889673Slinton * Shouldn't do this if user might be typing. 3899673Slinton * 3909673Slinton warning("old style symbol information found in \"%s\"", 3919673Slinton curfilename()); 3929673Slinton * 3939673Slinton */ 3949673Slinton } 3959673Slinton } else { 3969673Slinton entersym(name, np); 3979673Slinton } 3989673Slinton break; 3999673Slinton 4009673Slinton case N_PC: 4019673Slinton break; 4029673Slinton 4039840Slinton case N_LENG: 40411558Slinton default: 4059840Slinton /* 4069840Slinton * Should complain out this, obviously the wrong symbol format. 40711558Slinton * 4089673Slinton if (name != nil) { 4099673Slinton printf("%s, ", name); 4109673Slinton } 4119673Slinton printf("ntype %2x, desc %x, value %x\n", 4129673Slinton np->n_type, np->n_desc, np->n_value); 41311558Slinton * 41411558Slinton */ 4159673Slinton break; 4169673Slinton } 4179673Slinton } 4189673Slinton 4199673Slinton /* 4209673Slinton * Check to see if a global _name is already in the symbol table, 4219673Slinton * if not then insert it. 4229673Slinton */ 4239673Slinton 4249673Slinton private check_global(name, np) 4259673Slinton String name; 4269673Slinton register struct nlist *np; 4279673Slinton { 4289673Slinton register Name n; 42912542Scsvaf register Symbol t, u; 4309673Slinton 4319673Slinton if (not streq(name, "end")) { 4329673Slinton n = identname(name, true); 4339673Slinton if ((np->n_type&N_TYPE) == N_TEXT) { 4349673Slinton find(t, n) where 4359673Slinton t->level == program->level and isblock(t) 4369673Slinton endfind(t); 4379673Slinton if (t == nil) { 4389673Slinton t = insert(n); 4399673Slinton t->language = findlanguage(".s"); 4409673Slinton t->class = FUNC; 4419673Slinton t->type = t_int; 4429673Slinton t->block = curblock; 4439673Slinton t->level = program->level; 44411875Slinton t->symvalue.funcv.src = false; 4459673Slinton } 4469673Slinton t->symvalue.funcv.beginaddr = np->n_value; 4479673Slinton newfunc(t); 4489673Slinton findbeginning(t); 449*13938Slinton } else if ((np->n_type&N_TYPE) == N_BSS) { 4509673Slinton find(t, n) where 451*13938Slinton t->class == COMMON 45212542Scsvaf endfind(t); 453*13938Slinton if (t != nil) { 454*13938Slinton u = (Symbol) t->symvalue.common.offset; 455*13938Slinton while (u != nil) { 456*13938Slinton u->symvalue.offset = u->symvalue.common.offset+np->n_value; 457*13938Slinton u = u->symvalue.common.chain; 458*13938Slinton } 459*13938Slinton } else { 460*13938Slinton check_var(np, n); 4619673Slinton } 462*13938Slinton } else { 463*13938Slinton check_var(np, n); 4649673Slinton } 4659673Slinton } 4669673Slinton } 4679673Slinton 4689673Slinton /* 469*13938Slinton * Check to see if a namelist entry refers to a variable. 470*13938Slinton * If not, create a variable for the entry. In any case, 471*13938Slinton * set the offset of the variable according to the value field 472*13938Slinton * in the entry. 473*13938Slinton */ 474*13938Slinton 475*13938Slinton private check_var(np, n) 476*13938Slinton struct nlist *np; 477*13938Slinton register Name n; 478*13938Slinton { 479*13938Slinton register Symbol t; 480*13938Slinton 481*13938Slinton find(t, n) where 482*13938Slinton t->class == VAR and t->level == program->level 483*13938Slinton endfind(t); 484*13938Slinton if (t == nil) { 485*13938Slinton t = insert(n); 486*13938Slinton t->language = findlanguage(".s"); 487*13938Slinton t->class = VAR; 488*13938Slinton t->type = t_int; 489*13938Slinton t->level = program->level; 490*13938Slinton } 491*13938Slinton t->block = curblock; 492*13938Slinton t->symvalue.offset = np->n_value; 493*13938Slinton } 494*13938Slinton 495*13938Slinton /* 4969673Slinton * Check to see if a local _name is known in the current scope. 4979673Slinton * If not then enter it. 4989673Slinton */ 4999673Slinton 5009673Slinton private check_local(name, np) 5019673Slinton String name; 5029673Slinton register struct nlist *np; 5039673Slinton { 5049673Slinton register Name n; 5059673Slinton register Symbol t, cur; 5069673Slinton 5079673Slinton n = identname(name, true); 5089673Slinton cur = ((np->n_type&N_TYPE) == N_TEXT) ? curmodule : curblock; 5099673Slinton find(t, n) where t->block == cur endfind(t); 5109673Slinton if (t == nil) { 5119673Slinton t = insert(n); 5129673Slinton t->language = findlanguage(".s"); 5139673Slinton t->type = t_int; 5149673Slinton t->block = cur; 5159673Slinton t->level = cur->level; 5169673Slinton if ((np->n_type&N_TYPE) == N_TEXT) { 5179673Slinton t->class = FUNC; 51811875Slinton t->symvalue.funcv.src = false; 5199673Slinton t->symvalue.funcv.beginaddr = np->n_value; 5209673Slinton newfunc(t); 5219673Slinton findbeginning(t); 5229673Slinton } else { 5239673Slinton t->class = VAR; 5249673Slinton t->symvalue.offset = np->n_value; 5259673Slinton } 5269673Slinton } 5279673Slinton } 5289673Slinton 5299673Slinton /* 5309673Slinton * Check to see if a symbol corresponds to a object file name. 5319673Slinton * For some reason these are listed as in the text segment. 5329673Slinton */ 5339673Slinton 5349673Slinton private check_filename(name) 5359673Slinton String name; 5369673Slinton { 5379673Slinton register String mname; 5389673Slinton register Integer i; 5399673Slinton register Symbol s; 5409673Slinton 5419673Slinton mname = strdup(name); 5429673Slinton i = strlen(mname) - 2; 5439673Slinton if (i >= 0 and mname[i] == '.' and mname[i+1] == 'o') { 5449673Slinton mname[i] = '\0'; 5459673Slinton --i; 5469673Slinton while (mname[i] != '/' and i >= 0) { 5479673Slinton --i; 5489673Slinton } 5499673Slinton s = insert(identname(&mname[i+1], true)); 5509673Slinton s->language = findlanguage(".s"); 5519673Slinton s->class = MODULE; 55211769Slinton s->symvalue.funcv.beginaddr = 0; 55311769Slinton findbeginning(s); 5549673Slinton if (curblock->class != PROG) { 5559673Slinton exitblock(); 5569673Slinton if (curblock->class != PROG) { 5579673Slinton exitblock(); 5589673Slinton } 5599673Slinton } 5609673Slinton enterblock(s); 5619673Slinton curmodule = s; 5629673Slinton } 5639673Slinton } 5649673Slinton 5659673Slinton /* 5669673Slinton * Put an nlist into the symbol table. 5679673Slinton * If it's already there just add the associated information. 5689673Slinton * 5699673Slinton * Type information is encoded in the name following a ":". 5709673Slinton */ 5719673Slinton 5729673Slinton private Symbol constype(); 5739673Slinton private Char *curchar; 5749673Slinton 5759673Slinton #define skipchar(ptr, ch) { \ 5769673Slinton if (*ptr != ch) { \ 5779673Slinton panic("expected char '%c', found char '%c'", ch, *ptr); \ 5789673Slinton } \ 5799673Slinton ++ptr; \ 5809673Slinton } 5819673Slinton 5829673Slinton private entersym(str, np) 5839673Slinton String str; 5849673Slinton struct nlist *np; 5859673Slinton { 5869673Slinton register Symbol s; 5879673Slinton register char *p; 5889673Slinton register int c; 5899673Slinton register Name n; 5909673Slinton register Integer i; 5919673Slinton Boolean knowtype, isnew; 5929673Slinton Symclass class; 5939673Slinton Integer level; 5949673Slinton 5959673Slinton p = index(str, ':'); 5969673Slinton *p = '\0'; 5979673Slinton c = *(p+1); 5989673Slinton n = identname(str, true); 5999673Slinton if (index("FfGV", c) != nil) { 6009673Slinton if (c == 'F' or c == 'f') { 6019673Slinton class = FUNC; 6029673Slinton } else { 6039673Slinton class = VAR; 6049673Slinton } 6059673Slinton level = (c == 'f' ? curmodule->level : program->level); 6069673Slinton find(s, n) where s->level == level and s->class == class endfind(s); 6079673Slinton if (s == nil) { 6089673Slinton isnew = true; 6099673Slinton s = insert(n); 6109673Slinton } else { 6119673Slinton isnew = false; 6129673Slinton } 6139673Slinton } else { 6149673Slinton isnew = true; 6159673Slinton s = insert(n); 6169673Slinton } 6179673Slinton 6189673Slinton /* 6199673Slinton * Default attributes. 6209673Slinton */ 6219673Slinton s->language = curlang; 6229673Slinton s->class = VAR; 6239673Slinton s->block = curblock; 6249673Slinton s->level = curlevel; 6259673Slinton s->symvalue.offset = np->n_value; 6269673Slinton curchar = p + 2; 6279673Slinton knowtype = false; 6289673Slinton switch (c) { 6299673Slinton case 't': /* type name */ 6309673Slinton s->class = TYPE; 6319673Slinton i = getint(); 6329673Slinton if (i == 0) { 6339673Slinton panic("bad input on type \"%s\" at \"%s\"", symname(s), 6349673Slinton curchar); 6359673Slinton } else if (i >= NTYPES) { 6369673Slinton panic("too many types in file \"%s\"", curfilename()); 6379673Slinton } 6389673Slinton /* 6399673Slinton * A hack for C typedefs that don't create new types, 6409673Slinton * e.g. typedef unsigned int Hashvalue; 64111558Slinton * or typedef struct blah BLAH; 6429673Slinton */ 6439673Slinton if (*curchar == '\0') { 6449673Slinton s->type = typetable[i]; 6459673Slinton if (s->type == nil) { 64611558Slinton s->type = symbol_alloc(); 64711558Slinton typetable[i] = s->type; 6489673Slinton } 6499673Slinton knowtype = true; 6509673Slinton } else { 6519673Slinton typetable[i] = s; 6529673Slinton skipchar(curchar, '='); 6539673Slinton } 6549673Slinton break; 6559673Slinton 6569673Slinton case 'T': /* tag */ 6579673Slinton s->class = TAG; 6589673Slinton i = getint(); 6599673Slinton if (i == 0) { 6609673Slinton panic("bad input on tag \"%s\" at \"%s\"", symname(s), 6619673Slinton curchar); 6629673Slinton } else if (i >= NTYPES) { 6639673Slinton panic("too many types in file \"%s\"", curfilename()); 6649673Slinton } 6659673Slinton if (typetable[i] != nil) { 6669673Slinton typetable[i]->language = curlang; 6679673Slinton typetable[i]->class = TYPE; 6689673Slinton typetable[i]->type = s; 6699673Slinton } else { 6709673Slinton typetable[i] = s; 6719673Slinton } 6729673Slinton skipchar(curchar, '='); 6739673Slinton break; 6749673Slinton 6759673Slinton case 'F': /* public function */ 6769673Slinton case 'f': /* private function */ 6779673Slinton s->class = FUNC; 6789673Slinton if (curblock->class == FUNC or curblock->class == PROC) { 6799673Slinton exitblock(); 6809673Slinton } 6819673Slinton enterblock(s); 6829673Slinton if (c == 'F') { 6839673Slinton s->level = program->level; 6849673Slinton isnew = false; 6859673Slinton } 6869673Slinton curparam = s; 6879673Slinton if (isnew) { 68811875Slinton s->symvalue.funcv.src = false; 6899673Slinton s->symvalue.funcv.beginaddr = np->n_value; 6909673Slinton newfunc(s); 6919673Slinton findbeginning(s); 6929673Slinton } 6939673Slinton break; 6949673Slinton 6959673Slinton case 'G': /* public variable */ 6969673Slinton s->level = program->level; 6979673Slinton break; 6989673Slinton 6999673Slinton case 'S': /* private variable */ 7009673Slinton s->level = curmodule->level; 7019673Slinton s->block = curmodule; 7029673Slinton break; 7039673Slinton 70412542Scsvaf /* 70512542Scsvaf * keep global BSS variables chained so can resolve when get the start 70612542Scsvaf * of common; keep the list in order so f77 can display all vars in a COMMON 70712542Scsvaf */ 7089673Slinton case 'V': /* own variable */ 7099673Slinton s->level = 2; 71012542Scsvaf if (curcomm) { 71112542Scsvaf if (commchain != nil) { 71212542Scsvaf commchain->symvalue.common.chain = s; 71312542Scsvaf } 71412542Scsvaf else { 71512542Scsvaf curcomm->symvalue.common.offset = (int) s; 71612542Scsvaf } 71712542Scsvaf commchain = s; 71812542Scsvaf s->symvalue.common.offset = np->n_value; 71912542Scsvaf s->symvalue.common.chain = nil; 72012542Scsvaf } 7219673Slinton break; 7229673Slinton 7239673Slinton case 'r': /* register variable */ 7249673Slinton s->level = -(s->level); 7259673Slinton break; 7269673Slinton 7279673Slinton case 'p': /* parameter variable */ 7289673Slinton curparam->chain = s; 7299673Slinton curparam = s; 7309673Slinton break; 7319673Slinton 7329673Slinton case 'v': /* varies parameter */ 7339673Slinton s->class = REF; 7349673Slinton s->symvalue.offset = np->n_value; 7359673Slinton curparam->chain = s; 7369673Slinton curparam = s; 7379673Slinton break; 7389673Slinton 7399673Slinton default: /* local variable */ 7409673Slinton --curchar; 7419673Slinton break; 7429673Slinton } 7439673Slinton if (not knowtype) { 7449673Slinton s->type = constype(nil); 7459673Slinton if (s->class == TAG) { 7469673Slinton addtag(s); 7479673Slinton } 7489673Slinton } 7499673Slinton if (tracesyms) { 7509673Slinton printdecl(s); 7519673Slinton fflush(stdout); 7529673Slinton } 7539673Slinton } 7549673Slinton 7559673Slinton /* 7569673Slinton * Construct a type out of a string encoding. 7579673Slinton * 7589673Slinton * The forms of the string are 7599673Slinton * 7609673Slinton * <number> 7619673Slinton * <number>=<type> 7629673Slinton * r<type>;<number>;<number> $ subrange 7639673Slinton * a<type>;<type> $ array[index] of element 7649673Slinton * s{<name>:<type>;<number>;<number>} $ record 7659673Slinton * *<type> $ pointer 7669673Slinton */ 7679673Slinton 7689673Slinton private Symbol constype(type) 7699673Slinton Symbol type; 7709673Slinton { 7719673Slinton register Symbol t, u; 7729673Slinton register Char *p, *cur; 7739673Slinton register Integer n; 7749673Slinton Integer b; 7759673Slinton Name name; 7769673Slinton Char class; 7779673Slinton 7789673Slinton b = curlevel; 7799673Slinton if (isdigit(*curchar)) { 7809673Slinton n = getint(); 7819673Slinton if (n == 0) { 7829673Slinton panic("bad type number at \"%s\"", curchar); 7839673Slinton } else if (n >= NTYPES) { 7849673Slinton panic("too many types in file \"%s\"", curfilename()); 7859673Slinton } 7869673Slinton if (*curchar == '=') { 7879673Slinton if (typetable[n] != nil) { 7889673Slinton t = typetable[n]; 7899673Slinton } else { 7909673Slinton t = symbol_alloc(); 7919673Slinton typetable[n] = t; 7929673Slinton } 7939673Slinton ++curchar; 7949673Slinton constype(t); 7959673Slinton } else { 7969673Slinton t = typetable[n]; 7979673Slinton if (t == nil) { 7989673Slinton t = symbol_alloc(); 7999673Slinton typetable[n] = t; 8009673Slinton } 8019673Slinton } 8029673Slinton } else { 8039673Slinton if (type == nil) { 8049673Slinton t = symbol_alloc(); 8059673Slinton } else { 8069673Slinton t = type; 8079673Slinton } 8089673Slinton t->language = curlang; 8099673Slinton t->level = b; 81012542Scsvaf t->block = curblock; 8119673Slinton class = *curchar++; 8129673Slinton switch (class) { 81312542Scsvaf 8149673Slinton case 'r': 8159673Slinton t->class = RANGE; 8169673Slinton t->type = constype(nil); 8179673Slinton skipchar(curchar, ';'); 81812542Scsvaf /* some letters indicate a dynamic bound, ie what follows 81912542Scsvaf is the offset from the fp which contains the bound; this will 82012542Scsvaf need a different encoding when pc a['A'..'Z'] is 82112542Scsvaf added; J is a special flag to handle fortran a(*) bounds 82212542Scsvaf */ 82312542Scsvaf switch(*curchar) { 82412542Scsvaf case 'A': 82512542Scsvaf t->symvalue.rangev.lowertype = R_ARG; 82612542Scsvaf curchar++; 82712542Scsvaf break; 82812542Scsvaf 82912542Scsvaf case 'T': 83012542Scsvaf t->symvalue.rangev.lowertype = R_TEMP; 83112542Scsvaf curchar++; 83212542Scsvaf break; 83312542Scsvaf 83412542Scsvaf case 'J': 83512542Scsvaf t->symvalue.rangev.lowertype = R_ADJUST; 83612542Scsvaf curchar++; 83712542Scsvaf break; 83812542Scsvaf 83912542Scsvaf default: 84012542Scsvaf t->symvalue.rangev.lowertype = R_CONST; 84112542Scsvaf break; 84212542Scsvaf 84312542Scsvaf } 84412542Scsvaf t->symvalue.rangev.lower = getint(); 8459673Slinton skipchar(curchar, ';'); 84612542Scsvaf switch(*curchar) { 84712542Scsvaf case 'A': 84812542Scsvaf t->symvalue.rangev.uppertype = R_ARG; 84912542Scsvaf curchar++; 85012542Scsvaf break; 85112542Scsvaf 85212542Scsvaf case 'T': 85312542Scsvaf t->symvalue.rangev.uppertype = R_TEMP; 85412542Scsvaf curchar++; 85512542Scsvaf break; 85612542Scsvaf 85712542Scsvaf case 'J': 85812542Scsvaf t->symvalue.rangev.uppertype = R_ADJUST; 85912542Scsvaf curchar++; 86012542Scsvaf break; 86112542Scsvaf 86212542Scsvaf default: 86312542Scsvaf t->symvalue.rangev.uppertype = R_CONST; 86412542Scsvaf break; 86512542Scsvaf 86612542Scsvaf } 8679673Slinton t->symvalue.rangev.upper = getint(); 8689673Slinton break; 8699673Slinton 8709673Slinton case 'a': 8719673Slinton t->class = ARRAY; 8729673Slinton t->chain = constype(nil); 8739673Slinton skipchar(curchar, ';'); 8749673Slinton t->type = constype(nil); 8759673Slinton break; 8769673Slinton 8779673Slinton case 's': 8789673Slinton case 'u': 8799673Slinton t->class = (class == 's') ? RECORD : VARNT; 8809673Slinton t->symvalue.offset = getint(); 8819673Slinton u = t; 8829673Slinton cur = curchar; 8839673Slinton while (*cur != ';' and *cur != '\0') { 8849673Slinton p = index(cur, ':'); 8859673Slinton if (p == nil) { 8869673Slinton panic("index(\"%s\", ':') failed", curchar); 8879673Slinton } 8889673Slinton *p = '\0'; 8899673Slinton name = identname(cur, true); 8909673Slinton u->chain = newSymbol(name, b, FIELD, nil, nil); 8919673Slinton cur = p + 1; 8929673Slinton u = u->chain; 8939673Slinton u->language = curlang; 8949673Slinton curchar = cur; 8959673Slinton u->type = constype(nil); 8969673Slinton skipchar(curchar, ','); 8979673Slinton u->symvalue.field.offset = getint(); 8989673Slinton skipchar(curchar, ','); 8999673Slinton u->symvalue.field.length = getint(); 9009673Slinton skipchar(curchar, ';'); 9019673Slinton cur = curchar; 9029673Slinton } 9039673Slinton if (*cur == ';') { 9049673Slinton ++cur; 9059673Slinton } 9069673Slinton curchar = cur; 9079673Slinton break; 9089673Slinton 9099673Slinton case 'e': 9109673Slinton t->class = SCAL; 9119673Slinton u = t; 9129673Slinton while (*curchar != ';' and *curchar != '\0') { 9139673Slinton p = index(curchar, ':'); 9149673Slinton assert(p != nil); 9159673Slinton *p = '\0'; 9169673Slinton u->chain = insert(identname(curchar, true)); 9179673Slinton curchar = p + 1; 9189673Slinton u = u->chain; 9199673Slinton u->language = curlang; 9209673Slinton u->class = CONST; 9219673Slinton u->level = b; 9229673Slinton u->block = curblock; 9239673Slinton u->type = t; 9249673Slinton u->symvalue.iconval = getint(); 9259673Slinton skipchar(curchar, ','); 9269673Slinton } 9279673Slinton break; 9289673Slinton 9299673Slinton case '*': 9309673Slinton t->class = PTR; 9319673Slinton t->type = constype(nil); 9329673Slinton break; 9339673Slinton 9349673Slinton case 'f': 9359673Slinton t->class = FUNC; 9369673Slinton t->type = constype(nil); 9379673Slinton break; 9389673Slinton 9399673Slinton default: 9409673Slinton badcaseval(class); 9419673Slinton } 9429673Slinton } 9439673Slinton return t; 9449673Slinton } 9459673Slinton 9469673Slinton /* 9479673Slinton * Read an integer from the current position in the type string. 9489673Slinton */ 9499673Slinton 9509673Slinton private Integer getint() 9519673Slinton { 9529673Slinton register Integer n; 9539673Slinton register char *p; 9549673Slinton register Boolean isneg; 9559673Slinton 9569673Slinton n = 0; 9579673Slinton p = curchar; 9589673Slinton if (*p == '-') { 9599673Slinton isneg = true; 9609673Slinton ++p; 9619673Slinton } else { 9629673Slinton isneg = false; 9639673Slinton } 9649673Slinton while (isdigit(*p)) { 9659673Slinton n = 10*n + (*p - '0'); 9669673Slinton ++p; 9679673Slinton } 9689673Slinton curchar = p; 9699673Slinton return isneg ? (-n) : n; 9709673Slinton } 9719673Slinton 9729673Slinton /* 9739673Slinton * Add a tag name. This is a kludge to be able to refer 9749673Slinton * to tags that have the same name as some other symbol 9759673Slinton * in the same block. 9769673Slinton */ 9779673Slinton 9789673Slinton private addtag(s) 9799673Slinton register Symbol s; 9809673Slinton { 9819673Slinton register Symbol t; 9829673Slinton char buf[100]; 9839673Slinton 9849673Slinton sprintf(buf, "$$%.90s", ident(s->name)); 9859673Slinton t = insert(identname(buf, false)); 9869673Slinton t->language = s->language; 9879673Slinton t->class = TAG; 9889673Slinton t->type = s->type; 9899673Slinton t->block = s->block; 9909673Slinton } 9919673Slinton 9929673Slinton /* 9939673Slinton * Allocate file and line tables and initialize indices. 9949673Slinton */ 9959673Slinton 9969673Slinton private allocmaps(nf, nl) 9979673Slinton Integer nf, nl; 9989673Slinton { 9999673Slinton if (filetab != nil) { 10009673Slinton dispose(filetab); 10019673Slinton } 10029673Slinton if (linetab != nil) { 10039673Slinton dispose(linetab); 10049673Slinton } 10059673Slinton filetab = newarr(Filetab, nf); 10069673Slinton linetab = newarr(Linetab, nl); 10079673Slinton filep = filetab; 10089673Slinton linep = linetab; 10099673Slinton } 10109673Slinton 10119673Slinton /* 10129673Slinton * Add a file to the file table. 1013*13938Slinton * 1014*13938Slinton * If the new address is the same as the previous file address 1015*13938Slinton * this routine used to not enter the file, but this caused some 1016*13938Slinton * problems so it has been removed. It's not clear that this in 1017*13938Slinton * turn may not also cause a problem. 10189673Slinton */ 10199673Slinton 10209673Slinton private enterfile(filename, addr) 10219673Slinton String filename; 10229673Slinton Address addr; 10239673Slinton { 1024*13938Slinton filep->addr = addr; 1025*13938Slinton filep->filename = filename; 1026*13938Slinton filep->lineindex = linep - linetab; 1027*13938Slinton ++filep; 10289673Slinton } 10299673Slinton 10309673Slinton /* 10319673Slinton * Since we only estimated the number of lines (and it was a poor 10329673Slinton * estimation) and since we need to know the exact number of lines 10339673Slinton * to do a binary search, we set it when we're done. 10349673Slinton */ 10359673Slinton 10369673Slinton private setnlines() 10379673Slinton { 10389673Slinton nlhdr.nlines = linep - linetab; 10399673Slinton } 10409673Slinton 10419673Slinton /* 10429673Slinton * Similarly for nfiles ... 10439673Slinton */ 10449673Slinton 10459673Slinton private setnfiles() 10469673Slinton { 10479673Slinton nlhdr.nfiles = filep - filetab; 10489673Slinton setsource(filetab[0].filename); 10499673Slinton } 1050