19673Slinton /* Copyright (c) 1982 Regents of the University of California */ 29673Slinton 3*11875Slinton static char sccsid[] = "@(#)object.c 1.7 04/08/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; 419673Slinton 429673Slinton private Filetab *filep; 43*11875Slinton private Linetab *linep, *prevlinep; 449673Slinton private Address curfaddr; 459673Slinton 469673Slinton #define curfilename() (filep-1)->filename 479673Slinton 489673Slinton /* 499673Slinton * Blocks are figured out on the fly while reading the symbol table. 509673Slinton */ 519673Slinton 529673Slinton #define MAXBLKDEPTH 25 539673Slinton 549673Slinton private Symbol curblock; 559673Slinton private Symbol blkstack[MAXBLKDEPTH]; 569673Slinton private Integer curlevel; 579673Slinton 589673Slinton #define enterblock(b) { \ 599673Slinton blkstack[curlevel] = curblock; \ 609673Slinton ++curlevel; \ 619673Slinton b->level = curlevel; \ 629673Slinton b->block = curblock; \ 639673Slinton curblock = b; \ 649673Slinton } 659673Slinton 669673Slinton #define exitblock() { \ 67*11875Slinton if (curblock->class == FUNC or curblock->class == PROC) { \ 68*11875Slinton if (prevlinep != linep) { \ 69*11875Slinton curblock->symvalue.funcv.src = true; \ 70*11875Slinton } \ 71*11875Slinton } \ 729673Slinton --curlevel; \ 739673Slinton curblock = blkstack[curlevel]; \ 749673Slinton } 759673Slinton 769673Slinton /* 779673Slinton * Enter a source line or file name reference into the appropriate table. 789673Slinton * Expanded inline to reduce procedure calls. 799673Slinton * 809673Slinton * private enterline(linenumber, address) 819673Slinton * Lineno linenumber; 829673Slinton * Address address; 839673Slinton * ... 849673Slinton */ 859673Slinton 869673Slinton #define enterline(linenumber, address) \ 879673Slinton { \ 889673Slinton register Linetab *lp; \ 899673Slinton \ 909673Slinton lp = linep - 1; \ 919673Slinton if (linenumber != lp->line) { \ 929673Slinton if (address != lp->addr) { \ 939673Slinton ++lp; \ 949673Slinton } \ 959673Slinton lp->line = linenumber; \ 969673Slinton lp->addr = address; \ 979673Slinton linep = lp + 1; \ 989673Slinton } \ 999673Slinton } 1009673Slinton 1019673Slinton #define NTYPES 1000 1029673Slinton 1039673Slinton private Symbol typetable[NTYPES]; 1049673Slinton 1059673Slinton /* 1069673Slinton * Read in the namelist from the obj file. 1079673Slinton * 1089673Slinton * Reads and seeks are used instead of fread's and fseek's 1099673Slinton * for efficiency sake; there's a lot of data being read here. 1109673Slinton */ 1119673Slinton 1129673Slinton public readobj(file) 1139673Slinton String file; 1149673Slinton { 1159673Slinton Fileid f; 1169673Slinton struct exec hdr; 1179673Slinton struct nlist nlist; 1189673Slinton 1199673Slinton f = open(file, 0); 1209673Slinton if (f < 0) { 1219673Slinton fatal("can't open %s", file); 1229673Slinton } 1239673Slinton read(f, &hdr, sizeof(hdr)); 1249673Slinton objsize = hdr.a_text; 1259673Slinton nlhdr.nsyms = hdr.a_syms / sizeof(nlist); 1269673Slinton nlhdr.nfiles = nlhdr.nsyms; 1279673Slinton nlhdr.nlines = nlhdr.nsyms; 1289673Slinton lseek(f, (long) N_STROFF(hdr), 0); 1299673Slinton read(f, &(nlhdr.stringsize), sizeof(nlhdr.stringsize)); 1309673Slinton nlhdr.stringsize -= 4; 1319673Slinton stringtab = newarr(char, nlhdr.stringsize); 1329673Slinton read(f, stringtab, nlhdr.stringsize); 1339673Slinton allocmaps(nlhdr.nfiles, nlhdr.nlines); 1349673Slinton lseek(f, (long) N_SYMOFF(hdr), 0); 1359673Slinton readsyms(f); 1369673Slinton ordfunctab(); 1379673Slinton setnlines(); 1389673Slinton setnfiles(); 1399673Slinton close(f); 1409673Slinton } 1419673Slinton 1429673Slinton /* 1439673Slinton * Read in symbols from object file. 1449673Slinton */ 1459673Slinton 1469673Slinton private readsyms(f) 1479673Slinton Fileid f; 1489673Slinton { 1499673Slinton struct nlist *namelist; 1509673Slinton register struct nlist *np, *ub; 1519673Slinton register int index; 1529673Slinton register String name; 1539673Slinton register Boolean afterlg; 1549673Slinton 1559673Slinton initsyms(); 1569673Slinton namelist = newarr(struct nlist, nlhdr.nsyms); 1579673Slinton read(f, namelist, nlhdr.nsyms * sizeof(struct nlist)); 1589673Slinton afterlg = false; 1599673Slinton ub = &namelist[nlhdr.nsyms]; 1609673Slinton for (np = &namelist[0]; np < ub; np++) { 1619673Slinton index = np->n_un.n_strx; 1629673Slinton if (index != 0) { 1639673Slinton name = &stringtab[index - 4]; 1649673Slinton } else { 1659673Slinton name = nil; 1669673Slinton } 1679673Slinton /* 1689673Slinton * assumptions: 1699673Slinton * not an N_STAB ==> name != nil 1709673Slinton * name[0] == '-' ==> name == "-lg" 1719673Slinton * name[0] != '_' ==> filename or invisible 1729673Slinton * 1739673Slinton * The "-lg" signals the beginning of global loader symbols. 1749673Slinton */ 1759673Slinton if ((np->n_type&N_STAB) != 0) { 1769673Slinton enter_nl(name, np); 1779673Slinton } else if (name[0] == '-') { 1789673Slinton afterlg = true; 1799673Slinton if (curblock->class != PROG) { 1809673Slinton exitblock(); 1819673Slinton if (curblock->class != PROG) { 1829673Slinton exitblock(); 1839673Slinton } 1849673Slinton } 1859673Slinton enterline(0, (linep-1)->addr + 1); 18611104Slinton } else if (afterlg) { 18711104Slinton if (name[0] == '_') { 1889673Slinton check_global(&name[1], np); 1899673Slinton } 19011104Slinton } else if (name[0] == '_') { 19111104Slinton check_local(&name[1], np); 1929673Slinton } else if ((np->n_type&N_TEXT) == N_TEXT) { 1939673Slinton check_filename(name); 1949673Slinton } 1959673Slinton } 1969673Slinton dispose(namelist); 1979673Slinton } 1989673Slinton 1999673Slinton /* 2009673Slinton * Initialize symbol information. 2019673Slinton */ 2029673Slinton 2039673Slinton private initsyms() 2049673Slinton { 2059673Slinton curblock = nil; 2069673Slinton curlevel = 0; 2079673Slinton if (progname == nil) { 2089673Slinton progname = strdup(objname); 2099673Slinton if (rindex(progname, '/') != nil) { 2109673Slinton progname = rindex(progname, '/') + 1; 2119673Slinton } 2129673Slinton if (index(progname, '.') != nil) { 2139673Slinton *(index(progname, '.')) = '\0'; 2149673Slinton } 2159673Slinton } 2169673Slinton program = insert(identname(progname, true)); 2179673Slinton program->class = PROG; 21811769Slinton program->symvalue.funcv.beginaddr = 0; 21911769Slinton findbeginning(program); 2209673Slinton newfunc(program); 2219673Slinton enterblock(program); 2229673Slinton curmodule = program; 2239673Slinton t_boolean = maketype("$boolean", 0L, 1L); 2249673Slinton t_int = maketype("$integer", 0x80000000L, 0x7fffffffL); 2259673Slinton t_char = maketype("$char", 0L, 127L); 2269673Slinton t_real = maketype("$real", 4L, 0L); 2279673Slinton t_nil = maketype("$nil", 0L, 0L); 2289673Slinton } 2299673Slinton 2309673Slinton /* 2319673Slinton * Free all the object file information that's being stored. 2329673Slinton */ 2339673Slinton 2349673Slinton public objfree() 2359673Slinton { 2369673Slinton symbol_free(); 2379673Slinton keywords_free(); 2389673Slinton names_free(); 2399673Slinton dispose(stringtab); 2409673Slinton clrfunctab(); 2419673Slinton } 2429673Slinton 2439673Slinton /* 2449673Slinton * Enter a namelist entry. 2459673Slinton */ 2469673Slinton 2479673Slinton private enter_nl(name, np) 2489673Slinton String name; 2499673Slinton register struct nlist *np; 2509673Slinton { 2519673Slinton register Symbol s; 2529673Slinton String mname, suffix; 253*11875Slinton register Name n, nn; 2549673Slinton 2559673Slinton s = nil; 2569673Slinton if (name == nil) { 2579673Slinton n = nil; 2589673Slinton } else { 2599673Slinton n = identname(name, true); 2609673Slinton } 2619673Slinton switch (np->n_type) { 2629673Slinton case N_LBRAC: 2639673Slinton s = symbol_alloc(); 2649673Slinton s->class = PROC; 2659673Slinton enterblock(s); 2669673Slinton break; 2679673Slinton 2689673Slinton case N_RBRAC: 2699673Slinton exitblock(); 2709673Slinton break; 2719673Slinton 2729673Slinton case N_SLINE: 2739673Slinton enterline((Lineno) np->n_desc, (Address) np->n_value); 2749673Slinton break; 2759673Slinton 2769673Slinton /* 2779673Slinton * Compilation unit. C associates scope with filenames 2789673Slinton * so we treat them as "modules". The filename without 2799673Slinton * the suffix is used for the module name. 2809673Slinton * 2819673Slinton * Because there is no explicit "end-of-block" mark in 2829673Slinton * the object file, we must exit blocks for the current 2839673Slinton * procedure and module. 2849673Slinton */ 2859673Slinton case N_SO: 2869673Slinton mname = strdup(ident(n)); 2879673Slinton if (rindex(mname, '/') != nil) { 2889673Slinton mname = rindex(mname, '/') + 1; 2899673Slinton } 2909673Slinton suffix = rindex(mname, '.'); 2919673Slinton curlang = findlanguage(suffix); 2929673Slinton if (suffix != nil) { 2939673Slinton *suffix = '\0'; 2949673Slinton } 2959673Slinton if (curblock->class != PROG) { 2969673Slinton exitblock(); 2979673Slinton if (curblock->class != PROG) { 2989673Slinton exitblock(); 2999673Slinton } 3009673Slinton } 301*11875Slinton nn = identname(mname, true); 302*11875Slinton if (curmodule == nil or curmodule->name != nn) { 303*11875Slinton s = insert(nn); 304*11875Slinton s->class = MODULE; 305*11875Slinton s->symvalue.funcv.beginaddr = 0; 306*11875Slinton findbeginning(s); 307*11875Slinton } else { 308*11875Slinton s = curmodule; 309*11875Slinton } 3109673Slinton s->language = curlang; 3119673Slinton enterblock(s); 3129673Slinton curmodule = s; 3139673Slinton if (program->language == nil) { 3149673Slinton program->language = curlang; 3159673Slinton } 3169673Slinton warned = false; 3179673Slinton enterfile(ident(n), (Address) np->n_value); 31811769Slinton bzero(typetable, sizeof(typetable)); 3199673Slinton break; 3209673Slinton 3219673Slinton /* 3229673Slinton * Textually included files. 3239673Slinton */ 3249673Slinton case N_SOL: 3259673Slinton enterfile(name, (Address) np->n_value); 3269673Slinton break; 3279673Slinton 3289673Slinton /* 3299673Slinton * These symbols are assumed to have non-nil names. 3309673Slinton */ 3319673Slinton case N_GSYM: 3329673Slinton case N_FUN: 3339673Slinton case N_STSYM: 3349673Slinton case N_LCSYM: 3359673Slinton case N_RSYM: 3369673Slinton case N_PSYM: 3379673Slinton case N_LSYM: 3389673Slinton case N_SSYM: 3399673Slinton if (index(name, ':') == nil) { 3409673Slinton if (not warned) { 3419673Slinton warned = true; 3429673Slinton /* 3439673Slinton * Shouldn't do this if user might be typing. 3449673Slinton * 3459673Slinton warning("old style symbol information found in \"%s\"", 3469673Slinton curfilename()); 3479673Slinton * 3489673Slinton */ 3499673Slinton } 3509673Slinton } else { 3519673Slinton entersym(name, np); 3529673Slinton } 3539673Slinton break; 3549673Slinton 3559673Slinton case N_PC: 3569673Slinton break; 3579673Slinton 3589840Slinton case N_LENG: 35911558Slinton default: 3609840Slinton /* 3619840Slinton * Should complain out this, obviously the wrong symbol format. 36211558Slinton * 3639673Slinton if (name != nil) { 3649673Slinton printf("%s, ", name); 3659673Slinton } 3669673Slinton printf("ntype %2x, desc %x, value %x\n", 3679673Slinton np->n_type, np->n_desc, np->n_value); 36811558Slinton * 36911558Slinton */ 3709673Slinton break; 3719673Slinton } 3729673Slinton } 3739673Slinton 3749673Slinton /* 3759673Slinton * Check to see if a global _name is already in the symbol table, 3769673Slinton * if not then insert it. 3779673Slinton */ 3789673Slinton 3799673Slinton private check_global(name, np) 3809673Slinton String name; 3819673Slinton register struct nlist *np; 3829673Slinton { 3839673Slinton register Name n; 3849673Slinton register Symbol t; 3859673Slinton 3869673Slinton if (not streq(name, "end")) { 3879673Slinton n = identname(name, true); 3889673Slinton if ((np->n_type&N_TYPE) == N_TEXT) { 3899673Slinton find(t, n) where 3909673Slinton t->level == program->level and isblock(t) 3919673Slinton endfind(t); 3929673Slinton if (t == nil) { 3939673Slinton t = insert(n); 3949673Slinton t->language = findlanguage(".s"); 3959673Slinton t->class = FUNC; 3969673Slinton t->type = t_int; 3979673Slinton t->block = curblock; 3989673Slinton t->level = program->level; 399*11875Slinton t->symvalue.funcv.src = false; 4009673Slinton } 4019673Slinton t->symvalue.funcv.beginaddr = np->n_value; 4029673Slinton newfunc(t); 4039673Slinton findbeginning(t); 4049673Slinton } else { 4059673Slinton find(t, n) where 4069673Slinton t->class == VAR and t->level == program->level 4079673Slinton endfind(t); 4089673Slinton if (t == nil) { 4099673Slinton t = insert(n); 4109673Slinton t->language = findlanguage(".s"); 4119673Slinton t->class = VAR; 4129673Slinton t->type = t_int; 4139673Slinton t->block = curblock; 4149673Slinton t->level = program->level; 4159673Slinton } 4169673Slinton t->symvalue.offset = np->n_value; 4179673Slinton } 4189673Slinton } 4199673Slinton } 4209673Slinton 4219673Slinton /* 4229673Slinton * Check to see if a local _name is known in the current scope. 4239673Slinton * If not then enter it. 4249673Slinton */ 4259673Slinton 4269673Slinton private check_local(name, np) 4279673Slinton String name; 4289673Slinton register struct nlist *np; 4299673Slinton { 4309673Slinton register Name n; 4319673Slinton register Symbol t, cur; 4329673Slinton 4339673Slinton n = identname(name, true); 4349673Slinton cur = ((np->n_type&N_TYPE) == N_TEXT) ? curmodule : curblock; 4359673Slinton find(t, n) where t->block == cur endfind(t); 4369673Slinton if (t == nil) { 4379673Slinton t = insert(n); 4389673Slinton t->language = findlanguage(".s"); 4399673Slinton t->type = t_int; 4409673Slinton t->block = cur; 4419673Slinton t->level = cur->level; 4429673Slinton if ((np->n_type&N_TYPE) == N_TEXT) { 4439673Slinton t->class = FUNC; 444*11875Slinton t->symvalue.funcv.src = false; 4459673Slinton t->symvalue.funcv.beginaddr = np->n_value; 4469673Slinton newfunc(t); 4479673Slinton findbeginning(t); 4489673Slinton } else { 4499673Slinton t->class = VAR; 4509673Slinton t->symvalue.offset = np->n_value; 4519673Slinton } 4529673Slinton } 4539673Slinton } 4549673Slinton 4559673Slinton /* 4569673Slinton * Check to see if a symbol corresponds to a object file name. 4579673Slinton * For some reason these are listed as in the text segment. 4589673Slinton */ 4599673Slinton 4609673Slinton private check_filename(name) 4619673Slinton String name; 4629673Slinton { 4639673Slinton register String mname; 4649673Slinton register Integer i; 4659673Slinton register Symbol s; 4669673Slinton 4679673Slinton mname = strdup(name); 4689673Slinton i = strlen(mname) - 2; 4699673Slinton if (i >= 0 and mname[i] == '.' and mname[i+1] == 'o') { 4709673Slinton mname[i] = '\0'; 4719673Slinton --i; 4729673Slinton while (mname[i] != '/' and i >= 0) { 4739673Slinton --i; 4749673Slinton } 4759673Slinton s = insert(identname(&mname[i+1], true)); 4769673Slinton s->language = findlanguage(".s"); 4779673Slinton s->class = MODULE; 47811769Slinton s->symvalue.funcv.beginaddr = 0; 47911769Slinton findbeginning(s); 4809673Slinton if (curblock->class != PROG) { 4819673Slinton exitblock(); 4829673Slinton if (curblock->class != PROG) { 4839673Slinton exitblock(); 4849673Slinton } 4859673Slinton } 4869673Slinton enterblock(s); 4879673Slinton curmodule = s; 4889673Slinton } 4899673Slinton } 4909673Slinton 4919673Slinton /* 4929673Slinton * Put an nlist into the symbol table. 4939673Slinton * If it's already there just add the associated information. 4949673Slinton * 4959673Slinton * Type information is encoded in the name following a ":". 4969673Slinton */ 4979673Slinton 4989673Slinton private Symbol constype(); 4999673Slinton private Char *curchar; 5009673Slinton 5019673Slinton #define skipchar(ptr, ch) { \ 5029673Slinton if (*ptr != ch) { \ 5039673Slinton panic("expected char '%c', found char '%c'", ch, *ptr); \ 5049673Slinton } \ 5059673Slinton ++ptr; \ 5069673Slinton } 5079673Slinton 5089673Slinton private entersym(str, np) 5099673Slinton String str; 5109673Slinton struct nlist *np; 5119673Slinton { 5129673Slinton register Symbol s; 5139673Slinton register char *p; 5149673Slinton register int c; 5159673Slinton register Name n; 5169673Slinton register Integer i; 5179673Slinton Boolean knowtype, isnew; 5189673Slinton Symclass class; 5199673Slinton Integer level; 5209673Slinton 5219673Slinton p = index(str, ':'); 5229673Slinton *p = '\0'; 5239673Slinton c = *(p+1); 5249673Slinton n = identname(str, true); 5259673Slinton if (index("FfGV", c) != nil) { 5269673Slinton if (c == 'F' or c == 'f') { 5279673Slinton class = FUNC; 5289673Slinton } else { 5299673Slinton class = VAR; 5309673Slinton } 5319673Slinton level = (c == 'f' ? curmodule->level : program->level); 5329673Slinton find(s, n) where s->level == level and s->class == class endfind(s); 5339673Slinton if (s == nil) { 5349673Slinton isnew = true; 5359673Slinton s = insert(n); 5369673Slinton } else { 5379673Slinton isnew = false; 5389673Slinton } 5399673Slinton } else { 5409673Slinton isnew = true; 5419673Slinton s = insert(n); 5429673Slinton } 5439673Slinton 5449673Slinton /* 5459673Slinton * Default attributes. 5469673Slinton */ 5479673Slinton s->language = curlang; 5489673Slinton s->class = VAR; 5499673Slinton s->block = curblock; 5509673Slinton s->level = curlevel; 5519673Slinton s->symvalue.offset = np->n_value; 5529673Slinton curchar = p + 2; 5539673Slinton knowtype = false; 5549673Slinton switch (c) { 5559673Slinton case 't': /* type name */ 5569673Slinton s->class = TYPE; 5579673Slinton i = getint(); 5589673Slinton if (i == 0) { 5599673Slinton panic("bad input on type \"%s\" at \"%s\"", symname(s), 5609673Slinton curchar); 5619673Slinton } else if (i >= NTYPES) { 5629673Slinton panic("too many types in file \"%s\"", curfilename()); 5639673Slinton } 5649673Slinton /* 5659673Slinton * A hack for C typedefs that don't create new types, 5669673Slinton * e.g. typedef unsigned int Hashvalue; 56711558Slinton * or typedef struct blah BLAH; 5689673Slinton */ 5699673Slinton if (*curchar == '\0') { 5709673Slinton s->type = typetable[i]; 5719673Slinton if (s->type == nil) { 57211558Slinton s->type = symbol_alloc(); 57311558Slinton typetable[i] = s->type; 5749673Slinton } 5759673Slinton knowtype = true; 5769673Slinton } else { 5779673Slinton typetable[i] = s; 5789673Slinton skipchar(curchar, '='); 5799673Slinton } 5809673Slinton break; 5819673Slinton 5829673Slinton case 'T': /* tag */ 5839673Slinton s->class = TAG; 5849673Slinton i = getint(); 5859673Slinton if (i == 0) { 5869673Slinton panic("bad input on tag \"%s\" at \"%s\"", symname(s), 5879673Slinton curchar); 5889673Slinton } else if (i >= NTYPES) { 5899673Slinton panic("too many types in file \"%s\"", curfilename()); 5909673Slinton } 5919673Slinton if (typetable[i] != nil) { 5929673Slinton typetable[i]->language = curlang; 5939673Slinton typetable[i]->class = TYPE; 5949673Slinton typetable[i]->type = s; 5959673Slinton } else { 5969673Slinton typetable[i] = s; 5979673Slinton } 5989673Slinton skipchar(curchar, '='); 5999673Slinton break; 6009673Slinton 6019673Slinton case 'F': /* public function */ 6029673Slinton case 'f': /* private function */ 6039673Slinton s->class = FUNC; 6049673Slinton if (curblock->class == FUNC or curblock->class == PROC) { 6059673Slinton exitblock(); 6069673Slinton } 6079673Slinton enterblock(s); 6089673Slinton if (c == 'F') { 6099673Slinton s->level = program->level; 6109673Slinton isnew = false; 6119673Slinton } 6129673Slinton curparam = s; 6139673Slinton if (isnew) { 614*11875Slinton s->symvalue.funcv.src = false; 6159673Slinton s->symvalue.funcv.beginaddr = np->n_value; 6169673Slinton newfunc(s); 6179673Slinton findbeginning(s); 6189673Slinton } 6199673Slinton break; 6209673Slinton 6219673Slinton case 'G': /* public variable */ 6229673Slinton s->level = program->level; 6239673Slinton break; 6249673Slinton 6259673Slinton case 'S': /* private variable */ 6269673Slinton s->level = curmodule->level; 6279673Slinton s->block = curmodule; 6289673Slinton break; 6299673Slinton 6309673Slinton case 'V': /* own variable */ 6319673Slinton s->level = 2; 6329673Slinton break; 6339673Slinton 6349673Slinton case 'r': /* register variable */ 6359673Slinton s->level = -(s->level); 6369673Slinton break; 6379673Slinton 6389673Slinton case 'p': /* parameter variable */ 6399673Slinton curparam->chain = s; 6409673Slinton curparam = s; 6419673Slinton break; 6429673Slinton 6439673Slinton case 'v': /* varies parameter */ 6449673Slinton s->class = REF; 6459673Slinton s->symvalue.offset = np->n_value; 6469673Slinton curparam->chain = s; 6479673Slinton curparam = s; 6489673Slinton break; 6499673Slinton 6509673Slinton default: /* local variable */ 6519673Slinton --curchar; 6529673Slinton break; 6539673Slinton } 6549673Slinton if (not knowtype) { 6559673Slinton s->type = constype(nil); 6569673Slinton if (s->class == TAG) { 6579673Slinton addtag(s); 6589673Slinton } 6599673Slinton } 6609673Slinton if (tracesyms) { 6619673Slinton printdecl(s); 6629673Slinton fflush(stdout); 6639673Slinton } 6649673Slinton } 6659673Slinton 6669673Slinton /* 6679673Slinton * Construct a type out of a string encoding. 6689673Slinton * 6699673Slinton * The forms of the string are 6709673Slinton * 6719673Slinton * <number> 6729673Slinton * <number>=<type> 6739673Slinton * r<type>;<number>;<number> $ subrange 6749673Slinton * a<type>;<type> $ array[index] of element 6759673Slinton * s{<name>:<type>;<number>;<number>} $ record 6769673Slinton * *<type> $ pointer 6779673Slinton */ 6789673Slinton 6799673Slinton private Symbol constype(type) 6809673Slinton Symbol type; 6819673Slinton { 6829673Slinton register Symbol t, u; 6839673Slinton register Char *p, *cur; 6849673Slinton register Integer n; 6859673Slinton Integer b; 6869673Slinton Name name; 6879673Slinton Char class; 6889673Slinton 6899673Slinton b = curlevel; 6909673Slinton if (isdigit(*curchar)) { 6919673Slinton n = getint(); 6929673Slinton if (n == 0) { 6939673Slinton panic("bad type number at \"%s\"", curchar); 6949673Slinton } else if (n >= NTYPES) { 6959673Slinton panic("too many types in file \"%s\"", curfilename()); 6969673Slinton } 6979673Slinton if (*curchar == '=') { 6989673Slinton if (typetable[n] != nil) { 6999673Slinton t = typetable[n]; 7009673Slinton } else { 7019673Slinton t = symbol_alloc(); 7029673Slinton typetable[n] = t; 7039673Slinton } 7049673Slinton ++curchar; 7059673Slinton constype(t); 7069673Slinton } else { 7079673Slinton t = typetable[n]; 7089673Slinton if (t == nil) { 7099673Slinton t = symbol_alloc(); 7109673Slinton typetable[n] = t; 7119673Slinton } 7129673Slinton } 7139673Slinton } else { 7149673Slinton if (type == nil) { 7159673Slinton t = symbol_alloc(); 7169673Slinton } else { 7179673Slinton t = type; 7189673Slinton } 7199673Slinton t->language = curlang; 7209673Slinton t->level = b; 7219673Slinton class = *curchar++; 7229673Slinton switch (class) { 7239673Slinton case 'r': 7249673Slinton t->class = RANGE; 7259673Slinton t->type = constype(nil); 7269673Slinton skipchar(curchar, ';'); 7279673Slinton t->symvalue.rangev.lower = getint(); 7289673Slinton skipchar(curchar, ';'); 7299673Slinton t->symvalue.rangev.upper = getint(); 7309673Slinton break; 7319673Slinton 7329673Slinton case 'a': 7339673Slinton t->class = ARRAY; 7349673Slinton t->chain = constype(nil); 7359673Slinton skipchar(curchar, ';'); 7369673Slinton t->type = constype(nil); 7379673Slinton break; 7389673Slinton 7399673Slinton case 's': 7409673Slinton case 'u': 7419673Slinton t->class = (class == 's') ? RECORD : VARNT; 7429673Slinton t->symvalue.offset = getint(); 7439673Slinton u = t; 7449673Slinton cur = curchar; 7459673Slinton while (*cur != ';' and *cur != '\0') { 7469673Slinton p = index(cur, ':'); 7479673Slinton if (p == nil) { 7489673Slinton panic("index(\"%s\", ':') failed", curchar); 7499673Slinton } 7509673Slinton *p = '\0'; 7519673Slinton name = identname(cur, true); 7529673Slinton u->chain = newSymbol(name, b, FIELD, nil, nil); 7539673Slinton cur = p + 1; 7549673Slinton u = u->chain; 7559673Slinton u->language = curlang; 7569673Slinton curchar = cur; 7579673Slinton u->type = constype(nil); 7589673Slinton skipchar(curchar, ','); 7599673Slinton u->symvalue.field.offset = getint(); 7609673Slinton skipchar(curchar, ','); 7619673Slinton u->symvalue.field.length = getint(); 7629673Slinton skipchar(curchar, ';'); 7639673Slinton cur = curchar; 7649673Slinton } 7659673Slinton if (*cur == ';') { 7669673Slinton ++cur; 7679673Slinton } 7689673Slinton curchar = cur; 7699673Slinton break; 7709673Slinton 7719673Slinton case 'e': 7729673Slinton t->class = SCAL; 7739673Slinton u = t; 7749673Slinton while (*curchar != ';' and *curchar != '\0') { 7759673Slinton p = index(curchar, ':'); 7769673Slinton assert(p != nil); 7779673Slinton *p = '\0'; 7789673Slinton u->chain = insert(identname(curchar, true)); 7799673Slinton curchar = p + 1; 7809673Slinton u = u->chain; 7819673Slinton u->language = curlang; 7829673Slinton u->class = CONST; 7839673Slinton u->level = b; 7849673Slinton u->block = curblock; 7859673Slinton u->type = t; 7869673Slinton u->symvalue.iconval = getint(); 7879673Slinton skipchar(curchar, ','); 7889673Slinton } 7899673Slinton break; 7909673Slinton 7919673Slinton case '*': 7929673Slinton t->class = PTR; 7939673Slinton t->type = constype(nil); 7949673Slinton break; 7959673Slinton 7969673Slinton case 'f': 7979673Slinton t->class = FUNC; 7989673Slinton t->type = constype(nil); 7999673Slinton break; 8009673Slinton 8019673Slinton default: 8029673Slinton badcaseval(class); 8039673Slinton } 8049673Slinton } 8059673Slinton return t; 8069673Slinton } 8079673Slinton 8089673Slinton /* 8099673Slinton * Read an integer from the current position in the type string. 8109673Slinton */ 8119673Slinton 8129673Slinton private Integer getint() 8139673Slinton { 8149673Slinton register Integer n; 8159673Slinton register char *p; 8169673Slinton register Boolean isneg; 8179673Slinton 8189673Slinton n = 0; 8199673Slinton p = curchar; 8209673Slinton if (*p == '-') { 8219673Slinton isneg = true; 8229673Slinton ++p; 8239673Slinton } else { 8249673Slinton isneg = false; 8259673Slinton } 8269673Slinton while (isdigit(*p)) { 8279673Slinton n = 10*n + (*p - '0'); 8289673Slinton ++p; 8299673Slinton } 8309673Slinton curchar = p; 8319673Slinton return isneg ? (-n) : n; 8329673Slinton } 8339673Slinton 8349673Slinton /* 8359673Slinton * Add a tag name. This is a kludge to be able to refer 8369673Slinton * to tags that have the same name as some other symbol 8379673Slinton * in the same block. 8389673Slinton */ 8399673Slinton 8409673Slinton private addtag(s) 8419673Slinton register Symbol s; 8429673Slinton { 8439673Slinton register Symbol t; 8449673Slinton char buf[100]; 8459673Slinton 8469673Slinton sprintf(buf, "$$%.90s", ident(s->name)); 8479673Slinton t = insert(identname(buf, false)); 8489673Slinton t->language = s->language; 8499673Slinton t->class = TAG; 8509673Slinton t->type = s->type; 8519673Slinton t->block = s->block; 8529673Slinton } 8539673Slinton 8549673Slinton /* 8559673Slinton * Allocate file and line tables and initialize indices. 8569673Slinton */ 8579673Slinton 8589673Slinton private allocmaps(nf, nl) 8599673Slinton Integer nf, nl; 8609673Slinton { 8619673Slinton if (filetab != nil) { 8629673Slinton dispose(filetab); 8639673Slinton } 8649673Slinton if (linetab != nil) { 8659673Slinton dispose(linetab); 8669673Slinton } 8679673Slinton filetab = newarr(Filetab, nf); 8689673Slinton linetab = newarr(Linetab, nl); 8699673Slinton filep = filetab; 8709673Slinton linep = linetab; 8719673Slinton } 8729673Slinton 8739673Slinton /* 8749673Slinton * Add a file to the file table. 8759673Slinton */ 8769673Slinton 8779673Slinton private enterfile(filename, addr) 8789673Slinton String filename; 8799673Slinton Address addr; 8809673Slinton { 8819673Slinton if (addr != curfaddr) { 8829673Slinton filep->addr = addr; 8839673Slinton filep->filename = filename; 8849673Slinton filep->lineindex = linep - linetab; 8859673Slinton ++filep; 8869673Slinton curfaddr = addr; 8879673Slinton } 8889673Slinton } 8899673Slinton 8909673Slinton /* 8919673Slinton * Since we only estimated the number of lines (and it was a poor 8929673Slinton * estimation) and since we need to know the exact number of lines 8939673Slinton * to do a binary search, we set it when we're done. 8949673Slinton */ 8959673Slinton 8969673Slinton private setnlines() 8979673Slinton { 8989673Slinton nlhdr.nlines = linep - linetab; 8999673Slinton } 9009673Slinton 9019673Slinton /* 9029673Slinton * Similarly for nfiles ... 9039673Slinton */ 9049673Slinton 9059673Slinton private setnfiles() 9069673Slinton { 9079673Slinton nlhdr.nfiles = filep - filetab; 9089673Slinton setsource(filetab[0].filename); 9099673Slinton } 910