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