1*9657Slinton /* Copyright (c) 1982 Regents of the University of California */ 2*9657Slinton 3*9657Slinton static char sccsid[] = "@(#)@(#)symbols.c 1.1 12/15/82"; 4*9657Slinton 5*9657Slinton /* 6*9657Slinton * Symbol management. 7*9657Slinton */ 8*9657Slinton 9*9657Slinton #include "defs.h" 10*9657Slinton #include "symbols.h" 11*9657Slinton #include "languages.h" 12*9657Slinton #include "printsym.h" 13*9657Slinton #include "tree.h" 14*9657Slinton #include "operators.h" 15*9657Slinton #include "eval.h" 16*9657Slinton #include "mappings.h" 17*9657Slinton #include "events.h" 18*9657Slinton #include "process.h" 19*9657Slinton #include "runtime.h" 20*9657Slinton #include "machine.h" 21*9657Slinton #include "names.h" 22*9657Slinton 23*9657Slinton #ifndef public 24*9657Slinton typedef struct Symbol *Symbol; 25*9657Slinton 26*9657Slinton #include "machine.h" 27*9657Slinton #include "names.h" 28*9657Slinton #include "languages.h" 29*9657Slinton 30*9657Slinton /* 31*9657Slinton * Symbol classes 32*9657Slinton */ 33*9657Slinton 34*9657Slinton typedef enum { 35*9657Slinton BADUSE, CONST, TYPE, VAR, ARRAY, PTRFILE, RECORD, FIELD, 36*9657Slinton PROC, FUNC, FVAR, REF, PTR, FILET, SET, RANGE, 37*9657Slinton LABEL, WITHPTR, SCAL, STR, PROG, IMPROPER, VARNT, 38*9657Slinton FPROC, FFUNC, MODULE, TYPEREF, TAG 39*9657Slinton } Symclass; 40*9657Slinton 41*9657Slinton struct Symbol { 42*9657Slinton Name name; 43*9657Slinton Language language; 44*9657Slinton Symclass class : 8; 45*9657Slinton Integer level : 8; 46*9657Slinton Symbol type; 47*9657Slinton Symbol chain; 48*9657Slinton union { 49*9657Slinton int offset; /* variable address */ 50*9657Slinton long iconval; /* integer constant value */ 51*9657Slinton double fconval; /* floating constant value */ 52*9657Slinton struct { /* field offset and size (both in bits) */ 53*9657Slinton int offset; 54*9657Slinton int length; 55*9657Slinton } field; 56*9657Slinton struct { /* range bounds */ 57*9657Slinton long lower; 58*9657Slinton long upper; 59*9657Slinton } rangev; 60*9657Slinton struct { /* address of function value, code */ 61*9657Slinton int offset; 62*9657Slinton Address beginaddr; 63*9657Slinton } funcv; 64*9657Slinton struct { /* variant record info */ 65*9657Slinton int size; 66*9657Slinton Symbol vtorec; 67*9657Slinton Symbol vtag; 68*9657Slinton } varnt; 69*9657Slinton } symvalue; 70*9657Slinton Symbol block; /* symbol containing this symbol */ 71*9657Slinton Symbol next_sym; /* hash chain */ 72*9657Slinton }; 73*9657Slinton 74*9657Slinton /* 75*9657Slinton * Basic types. 76*9657Slinton */ 77*9657Slinton 78*9657Slinton Symbol t_boolean; 79*9657Slinton Symbol t_char; 80*9657Slinton Symbol t_int; 81*9657Slinton Symbol t_real; 82*9657Slinton Symbol t_nil; 83*9657Slinton 84*9657Slinton Symbol program; 85*9657Slinton Symbol curfunc; 86*9657Slinton 87*9657Slinton #define symname(s) ident(s->name) 88*9657Slinton #define codeloc(f) ((f)->symvalue.funcv.beginaddr) 89*9657Slinton #define isblock(s) (Boolean) ( \ 90*9657Slinton s->class == FUNC or s->class == PROC or \ 91*9657Slinton s->class == MODULE or s->class == PROG \ 92*9657Slinton ) 93*9657Slinton 94*9657Slinton #include "tree.h" 95*9657Slinton 96*9657Slinton /* 97*9657Slinton * Some macros to make finding a symbol with certain attributes. 98*9657Slinton */ 99*9657Slinton 100*9657Slinton #define find(s, withname) \ 101*9657Slinton { \ 102*9657Slinton s = lookup(withname); \ 103*9657Slinton while (s != nil and not (s->name == (withname) and 104*9657Slinton 105*9657Slinton #define where /* qualification */ 106*9657Slinton 107*9657Slinton #define endfind(s) )) { \ 108*9657Slinton s = s->next_sym; \ 109*9657Slinton } \ 110*9657Slinton } 111*9657Slinton 112*9657Slinton #endif 113*9657Slinton 114*9657Slinton /* 115*9657Slinton * Symbol table structure currently does not support deletions. 116*9657Slinton */ 117*9657Slinton 118*9657Slinton #define HASHTABLESIZE 2003 119*9657Slinton 120*9657Slinton private Symbol hashtab[HASHTABLESIZE]; 121*9657Slinton 122*9657Slinton #define hash(name) ((((unsigned) name) >> 2) mod HASHTABLESIZE) 123*9657Slinton 124*9657Slinton /* 125*9657Slinton * Allocate a new symbol. 126*9657Slinton */ 127*9657Slinton 128*9657Slinton #define SYMBLOCKSIZE 1000 129*9657Slinton 130*9657Slinton typedef struct Sympool { 131*9657Slinton struct Symbol sym[SYMBLOCKSIZE]; 132*9657Slinton struct Sympool *prevpool; 133*9657Slinton } *Sympool; 134*9657Slinton 135*9657Slinton private Sympool sympool = nil; 136*9657Slinton private Integer nleft = 0; 137*9657Slinton private struct Sympool zeropool; 138*9657Slinton 139*9657Slinton public Symbol symbol_alloc() 140*9657Slinton { 141*9657Slinton register Sympool newpool; 142*9657Slinton 143*9657Slinton if (nleft <= 0) { 144*9657Slinton newpool = new(Sympool); 145*9657Slinton *newpool = zeropool; 146*9657Slinton newpool->prevpool = sympool; 147*9657Slinton sympool = newpool; 148*9657Slinton nleft = SYMBLOCKSIZE; 149*9657Slinton } 150*9657Slinton --nleft; 151*9657Slinton return &(sympool->sym[nleft]); 152*9657Slinton } 153*9657Slinton 154*9657Slinton /* 155*9657Slinton * Free all the symbols currently allocated. 156*9657Slinton */ 157*9657Slinton 158*9657Slinton public symbol_free() 159*9657Slinton { 160*9657Slinton Sympool s, t; 161*9657Slinton register Integer i; 162*9657Slinton 163*9657Slinton s = sympool; 164*9657Slinton while (s != nil) { 165*9657Slinton t = s->prevpool; 166*9657Slinton dispose(s); 167*9657Slinton s = t; 168*9657Slinton } 169*9657Slinton for (i = 0; i < HASHTABLESIZE; i++) { 170*9657Slinton hashtab[i] = nil; 171*9657Slinton } 172*9657Slinton sympool = nil; 173*9657Slinton nleft = 0; 174*9657Slinton } 175*9657Slinton 176*9657Slinton /* 177*9657Slinton * Create a new symbol with the given attributes. 178*9657Slinton */ 179*9657Slinton 180*9657Slinton public Symbol newSymbol(name, blevel, class, type, chain) 181*9657Slinton Name name; 182*9657Slinton Integer blevel; 183*9657Slinton Symclass class; 184*9657Slinton Symbol type; 185*9657Slinton Symbol chain; 186*9657Slinton { 187*9657Slinton register Symbol s; 188*9657Slinton 189*9657Slinton s = symbol_alloc(); 190*9657Slinton s->name = name; 191*9657Slinton s->level = blevel; 192*9657Slinton s->class = class; 193*9657Slinton s->type = type; 194*9657Slinton s->chain = chain; 195*9657Slinton return s; 196*9657Slinton } 197*9657Slinton 198*9657Slinton /* 199*9657Slinton * Insert a symbol into the hash table. 200*9657Slinton */ 201*9657Slinton 202*9657Slinton public Symbol insert(name) 203*9657Slinton Name name; 204*9657Slinton { 205*9657Slinton register Symbol s; 206*9657Slinton register unsigned int h; 207*9657Slinton 208*9657Slinton h = hash(name); 209*9657Slinton s = symbol_alloc(); 210*9657Slinton s->name = name; 211*9657Slinton s->next_sym = hashtab[h]; 212*9657Slinton hashtab[h] = s; 213*9657Slinton return s; 214*9657Slinton } 215*9657Slinton 216*9657Slinton /* 217*9657Slinton * Symbol lookup. 218*9657Slinton */ 219*9657Slinton 220*9657Slinton public Symbol lookup(name) 221*9657Slinton Name name; 222*9657Slinton { 223*9657Slinton register Symbol s; 224*9657Slinton register unsigned int h; 225*9657Slinton 226*9657Slinton h = hash(name); 227*9657Slinton s = hashtab[h]; 228*9657Slinton while (s != nil and s->name != name) { 229*9657Slinton s = s->next_sym; 230*9657Slinton } 231*9657Slinton return s; 232*9657Slinton } 233*9657Slinton 234*9657Slinton /* 235*9657Slinton * Dump out all the variables associated with the given 236*9657Slinton * procedure, function, or program at the given recursive level. 237*9657Slinton * 238*9657Slinton * This is quite inefficient. We traverse the entire symbol table 239*9657Slinton * each time we're called. The assumption is that this routine 240*9657Slinton * won't be called frequently enough to merit improved performance. 241*9657Slinton */ 242*9657Slinton 243*9657Slinton public dumpvars(f, frame) 244*9657Slinton Symbol f; 245*9657Slinton Frame frame; 246*9657Slinton { 247*9657Slinton register Integer i; 248*9657Slinton register Symbol s; 249*9657Slinton 250*9657Slinton for (i = 0; i < HASHTABLESIZE; i++) { 251*9657Slinton for (s = hashtab[i]; s != nil; s = s->next_sym) { 252*9657Slinton if (container(s) == f) { 253*9657Slinton if (should_print(s)) { 254*9657Slinton printv(s, frame); 255*9657Slinton putchar('\n'); 256*9657Slinton } else if (s->class == MODULE) { 257*9657Slinton dumpvars(s, frame); 258*9657Slinton } 259*9657Slinton } 260*9657Slinton } 261*9657Slinton } 262*9657Slinton } 263*9657Slinton 264*9657Slinton /* 265*9657Slinton * Create a builtin type. 266*9657Slinton * Builtin types are circular in that btype->type->type = btype. 267*9657Slinton */ 268*9657Slinton 269*9657Slinton public Symbol maketype(name, lower, upper) 270*9657Slinton String name; 271*9657Slinton long lower; 272*9657Slinton long upper; 273*9657Slinton { 274*9657Slinton register Symbol s; 275*9657Slinton 276*9657Slinton s = newSymbol(identname(name, true), 0, TYPE, nil, nil); 277*9657Slinton s->language = findlanguage(".c"); 278*9657Slinton s->type = newSymbol(nil, 0, RANGE, s, nil); 279*9657Slinton s->type->symvalue.rangev.lower = lower; 280*9657Slinton s->type->symvalue.rangev.upper = upper; 281*9657Slinton return s; 282*9657Slinton } 283*9657Slinton 284*9657Slinton /* 285*9657Slinton * These functions are now compiled inline. 286*9657Slinton * 287*9657Slinton * public String symname(s) 288*9657Slinton Symbol s; 289*9657Slinton { 290*9657Slinton checkref(s); 291*9657Slinton return ident(s->name); 292*9657Slinton } 293*9657Slinton 294*9657Slinton * 295*9657Slinton * public Address codeloc(f) 296*9657Slinton Symbol f; 297*9657Slinton { 298*9657Slinton checkref(f); 299*9657Slinton if (not isblock(f)) { 300*9657Slinton panic("codeloc: \"%s\" is not a block", ident(f->name)); 301*9657Slinton } 302*9657Slinton return f->symvalue.funcv.beginaddr; 303*9657Slinton } 304*9657Slinton * 305*9657Slinton */ 306*9657Slinton 307*9657Slinton /* 308*9657Slinton * Reduce type to avoid worrying about type names. 309*9657Slinton */ 310*9657Slinton 311*9657Slinton public Symbol rtype(type) 312*9657Slinton Symbol type; 313*9657Slinton { 314*9657Slinton register Symbol t; 315*9657Slinton 316*9657Slinton t = type; 317*9657Slinton if (t != nil) { 318*9657Slinton if (t->class == VAR or t->class == FIELD) { 319*9657Slinton t = t->type; 320*9657Slinton } 321*9657Slinton while (t->class == TYPE or t->class == TAG) { 322*9657Slinton t = t->type; 323*9657Slinton } 324*9657Slinton } 325*9657Slinton return t; 326*9657Slinton } 327*9657Slinton 328*9657Slinton public Integer level(s) 329*9657Slinton Symbol s; 330*9657Slinton { 331*9657Slinton checkref(s); 332*9657Slinton return s->level; 333*9657Slinton } 334*9657Slinton 335*9657Slinton public Symbol container(s) 336*9657Slinton Symbol s; 337*9657Slinton { 338*9657Slinton checkref(s); 339*9657Slinton return s->block; 340*9657Slinton } 341*9657Slinton 342*9657Slinton /* 343*9657Slinton * Return the object address of the given symbol. 344*9657Slinton * 345*9657Slinton * There are the following possibilities: 346*9657Slinton * 347*9657Slinton * globals - just take offset 348*9657Slinton * locals - take offset from locals base 349*9657Slinton * arguments - take offset from argument base 350*9657Slinton * register - offset is register number 351*9657Slinton */ 352*9657Slinton 353*9657Slinton #define isglobal(s) (s->level == 1 or s->level == 2) 354*9657Slinton #define islocaloff(s) (s->level >= 3 and s->symvalue.offset < 0) 355*9657Slinton #define isparamoff(s) (s->level >= 3 and s->symvalue.offset >= 0) 356*9657Slinton #define isreg(s) (s->level < 0) 357*9657Slinton 358*9657Slinton public Address address(s, frame) 359*9657Slinton Symbol s; 360*9657Slinton Frame frame; 361*9657Slinton { 362*9657Slinton register Frame frp; 363*9657Slinton register Address addr; 364*9657Slinton register Symbol cur; 365*9657Slinton 366*9657Slinton checkref(s); 367*9657Slinton if (not isactive(s->block)) { 368*9657Slinton error("\"%s\" is not currently defined", symname(s)); 369*9657Slinton } else if (isglobal(s)) { 370*9657Slinton addr = s->symvalue.offset; 371*9657Slinton } else { 372*9657Slinton frp = frame; 373*9657Slinton if (frp == nil) { 374*9657Slinton cur = s->block; 375*9657Slinton while (cur != nil and cur->class == MODULE) { 376*9657Slinton cur = cur->block; 377*9657Slinton } 378*9657Slinton if (cur == nil) { 379*9657Slinton cur = whatblock(pc); 380*9657Slinton } 381*9657Slinton frp = findframe(cur); 382*9657Slinton if (frp == nil) { 383*9657Slinton panic("unexpected nil frame for \"%s\"", symname(s)); 384*9657Slinton } 385*9657Slinton } 386*9657Slinton if (islocaloff(s)) { 387*9657Slinton addr = locals_base(frp) + s->symvalue.offset; 388*9657Slinton } else if (isparamoff(s)) { 389*9657Slinton addr = args_base(frp) + s->symvalue.offset; 390*9657Slinton } else if (isreg(s)) { 391*9657Slinton addr = savereg(s->symvalue.offset, frp); 392*9657Slinton } else { 393*9657Slinton panic("address: bad symbol \"%s\"", symname(s)); 394*9657Slinton } 395*9657Slinton } 396*9657Slinton return addr; 397*9657Slinton } 398*9657Slinton 399*9657Slinton /* 400*9657Slinton * Define a symbol used to access register values. 401*9657Slinton */ 402*9657Slinton 403*9657Slinton public defregname(n, r) 404*9657Slinton Name n; 405*9657Slinton Integer r; 406*9657Slinton { 407*9657Slinton register Symbol s, t; 408*9657Slinton 409*9657Slinton s = insert(n); 410*9657Slinton t = newSymbol(nil, 0, PTR, t_int, nil); 411*9657Slinton t->language = findlanguage(".s"); 412*9657Slinton s->language = t->language; 413*9657Slinton s->class = VAR; 414*9657Slinton s->level = -3; 415*9657Slinton s->type = t; 416*9657Slinton s->block = program; 417*9657Slinton s->symvalue.offset = r; 418*9657Slinton } 419*9657Slinton 420*9657Slinton /* 421*9657Slinton * Resolve an "abstract" type reference. 422*9657Slinton * 423*9657Slinton * It is possible in C to define a pointer to a type, but never define 424*9657Slinton * the type in a particular source file. Here we try to resolve 425*9657Slinton * the type definition. This is problematic, it is possible to 426*9657Slinton * have multiple, different definitions for the same name type. 427*9657Slinton */ 428*9657Slinton 429*9657Slinton public findtype(s) 430*9657Slinton Symbol s; 431*9657Slinton { 432*9657Slinton register Symbol t, u, prev; 433*9657Slinton 434*9657Slinton u = s; 435*9657Slinton prev = nil; 436*9657Slinton while (u != nil and u->class != BADUSE) { 437*9657Slinton if (u->name != nil) { 438*9657Slinton prev = u; 439*9657Slinton } 440*9657Slinton u = u->type; 441*9657Slinton } 442*9657Slinton if (prev == nil) { 443*9657Slinton error("couldn't find link to type reference"); 444*9657Slinton } 445*9657Slinton find(t, prev->name) where 446*9657Slinton t->type != nil and t->class == prev->class and 447*9657Slinton t->type->class != BADUSE and t->block->class == MODULE 448*9657Slinton endfind(t); 449*9657Slinton if (t == nil) { 450*9657Slinton error("couldn't resolve reference"); 451*9657Slinton } else { 452*9657Slinton prev->type = t->type; 453*9657Slinton } 454*9657Slinton } 455*9657Slinton 456*9657Slinton /* 457*9657Slinton * Find the size in bytes of the given type. 458*9657Slinton * 459*9657Slinton * This is probably the WRONG thing to do. The size should be kept 460*9657Slinton * as an attribute in the symbol information as is done for structures 461*9657Slinton * and fields. I haven't gotten around to cleaning this up yet. 462*9657Slinton */ 463*9657Slinton 464*9657Slinton #define MINCHAR -128 465*9657Slinton #define MAXCHAR 127 466*9657Slinton #define MINSHORT -32768 467*9657Slinton #define MAXSHORT 32767 468*9657Slinton 469*9657Slinton public Integer size(sym) 470*9657Slinton Symbol sym; 471*9657Slinton { 472*9657Slinton register Symbol s, t; 473*9657Slinton register int nel, elsize; 474*9657Slinton long lower, upper; 475*9657Slinton int r; 476*9657Slinton 477*9657Slinton t = sym; 478*9657Slinton checkref(t); 479*9657Slinton switch (t->class) { 480*9657Slinton case RANGE: 481*9657Slinton lower = t->symvalue.rangev.lower; 482*9657Slinton upper = t->symvalue.rangev.upper; 483*9657Slinton if (upper == 0 and lower > 0) { /* real */ 484*9657Slinton r = lower; 485*9657Slinton } else if (lower >= MINCHAR and upper <= MAXCHAR) { 486*9657Slinton r = sizeof(char); 487*9657Slinton } else if (lower >= MINSHORT and upper <= MAXSHORT) { 488*9657Slinton r = sizeof(short); 489*9657Slinton } else { 490*9657Slinton r = sizeof(long); 491*9657Slinton } 492*9657Slinton break; 493*9657Slinton 494*9657Slinton case ARRAY: 495*9657Slinton elsize = size(t->type); 496*9657Slinton nel = 1; 497*9657Slinton for (t = t->chain; t != nil; t = t->chain) { 498*9657Slinton s = rtype(t); 499*9657Slinton lower = s->symvalue.rangev.lower; 500*9657Slinton upper = s->symvalue.rangev.upper; 501*9657Slinton nel *= (upper-lower+1); 502*9657Slinton } 503*9657Slinton r = nel*elsize; 504*9657Slinton break; 505*9657Slinton 506*9657Slinton case VAR: 507*9657Slinton case FVAR: 508*9657Slinton r = size(t->type); 509*9657Slinton if (r < sizeof(Word)) { 510*9657Slinton r = sizeof(Word); 511*9657Slinton } 512*9657Slinton break; 513*9657Slinton 514*9657Slinton case CONST: 515*9657Slinton r = size(t->type); 516*9657Slinton break; 517*9657Slinton 518*9657Slinton case TYPE: 519*9657Slinton if (t->type->class == PTR and t->type->type->class == BADUSE) { 520*9657Slinton findtype(t); 521*9657Slinton } 522*9657Slinton r = size(t->type); 523*9657Slinton break; 524*9657Slinton 525*9657Slinton case TAG: 526*9657Slinton r = size(t->type); 527*9657Slinton break; 528*9657Slinton 529*9657Slinton case FIELD: 530*9657Slinton r = (t->symvalue.field.length + 7) div 8; 531*9657Slinton break; 532*9657Slinton 533*9657Slinton case RECORD: 534*9657Slinton case VARNT: 535*9657Slinton r = t->symvalue.offset; 536*9657Slinton if (r == 0 and t->chain != nil) { 537*9657Slinton panic("missing size information for record"); 538*9657Slinton } 539*9657Slinton break; 540*9657Slinton 541*9657Slinton case PTR: 542*9657Slinton case REF: 543*9657Slinton case FILET: 544*9657Slinton r = sizeof(Word); 545*9657Slinton break; 546*9657Slinton 547*9657Slinton case SCAL: 548*9657Slinton if (t->symvalue.iconval > 255) { 549*9657Slinton r = sizeof(short); 550*9657Slinton } else { 551*9657Slinton r = sizeof(char); 552*9657Slinton } 553*9657Slinton break; 554*9657Slinton 555*9657Slinton case FPROC: 556*9657Slinton case FFUNC: 557*9657Slinton r = sizeof(Word); 558*9657Slinton break; 559*9657Slinton 560*9657Slinton case PROC: 561*9657Slinton case FUNC: 562*9657Slinton case MODULE: 563*9657Slinton case PROG: 564*9657Slinton r = sizeof(Symbol); 565*9657Slinton break; 566*9657Slinton 567*9657Slinton default: 568*9657Slinton if (ord(t->class) > ord(TYPEREF)) { 569*9657Slinton panic("size: bad class (%d)", ord(t->class)); 570*9657Slinton } else { 571*9657Slinton error("improper operation on a %s", classname(t)); 572*9657Slinton } 573*9657Slinton /* NOTREACHED */ 574*9657Slinton } 575*9657Slinton if (r < sizeof(Word) and isparam(sym)) { 576*9657Slinton r = sizeof(Word); 577*9657Slinton } 578*9657Slinton return r; 579*9657Slinton } 580*9657Slinton 581*9657Slinton /* 582*9657Slinton * Test if a symbol is a parameter. This is true if there 583*9657Slinton * is a cycle from s->block to s via chain pointers. 584*9657Slinton */ 585*9657Slinton 586*9657Slinton public Boolean isparam(s) 587*9657Slinton Symbol s; 588*9657Slinton { 589*9657Slinton register Symbol t; 590*9657Slinton 591*9657Slinton t = s->block; 592*9657Slinton while (t != nil and t != s) { 593*9657Slinton t = t->chain; 594*9657Slinton } 595*9657Slinton return (Boolean) (t != nil); 596*9657Slinton } 597*9657Slinton 598*9657Slinton /* 599*9657Slinton * Test if a symbol is a var parameter, i.e. has class REF. 600*9657Slinton */ 601*9657Slinton 602*9657Slinton public Boolean isvarparam(s) 603*9657Slinton Symbol s; 604*9657Slinton { 605*9657Slinton return (Boolean) (s->class == REF); 606*9657Slinton } 607*9657Slinton 608*9657Slinton /* 609*9657Slinton * Test if a symbol is a variable (actually any addressible quantity 610*9657Slinton * with do). 611*9657Slinton */ 612*9657Slinton 613*9657Slinton public Boolean isvariable(s) 614*9657Slinton register Symbol s; 615*9657Slinton { 616*9657Slinton return (Boolean) (s->class == VAR or s->class == FVAR or s->class == REF); 617*9657Slinton } 618*9657Slinton 619*9657Slinton /* 620*9657Slinton * Test if a symbol is a block, e.g. function, procedure, or the 621*9657Slinton * main program. 622*9657Slinton * 623*9657Slinton * This function is now expanded inline for efficiency. 624*9657Slinton * 625*9657Slinton * public Boolean isblock(s) 626*9657Slinton register Symbol s; 627*9657Slinton { 628*9657Slinton return (Boolean) ( 629*9657Slinton s->class == FUNC or s->class == PROC or 630*9657Slinton s->class == MODULE or s->class == PROG 631*9657Slinton ); 632*9657Slinton } 633*9657Slinton * 634*9657Slinton */ 635*9657Slinton 636*9657Slinton /* 637*9657Slinton * Test if a symbol is a module. 638*9657Slinton */ 639*9657Slinton 640*9657Slinton public Boolean ismodule(s) 641*9657Slinton register Symbol s; 642*9657Slinton { 643*9657Slinton return (Boolean) (s->class == MODULE); 644*9657Slinton } 645*9657Slinton 646*9657Slinton /* 647*9657Slinton * Test if a symbol is builtin, that is, a predefined type or 648*9657Slinton * reserved word. 649*9657Slinton */ 650*9657Slinton 651*9657Slinton public Boolean isbuiltin(s) 652*9657Slinton register Symbol s; 653*9657Slinton { 654*9657Slinton return (Boolean) (s->level == 0 and s->class != PROG and s->class != VAR); 655*9657Slinton } 656*9657Slinton 657*9657Slinton /* 658*9657Slinton * Test if two types match. 659*9657Slinton * Equivalent names implies a match in any language. 660*9657Slinton * 661*9657Slinton * Special symbols must be handled with care. 662*9657Slinton */ 663*9657Slinton 664*9657Slinton public Boolean compatible(t1, t2) 665*9657Slinton register Symbol t1, t2; 666*9657Slinton { 667*9657Slinton Boolean b; 668*9657Slinton 669*9657Slinton if (t1 == t2) { 670*9657Slinton b = true; 671*9657Slinton } else if (t1 == nil or t2 == nil) { 672*9657Slinton b = false; 673*9657Slinton } else if (t1 == procsym) { 674*9657Slinton b = isblock(t2); 675*9657Slinton } else if (t2 == procsym) { 676*9657Slinton b = isblock(t1); 677*9657Slinton } else if (t1->language == nil) { 678*9657Slinton b = (Boolean) (t2->language == nil or 679*9657Slinton (*language_op(t2->language, L_TYPEMATCH))(t1, t2)); 680*9657Slinton } else { 681*9657Slinton b = (Boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2); 682*9657Slinton } 683*9657Slinton return b; 684*9657Slinton } 685*9657Slinton 686*9657Slinton /* 687*9657Slinton * Check for a type of the given name. 688*9657Slinton */ 689*9657Slinton 690*9657Slinton public Boolean istypename(type, name) 691*9657Slinton Symbol type; 692*9657Slinton String name; 693*9657Slinton { 694*9657Slinton Symbol t; 695*9657Slinton Boolean b; 696*9657Slinton 697*9657Slinton t = type; 698*9657Slinton checkref(t); 699*9657Slinton b = (Boolean) ( 700*9657Slinton t->class == TYPE and t->name == identname(name, true) 701*9657Slinton ); 702*9657Slinton return b; 703*9657Slinton } 704*9657Slinton 705*9657Slinton /* 706*9657Slinton * Test if the name of a symbol is uniquely defined or not. 707*9657Slinton */ 708*9657Slinton 709*9657Slinton public Boolean isambiguous(s) 710*9657Slinton register Symbol s; 711*9657Slinton { 712*9657Slinton register Symbol t; 713*9657Slinton 714*9657Slinton find(t, s->name) where t != s endfind(t); 715*9657Slinton return (Boolean) (t != nil); 716*9657Slinton } 717*9657Slinton 718*9657Slinton typedef char *Arglist; 719*9657Slinton 720*9657Slinton #define nextarg(type) ((type *) (ap += sizeof(type)))[-1] 721*9657Slinton 722*9657Slinton private Symbol mkstring(); 723*9657Slinton private Symbol namenode(); 724*9657Slinton 725*9657Slinton /* 726*9657Slinton * Determine the type of a parse tree. 727*9657Slinton * Also make some symbol-dependent changes to the tree such as 728*9657Slinton * changing removing RVAL nodes for constant symbols. 729*9657Slinton */ 730*9657Slinton 731*9657Slinton public assigntypes(p) 732*9657Slinton register Node p; 733*9657Slinton { 734*9657Slinton register Node p1; 735*9657Slinton register Symbol s; 736*9657Slinton 737*9657Slinton switch (p->op) { 738*9657Slinton case O_SYM: 739*9657Slinton p->nodetype = namenode(p); 740*9657Slinton break; 741*9657Slinton 742*9657Slinton case O_LCON: 743*9657Slinton p->nodetype = t_int; 744*9657Slinton break; 745*9657Slinton 746*9657Slinton case O_FCON: 747*9657Slinton p->nodetype = t_real; 748*9657Slinton break; 749*9657Slinton 750*9657Slinton case O_SCON: 751*9657Slinton p->value.scon = strdup(p->value.scon); 752*9657Slinton s = mkstring(p->value.scon); 753*9657Slinton if (s == t_char) { 754*9657Slinton p->op = O_LCON; 755*9657Slinton p->value.lcon = p->value.scon[0]; 756*9657Slinton } 757*9657Slinton p->nodetype = s; 758*9657Slinton break; 759*9657Slinton 760*9657Slinton case O_INDIR: 761*9657Slinton p1 = p->value.arg[0]; 762*9657Slinton chkclass(p1, PTR); 763*9657Slinton p->nodetype = rtype(p1->nodetype)->type; 764*9657Slinton break; 765*9657Slinton 766*9657Slinton case O_DOT: 767*9657Slinton p->nodetype = p->value.arg[1]->value.sym; 768*9657Slinton break; 769*9657Slinton 770*9657Slinton case O_RVAL: 771*9657Slinton p1 = p->value.arg[0]; 772*9657Slinton p->nodetype = p1->nodetype; 773*9657Slinton if (p1->op == O_SYM) { 774*9657Slinton if (p1->nodetype->class == FUNC) { 775*9657Slinton p->op = O_CALL; 776*9657Slinton p->value.arg[1] = nil; 777*9657Slinton } else if (p1->value.sym->class == CONST) { 778*9657Slinton if (compatible(p1->value.sym->type, t_real)) { 779*9657Slinton p->op = O_FCON; 780*9657Slinton p->value.fcon = p1->value.sym->symvalue.fconval; 781*9657Slinton p->nodetype = t_real; 782*9657Slinton dispose(p1); 783*9657Slinton } else { 784*9657Slinton p->op = O_LCON; 785*9657Slinton p->value.lcon = p1->value.sym->symvalue.iconval; 786*9657Slinton p->nodetype = p1->value.sym->type; 787*9657Slinton dispose(p1); 788*9657Slinton } 789*9657Slinton } else if (isreg(p1->value.sym)) { 790*9657Slinton p->op = O_SYM; 791*9657Slinton p->value.sym = p1->value.sym; 792*9657Slinton dispose(p1); 793*9657Slinton } 794*9657Slinton } else if (p1->op == O_INDIR and p1->value.arg[0]->op == O_SYM) { 795*9657Slinton s = p1->value.arg[0]->value.sym; 796*9657Slinton if (isreg(s)) { 797*9657Slinton p1->op = O_SYM; 798*9657Slinton dispose(p1->value.arg[0]); 799*9657Slinton p1->value.sym = s; 800*9657Slinton p1->nodetype = s; 801*9657Slinton } 802*9657Slinton } 803*9657Slinton break; 804*9657Slinton 805*9657Slinton /* 806*9657Slinton * Perform a cast if the call is of the form "type(expr)". 807*9657Slinton */ 808*9657Slinton case O_CALL: 809*9657Slinton p1 = p->value.arg[0]; 810*9657Slinton if (p1->op == O_SYM and 811*9657Slinton (p1->value.sym->class == TYPE or p1->value.sym->class == TAG)) { 812*9657Slinton s = p1->value.sym; 813*9657Slinton dispose(p1); 814*9657Slinton p1 = p->value.arg[1]; 815*9657Slinton assert(p1->op == O_COMMA); 816*9657Slinton if (p1->value.arg[1] != nil) { 817*9657Slinton error("unexpected comma within type conversion"); 818*9657Slinton } 819*9657Slinton p->op = O_RVAL; 820*9657Slinton p->value.arg[0] = p1->value.arg[0]; 821*9657Slinton p->nodetype = s; 822*9657Slinton p->value.arg[0]->nodetype = s; 823*9657Slinton dispose(p1); 824*9657Slinton } else { 825*9657Slinton p->nodetype = rtype(p1->nodetype)->type; 826*9657Slinton } 827*9657Slinton break; 828*9657Slinton 829*9657Slinton case O_ITOF: 830*9657Slinton p->nodetype = t_real; 831*9657Slinton break; 832*9657Slinton 833*9657Slinton case O_NEG: 834*9657Slinton s = p->value.arg[0]->nodetype; 835*9657Slinton if (not compatible(s, t_int)) { 836*9657Slinton if (not compatible(s, t_real)) { 837*9657Slinton beginerrmsg(); 838*9657Slinton prtree(stderr, p->value.arg[0]); 839*9657Slinton fprintf(stderr, "is improper type"); 840*9657Slinton enderrmsg(); 841*9657Slinton } else { 842*9657Slinton p->op = O_NEGF; 843*9657Slinton } 844*9657Slinton } 845*9657Slinton p->nodetype = s; 846*9657Slinton break; 847*9657Slinton 848*9657Slinton case O_ADD: 849*9657Slinton case O_SUB: 850*9657Slinton case O_MUL: 851*9657Slinton case O_LT: 852*9657Slinton case O_LE: 853*9657Slinton case O_GT: 854*9657Slinton case O_GE: 855*9657Slinton case O_EQ: 856*9657Slinton case O_NE: 857*9657Slinton { 858*9657Slinton Boolean t1real, t2real; 859*9657Slinton Symbol t1, t2; 860*9657Slinton 861*9657Slinton t1 = rtype(p->value.arg[0]->nodetype); 862*9657Slinton t2 = rtype(p->value.arg[1]->nodetype); 863*9657Slinton t1real = compatible(t1, t_real); 864*9657Slinton t2real = compatible(t2, t_real); 865*9657Slinton if (t1real or t2real) { 866*9657Slinton p->op = (Operator) (ord(p->op) + 1); 867*9657Slinton if (not t1real) { 868*9657Slinton p->value.arg[0] = build(O_ITOF, p->value.arg[0]); 869*9657Slinton } else if (not t2real) { 870*9657Slinton p->value.arg[1] = build(O_ITOF, p->value.arg[1]); 871*9657Slinton } 872*9657Slinton } else { 873*9657Slinton if (t1real) { 874*9657Slinton convert(&(p->value.arg[0]), t_int, O_NOP); 875*9657Slinton } 876*9657Slinton if (t2real) { 877*9657Slinton convert(&(p->value.arg[1]), t_int, O_NOP); 878*9657Slinton } 879*9657Slinton } 880*9657Slinton if (ord(p->op) >= ord(O_LT)) { 881*9657Slinton p->nodetype = t_boolean; 882*9657Slinton } else { 883*9657Slinton if (t1real or t2real) { 884*9657Slinton p->nodetype = t_real; 885*9657Slinton } else { 886*9657Slinton p->nodetype = t_int; 887*9657Slinton } 888*9657Slinton } 889*9657Slinton break; 890*9657Slinton } 891*9657Slinton 892*9657Slinton case O_DIVF: 893*9657Slinton convert(&(p->value.arg[0]), t_real, O_ITOF); 894*9657Slinton convert(&(p->value.arg[1]), t_real, O_ITOF); 895*9657Slinton p->nodetype = t_real; 896*9657Slinton break; 897*9657Slinton 898*9657Slinton case O_DIV: 899*9657Slinton case O_MOD: 900*9657Slinton convert(&(p->value.arg[0]), t_int, O_NOP); 901*9657Slinton convert(&(p->value.arg[1]), t_int, O_NOP); 902*9657Slinton p->nodetype = t_int; 903*9657Slinton break; 904*9657Slinton 905*9657Slinton case O_AND: 906*9657Slinton case O_OR: 907*9657Slinton chkboolean(p->value.arg[0]); 908*9657Slinton chkboolean(p->value.arg[1]); 909*9657Slinton p->nodetype = t_boolean; 910*9657Slinton break; 911*9657Slinton 912*9657Slinton case O_QLINE: 913*9657Slinton p->nodetype = t_int; 914*9657Slinton break; 915*9657Slinton 916*9657Slinton default: 917*9657Slinton p->nodetype = nil; 918*9657Slinton break; 919*9657Slinton } 920*9657Slinton } 921*9657Slinton 922*9657Slinton /* 923*9657Slinton * Create a node for a name. The symbol for the name has already 924*9657Slinton * been chosen, either implicitly with "which" or explicitly from 925*9657Slinton * the dot routine. 926*9657Slinton */ 927*9657Slinton 928*9657Slinton private Symbol namenode(p) 929*9657Slinton Node p; 930*9657Slinton { 931*9657Slinton register Symbol r, s; 932*9657Slinton register Node np; 933*9657Slinton 934*9657Slinton s = p->value.sym; 935*9657Slinton if (s->class == REF) { 936*9657Slinton np = new(Node); 937*9657Slinton np->op = p->op; 938*9657Slinton np->nodetype = s; 939*9657Slinton np->value.sym = s; 940*9657Slinton p->op = O_INDIR; 941*9657Slinton p->value.arg[0] = np; 942*9657Slinton } 943*9657Slinton /* 944*9657Slinton * Old way 945*9657Slinton * 946*9657Slinton if (s->class == CONST or s->class == VAR or s->class == FVAR) { 947*9657Slinton r = s->type; 948*9657Slinton } else { 949*9657Slinton r = s; 950*9657Slinton } 951*9657Slinton * 952*9657Slinton */ 953*9657Slinton return s; 954*9657Slinton } 955*9657Slinton 956*9657Slinton /* 957*9657Slinton * Convert a tree to a type via a conversion operator; 958*9657Slinton * if this isn't possible generate an error. 959*9657Slinton * 960*9657Slinton * Note the tree is call by address, hence the #define below. 961*9657Slinton */ 962*9657Slinton 963*9657Slinton private convert(tp, typeto, op) 964*9657Slinton Node *tp; 965*9657Slinton Symbol typeto; 966*9657Slinton Operator op; 967*9657Slinton { 968*9657Slinton #define tree (*tp) 969*9657Slinton 970*9657Slinton Symbol s; 971*9657Slinton 972*9657Slinton s = rtype(tree->nodetype); 973*9657Slinton typeto = rtype(typeto); 974*9657Slinton if (compatible(typeto, t_real) and compatible(s, t_int)) { 975*9657Slinton tree = build(op, tree); 976*9657Slinton } else if (not compatible(s, typeto)) { 977*9657Slinton beginerrmsg(); 978*9657Slinton prtree(stderr, s); 979*9657Slinton fprintf(stderr, " is improper type"); 980*9657Slinton enderrmsg(); 981*9657Slinton } else if (op != O_NOP and s != typeto) { 982*9657Slinton tree = build(op, tree); 983*9657Slinton } 984*9657Slinton 985*9657Slinton #undef tree 986*9657Slinton } 987*9657Slinton 988*9657Slinton /* 989*9657Slinton * Construct a node for the dot operator. 990*9657Slinton * 991*9657Slinton * If the left operand is not a record, but rather a procedure 992*9657Slinton * or function, then we interpret the "." as referencing an 993*9657Slinton * "invisible" variable; i.e. a variable within a dynamically 994*9657Slinton * active block but not within the static scope of the current procedure. 995*9657Slinton */ 996*9657Slinton 997*9657Slinton public Node dot(record, fieldname) 998*9657Slinton Node record; 999*9657Slinton Name fieldname; 1000*9657Slinton { 1001*9657Slinton register Node p; 1002*9657Slinton register Symbol s, t; 1003*9657Slinton 1004*9657Slinton if (isblock(record->nodetype)) { 1005*9657Slinton find(s, fieldname) where 1006*9657Slinton s->block == record->nodetype and 1007*9657Slinton s->class != FIELD and s->class != TAG 1008*9657Slinton endfind(s); 1009*9657Slinton if (s == nil) { 1010*9657Slinton beginerrmsg(); 1011*9657Slinton fprintf(stderr, "\"%s\" is not defined in ", ident(fieldname)); 1012*9657Slinton printname(stderr, record->nodetype); 1013*9657Slinton enderrmsg(); 1014*9657Slinton } 1015*9657Slinton p = new(Node); 1016*9657Slinton p->op = O_SYM; 1017*9657Slinton p->value.sym = s; 1018*9657Slinton p->nodetype = namenode(p); 1019*9657Slinton } else { 1020*9657Slinton p = record; 1021*9657Slinton t = rtype(p->nodetype); 1022*9657Slinton if (t->class == PTR) { 1023*9657Slinton s = findfield(fieldname, t->type); 1024*9657Slinton } else { 1025*9657Slinton s = findfield(fieldname, t); 1026*9657Slinton } 1027*9657Slinton if (s == nil) { 1028*9657Slinton beginerrmsg(); 1029*9657Slinton fprintf(stderr, "\"%s\" is not a field in ", ident(fieldname)); 1030*9657Slinton prtree(stderr, record); 1031*9657Slinton enderrmsg(); 1032*9657Slinton } 1033*9657Slinton if (t->class == PTR and not isreg(record->nodetype)) { 1034*9657Slinton p = build(O_INDIR, record); 1035*9657Slinton } 1036*9657Slinton p = build(O_DOT, p, build(O_SYM, s)); 1037*9657Slinton } 1038*9657Slinton return p; 1039*9657Slinton } 1040*9657Slinton 1041*9657Slinton /* 1042*9657Slinton * Return a tree corresponding to an array reference and do the 1043*9657Slinton * error checking. 1044*9657Slinton */ 1045*9657Slinton 1046*9657Slinton public Node subscript(a, slist) 1047*9657Slinton Node a, slist; 1048*9657Slinton { 1049*9657Slinton register Symbol t; 1050*9657Slinton register Node p; 1051*9657Slinton Symbol etype, atype, eltype; 1052*9657Slinton Node esub, olda; 1053*9657Slinton 1054*9657Slinton olda = a; 1055*9657Slinton t = rtype(a->nodetype); 1056*9657Slinton if (t->class != ARRAY) { 1057*9657Slinton beginerrmsg(); 1058*9657Slinton prtree(stderr, a); 1059*9657Slinton fprintf(stderr, " is not an array"); 1060*9657Slinton enderrmsg(); 1061*9657Slinton } 1062*9657Slinton eltype = t->type; 1063*9657Slinton p = slist; 1064*9657Slinton t = t->chain; 1065*9657Slinton for (; p != nil and t != nil; p = p->value.arg[1], t = t->chain) { 1066*9657Slinton esub = p->value.arg[0]; 1067*9657Slinton etype = rtype(esub->nodetype); 1068*9657Slinton atype = rtype(t); 1069*9657Slinton if (not compatible(atype, etype)) { 1070*9657Slinton beginerrmsg(); 1071*9657Slinton fprintf(stderr, "subscript "); 1072*9657Slinton prtree(stderr, esub); 1073*9657Slinton fprintf(stderr, " is the wrong type"); 1074*9657Slinton enderrmsg(); 1075*9657Slinton } 1076*9657Slinton a = build(O_INDEX, a, esub); 1077*9657Slinton a->nodetype = eltype; 1078*9657Slinton } 1079*9657Slinton if (p != nil or t != nil) { 1080*9657Slinton beginerrmsg(); 1081*9657Slinton if (p != nil) { 1082*9657Slinton fprintf(stderr, "too many subscripts for "); 1083*9657Slinton } else { 1084*9657Slinton fprintf(stderr, "not enough subscripts for "); 1085*9657Slinton } 1086*9657Slinton prtree(stderr, olda); 1087*9657Slinton enderrmsg(); 1088*9657Slinton } 1089*9657Slinton return a; 1090*9657Slinton } 1091*9657Slinton 1092*9657Slinton /* 1093*9657Slinton * Evaluate a subscript index. 1094*9657Slinton */ 1095*9657Slinton 1096*9657Slinton public int evalindex(s, i) 1097*9657Slinton Symbol s; 1098*9657Slinton long i; 1099*9657Slinton { 1100*9657Slinton long lb, ub; 1101*9657Slinton 1102*9657Slinton s = rtype(s)->chain; 1103*9657Slinton lb = s->symvalue.rangev.lower; 1104*9657Slinton ub = s->symvalue.rangev.upper; 1105*9657Slinton if (i < lb or i > ub) { 1106*9657Slinton error("subscript out of range"); 1107*9657Slinton } 1108*9657Slinton return (i - lb); 1109*9657Slinton } 1110*9657Slinton 1111*9657Slinton /* 1112*9657Slinton * Check to see if a tree is boolean-valued, if not it's an error. 1113*9657Slinton */ 1114*9657Slinton 1115*9657Slinton public chkboolean(p) 1116*9657Slinton register Node p; 1117*9657Slinton { 1118*9657Slinton if (p->nodetype != t_boolean) { 1119*9657Slinton beginerrmsg(); 1120*9657Slinton fprintf(stderr, "found "); 1121*9657Slinton prtree(stderr, p); 1122*9657Slinton fprintf(stderr, ", expected boolean expression"); 1123*9657Slinton enderrmsg(); 1124*9657Slinton } 1125*9657Slinton } 1126*9657Slinton 1127*9657Slinton /* 1128*9657Slinton * Check to make sure the given tree has a type of the given class. 1129*9657Slinton */ 1130*9657Slinton 1131*9657Slinton private chkclass(p, class) 1132*9657Slinton Node p; 1133*9657Slinton Symclass class; 1134*9657Slinton { 1135*9657Slinton struct Symbol tmpsym; 1136*9657Slinton 1137*9657Slinton tmpsym.class = class; 1138*9657Slinton if (rtype(p->nodetype)->class != class) { 1139*9657Slinton beginerrmsg(); 1140*9657Slinton fprintf(stderr, "\""); 1141*9657Slinton prtree(stderr, p); 1142*9657Slinton fprintf(stderr, "\" is not a %s", classname(&tmpsym)); 1143*9657Slinton enderrmsg(); 1144*9657Slinton } 1145*9657Slinton } 1146*9657Slinton 1147*9657Slinton /* 1148*9657Slinton * Construct a node for the type of a string. While we're at it, 1149*9657Slinton * scan the string for '' that collapse to ', and chop off the ends. 1150*9657Slinton */ 1151*9657Slinton 1152*9657Slinton private Symbol mkstring(str) 1153*9657Slinton String str; 1154*9657Slinton { 1155*9657Slinton register char *p, *q; 1156*9657Slinton register Symbol s; 1157*9657Slinton 1158*9657Slinton p = str; 1159*9657Slinton q = str; 1160*9657Slinton while (*p != '\0') { 1161*9657Slinton if (*p == '\\') { 1162*9657Slinton ++p; 1163*9657Slinton } 1164*9657Slinton *q = *p; 1165*9657Slinton ++p; 1166*9657Slinton ++q; 1167*9657Slinton } 1168*9657Slinton *q = '\0'; 1169*9657Slinton s = newSymbol(nil, 0, ARRAY, t_char, nil); 1170*9657Slinton s->language = findlanguage(".s"); 1171*9657Slinton s->chain = newSymbol(nil, 0, RANGE, t_int, nil); 1172*9657Slinton s->chain->language = s->language; 1173*9657Slinton s->chain->symvalue.rangev.lower = 1; 1174*9657Slinton s->chain->symvalue.rangev.upper = p - str + 1; 1175*9657Slinton return s; 1176*9657Slinton } 1177*9657Slinton 1178*9657Slinton /* 1179*9657Slinton * Free up the space allocated for a string type. 1180*9657Slinton */ 1181*9657Slinton 1182*9657Slinton public unmkstring(s) 1183*9657Slinton Symbol s; 1184*9657Slinton { 1185*9657Slinton dispose(s->chain); 1186*9657Slinton } 1187*9657Slinton 1188*9657Slinton /* 1189*9657Slinton * Figure out the "current" variable or function being referred to, 1190*9657Slinton * this is either the active one or the most visible from the 1191*9657Slinton * current scope. 1192*9657Slinton */ 1193*9657Slinton 1194*9657Slinton public Symbol which(n) 1195*9657Slinton Name n; 1196*9657Slinton { 1197*9657Slinton register Symbol s, p, t, f; 1198*9657Slinton 1199*9657Slinton find(s, n) where s->class != FIELD and s->class != TAG endfind(s); 1200*9657Slinton if (s == nil) { 1201*9657Slinton s = lookup(n); 1202*9657Slinton } 1203*9657Slinton if (s == nil) { 1204*9657Slinton error("\"%s\" is not defined", ident(n)); 1205*9657Slinton } else if (s == program or isbuiltin(s)) { 1206*9657Slinton t = s; 1207*9657Slinton } else { 1208*9657Slinton /* 1209*9657Slinton * Old way 1210*9657Slinton * 1211*9657Slinton if (not isactive(program)) { 1212*9657Slinton f = program; 1213*9657Slinton } else { 1214*9657Slinton f = whatblock(pc); 1215*9657Slinton if (f == nil) { 1216*9657Slinton panic("no block for addr 0x%x", pc); 1217*9657Slinton } 1218*9657Slinton } 1219*9657Slinton * 1220*9657Slinton * Now start with curfunc. 1221*9657Slinton */ 1222*9657Slinton p = curfunc; 1223*9657Slinton do { 1224*9657Slinton find(t, n) where 1225*9657Slinton t->block == p and t->class != FIELD and t->class != TAG 1226*9657Slinton endfind(t); 1227*9657Slinton p = p->block; 1228*9657Slinton } while (t == nil and p != nil); 1229*9657Slinton if (t == nil) { 1230*9657Slinton t = s; 1231*9657Slinton } 1232*9657Slinton } 1233*9657Slinton return t; 1234*9657Slinton } 1235*9657Slinton 1236*9657Slinton /* 1237*9657Slinton * Find the symbol which is has the same name and scope as the 1238*9657Slinton * given symbol but is of the given field. Return nil if there is none. 1239*9657Slinton */ 1240*9657Slinton 1241*9657Slinton public Symbol findfield(fieldname, record) 1242*9657Slinton Name fieldname; 1243*9657Slinton Symbol record; 1244*9657Slinton { 1245*9657Slinton register Symbol t; 1246*9657Slinton 1247*9657Slinton t = rtype(record)->chain; 1248*9657Slinton while (t != nil and t->name != fieldname) { 1249*9657Slinton t = t->chain; 1250*9657Slinton } 1251*9657Slinton return t; 1252*9657Slinton } 1253