1*9673Slinton /* Copyright (c) 1982 Regents of the University of California */ 2*9673Slinton 3*9673Slinton static char sccsid[] = "@(#)@(#)object.c 1.1 12/15/82"; 4*9673Slinton 5*9673Slinton /* 6*9673Slinton * Object code interface, mainly for extraction of symbolic information. 7*9673Slinton */ 8*9673Slinton 9*9673Slinton #include "defs.h" 10*9673Slinton #include "object.h" 11*9673Slinton #include "main.h" 12*9673Slinton #include "symbols.h" 13*9673Slinton #include "names.h" 14*9673Slinton #include "languages.h" 15*9673Slinton #include "mappings.h" 16*9673Slinton #include "lists.h" 17*9673Slinton #include <a.out.h> 18*9673Slinton #include <stab.h> 19*9673Slinton #include <ctype.h> 20*9673Slinton 21*9673Slinton #ifndef public 22*9673Slinton 23*9673Slinton struct { 24*9673Slinton unsigned int stringsize; /* size of the dumped string table */ 25*9673Slinton unsigned int nsyms; /* number of symbols */ 26*9673Slinton unsigned int nfiles; /* number of files */ 27*9673Slinton unsigned int nlines; /* number of lines */ 28*9673Slinton } nlhdr; 29*9673Slinton 30*9673Slinton #endif 31*9673Slinton 32*9673Slinton public String objname = "a.out"; 33*9673Slinton public Integer objsize; 34*9673Slinton public char *stringtab; 35*9673Slinton 36*9673Slinton private String progname = nil; 37*9673Slinton private Language curlang; 38*9673Slinton private Symbol curmodule; 39*9673Slinton private Symbol curparam; 40*9673Slinton private Boolean warned; 41*9673Slinton 42*9673Slinton private Filetab *filep; 43*9673Slinton private Linetab *linep; 44*9673Slinton private Address curfaddr; 45*9673Slinton 46*9673Slinton #define curfilename() (filep-1)->filename 47*9673Slinton 48*9673Slinton /* 49*9673Slinton * Blocks are figured out on the fly while reading the symbol table. 50*9673Slinton */ 51*9673Slinton 52*9673Slinton #define MAXBLKDEPTH 25 53*9673Slinton 54*9673Slinton private Symbol curblock; 55*9673Slinton private Symbol blkstack[MAXBLKDEPTH]; 56*9673Slinton private Integer curlevel; 57*9673Slinton 58*9673Slinton #define enterblock(b) { \ 59*9673Slinton blkstack[curlevel] = curblock; \ 60*9673Slinton ++curlevel; \ 61*9673Slinton b->level = curlevel; \ 62*9673Slinton b->block = curblock; \ 63*9673Slinton curblock = b; \ 64*9673Slinton } 65*9673Slinton 66*9673Slinton #define exitblock() { \ 67*9673Slinton --curlevel; \ 68*9673Slinton curblock = blkstack[curlevel]; \ 69*9673Slinton } 70*9673Slinton 71*9673Slinton /* 72*9673Slinton * Enter a source line or file name reference into the appropriate table. 73*9673Slinton * Expanded inline to reduce procedure calls. 74*9673Slinton * 75*9673Slinton * private enterline(linenumber, address) 76*9673Slinton * Lineno linenumber; 77*9673Slinton * Address address; 78*9673Slinton * ... 79*9673Slinton */ 80*9673Slinton 81*9673Slinton #define enterline(linenumber, address) \ 82*9673Slinton { \ 83*9673Slinton register Linetab *lp; \ 84*9673Slinton \ 85*9673Slinton lp = linep - 1; \ 86*9673Slinton if (linenumber != lp->line) { \ 87*9673Slinton if (address != lp->addr) { \ 88*9673Slinton ++lp; \ 89*9673Slinton } \ 90*9673Slinton lp->line = linenumber; \ 91*9673Slinton lp->addr = address; \ 92*9673Slinton linep = lp + 1; \ 93*9673Slinton } \ 94*9673Slinton } 95*9673Slinton 96*9673Slinton #define NTYPES 1000 97*9673Slinton 98*9673Slinton private Symbol typetable[NTYPES]; 99*9673Slinton 100*9673Slinton /* 101*9673Slinton * Read in the namelist from the obj file. 102*9673Slinton * 103*9673Slinton * Reads and seeks are used instead of fread's and fseek's 104*9673Slinton * for efficiency sake; there's a lot of data being read here. 105*9673Slinton */ 106*9673Slinton 107*9673Slinton public readobj(file) 108*9673Slinton String file; 109*9673Slinton { 110*9673Slinton Fileid f; 111*9673Slinton struct exec hdr; 112*9673Slinton struct nlist nlist; 113*9673Slinton 114*9673Slinton f = open(file, 0); 115*9673Slinton if (f < 0) { 116*9673Slinton fatal("can't open %s", file); 117*9673Slinton } 118*9673Slinton read(f, &hdr, sizeof(hdr)); 119*9673Slinton objsize = hdr.a_text; 120*9673Slinton nlhdr.nsyms = hdr.a_syms / sizeof(nlist); 121*9673Slinton nlhdr.nfiles = nlhdr.nsyms; 122*9673Slinton nlhdr.nlines = nlhdr.nsyms; 123*9673Slinton lseek(f, (long) N_STROFF(hdr), 0); 124*9673Slinton read(f, &(nlhdr.stringsize), sizeof(nlhdr.stringsize)); 125*9673Slinton nlhdr.stringsize -= 4; 126*9673Slinton stringtab = newarr(char, nlhdr.stringsize); 127*9673Slinton read(f, stringtab, nlhdr.stringsize); 128*9673Slinton allocmaps(nlhdr.nfiles, nlhdr.nlines); 129*9673Slinton lseek(f, (long) N_SYMOFF(hdr), 0); 130*9673Slinton readsyms(f); 131*9673Slinton ordfunctab(); 132*9673Slinton setnlines(); 133*9673Slinton setnfiles(); 134*9673Slinton close(f); 135*9673Slinton } 136*9673Slinton 137*9673Slinton /* 138*9673Slinton * Read in symbols from object file. 139*9673Slinton */ 140*9673Slinton 141*9673Slinton private readsyms(f) 142*9673Slinton Fileid f; 143*9673Slinton { 144*9673Slinton struct nlist *namelist; 145*9673Slinton register struct nlist *np, *ub; 146*9673Slinton register int index; 147*9673Slinton register String name; 148*9673Slinton register Boolean afterlg; 149*9673Slinton 150*9673Slinton initsyms(); 151*9673Slinton namelist = newarr(struct nlist, nlhdr.nsyms); 152*9673Slinton read(f, namelist, nlhdr.nsyms * sizeof(struct nlist)); 153*9673Slinton afterlg = false; 154*9673Slinton ub = &namelist[nlhdr.nsyms]; 155*9673Slinton for (np = &namelist[0]; np < ub; np++) { 156*9673Slinton index = np->n_un.n_strx; 157*9673Slinton if (index != 0) { 158*9673Slinton name = &stringtab[index - 4]; 159*9673Slinton } else { 160*9673Slinton name = nil; 161*9673Slinton } 162*9673Slinton /* 163*9673Slinton * assumptions: 164*9673Slinton * not an N_STAB ==> name != nil 165*9673Slinton * name[0] == '-' ==> name == "-lg" 166*9673Slinton * name[0] != '_' ==> filename or invisible 167*9673Slinton * 168*9673Slinton * The "-lg" signals the beginning of global loader symbols. 169*9673Slinton */ 170*9673Slinton if ((np->n_type&N_STAB) != 0) { 171*9673Slinton enter_nl(name, np); 172*9673Slinton } else if (name[0] == '-') { 173*9673Slinton afterlg = true; 174*9673Slinton if (curblock->class != PROG) { 175*9673Slinton exitblock(); 176*9673Slinton if (curblock->class != PROG) { 177*9673Slinton exitblock(); 178*9673Slinton } 179*9673Slinton } 180*9673Slinton enterline(0, (linep-1)->addr + 1); 181*9673Slinton } else if (name[0] == '_') { 182*9673Slinton if (afterlg) { 183*9673Slinton check_global(&name[1], np); 184*9673Slinton } else if (curblock->name != nil) { 185*9673Slinton check_local(&name[1], np); 186*9673Slinton } 187*9673Slinton } else if ((np->n_type&N_TEXT) == N_TEXT) { 188*9673Slinton check_filename(name); 189*9673Slinton } 190*9673Slinton } 191*9673Slinton dispose(namelist); 192*9673Slinton } 193*9673Slinton 194*9673Slinton /* 195*9673Slinton * Initialize symbol information. 196*9673Slinton */ 197*9673Slinton 198*9673Slinton private initsyms() 199*9673Slinton { 200*9673Slinton curblock = nil; 201*9673Slinton curlevel = 0; 202*9673Slinton if (progname == nil) { 203*9673Slinton progname = strdup(objname); 204*9673Slinton if (rindex(progname, '/') != nil) { 205*9673Slinton progname = rindex(progname, '/') + 1; 206*9673Slinton } 207*9673Slinton if (index(progname, '.') != nil) { 208*9673Slinton *(index(progname, '.')) = '\0'; 209*9673Slinton } 210*9673Slinton } 211*9673Slinton program = insert(identname(progname, true)); 212*9673Slinton program->class = PROG; 213*9673Slinton newfunc(program); 214*9673Slinton findbeginning(program); 215*9673Slinton enterblock(program); 216*9673Slinton curmodule = program; 217*9673Slinton t_boolean = maketype("$boolean", 0L, 1L); 218*9673Slinton t_int = maketype("$integer", 0x80000000L, 0x7fffffffL); 219*9673Slinton t_char = maketype("$char", 0L, 127L); 220*9673Slinton t_real = maketype("$real", 4L, 0L); 221*9673Slinton t_nil = maketype("$nil", 0L, 0L); 222*9673Slinton } 223*9673Slinton 224*9673Slinton /* 225*9673Slinton * Free all the object file information that's being stored. 226*9673Slinton */ 227*9673Slinton 228*9673Slinton public objfree() 229*9673Slinton { 230*9673Slinton symbol_free(); 231*9673Slinton keywords_free(); 232*9673Slinton names_free(); 233*9673Slinton dispose(stringtab); 234*9673Slinton clrfunctab(); 235*9673Slinton } 236*9673Slinton 237*9673Slinton /* 238*9673Slinton * Enter a namelist entry. 239*9673Slinton */ 240*9673Slinton 241*9673Slinton private enter_nl(name, np) 242*9673Slinton String name; 243*9673Slinton register struct nlist *np; 244*9673Slinton { 245*9673Slinton register Symbol s; 246*9673Slinton String mname, suffix; 247*9673Slinton register Name n; 248*9673Slinton register Symbol *tt; 249*9673Slinton 250*9673Slinton s = nil; 251*9673Slinton if (name == nil) { 252*9673Slinton n = nil; 253*9673Slinton } else { 254*9673Slinton n = identname(name, true); 255*9673Slinton } 256*9673Slinton switch (np->n_type) { 257*9673Slinton case N_LBRAC: 258*9673Slinton s = symbol_alloc(); 259*9673Slinton s->class = PROC; 260*9673Slinton enterblock(s); 261*9673Slinton break; 262*9673Slinton 263*9673Slinton case N_RBRAC: 264*9673Slinton exitblock(); 265*9673Slinton break; 266*9673Slinton 267*9673Slinton case N_SLINE: 268*9673Slinton enterline((Lineno) np->n_desc, (Address) np->n_value); 269*9673Slinton break; 270*9673Slinton 271*9673Slinton /* 272*9673Slinton * Compilation unit. C associates scope with filenames 273*9673Slinton * so we treat them as "modules". The filename without 274*9673Slinton * the suffix is used for the module name. 275*9673Slinton * 276*9673Slinton * Because there is no explicit "end-of-block" mark in 277*9673Slinton * the object file, we must exit blocks for the current 278*9673Slinton * procedure and module. 279*9673Slinton */ 280*9673Slinton case N_SO: 281*9673Slinton mname = strdup(ident(n)); 282*9673Slinton if (rindex(mname, '/') != nil) { 283*9673Slinton mname = rindex(mname, '/') + 1; 284*9673Slinton } 285*9673Slinton suffix = rindex(mname, '.'); 286*9673Slinton curlang = findlanguage(suffix); 287*9673Slinton if (suffix != nil) { 288*9673Slinton *suffix = '\0'; 289*9673Slinton } 290*9673Slinton if (curblock->class != PROG) { 291*9673Slinton exitblock(); 292*9673Slinton if (curblock->class != PROG) { 293*9673Slinton exitblock(); 294*9673Slinton } 295*9673Slinton } 296*9673Slinton s = insert(identname(mname, true)); 297*9673Slinton s->language = curlang; 298*9673Slinton s->class = MODULE; 299*9673Slinton enterblock(s); 300*9673Slinton curmodule = s; 301*9673Slinton if (program->language == nil) { 302*9673Slinton program->language = curlang; 303*9673Slinton } 304*9673Slinton warned = false; 305*9673Slinton enterfile(ident(n), (Address) np->n_value); 306*9673Slinton for (tt = &typetable[0]; tt < &typetable[NTYPES]; tt++) { 307*9673Slinton *tt = nil; 308*9673Slinton } 309*9673Slinton break; 310*9673Slinton 311*9673Slinton /* 312*9673Slinton * Textually included files. 313*9673Slinton */ 314*9673Slinton case N_SOL: 315*9673Slinton enterfile(name, (Address) np->n_value); 316*9673Slinton break; 317*9673Slinton 318*9673Slinton /* 319*9673Slinton * These symbols are assumed to have non-nil names. 320*9673Slinton */ 321*9673Slinton case N_GSYM: 322*9673Slinton case N_FUN: 323*9673Slinton case N_STSYM: 324*9673Slinton case N_LCSYM: 325*9673Slinton case N_RSYM: 326*9673Slinton case N_PSYM: 327*9673Slinton case N_LSYM: 328*9673Slinton case N_SSYM: 329*9673Slinton if (index(name, ':') == nil) { 330*9673Slinton if (not warned) { 331*9673Slinton warned = true; 332*9673Slinton /* 333*9673Slinton * Shouldn't do this if user might be typing. 334*9673Slinton * 335*9673Slinton warning("old style symbol information found in \"%s\"", 336*9673Slinton curfilename()); 337*9673Slinton * 338*9673Slinton */ 339*9673Slinton } 340*9673Slinton } else { 341*9673Slinton entersym(name, np); 342*9673Slinton } 343*9673Slinton break; 344*9673Slinton 345*9673Slinton case N_PC: 346*9673Slinton break; 347*9673Slinton 348*9673Slinton default: 349*9673Slinton if (name != nil) { 350*9673Slinton printf("%s, ", name); 351*9673Slinton } 352*9673Slinton printf("ntype %2x, desc %x, value %x\n", 353*9673Slinton np->n_type, np->n_desc, np->n_value); 354*9673Slinton break; 355*9673Slinton } 356*9673Slinton } 357*9673Slinton 358*9673Slinton /* 359*9673Slinton * Check to see if a global _name is already in the symbol table, 360*9673Slinton * if not then insert it. 361*9673Slinton */ 362*9673Slinton 363*9673Slinton private check_global(name, np) 364*9673Slinton String name; 365*9673Slinton register struct nlist *np; 366*9673Slinton { 367*9673Slinton register Name n; 368*9673Slinton register Symbol t; 369*9673Slinton 370*9673Slinton if (not streq(name, "end")) { 371*9673Slinton n = identname(name, true); 372*9673Slinton if ((np->n_type&N_TYPE) == N_TEXT) { 373*9673Slinton find(t, n) where 374*9673Slinton t->level == program->level and isblock(t) 375*9673Slinton endfind(t); 376*9673Slinton if (t == nil) { 377*9673Slinton t = insert(n); 378*9673Slinton t->language = findlanguage(".s"); 379*9673Slinton t->class = FUNC; 380*9673Slinton t->type = t_int; 381*9673Slinton t->block = curblock; 382*9673Slinton t->level = program->level; 383*9673Slinton } 384*9673Slinton t->symvalue.funcv.beginaddr = np->n_value; 385*9673Slinton newfunc(t); 386*9673Slinton findbeginning(t); 387*9673Slinton } else { 388*9673Slinton find(t, n) where 389*9673Slinton t->class == VAR and t->level == program->level 390*9673Slinton endfind(t); 391*9673Slinton if (t == nil) { 392*9673Slinton t = insert(n); 393*9673Slinton t->language = findlanguage(".s"); 394*9673Slinton t->class = VAR; 395*9673Slinton t->type = t_int; 396*9673Slinton t->block = curblock; 397*9673Slinton t->level = program->level; 398*9673Slinton } 399*9673Slinton t->symvalue.offset = np->n_value; 400*9673Slinton } 401*9673Slinton } 402*9673Slinton } 403*9673Slinton 404*9673Slinton /* 405*9673Slinton * Check to see if a local _name is known in the current scope. 406*9673Slinton * If not then enter it. 407*9673Slinton */ 408*9673Slinton 409*9673Slinton private check_local(name, np) 410*9673Slinton String name; 411*9673Slinton register struct nlist *np; 412*9673Slinton { 413*9673Slinton register Name n; 414*9673Slinton register Symbol t, cur; 415*9673Slinton 416*9673Slinton n = identname(name, true); 417*9673Slinton cur = ((np->n_type&N_TYPE) == N_TEXT) ? curmodule : curblock; 418*9673Slinton find(t, n) where t->block == cur endfind(t); 419*9673Slinton if (t == nil) { 420*9673Slinton t = insert(n); 421*9673Slinton t->language = findlanguage(".s"); 422*9673Slinton t->type = t_int; 423*9673Slinton t->block = cur; 424*9673Slinton t->level = cur->level; 425*9673Slinton if ((np->n_type&N_TYPE) == N_TEXT) { 426*9673Slinton t->class = FUNC; 427*9673Slinton t->symvalue.funcv.beginaddr = np->n_value; 428*9673Slinton newfunc(t); 429*9673Slinton findbeginning(t); 430*9673Slinton } else { 431*9673Slinton t->class = VAR; 432*9673Slinton t->symvalue.offset = np->n_value; 433*9673Slinton } 434*9673Slinton } 435*9673Slinton } 436*9673Slinton 437*9673Slinton /* 438*9673Slinton * Check to see if a symbol corresponds to a object file name. 439*9673Slinton * For some reason these are listed as in the text segment. 440*9673Slinton */ 441*9673Slinton 442*9673Slinton private check_filename(name) 443*9673Slinton String name; 444*9673Slinton { 445*9673Slinton register String mname; 446*9673Slinton register Integer i; 447*9673Slinton register Symbol s; 448*9673Slinton 449*9673Slinton mname = strdup(name); 450*9673Slinton i = strlen(mname) - 2; 451*9673Slinton if (i >= 0 and mname[i] == '.' and mname[i+1] == 'o') { 452*9673Slinton mname[i] = '\0'; 453*9673Slinton --i; 454*9673Slinton while (mname[i] != '/' and i >= 0) { 455*9673Slinton --i; 456*9673Slinton } 457*9673Slinton s = insert(identname(&mname[i+1], true)); 458*9673Slinton s->language = findlanguage(".s"); 459*9673Slinton s->class = MODULE; 460*9673Slinton if (curblock->class != PROG) { 461*9673Slinton exitblock(); 462*9673Slinton if (curblock->class != PROG) { 463*9673Slinton exitblock(); 464*9673Slinton } 465*9673Slinton } 466*9673Slinton enterblock(s); 467*9673Slinton curmodule = s; 468*9673Slinton } 469*9673Slinton } 470*9673Slinton 471*9673Slinton /* 472*9673Slinton * Put an nlist into the symbol table. 473*9673Slinton * If it's already there just add the associated information. 474*9673Slinton * 475*9673Slinton * Type information is encoded in the name following a ":". 476*9673Slinton */ 477*9673Slinton 478*9673Slinton private Symbol constype(); 479*9673Slinton private Char *curchar; 480*9673Slinton 481*9673Slinton #define skipchar(ptr, ch) { \ 482*9673Slinton if (*ptr != ch) { \ 483*9673Slinton panic("expected char '%c', found char '%c'", ch, *ptr); \ 484*9673Slinton } \ 485*9673Slinton ++ptr; \ 486*9673Slinton } 487*9673Slinton 488*9673Slinton private entersym(str, np) 489*9673Slinton String str; 490*9673Slinton struct nlist *np; 491*9673Slinton { 492*9673Slinton register Symbol s; 493*9673Slinton register char *p; 494*9673Slinton register int c; 495*9673Slinton register Name n; 496*9673Slinton register Integer i; 497*9673Slinton Boolean knowtype, isnew; 498*9673Slinton Symclass class; 499*9673Slinton Integer level; 500*9673Slinton 501*9673Slinton p = index(str, ':'); 502*9673Slinton *p = '\0'; 503*9673Slinton c = *(p+1); 504*9673Slinton n = identname(str, true); 505*9673Slinton if (index("FfGV", c) != nil) { 506*9673Slinton if (c == 'F' or c == 'f') { 507*9673Slinton class = FUNC; 508*9673Slinton } else { 509*9673Slinton class = VAR; 510*9673Slinton } 511*9673Slinton level = (c == 'f' ? curmodule->level : program->level); 512*9673Slinton find(s, n) where s->level == level and s->class == class endfind(s); 513*9673Slinton if (s == nil) { 514*9673Slinton isnew = true; 515*9673Slinton s = insert(n); 516*9673Slinton } else { 517*9673Slinton isnew = false; 518*9673Slinton } 519*9673Slinton } else { 520*9673Slinton isnew = true; 521*9673Slinton s = insert(n); 522*9673Slinton } 523*9673Slinton 524*9673Slinton /* 525*9673Slinton * Default attributes. 526*9673Slinton */ 527*9673Slinton s->language = curlang; 528*9673Slinton s->class = VAR; 529*9673Slinton s->block = curblock; 530*9673Slinton s->level = curlevel; 531*9673Slinton s->symvalue.offset = np->n_value; 532*9673Slinton curchar = p + 2; 533*9673Slinton knowtype = false; 534*9673Slinton switch (c) { 535*9673Slinton case 't': /* type name */ 536*9673Slinton s->class = TYPE; 537*9673Slinton i = getint(); 538*9673Slinton if (i == 0) { 539*9673Slinton panic("bad input on type \"%s\" at \"%s\"", symname(s), 540*9673Slinton curchar); 541*9673Slinton } else if (i >= NTYPES) { 542*9673Slinton panic("too many types in file \"%s\"", curfilename()); 543*9673Slinton } 544*9673Slinton /* 545*9673Slinton * A hack for C typedefs that don't create new types, 546*9673Slinton * e.g. typedef unsigned int Hashvalue; 547*9673Slinton */ 548*9673Slinton if (*curchar == '\0') { 549*9673Slinton s->type = typetable[i]; 550*9673Slinton if (s->type == nil) { 551*9673Slinton panic("nil type for %d", i); 552*9673Slinton } 553*9673Slinton knowtype = true; 554*9673Slinton } else { 555*9673Slinton typetable[i] = s; 556*9673Slinton skipchar(curchar, '='); 557*9673Slinton } 558*9673Slinton break; 559*9673Slinton 560*9673Slinton case 'T': /* tag */ 561*9673Slinton s->class = TAG; 562*9673Slinton i = getint(); 563*9673Slinton if (i == 0) { 564*9673Slinton panic("bad input on tag \"%s\" at \"%s\"", symname(s), 565*9673Slinton curchar); 566*9673Slinton } else if (i >= NTYPES) { 567*9673Slinton panic("too many types in file \"%s\"", curfilename()); 568*9673Slinton } 569*9673Slinton if (typetable[i] != nil) { 570*9673Slinton typetable[i]->language = curlang; 571*9673Slinton typetable[i]->class = TYPE; 572*9673Slinton typetable[i]->type = s; 573*9673Slinton } else { 574*9673Slinton typetable[i] = s; 575*9673Slinton } 576*9673Slinton skipchar(curchar, '='); 577*9673Slinton break; 578*9673Slinton 579*9673Slinton case 'F': /* public function */ 580*9673Slinton case 'f': /* private function */ 581*9673Slinton s->class = FUNC; 582*9673Slinton if (curblock->class == FUNC or curblock->class == PROC) { 583*9673Slinton exitblock(); 584*9673Slinton } 585*9673Slinton enterblock(s); 586*9673Slinton if (c == 'F') { 587*9673Slinton s->level = program->level; 588*9673Slinton isnew = false; 589*9673Slinton } 590*9673Slinton curparam = s; 591*9673Slinton if (isnew) { 592*9673Slinton s->symvalue.funcv.beginaddr = np->n_value; 593*9673Slinton newfunc(s); 594*9673Slinton findbeginning(s); 595*9673Slinton } 596*9673Slinton break; 597*9673Slinton 598*9673Slinton case 'G': /* public variable */ 599*9673Slinton s->level = program->level; 600*9673Slinton break; 601*9673Slinton 602*9673Slinton case 'S': /* private variable */ 603*9673Slinton s->level = curmodule->level; 604*9673Slinton s->block = curmodule; 605*9673Slinton break; 606*9673Slinton 607*9673Slinton case 'V': /* own variable */ 608*9673Slinton s->level = 2; 609*9673Slinton break; 610*9673Slinton 611*9673Slinton case 'r': /* register variable */ 612*9673Slinton s->level = -(s->level); 613*9673Slinton break; 614*9673Slinton 615*9673Slinton case 'p': /* parameter variable */ 616*9673Slinton curparam->chain = s; 617*9673Slinton curparam = s; 618*9673Slinton break; 619*9673Slinton 620*9673Slinton case 'v': /* varies parameter */ 621*9673Slinton s->class = REF; 622*9673Slinton s->symvalue.offset = np->n_value; 623*9673Slinton curparam->chain = s; 624*9673Slinton curparam = s; 625*9673Slinton break; 626*9673Slinton 627*9673Slinton default: /* local variable */ 628*9673Slinton --curchar; 629*9673Slinton break; 630*9673Slinton } 631*9673Slinton if (not knowtype) { 632*9673Slinton s->type = constype(nil); 633*9673Slinton if (s->class == TAG) { 634*9673Slinton addtag(s); 635*9673Slinton } 636*9673Slinton } 637*9673Slinton if (tracesyms) { 638*9673Slinton printdecl(s); 639*9673Slinton fflush(stdout); 640*9673Slinton } 641*9673Slinton } 642*9673Slinton 643*9673Slinton /* 644*9673Slinton * Construct a type out of a string encoding. 645*9673Slinton * 646*9673Slinton * The forms of the string are 647*9673Slinton * 648*9673Slinton * <number> 649*9673Slinton * <number>=<type> 650*9673Slinton * r<type>;<number>;<number> $ subrange 651*9673Slinton * a<type>;<type> $ array[index] of element 652*9673Slinton * s{<name>:<type>;<number>;<number>} $ record 653*9673Slinton * *<type> $ pointer 654*9673Slinton */ 655*9673Slinton 656*9673Slinton private Symbol constype(type) 657*9673Slinton Symbol type; 658*9673Slinton { 659*9673Slinton register Symbol t, u; 660*9673Slinton register Char *p, *cur; 661*9673Slinton register Integer n; 662*9673Slinton Integer b; 663*9673Slinton Name name; 664*9673Slinton Char class; 665*9673Slinton 666*9673Slinton b = curlevel; 667*9673Slinton if (isdigit(*curchar)) { 668*9673Slinton n = getint(); 669*9673Slinton if (n == 0) { 670*9673Slinton panic("bad type number at \"%s\"", curchar); 671*9673Slinton } else if (n >= NTYPES) { 672*9673Slinton panic("too many types in file \"%s\"", curfilename()); 673*9673Slinton } 674*9673Slinton if (*curchar == '=') { 675*9673Slinton if (typetable[n] != nil) { 676*9673Slinton t = typetable[n]; 677*9673Slinton } else { 678*9673Slinton t = symbol_alloc(); 679*9673Slinton typetable[n] = t; 680*9673Slinton } 681*9673Slinton ++curchar; 682*9673Slinton constype(t); 683*9673Slinton } else { 684*9673Slinton t = typetable[n]; 685*9673Slinton if (t == nil) { 686*9673Slinton t = symbol_alloc(); 687*9673Slinton typetable[n] = t; 688*9673Slinton } 689*9673Slinton } 690*9673Slinton } else { 691*9673Slinton if (type == nil) { 692*9673Slinton t = symbol_alloc(); 693*9673Slinton } else { 694*9673Slinton t = type; 695*9673Slinton } 696*9673Slinton t->language = curlang; 697*9673Slinton t->level = b; 698*9673Slinton class = *curchar++; 699*9673Slinton switch (class) { 700*9673Slinton case 'r': 701*9673Slinton t->class = RANGE; 702*9673Slinton t->type = constype(nil); 703*9673Slinton skipchar(curchar, ';'); 704*9673Slinton t->symvalue.rangev.lower = getint(); 705*9673Slinton skipchar(curchar, ';'); 706*9673Slinton t->symvalue.rangev.upper = getint(); 707*9673Slinton break; 708*9673Slinton 709*9673Slinton case 'a': 710*9673Slinton t->class = ARRAY; 711*9673Slinton t->chain = constype(nil); 712*9673Slinton skipchar(curchar, ';'); 713*9673Slinton t->type = constype(nil); 714*9673Slinton break; 715*9673Slinton 716*9673Slinton case 's': 717*9673Slinton case 'u': 718*9673Slinton t->class = (class == 's') ? RECORD : VARNT; 719*9673Slinton t->symvalue.offset = getint(); 720*9673Slinton u = t; 721*9673Slinton cur = curchar; 722*9673Slinton while (*cur != ';' and *cur != '\0') { 723*9673Slinton p = index(cur, ':'); 724*9673Slinton if (p == nil) { 725*9673Slinton panic("index(\"%s\", ':') failed", curchar); 726*9673Slinton } 727*9673Slinton *p = '\0'; 728*9673Slinton name = identname(cur, true); 729*9673Slinton u->chain = newSymbol(name, b, FIELD, nil, nil); 730*9673Slinton cur = p + 1; 731*9673Slinton u = u->chain; 732*9673Slinton u->language = curlang; 733*9673Slinton curchar = cur; 734*9673Slinton u->type = constype(nil); 735*9673Slinton skipchar(curchar, ','); 736*9673Slinton u->symvalue.field.offset = getint(); 737*9673Slinton skipchar(curchar, ','); 738*9673Slinton u->symvalue.field.length = getint(); 739*9673Slinton skipchar(curchar, ';'); 740*9673Slinton cur = curchar; 741*9673Slinton } 742*9673Slinton if (*cur == ';') { 743*9673Slinton ++cur; 744*9673Slinton } 745*9673Slinton curchar = cur; 746*9673Slinton break; 747*9673Slinton 748*9673Slinton case 'e': 749*9673Slinton t->class = SCAL; 750*9673Slinton u = t; 751*9673Slinton while (*curchar != ';' and *curchar != '\0') { 752*9673Slinton p = index(curchar, ':'); 753*9673Slinton assert(p != nil); 754*9673Slinton *p = '\0'; 755*9673Slinton u->chain = insert(identname(curchar, true)); 756*9673Slinton curchar = p + 1; 757*9673Slinton u = u->chain; 758*9673Slinton u->language = curlang; 759*9673Slinton u->class = CONST; 760*9673Slinton u->level = b; 761*9673Slinton u->block = curblock; 762*9673Slinton u->type = t; 763*9673Slinton u->symvalue.iconval = getint(); 764*9673Slinton skipchar(curchar, ','); 765*9673Slinton } 766*9673Slinton break; 767*9673Slinton 768*9673Slinton case '*': 769*9673Slinton t->class = PTR; 770*9673Slinton t->type = constype(nil); 771*9673Slinton break; 772*9673Slinton 773*9673Slinton case 'f': 774*9673Slinton t->class = FUNC; 775*9673Slinton t->type = constype(nil); 776*9673Slinton break; 777*9673Slinton 778*9673Slinton default: 779*9673Slinton badcaseval(class); 780*9673Slinton } 781*9673Slinton } 782*9673Slinton return t; 783*9673Slinton } 784*9673Slinton 785*9673Slinton /* 786*9673Slinton * Read an integer from the current position in the type string. 787*9673Slinton */ 788*9673Slinton 789*9673Slinton private Integer getint() 790*9673Slinton { 791*9673Slinton register Integer n; 792*9673Slinton register char *p; 793*9673Slinton register Boolean isneg; 794*9673Slinton 795*9673Slinton n = 0; 796*9673Slinton p = curchar; 797*9673Slinton if (*p == '-') { 798*9673Slinton isneg = true; 799*9673Slinton ++p; 800*9673Slinton } else { 801*9673Slinton isneg = false; 802*9673Slinton } 803*9673Slinton while (isdigit(*p)) { 804*9673Slinton n = 10*n + (*p - '0'); 805*9673Slinton ++p; 806*9673Slinton } 807*9673Slinton curchar = p; 808*9673Slinton return isneg ? (-n) : n; 809*9673Slinton } 810*9673Slinton 811*9673Slinton /* 812*9673Slinton * Add a tag name. This is a kludge to be able to refer 813*9673Slinton * to tags that have the same name as some other symbol 814*9673Slinton * in the same block. 815*9673Slinton */ 816*9673Slinton 817*9673Slinton private addtag(s) 818*9673Slinton register Symbol s; 819*9673Slinton { 820*9673Slinton register Symbol t; 821*9673Slinton char buf[100]; 822*9673Slinton 823*9673Slinton sprintf(buf, "$$%.90s", ident(s->name)); 824*9673Slinton t = insert(identname(buf, false)); 825*9673Slinton t->language = s->language; 826*9673Slinton t->class = TAG; 827*9673Slinton t->type = s->type; 828*9673Slinton t->block = s->block; 829*9673Slinton } 830*9673Slinton 831*9673Slinton /* 832*9673Slinton * Allocate file and line tables and initialize indices. 833*9673Slinton */ 834*9673Slinton 835*9673Slinton private allocmaps(nf, nl) 836*9673Slinton Integer nf, nl; 837*9673Slinton { 838*9673Slinton if (filetab != nil) { 839*9673Slinton dispose(filetab); 840*9673Slinton } 841*9673Slinton if (linetab != nil) { 842*9673Slinton dispose(linetab); 843*9673Slinton } 844*9673Slinton filetab = newarr(Filetab, nf); 845*9673Slinton linetab = newarr(Linetab, nl); 846*9673Slinton filep = filetab; 847*9673Slinton linep = linetab; 848*9673Slinton } 849*9673Slinton 850*9673Slinton /* 851*9673Slinton * Add a file to the file table. 852*9673Slinton */ 853*9673Slinton 854*9673Slinton private enterfile(filename, addr) 855*9673Slinton String filename; 856*9673Slinton Address addr; 857*9673Slinton { 858*9673Slinton if (addr != curfaddr) { 859*9673Slinton filep->addr = addr; 860*9673Slinton filep->filename = filename; 861*9673Slinton filep->lineindex = linep - linetab; 862*9673Slinton ++filep; 863*9673Slinton curfaddr = addr; 864*9673Slinton } 865*9673Slinton } 866*9673Slinton 867*9673Slinton /* 868*9673Slinton * Since we only estimated the number of lines (and it was a poor 869*9673Slinton * estimation) and since we need to know the exact number of lines 870*9673Slinton * to do a binary search, we set it when we're done. 871*9673Slinton */ 872*9673Slinton 873*9673Slinton private setnlines() 874*9673Slinton { 875*9673Slinton nlhdr.nlines = linep - linetab; 876*9673Slinton } 877*9673Slinton 878*9673Slinton /* 879*9673Slinton * Similarly for nfiles ... 880*9673Slinton */ 881*9673Slinton 882*9673Slinton private setnfiles() 883*9673Slinton { 884*9673Slinton nlhdr.nfiles = filep - filetab; 885*9673Slinton setsource(filetab[0].filename); 886*9673Slinton } 887