19673Slinton /* Copyright (c) 1982 Regents of the University of California */ 29673Slinton 3*11558Slinton static char sccsid[] = "@(#)object.c 1.5 03/13/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; 2139673Slinton newfunc(program); 2149673Slinton findbeginning(program); 2159673Slinton enterblock(program); 2169673Slinton curmodule = program; 2179673Slinton t_boolean = maketype("$boolean", 0L, 1L); 2189673Slinton t_int = maketype("$integer", 0x80000000L, 0x7fffffffL); 2199673Slinton t_char = maketype("$char", 0L, 127L); 2209673Slinton t_real = maketype("$real", 4L, 0L); 2219673Slinton t_nil = maketype("$nil", 0L, 0L); 2229673Slinton } 2239673Slinton 2249673Slinton /* 2259673Slinton * Free all the object file information that's being stored. 2269673Slinton */ 2279673Slinton 2289673Slinton public objfree() 2299673Slinton { 2309673Slinton symbol_free(); 2319673Slinton keywords_free(); 2329673Slinton names_free(); 2339673Slinton dispose(stringtab); 2349673Slinton clrfunctab(); 2359673Slinton } 2369673Slinton 2379673Slinton /* 2389673Slinton * Enter a namelist entry. 2399673Slinton */ 2409673Slinton 2419673Slinton private enter_nl(name, np) 2429673Slinton String name; 2439673Slinton register struct nlist *np; 2449673Slinton { 2459673Slinton register Symbol s; 2469673Slinton String mname, suffix; 2479673Slinton register Name n; 2489673Slinton register Symbol *tt; 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; 2999673Slinton enterblock(s); 3009673Slinton curmodule = s; 3019673Slinton if (program->language == nil) { 3029673Slinton program->language = curlang; 3039673Slinton } 3049673Slinton warned = false; 3059673Slinton enterfile(ident(n), (Address) np->n_value); 3069673Slinton for (tt = &typetable[0]; tt < &typetable[NTYPES]; tt++) { 3079673Slinton *tt = nil; 3089673Slinton } 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: 349*11558Slinton default: 3509840Slinton /* 3519840Slinton * Should complain out this, obviously the wrong symbol format. 352*11558Slinton * 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); 358*11558Slinton * 359*11558Slinton */ 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; 4669673Slinton if (curblock->class != PROG) { 4679673Slinton exitblock(); 4689673Slinton if (curblock->class != PROG) { 4699673Slinton exitblock(); 4709673Slinton } 4719673Slinton } 4729673Slinton enterblock(s); 4739673Slinton curmodule = s; 4749673Slinton } 4759673Slinton } 4769673Slinton 4779673Slinton /* 4789673Slinton * Put an nlist into the symbol table. 4799673Slinton * If it's already there just add the associated information. 4809673Slinton * 4819673Slinton * Type information is encoded in the name following a ":". 4829673Slinton */ 4839673Slinton 4849673Slinton private Symbol constype(); 4859673Slinton private Char *curchar; 4869673Slinton 4879673Slinton #define skipchar(ptr, ch) { \ 4889673Slinton if (*ptr != ch) { \ 4899673Slinton panic("expected char '%c', found char '%c'", ch, *ptr); \ 4909673Slinton } \ 4919673Slinton ++ptr; \ 4929673Slinton } 4939673Slinton 4949673Slinton private entersym(str, np) 4959673Slinton String str; 4969673Slinton struct nlist *np; 4979673Slinton { 4989673Slinton register Symbol s; 4999673Slinton register char *p; 5009673Slinton register int c; 5019673Slinton register Name n; 5029673Slinton register Integer i; 5039673Slinton Boolean knowtype, isnew; 5049673Slinton Symclass class; 5059673Slinton Integer level; 5069673Slinton 5079673Slinton p = index(str, ':'); 5089673Slinton *p = '\0'; 5099673Slinton c = *(p+1); 5109673Slinton n = identname(str, true); 5119673Slinton if (index("FfGV", c) != nil) { 5129673Slinton if (c == 'F' or c == 'f') { 5139673Slinton class = FUNC; 5149673Slinton } else { 5159673Slinton class = VAR; 5169673Slinton } 5179673Slinton level = (c == 'f' ? curmodule->level : program->level); 5189673Slinton find(s, n) where s->level == level and s->class == class endfind(s); 5199673Slinton if (s == nil) { 5209673Slinton isnew = true; 5219673Slinton s = insert(n); 5229673Slinton } else { 5239673Slinton isnew = false; 5249673Slinton } 5259673Slinton } else { 5269673Slinton isnew = true; 5279673Slinton s = insert(n); 5289673Slinton } 5299673Slinton 5309673Slinton /* 5319673Slinton * Default attributes. 5329673Slinton */ 5339673Slinton s->language = curlang; 5349673Slinton s->class = VAR; 5359673Slinton s->block = curblock; 5369673Slinton s->level = curlevel; 5379673Slinton s->symvalue.offset = np->n_value; 5389673Slinton curchar = p + 2; 5399673Slinton knowtype = false; 5409673Slinton switch (c) { 5419673Slinton case 't': /* type name */ 5429673Slinton s->class = TYPE; 5439673Slinton i = getint(); 5449673Slinton if (i == 0) { 5459673Slinton panic("bad input on type \"%s\" at \"%s\"", symname(s), 5469673Slinton curchar); 5479673Slinton } else if (i >= NTYPES) { 5489673Slinton panic("too many types in file \"%s\"", curfilename()); 5499673Slinton } 5509673Slinton /* 5519673Slinton * A hack for C typedefs that don't create new types, 5529673Slinton * e.g. typedef unsigned int Hashvalue; 553*11558Slinton * or typedef struct blah BLAH; 5549673Slinton */ 5559673Slinton if (*curchar == '\0') { 5569673Slinton s->type = typetable[i]; 5579673Slinton if (s->type == nil) { 558*11558Slinton s->type = symbol_alloc(); 559*11558Slinton typetable[i] = s->type; 5609673Slinton } 5619673Slinton knowtype = true; 5629673Slinton } else { 5639673Slinton typetable[i] = s; 5649673Slinton skipchar(curchar, '='); 5659673Slinton } 5669673Slinton break; 5679673Slinton 5689673Slinton case 'T': /* tag */ 5699673Slinton s->class = TAG; 5709673Slinton i = getint(); 5719673Slinton if (i == 0) { 5729673Slinton panic("bad input on tag \"%s\" at \"%s\"", symname(s), 5739673Slinton curchar); 5749673Slinton } else if (i >= NTYPES) { 5759673Slinton panic("too many types in file \"%s\"", curfilename()); 5769673Slinton } 5779673Slinton if (typetable[i] != nil) { 5789673Slinton typetable[i]->language = curlang; 5799673Slinton typetable[i]->class = TYPE; 5809673Slinton typetable[i]->type = s; 5819673Slinton } else { 5829673Slinton typetable[i] = s; 5839673Slinton } 5849673Slinton skipchar(curchar, '='); 5859673Slinton break; 5869673Slinton 5879673Slinton case 'F': /* public function */ 5889673Slinton case 'f': /* private function */ 5899673Slinton s->class = FUNC; 5909673Slinton if (curblock->class == FUNC or curblock->class == PROC) { 5919673Slinton exitblock(); 5929673Slinton } 5939673Slinton enterblock(s); 5949673Slinton if (c == 'F') { 5959673Slinton s->level = program->level; 5969673Slinton isnew = false; 5979673Slinton } 5989673Slinton curparam = s; 5999673Slinton if (isnew) { 6009673Slinton s->symvalue.funcv.beginaddr = np->n_value; 6019673Slinton newfunc(s); 6029673Slinton findbeginning(s); 6039673Slinton } 6049673Slinton break; 6059673Slinton 6069673Slinton case 'G': /* public variable */ 6079673Slinton s->level = program->level; 6089673Slinton break; 6099673Slinton 6109673Slinton case 'S': /* private variable */ 6119673Slinton s->level = curmodule->level; 6129673Slinton s->block = curmodule; 6139673Slinton break; 6149673Slinton 6159673Slinton case 'V': /* own variable */ 6169673Slinton s->level = 2; 6179673Slinton break; 6189673Slinton 6199673Slinton case 'r': /* register variable */ 6209673Slinton s->level = -(s->level); 6219673Slinton break; 6229673Slinton 6239673Slinton case 'p': /* parameter variable */ 6249673Slinton curparam->chain = s; 6259673Slinton curparam = s; 6269673Slinton break; 6279673Slinton 6289673Slinton case 'v': /* varies parameter */ 6299673Slinton s->class = REF; 6309673Slinton s->symvalue.offset = np->n_value; 6319673Slinton curparam->chain = s; 6329673Slinton curparam = s; 6339673Slinton break; 6349673Slinton 6359673Slinton default: /* local variable */ 6369673Slinton --curchar; 6379673Slinton break; 6389673Slinton } 6399673Slinton if (not knowtype) { 6409673Slinton s->type = constype(nil); 6419673Slinton if (s->class == TAG) { 6429673Slinton addtag(s); 6439673Slinton } 6449673Slinton } 6459673Slinton if (tracesyms) { 6469673Slinton printdecl(s); 6479673Slinton fflush(stdout); 6489673Slinton } 6499673Slinton } 6509673Slinton 6519673Slinton /* 6529673Slinton * Construct a type out of a string encoding. 6539673Slinton * 6549673Slinton * The forms of the string are 6559673Slinton * 6569673Slinton * <number> 6579673Slinton * <number>=<type> 6589673Slinton * r<type>;<number>;<number> $ subrange 6599673Slinton * a<type>;<type> $ array[index] of element 6609673Slinton * s{<name>:<type>;<number>;<number>} $ record 6619673Slinton * *<type> $ pointer 6629673Slinton */ 6639673Slinton 6649673Slinton private Symbol constype(type) 6659673Slinton Symbol type; 6669673Slinton { 6679673Slinton register Symbol t, u; 6689673Slinton register Char *p, *cur; 6699673Slinton register Integer n; 6709673Slinton Integer b; 6719673Slinton Name name; 6729673Slinton Char class; 6739673Slinton 6749673Slinton b = curlevel; 6759673Slinton if (isdigit(*curchar)) { 6769673Slinton n = getint(); 6779673Slinton if (n == 0) { 6789673Slinton panic("bad type number at \"%s\"", curchar); 6799673Slinton } else if (n >= NTYPES) { 6809673Slinton panic("too many types in file \"%s\"", curfilename()); 6819673Slinton } 6829673Slinton if (*curchar == '=') { 6839673Slinton if (typetable[n] != nil) { 6849673Slinton t = typetable[n]; 6859673Slinton } else { 6869673Slinton t = symbol_alloc(); 6879673Slinton typetable[n] = t; 6889673Slinton } 6899673Slinton ++curchar; 6909673Slinton constype(t); 6919673Slinton } else { 6929673Slinton t = typetable[n]; 6939673Slinton if (t == nil) { 6949673Slinton t = symbol_alloc(); 6959673Slinton typetable[n] = t; 6969673Slinton } 6979673Slinton } 6989673Slinton } else { 6999673Slinton if (type == nil) { 7009673Slinton t = symbol_alloc(); 7019673Slinton } else { 7029673Slinton t = type; 7039673Slinton } 7049673Slinton t->language = curlang; 7059673Slinton t->level = b; 7069673Slinton class = *curchar++; 7079673Slinton switch (class) { 7089673Slinton case 'r': 7099673Slinton t->class = RANGE; 7109673Slinton t->type = constype(nil); 7119673Slinton skipchar(curchar, ';'); 7129673Slinton t->symvalue.rangev.lower = getint(); 7139673Slinton skipchar(curchar, ';'); 7149673Slinton t->symvalue.rangev.upper = getint(); 7159673Slinton break; 7169673Slinton 7179673Slinton case 'a': 7189673Slinton t->class = ARRAY; 7199673Slinton t->chain = constype(nil); 7209673Slinton skipchar(curchar, ';'); 7219673Slinton t->type = constype(nil); 7229673Slinton break; 7239673Slinton 7249673Slinton case 's': 7259673Slinton case 'u': 7269673Slinton t->class = (class == 's') ? RECORD : VARNT; 7279673Slinton t->symvalue.offset = getint(); 7289673Slinton u = t; 7299673Slinton cur = curchar; 7309673Slinton while (*cur != ';' and *cur != '\0') { 7319673Slinton p = index(cur, ':'); 7329673Slinton if (p == nil) { 7339673Slinton panic("index(\"%s\", ':') failed", curchar); 7349673Slinton } 7359673Slinton *p = '\0'; 7369673Slinton name = identname(cur, true); 7379673Slinton u->chain = newSymbol(name, b, FIELD, nil, nil); 7389673Slinton cur = p + 1; 7399673Slinton u = u->chain; 7409673Slinton u->language = curlang; 7419673Slinton curchar = cur; 7429673Slinton u->type = constype(nil); 7439673Slinton skipchar(curchar, ','); 7449673Slinton u->symvalue.field.offset = getint(); 7459673Slinton skipchar(curchar, ','); 7469673Slinton u->symvalue.field.length = getint(); 7479673Slinton skipchar(curchar, ';'); 7489673Slinton cur = curchar; 7499673Slinton } 7509673Slinton if (*cur == ';') { 7519673Slinton ++cur; 7529673Slinton } 7539673Slinton curchar = cur; 7549673Slinton break; 7559673Slinton 7569673Slinton case 'e': 7579673Slinton t->class = SCAL; 7589673Slinton u = t; 7599673Slinton while (*curchar != ';' and *curchar != '\0') { 7609673Slinton p = index(curchar, ':'); 7619673Slinton assert(p != nil); 7629673Slinton *p = '\0'; 7639673Slinton u->chain = insert(identname(curchar, true)); 7649673Slinton curchar = p + 1; 7659673Slinton u = u->chain; 7669673Slinton u->language = curlang; 7679673Slinton u->class = CONST; 7689673Slinton u->level = b; 7699673Slinton u->block = curblock; 7709673Slinton u->type = t; 7719673Slinton u->symvalue.iconval = getint(); 7729673Slinton skipchar(curchar, ','); 7739673Slinton } 7749673Slinton break; 7759673Slinton 7769673Slinton case '*': 7779673Slinton t->class = PTR; 7789673Slinton t->type = constype(nil); 7799673Slinton break; 7809673Slinton 7819673Slinton case 'f': 7829673Slinton t->class = FUNC; 7839673Slinton t->type = constype(nil); 7849673Slinton break; 7859673Slinton 7869673Slinton default: 7879673Slinton badcaseval(class); 7889673Slinton } 7899673Slinton } 7909673Slinton return t; 7919673Slinton } 7929673Slinton 7939673Slinton /* 7949673Slinton * Read an integer from the current position in the type string. 7959673Slinton */ 7969673Slinton 7979673Slinton private Integer getint() 7989673Slinton { 7999673Slinton register Integer n; 8009673Slinton register char *p; 8019673Slinton register Boolean isneg; 8029673Slinton 8039673Slinton n = 0; 8049673Slinton p = curchar; 8059673Slinton if (*p == '-') { 8069673Slinton isneg = true; 8079673Slinton ++p; 8089673Slinton } else { 8099673Slinton isneg = false; 8109673Slinton } 8119673Slinton while (isdigit(*p)) { 8129673Slinton n = 10*n + (*p - '0'); 8139673Slinton ++p; 8149673Slinton } 8159673Slinton curchar = p; 8169673Slinton return isneg ? (-n) : n; 8179673Slinton } 8189673Slinton 8199673Slinton /* 8209673Slinton * Add a tag name. This is a kludge to be able to refer 8219673Slinton * to tags that have the same name as some other symbol 8229673Slinton * in the same block. 8239673Slinton */ 8249673Slinton 8259673Slinton private addtag(s) 8269673Slinton register Symbol s; 8279673Slinton { 8289673Slinton register Symbol t; 8299673Slinton char buf[100]; 8309673Slinton 8319673Slinton sprintf(buf, "$$%.90s", ident(s->name)); 8329673Slinton t = insert(identname(buf, false)); 8339673Slinton t->language = s->language; 8349673Slinton t->class = TAG; 8359673Slinton t->type = s->type; 8369673Slinton t->block = s->block; 8379673Slinton } 8389673Slinton 8399673Slinton /* 8409673Slinton * Allocate file and line tables and initialize indices. 8419673Slinton */ 8429673Slinton 8439673Slinton private allocmaps(nf, nl) 8449673Slinton Integer nf, nl; 8459673Slinton { 8469673Slinton if (filetab != nil) { 8479673Slinton dispose(filetab); 8489673Slinton } 8499673Slinton if (linetab != nil) { 8509673Slinton dispose(linetab); 8519673Slinton } 8529673Slinton filetab = newarr(Filetab, nf); 8539673Slinton linetab = newarr(Linetab, nl); 8549673Slinton filep = filetab; 8559673Slinton linep = linetab; 8569673Slinton } 8579673Slinton 8589673Slinton /* 8599673Slinton * Add a file to the file table. 8609673Slinton */ 8619673Slinton 8629673Slinton private enterfile(filename, addr) 8639673Slinton String filename; 8649673Slinton Address addr; 8659673Slinton { 8669673Slinton if (addr != curfaddr) { 8679673Slinton filep->addr = addr; 8689673Slinton filep->filename = filename; 8699673Slinton filep->lineindex = linep - linetab; 8709673Slinton ++filep; 8719673Slinton curfaddr = addr; 8729673Slinton } 8739673Slinton } 8749673Slinton 8759673Slinton /* 8769673Slinton * Since we only estimated the number of lines (and it was a poor 8779673Slinton * estimation) and since we need to know the exact number of lines 8789673Slinton * to do a binary search, we set it when we're done. 8799673Slinton */ 8809673Slinton 8819673Slinton private setnlines() 8829673Slinton { 8839673Slinton nlhdr.nlines = linep - linetab; 8849673Slinton } 8859673Slinton 8869673Slinton /* 8879673Slinton * Similarly for nfiles ... 8889673Slinton */ 8899673Slinton 8909673Slinton private setnfiles() 8919673Slinton { 8929673Slinton nlhdr.nfiles = filep - filetab; 8939673Slinton setsource(filetab[0].filename); 8949673Slinton } 895