xref: /csrg-svn/old/dbx/symbols.c (revision 12547)
19657Slinton /* Copyright (c) 1982 Regents of the University of California */
29657Slinton 
3*12547Scsvaf static char sccsid[] = "@(#)symbols.c 1.8 05/18/83";
49657Slinton 
59657Slinton /*
69657Slinton  * Symbol management.
79657Slinton  */
89657Slinton 
99657Slinton #include "defs.h"
109657Slinton #include "symbols.h"
119657Slinton #include "languages.h"
129657Slinton #include "printsym.h"
139657Slinton #include "tree.h"
149657Slinton #include "operators.h"
159657Slinton #include "eval.h"
169657Slinton #include "mappings.h"
179657Slinton #include "events.h"
189657Slinton #include "process.h"
199657Slinton #include "runtime.h"
209657Slinton #include "machine.h"
219657Slinton #include "names.h"
229657Slinton 
239657Slinton #ifndef public
249657Slinton typedef struct Symbol *Symbol;
259657Slinton 
269657Slinton #include "machine.h"
279657Slinton #include "names.h"
289657Slinton #include "languages.h"
299657Slinton 
309657Slinton /*
319657Slinton  * Symbol classes
329657Slinton  */
339657Slinton 
349657Slinton typedef enum {
359657Slinton     BADUSE, CONST, TYPE, VAR, ARRAY, PTRFILE, RECORD, FIELD,
36*12547Scsvaf     PROC, FUNC, FVAR, REF, PTR, FILET, SET, RANGE,
379657Slinton     LABEL, WITHPTR, SCAL, STR, PROG, IMPROPER, VARNT,
38*12547Scsvaf     FPROC, FFUNC, MODULE, TAG, COMMON, TYPEREF
399657Slinton } Symclass;
409657Slinton 
41*12547Scsvaf typedef enum { R_CONST, R_TEMP, R_ARG, R_ADJUST } Rangetype;
42*12547Scsvaf 
439657Slinton struct Symbol {
449657Slinton     Name name;
459657Slinton     Language language;
469657Slinton     Symclass class : 8;
479657Slinton     Integer level : 8;
489657Slinton     Symbol type;
499657Slinton     Symbol chain;
509657Slinton     union {
519657Slinton 	int offset;		/* variable address */
529657Slinton 	long iconval;		/* integer constant value */
539657Slinton 	double fconval;		/* floating constant value */
549657Slinton 	struct {		/* field offset and size (both in bits) */
559657Slinton 	    int offset;
569657Slinton 	    int length;
579657Slinton 	} field;
58*12547Scsvaf 	struct {		/* common offset and chain; used to relocate */
59*12547Scsvaf 	    int offset;         /* vars in global BSS */
60*12547Scsvaf 	    Symbol chain;
61*12547Scsvaf 	} common;
629657Slinton 	struct {		/* range bounds */
63*12547Scsvaf             Rangetype lowertype : 16;
64*12547Scsvaf             Rangetype uppertype : 16;
659657Slinton 	    long lower;
669657Slinton 	    long upper;
679657Slinton 	} rangev;
6811865Slinton 	struct {
6911865Slinton 	    int offset : 16;	/* offset for of function value */
7011865Slinton 	    Boolean src : 16;	/* true if there is source line info */
7111865Slinton 	    Address beginaddr;	/* address of function code */
729657Slinton 	} funcv;
739657Slinton 	struct {		/* variant record info */
749657Slinton 	    int size;
759657Slinton 	    Symbol vtorec;
769657Slinton 	    Symbol vtag;
779657Slinton 	} varnt;
789657Slinton     } symvalue;
799657Slinton     Symbol block;		/* symbol containing this symbol */
809657Slinton     Symbol next_sym;		/* hash chain */
819657Slinton };
829657Slinton 
839657Slinton /*
849657Slinton  * Basic types.
859657Slinton  */
869657Slinton 
879657Slinton Symbol t_boolean;
889657Slinton Symbol t_char;
899657Slinton Symbol t_int;
909657Slinton Symbol t_real;
919657Slinton Symbol t_nil;
929657Slinton 
939657Slinton Symbol program;
949657Slinton Symbol curfunc;
959657Slinton 
969657Slinton #define symname(s) ident(s->name)
979657Slinton #define codeloc(f) ((f)->symvalue.funcv.beginaddr)
989657Slinton #define isblock(s) (Boolean) ( \
999657Slinton     s->class == FUNC or s->class == PROC or \
1009657Slinton     s->class == MODULE or s->class == PROG \
1019657Slinton )
1029657Slinton 
10311865Slinton #define nosource(f) (not (f)->symvalue.funcv.src)
10411865Slinton 
1059657Slinton #include "tree.h"
1069657Slinton 
1079657Slinton /*
1089657Slinton  * Some macros to make finding a symbol with certain attributes.
1099657Slinton  */
1109657Slinton 
1119657Slinton #define find(s, withname) \
1129657Slinton { \
1139657Slinton     s = lookup(withname); \
1149657Slinton     while (s != nil and not (s->name == (withname) and
1159657Slinton 
1169657Slinton #define where /* qualification */
1179657Slinton 
1189657Slinton #define endfind(s) )) { \
1199657Slinton 	s = s->next_sym; \
1209657Slinton     } \
1219657Slinton }
1229657Slinton 
1239657Slinton #endif
1249657Slinton 
1259657Slinton /*
1269657Slinton  * Symbol table structure currently does not support deletions.
1279657Slinton  */
1289657Slinton 
1299657Slinton #define HASHTABLESIZE 2003
1309657Slinton 
1319657Slinton private Symbol hashtab[HASHTABLESIZE];
1329657Slinton 
1339657Slinton #define hash(name) ((((unsigned) name) >> 2) mod HASHTABLESIZE)
1349657Slinton 
1359657Slinton /*
1369657Slinton  * Allocate a new symbol.
1379657Slinton  */
1389657Slinton 
13911171Slinton #define SYMBLOCKSIZE 100
1409657Slinton 
1419657Slinton typedef struct Sympool {
1429657Slinton     struct Symbol sym[SYMBLOCKSIZE];
1439657Slinton     struct Sympool *prevpool;
1449657Slinton } *Sympool;
1459657Slinton 
1469657Slinton private Sympool sympool = nil;
1479657Slinton private Integer nleft = 0;
1489657Slinton 
1499657Slinton public Symbol symbol_alloc()
1509657Slinton {
1519657Slinton     register Sympool newpool;
1529657Slinton 
1539657Slinton     if (nleft <= 0) {
1549657Slinton 	newpool = new(Sympool);
15511171Slinton 	bzero(newpool, sizeof(newpool));
1569657Slinton 	newpool->prevpool = sympool;
1579657Slinton 	sympool = newpool;
1589657Slinton 	nleft = SYMBLOCKSIZE;
1599657Slinton     }
1609657Slinton     --nleft;
1619657Slinton     return &(sympool->sym[nleft]);
1629657Slinton }
1639657Slinton 
164*12547Scsvaf 
165*12547Scsvaf public symbol_dump(func)
166*12547Scsvaf Symbol func;
167*12547Scsvaf {
168*12547Scsvaf   register Symbol s;
169*12547Scsvaf   register Integer i;
170*12547Scsvaf 
171*12547Scsvaf 	printf(" symbols in %s \n",symname(func));
172*12547Scsvaf 	for(i=0; i< HASHTABLESIZE; i++)
173*12547Scsvaf 	   for(s=hashtab[i]; s != nil; s=s->next_sym)  {
174*12547Scsvaf 		if (s->block == func) psym(s);
175*12547Scsvaf 		}
176*12547Scsvaf }
177*12547Scsvaf 
1789657Slinton /*
1799657Slinton  * Free all the symbols currently allocated.
1809657Slinton  */
1819657Slinton public symbol_free()
1829657Slinton {
1839657Slinton     Sympool s, t;
1849657Slinton     register Integer i;
1859657Slinton 
1869657Slinton     s = sympool;
1879657Slinton     while (s != nil) {
1889657Slinton 	t = s->prevpool;
1899657Slinton 	dispose(s);
1909657Slinton 	s = t;
1919657Slinton     }
1929657Slinton     for (i = 0; i < HASHTABLESIZE; i++) {
1939657Slinton 	hashtab[i] = nil;
1949657Slinton     }
1959657Slinton     sympool = nil;
1969657Slinton     nleft = 0;
1979657Slinton }
1989657Slinton 
1999657Slinton /*
2009657Slinton  * Create a new symbol with the given attributes.
2019657Slinton  */
2029657Slinton 
2039657Slinton public Symbol newSymbol(name, blevel, class, type, chain)
2049657Slinton Name name;
2059657Slinton Integer blevel;
2069657Slinton Symclass class;
2079657Slinton Symbol type;
2089657Slinton Symbol chain;
2099657Slinton {
2109657Slinton     register Symbol s;
2119657Slinton 
2129657Slinton     s = symbol_alloc();
2139657Slinton     s->name = name;
2149657Slinton     s->level = blevel;
2159657Slinton     s->class = class;
2169657Slinton     s->type = type;
2179657Slinton     s->chain = chain;
2189657Slinton     return s;
2199657Slinton }
2209657Slinton 
2219657Slinton /*
2229657Slinton  * Insert a symbol into the hash table.
2239657Slinton  */
2249657Slinton 
2259657Slinton public Symbol insert(name)
2269657Slinton Name name;
2279657Slinton {
2289657Slinton     register Symbol s;
2299657Slinton     register unsigned int h;
2309657Slinton 
2319657Slinton     h = hash(name);
2329657Slinton     s = symbol_alloc();
2339657Slinton     s->name = name;
2349657Slinton     s->next_sym = hashtab[h];
2359657Slinton     hashtab[h] = s;
2369657Slinton     return s;
2379657Slinton }
2389657Slinton 
2399657Slinton /*
2409657Slinton  * Symbol lookup.
2419657Slinton  */
2429657Slinton 
2439657Slinton public Symbol lookup(name)
2449657Slinton Name name;
2459657Slinton {
2469657Slinton     register Symbol s;
2479657Slinton     register unsigned int h;
2489657Slinton 
2499657Slinton     h = hash(name);
2509657Slinton     s = hashtab[h];
2519657Slinton     while (s != nil and s->name != name) {
2529657Slinton 	s = s->next_sym;
2539657Slinton     }
2549657Slinton     return s;
2559657Slinton }
2569657Slinton 
2579657Slinton /*
2589657Slinton  * Dump out all the variables associated with the given
2599657Slinton  * procedure, function, or program at the given recursive level.
2609657Slinton  *
2619657Slinton  * This is quite inefficient.  We traverse the entire symbol table
2629657Slinton  * each time we're called.  The assumption is that this routine
2639657Slinton  * won't be called frequently enough to merit improved performance.
2649657Slinton  */
2659657Slinton 
2669657Slinton public dumpvars(f, frame)
2679657Slinton Symbol f;
2689657Slinton Frame frame;
2699657Slinton {
2709657Slinton     register Integer i;
2719657Slinton     register Symbol s;
2729657Slinton 
2739657Slinton     for (i = 0; i < HASHTABLESIZE; i++) {
2749657Slinton 	for (s = hashtab[i]; s != nil; s = s->next_sym) {
2759657Slinton 	    if (container(s) == f) {
2769657Slinton 		if (should_print(s)) {
2779657Slinton 		    printv(s, frame);
2789657Slinton 		    putchar('\n');
2799657Slinton 		} else if (s->class == MODULE) {
2809657Slinton 		    dumpvars(s, frame);
2819657Slinton 		}
2829657Slinton 	    }
2839657Slinton 	}
2849657Slinton     }
2859657Slinton }
2869657Slinton 
2879657Slinton /*
2889657Slinton  * Create a builtin type.
2899657Slinton  * Builtin types are circular in that btype->type->type = btype.
2909657Slinton  */
2919657Slinton 
2929657Slinton public Symbol maketype(name, lower, upper)
2939657Slinton String name;
2949657Slinton long lower;
2959657Slinton long upper;
2969657Slinton {
2979657Slinton     register Symbol s;
2989657Slinton 
2999657Slinton     s = newSymbol(identname(name, true), 0, TYPE, nil, nil);
3009657Slinton     s->language = findlanguage(".c");
3019657Slinton     s->type = newSymbol(nil, 0, RANGE, s, nil);
3029657Slinton     s->type->symvalue.rangev.lower = lower;
3039657Slinton     s->type->symvalue.rangev.upper = upper;
3049657Slinton     return s;
3059657Slinton }
3069657Slinton 
3079657Slinton /*
3089657Slinton  * These functions are now compiled inline.
3099657Slinton  *
3109657Slinton  * public String symname(s)
3119657Slinton Symbol s;
3129657Slinton {
3139657Slinton     checkref(s);
3149657Slinton     return ident(s->name);
3159657Slinton }
3169657Slinton 
3179657Slinton  *
3189657Slinton  * public Address codeloc(f)
3199657Slinton Symbol f;
3209657Slinton {
3219657Slinton     checkref(f);
3229657Slinton     if (not isblock(f)) {
3239657Slinton 	panic("codeloc: \"%s\" is not a block", ident(f->name));
3249657Slinton     }
3259657Slinton     return f->symvalue.funcv.beginaddr;
3269657Slinton }
3279657Slinton  *
3289657Slinton  */
3299657Slinton 
3309657Slinton /*
3319657Slinton  * Reduce type to avoid worrying about type names.
3329657Slinton  */
3339657Slinton 
3349657Slinton public Symbol rtype(type)
3359657Slinton Symbol type;
3369657Slinton {
3379657Slinton     register Symbol t;
3389657Slinton 
3399657Slinton     t = type;
3409657Slinton     if (t != nil) {
341*12547Scsvaf 	if (t->class == VAR or t->class == FIELD or t->class == REF ) {
3429657Slinton 	    t = t->type;
3439657Slinton 	}
3449657Slinton 	while (t->class == TYPE or t->class == TAG) {
3459657Slinton 	    t = t->type;
3469657Slinton 	}
3479657Slinton     }
3489657Slinton     return t;
3499657Slinton }
3509657Slinton 
3519657Slinton public Integer level(s)
3529657Slinton Symbol s;
3539657Slinton {
3549657Slinton     checkref(s);
3559657Slinton     return s->level;
3569657Slinton }
3579657Slinton 
3589657Slinton public Symbol container(s)
3599657Slinton Symbol s;
3609657Slinton {
3619657Slinton     checkref(s);
3629657Slinton     return s->block;
3639657Slinton }
3649657Slinton 
3659657Slinton /*
3669657Slinton  * Return the object address of the given symbol.
3679657Slinton  *
3689657Slinton  * There are the following possibilities:
3699657Slinton  *
3709657Slinton  *	globals		- just take offset
3719657Slinton  *	locals		- take offset from locals base
3729657Slinton  *	arguments	- take offset from argument base
3739657Slinton  *	register	- offset is register number
3749657Slinton  */
3759657Slinton 
3769657Slinton #define isglobal(s)		(s->level == 1 or s->level == 2)
3779657Slinton #define islocaloff(s)		(s->level >= 3 and s->symvalue.offset < 0)
3789657Slinton #define isparamoff(s)		(s->level >= 3 and s->symvalue.offset >= 0)
3799657Slinton #define isreg(s)		(s->level < 0)
3809657Slinton 
3819657Slinton public Address address(s, frame)
3829657Slinton Symbol s;
3839657Slinton Frame frame;
3849657Slinton {
3859657Slinton     register Frame frp;
3869657Slinton     register Address addr;
3879657Slinton     register Symbol cur;
3889657Slinton 
3899657Slinton     checkref(s);
3909657Slinton     if (not isactive(s->block)) {
3919657Slinton 	error("\"%s\" is not currently defined", symname(s));
3929657Slinton     } else if (isglobal(s)) {
3939657Slinton 	addr = s->symvalue.offset;
3949657Slinton     } else {
3959657Slinton 	frp = frame;
3969657Slinton 	if (frp == nil) {
3979657Slinton 	    cur = s->block;
3989657Slinton 	    while (cur != nil and cur->class == MODULE) {
3999657Slinton 		cur = cur->block;
4009657Slinton 	    }
4019657Slinton 	    if (cur == nil) {
4029657Slinton 		cur = whatblock(pc);
4039657Slinton 	    }
4049657Slinton 	    frp = findframe(cur);
4059657Slinton 	    if (frp == nil) {
4069657Slinton 		panic("unexpected nil frame for \"%s\"", symname(s));
4079657Slinton 	    }
4089657Slinton 	}
4099657Slinton 	if (islocaloff(s)) {
4109657Slinton 	    addr = locals_base(frp) + s->symvalue.offset;
4119657Slinton 	} else if (isparamoff(s)) {
4129657Slinton 	    addr = args_base(frp) + s->symvalue.offset;
4139657Slinton 	} else if (isreg(s)) {
4149657Slinton 	    addr = savereg(s->symvalue.offset, frp);
4159657Slinton 	} else {
4169657Slinton 	    panic("address: bad symbol \"%s\"", symname(s));
4179657Slinton 	}
4189657Slinton     }
4199657Slinton     return addr;
4209657Slinton }
4219657Slinton 
4229657Slinton /*
4239657Slinton  * Define a symbol used to access register values.
4249657Slinton  */
4259657Slinton 
4269657Slinton public defregname(n, r)
4279657Slinton Name n;
4289657Slinton Integer r;
4299657Slinton {
4309657Slinton     register Symbol s, t;
4319657Slinton 
4329657Slinton     s = insert(n);
4339657Slinton     t = newSymbol(nil, 0, PTR, t_int, nil);
4349657Slinton     t->language = findlanguage(".s");
4359657Slinton     s->language = t->language;
4369657Slinton     s->class = VAR;
4379657Slinton     s->level = -3;
4389657Slinton     s->type = t;
4399657Slinton     s->block = program;
4409657Slinton     s->symvalue.offset = r;
4419657Slinton }
4429657Slinton 
4439657Slinton /*
4449657Slinton  * Resolve an "abstract" type reference.
4459657Slinton  *
4469657Slinton  * It is possible in C to define a pointer to a type, but never define
4479657Slinton  * the type in a particular source file.  Here we try to resolve
4489657Slinton  * the type definition.  This is problematic, it is possible to
4499657Slinton  * have multiple, different definitions for the same name type.
4509657Slinton  */
4519657Slinton 
4529657Slinton public findtype(s)
4539657Slinton Symbol s;
4549657Slinton {
4559657Slinton     register Symbol t, u, prev;
4569657Slinton 
4579657Slinton     u = s;
4589657Slinton     prev = nil;
4599657Slinton     while (u != nil and u->class != BADUSE) {
4609657Slinton 	if (u->name != nil) {
4619657Slinton 	    prev = u;
4629657Slinton 	}
4639657Slinton 	u = u->type;
4649657Slinton     }
4659657Slinton     if (prev == nil) {
4669657Slinton 	error("couldn't find link to type reference");
4679657Slinton     }
4689657Slinton     find(t, prev->name) where
4699657Slinton 	t->type != nil and t->class == prev->class and
4709657Slinton 	t->type->class != BADUSE and t->block->class == MODULE
4719657Slinton     endfind(t);
4729657Slinton     if (t == nil) {
4739657Slinton 	error("couldn't resolve reference");
4749657Slinton     } else {
4759657Slinton 	prev->type = t->type;
4769657Slinton     }
4779657Slinton }
4789657Slinton 
4799657Slinton /*
4809657Slinton  * Find the size in bytes of the given type.
4819657Slinton  *
4829657Slinton  * This is probably the WRONG thing to do.  The size should be kept
4839657Slinton  * as an attribute in the symbol information as is done for structures
4849657Slinton  * and fields.  I haven't gotten around to cleaning this up yet.
4859657Slinton  */
4869657Slinton 
487*12547Scsvaf #define MAXUCHAR 255
488*12547Scsvaf #define MAXUSHORT 65535L
4899657Slinton #define MINCHAR -128
4909657Slinton #define MAXCHAR 127
4919657Slinton #define MINSHORT -32768
4929657Slinton #define MAXSHORT 32767
4939657Slinton 
4949657Slinton public Integer size(sym)
4959657Slinton Symbol sym;
4969657Slinton {
4979657Slinton     register Symbol s, t;
4989657Slinton     register int nel, elsize;
4999657Slinton     long lower, upper;
5009657Slinton     int r;
5019657Slinton 
5029657Slinton     t = sym;
5039657Slinton     checkref(t);
5049657Slinton     switch (t->class) {
5059657Slinton 	case RANGE:
5069657Slinton 	    lower = t->symvalue.rangev.lower;
5079657Slinton 	    upper = t->symvalue.rangev.upper;
5089657Slinton 	    if (upper == 0 and lower > 0) {		/* real */
5099657Slinton 		r = lower;
51012045Slinton 	    } else if (
511*12547Scsvaf   		(lower >= MINCHAR and upper <= MAXCHAR) or
512*12547Scsvaf   		(lower >= 0 and upper <= MAXUCHAR)
513*12547Scsvaf   	      ) {
5149657Slinton 		r = sizeof(char);
515*12547Scsvaf   	    } else if (
516*12547Scsvaf   		(lower >= MINSHORT and upper <= MAXSHORT) or
517*12547Scsvaf   		(lower >= 0 and upper <= MAXUSHORT)
518*12547Scsvaf   	      ) {
5199657Slinton 		r = sizeof(short);
5209657Slinton 	    } else {
5219657Slinton 		r = sizeof(long);
5229657Slinton 	    }
5239657Slinton 	    break;
5249657Slinton 
5259657Slinton 	case ARRAY:
5269657Slinton 	    elsize = size(t->type);
5279657Slinton 	    nel = 1;
5289657Slinton 	    for (t = t->chain; t != nil; t = t->chain) {
529*12547Scsvaf 
530*12547Scsvaf 		if(t->symvalue.rangev.lowertype == R_ARG
531*12547Scsvaf                    or t->symvalue.rangev.lowertype == R_TEMP )  {
532*12547Scsvaf 			if( ! getbound(t, t->symvalue.rangev.lower,
533*12547Scsvaf 		                         t->symvalue.rangev.lowertype, &lower))
534*12547Scsvaf 			error(" dynamic bounds not currently available ");
535*12547Scsvaf 		}
536*12547Scsvaf 		else lower = t->symvalue.rangev.lower;
537*12547Scsvaf 
538*12547Scsvaf 		if(t->symvalue.rangev.uppertype == R_ARG
539*12547Scsvaf                    or t->symvalue.rangev.uppertype == R_TEMP )  {
540*12547Scsvaf 			if( ! getbound(t, t->symvalue.rangev.upper,
541*12547Scsvaf 		                         t->symvalue.rangev.uppertype, &upper))
542*12547Scsvaf 			error(" dynamic bounds not currently available ");
543*12547Scsvaf 		}
544*12547Scsvaf 		else upper = t->symvalue.rangev.upper;
5459657Slinton 		nel *= (upper-lower+1);
5469657Slinton 	    }
5479657Slinton 	    r = nel*elsize;
5489657Slinton 	    break;
5499657Slinton 
550*12547Scsvaf 	case REF:
5519657Slinton 	case VAR:
5529657Slinton 	case FVAR:
5539657Slinton 	    r = size(t->type);
55412127Slinton 	    /*
55512127Slinton 	     *
55612045Slinton 	    if (r < sizeof(Word) and isparam(t)) {
5579657Slinton 		r = sizeof(Word);
5589657Slinton 	    }
559*12547Scsvaf 	    */
5609657Slinton 	    break;
5619657Slinton 
5629657Slinton 	case CONST:
5639657Slinton 	    r = size(t->type);
5649657Slinton 	    break;
5659657Slinton 
5669657Slinton 	case TYPE:
5679657Slinton 	    if (t->type->class == PTR and t->type->type->class == BADUSE) {
5689657Slinton 		findtype(t);
5699657Slinton 	    }
5709657Slinton 	    r = size(t->type);
5719657Slinton 	    break;
5729657Slinton 
5739657Slinton 	case TAG:
5749657Slinton 	    r = size(t->type);
5759657Slinton 	    break;
5769657Slinton 
5779657Slinton 	case FIELD:
5789657Slinton 	    r = (t->symvalue.field.length + 7) div 8;
5799657Slinton 	    break;
5809657Slinton 
5819657Slinton 	case RECORD:
5829657Slinton 	case VARNT:
5839657Slinton 	    r = t->symvalue.offset;
5849657Slinton 	    if (r == 0 and t->chain != nil) {
5859657Slinton 		panic("missing size information for record");
5869657Slinton 	    }
5879657Slinton 	    break;
5889657Slinton 
5899657Slinton 	case PTR:
5909657Slinton 	case FILET:
5919657Slinton 	    r = sizeof(Word);
5929657Slinton 	    break;
5939657Slinton 
5949657Slinton 	case SCAL:
5959657Slinton 	    if (t->symvalue.iconval > 255) {
5969657Slinton 		r = sizeof(short);
5979657Slinton 	    } else {
5989657Slinton 		r = sizeof(char);
5999657Slinton 	    }
6009657Slinton 	    break;
6019657Slinton 
6029657Slinton 	case FPROC:
6039657Slinton 	case FFUNC:
6049657Slinton 	    r = sizeof(Word);
6059657Slinton 	    break;
6069657Slinton 
6079657Slinton 	case PROC:
6089657Slinton 	case FUNC:
6099657Slinton 	case MODULE:
6109657Slinton 	case PROG:
6119657Slinton 	    r = sizeof(Symbol);
6129657Slinton 	    break;
6139657Slinton 
6149657Slinton 	default:
6159657Slinton 	    if (ord(t->class) > ord(TYPEREF)) {
6169657Slinton 		panic("size: bad class (%d)", ord(t->class));
6179657Slinton 	    } else {
6189657Slinton 		error("improper operation on a %s", classname(t));
6199657Slinton 	    }
6209657Slinton 	    /* NOTREACHED */
6219657Slinton     }
6229657Slinton     return r;
6239657Slinton }
6249657Slinton 
6259657Slinton /*
6269657Slinton  * Test if a symbol is a parameter.  This is true if there
6279657Slinton  * is a cycle from s->block to s via chain pointers.
6289657Slinton  */
6299657Slinton 
6309657Slinton public Boolean isparam(s)
6319657Slinton Symbol s;
6329657Slinton {
6339657Slinton     register Symbol t;
6349657Slinton 
6359657Slinton     t = s->block;
6369657Slinton     while (t != nil and t != s) {
6379657Slinton 	t = t->chain;
6389657Slinton     }
6399657Slinton     return (Boolean) (t != nil);
6409657Slinton }
6419657Slinton 
6429657Slinton /*
6439657Slinton  * Test if a symbol is a var parameter, i.e. has class REF.
6449657Slinton  */
6459657Slinton 
6469657Slinton public Boolean isvarparam(s)
6479657Slinton Symbol s;
6489657Slinton {
6499657Slinton     return (Boolean) (s->class == REF);
6509657Slinton }
6519657Slinton 
6529657Slinton /*
6539657Slinton  * Test if a symbol is a variable (actually any addressible quantity
6549657Slinton  * with do).
6559657Slinton  */
6569657Slinton 
6579657Slinton public Boolean isvariable(s)
6589657Slinton register Symbol s;
6599657Slinton {
6609657Slinton     return (Boolean) (s->class == VAR or s->class == FVAR or s->class == REF);
6619657Slinton }
6629657Slinton 
6639657Slinton /*
6649657Slinton  * Test if a symbol is a block, e.g. function, procedure, or the
6659657Slinton  * main program.
6669657Slinton  *
6679657Slinton  * This function is now expanded inline for efficiency.
6689657Slinton  *
6699657Slinton  * public Boolean isblock(s)
6709657Slinton register Symbol s;
6719657Slinton {
6729657Slinton     return (Boolean) (
6739657Slinton 	s->class == FUNC or s->class == PROC or
6749657Slinton 	s->class == MODULE or s->class == PROG
6759657Slinton     );
6769657Slinton }
6779657Slinton  *
6789657Slinton  */
6799657Slinton 
6809657Slinton /*
6819657Slinton  * Test if a symbol is a module.
6829657Slinton  */
6839657Slinton 
6849657Slinton public Boolean ismodule(s)
6859657Slinton register Symbol s;
6869657Slinton {
6879657Slinton     return (Boolean) (s->class == MODULE);
6889657Slinton }
6899657Slinton 
6909657Slinton /*
6919657Slinton  * Test if a symbol is builtin, that is, a predefined type or
6929657Slinton  * reserved word.
6939657Slinton  */
6949657Slinton 
6959657Slinton public Boolean isbuiltin(s)
6969657Slinton register Symbol s;
6979657Slinton {
6989657Slinton     return (Boolean) (s->level == 0 and s->class != PROG and s->class != VAR);
6999657Slinton }
7009657Slinton 
7019657Slinton /*
7029657Slinton  * Test if two types match.
7039657Slinton  * Equivalent names implies a match in any language.
7049657Slinton  *
7059657Slinton  * Special symbols must be handled with care.
7069657Slinton  */
7079657Slinton 
7089657Slinton public Boolean compatible(t1, t2)
7099657Slinton register Symbol t1, t2;
7109657Slinton {
7119657Slinton     Boolean b;
7129657Slinton 
7139657Slinton     if (t1 == t2) {
7149657Slinton 	b = true;
7159657Slinton     } else if (t1 == nil or t2 == nil) {
7169657Slinton 	b = false;
7179657Slinton     } else if (t1 == procsym) {
7189657Slinton 	b = isblock(t2);
7199657Slinton     } else if (t2 == procsym) {
7209657Slinton 	b = isblock(t1);
7219657Slinton     } else if (t1->language == nil) {
7229657Slinton 	b = (Boolean) (t2->language == nil or
7239657Slinton 	    (*language_op(t2->language, L_TYPEMATCH))(t1, t2));
724*12547Scsvaf     } else if (t2->language == nil) {
725*12547Scsvaf 	b = (Boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2);
726*12547Scsvaf     } else if ( isbuiltin(t1) or isbuiltin(t1->type) ) {
727*12547Scsvaf 	b = (Boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2);
7289657Slinton     } else {
7299657Slinton 	b = (Boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2);
7309657Slinton     }
7319657Slinton     return b;
7329657Slinton }
7339657Slinton 
7349657Slinton /*
7359657Slinton  * Check for a type of the given name.
7369657Slinton  */
7379657Slinton 
7389657Slinton public Boolean istypename(type, name)
7399657Slinton Symbol type;
7409657Slinton String name;
7419657Slinton {
7429657Slinton     Symbol t;
7439657Slinton     Boolean b;
7449657Slinton 
7459657Slinton     t = type;
7469657Slinton     checkref(t);
7479657Slinton     b = (Boolean) (
7489657Slinton 	t->class == TYPE and t->name == identname(name, true)
7499657Slinton     );
7509657Slinton     return b;
7519657Slinton }
7529657Slinton 
7539657Slinton /*
7549657Slinton  * Test if the name of a symbol is uniquely defined or not.
7559657Slinton  */
7569657Slinton 
7579657Slinton public Boolean isambiguous(s)
7589657Slinton register Symbol s;
7599657Slinton {
7609657Slinton     register Symbol t;
7619657Slinton 
7629657Slinton     find(t, s->name) where t != s endfind(t);
7639657Slinton     return (Boolean) (t != nil);
7649657Slinton }
7659657Slinton 
7669657Slinton typedef char *Arglist;
7679657Slinton 
7689657Slinton #define nextarg(type)  ((type *) (ap += sizeof(type)))[-1]
7699657Slinton 
7709657Slinton private Symbol mkstring();
7719657Slinton private Symbol namenode();
7729657Slinton 
7739657Slinton /*
7749657Slinton  * Determine the type of a parse tree.
7759657Slinton  * Also make some symbol-dependent changes to the tree such as
7769657Slinton  * changing removing RVAL nodes for constant symbols.
7779657Slinton  */
7789657Slinton 
7799657Slinton public assigntypes(p)
7809657Slinton register Node p;
7819657Slinton {
7829657Slinton     register Node p1;
7839657Slinton     register Symbol s;
7849657Slinton 
7859657Slinton     switch (p->op) {
7869657Slinton 	case O_SYM:
7879657Slinton 	    p->nodetype = namenode(p);
7889657Slinton 	    break;
7899657Slinton 
7909657Slinton 	case O_LCON:
7919657Slinton 	    p->nodetype = t_int;
7929657Slinton 	    break;
7939657Slinton 
7949657Slinton 	case O_FCON:
7959657Slinton 	    p->nodetype = t_real;
7969657Slinton 	    break;
7979657Slinton 
7989657Slinton 	case O_SCON:
7999657Slinton 	    p->value.scon = strdup(p->value.scon);
8009657Slinton 	    s = mkstring(p->value.scon);
8019657Slinton 	    if (s == t_char) {
8029657Slinton 		p->op = O_LCON;
8039657Slinton 		p->value.lcon = p->value.scon[0];
8049657Slinton 	    }
8059657Slinton 	    p->nodetype = s;
8069657Slinton 	    break;
8079657Slinton 
8089657Slinton 	case O_INDIR:
8099657Slinton 	    p1 = p->value.arg[0];
8109657Slinton 	    chkclass(p1, PTR);
8119657Slinton 	    p->nodetype = rtype(p1->nodetype)->type;
8129657Slinton 	    break;
8139657Slinton 
8149657Slinton 	case O_DOT:
8159657Slinton 	    p->nodetype = p->value.arg[1]->value.sym;
8169657Slinton 	    break;
8179657Slinton 
8189657Slinton 	case O_RVAL:
8199657Slinton 	    p1 = p->value.arg[0];
8209657Slinton 	    p->nodetype = p1->nodetype;
8219657Slinton 	    if (p1->op == O_SYM) {
8229657Slinton 		if (p1->nodetype->class == FUNC) {
8239657Slinton 		    p->op = O_CALL;
8249657Slinton 		    p->value.arg[1] = nil;
8259657Slinton 		} else if (p1->value.sym->class == CONST) {
8269657Slinton 		    if (compatible(p1->value.sym->type, t_real)) {
8279657Slinton 			p->op = O_FCON;
8289657Slinton 			p->value.fcon = p1->value.sym->symvalue.fconval;
8299657Slinton 			p->nodetype = t_real;
8309657Slinton 			dispose(p1);
8319657Slinton 		    } else {
8329657Slinton 			p->op = O_LCON;
8339657Slinton 			p->value.lcon = p1->value.sym->symvalue.iconval;
8349657Slinton 			p->nodetype = p1->value.sym->type;
8359657Slinton 			dispose(p1);
8369657Slinton 		    }
8379657Slinton 		} else if (isreg(p1->value.sym)) {
8389657Slinton 		    p->op = O_SYM;
8399657Slinton 		    p->value.sym = p1->value.sym;
8409657Slinton 		    dispose(p1);
8419657Slinton 		}
8429657Slinton 	    } else if (p1->op == O_INDIR and p1->value.arg[0]->op == O_SYM) {
8439657Slinton 		s = p1->value.arg[0]->value.sym;
8449657Slinton 		if (isreg(s)) {
8459657Slinton 		    p1->op = O_SYM;
8469657Slinton 		    dispose(p1->value.arg[0]);
8479657Slinton 		    p1->value.sym = s;
8489657Slinton 		    p1->nodetype = s;
8499657Slinton 		}
8509657Slinton 	    }
8519657Slinton 	    break;
8529657Slinton 
8539657Slinton 	/*
8549657Slinton 	 * Perform a cast if the call is of the form "type(expr)".
8559657Slinton 	 */
8569657Slinton 	case O_CALL:
8579657Slinton 	    p1 = p->value.arg[0];
85811171Slinton 	    p->nodetype = rtype(p1->nodetype)->type;
8599657Slinton 	    break;
8609657Slinton 
86111171Slinton 	case O_TYPERENAME:
86211171Slinton 	    p->nodetype = p->value.arg[1]->nodetype;
86311171Slinton 	    break;
86411171Slinton 
8659657Slinton 	case O_ITOF:
8669657Slinton 	    p->nodetype = t_real;
8679657Slinton 	    break;
8689657Slinton 
8699657Slinton 	case O_NEG:
8709657Slinton 	    s = p->value.arg[0]->nodetype;
8719657Slinton 	    if (not compatible(s, t_int)) {
8729657Slinton 		if (not compatible(s, t_real)) {
8739657Slinton 		    beginerrmsg();
8749657Slinton 		    prtree(stderr, p->value.arg[0]);
8759657Slinton 		    fprintf(stderr, "is improper type");
8769657Slinton 		    enderrmsg();
8779657Slinton 		} else {
8789657Slinton 		    p->op = O_NEGF;
8799657Slinton 		}
8809657Slinton 	    }
8819657Slinton 	    p->nodetype = s;
8829657Slinton 	    break;
8839657Slinton 
8849657Slinton 	case O_ADD:
8859657Slinton 	case O_SUB:
8869657Slinton 	case O_MUL:
8879657Slinton 	case O_LT:
8889657Slinton 	case O_LE:
8899657Slinton 	case O_GT:
8909657Slinton 	case O_GE:
8919657Slinton 	case O_EQ:
8929657Slinton 	case O_NE:
8939657Slinton 	{
8949657Slinton 	    Boolean t1real, t2real;
8959657Slinton 	    Symbol t1, t2;
8969657Slinton 
8979657Slinton 	    t1 = rtype(p->value.arg[0]->nodetype);
8989657Slinton 	    t2 = rtype(p->value.arg[1]->nodetype);
8999657Slinton 	    t1real = compatible(t1, t_real);
9009657Slinton 	    t2real = compatible(t2, t_real);
9019657Slinton 	    if (t1real or t2real) {
9029657Slinton 		p->op = (Operator) (ord(p->op) + 1);
9039657Slinton 		if (not t1real) {
9049657Slinton 		    p->value.arg[0] = build(O_ITOF, p->value.arg[0]);
9059657Slinton 		} else if (not t2real) {
9069657Slinton 		    p->value.arg[1] = build(O_ITOF, p->value.arg[1]);
9079657Slinton 		}
9089657Slinton 	    } else {
9099657Slinton 		if (t1real) {
9109657Slinton 		    convert(&(p->value.arg[0]), t_int, O_NOP);
9119657Slinton 		}
9129657Slinton 		if (t2real) {
9139657Slinton 		    convert(&(p->value.arg[1]), t_int, O_NOP);
9149657Slinton 		}
9159657Slinton 	    }
9169657Slinton 	    if (ord(p->op) >= ord(O_LT)) {
9179657Slinton 		p->nodetype = t_boolean;
9189657Slinton 	    } else {
9199657Slinton 		if (t1real or t2real) {
9209657Slinton 		    p->nodetype = t_real;
9219657Slinton 		} else {
9229657Slinton 		    p->nodetype = t_int;
9239657Slinton 		}
9249657Slinton 	    }
9259657Slinton 	    break;
9269657Slinton 	}
9279657Slinton 
9289657Slinton 	case O_DIVF:
9299657Slinton 	    convert(&(p->value.arg[0]), t_real, O_ITOF);
9309657Slinton 	    convert(&(p->value.arg[1]), t_real, O_ITOF);
9319657Slinton 	    p->nodetype = t_real;
9329657Slinton 	    break;
9339657Slinton 
9349657Slinton 	case O_DIV:
9359657Slinton 	case O_MOD:
9369657Slinton 	    convert(&(p->value.arg[0]), t_int, O_NOP);
9379657Slinton 	    convert(&(p->value.arg[1]), t_int, O_NOP);
9389657Slinton 	    p->nodetype = t_int;
9399657Slinton 	    break;
9409657Slinton 
9419657Slinton 	case O_AND:
9429657Slinton 	case O_OR:
9439657Slinton 	    chkboolean(p->value.arg[0]);
9449657Slinton 	    chkboolean(p->value.arg[1]);
9459657Slinton 	    p->nodetype = t_boolean;
9469657Slinton 	    break;
9479657Slinton 
9489657Slinton 	case O_QLINE:
9499657Slinton 	    p->nodetype = t_int;
9509657Slinton 	    break;
9519657Slinton 
9529657Slinton 	default:
9539657Slinton 	    p->nodetype = nil;
9549657Slinton 	    break;
9559657Slinton     }
9569657Slinton }
9579657Slinton 
9589657Slinton /*
9599657Slinton  * Create a node for a name.  The symbol for the name has already
9609657Slinton  * been chosen, either implicitly with "which" or explicitly from
9619657Slinton  * the dot routine.
9629657Slinton  */
9639657Slinton 
9649657Slinton private Symbol namenode(p)
9659657Slinton Node p;
9669657Slinton {
9679657Slinton     register Symbol r, s;
9689657Slinton     register Node np;
9699657Slinton 
9709657Slinton     s = p->value.sym;
9719657Slinton     if (s->class == REF) {
9729657Slinton 	np = new(Node);
9739657Slinton 	np->op = p->op;
9749657Slinton 	np->nodetype = s;
9759657Slinton 	np->value.sym = s;
9769657Slinton 	p->op = O_INDIR;
9779657Slinton 	p->value.arg[0] = np;
9789657Slinton     }
9799657Slinton /*
9809657Slinton  * Old way
9819657Slinton  *
9829657Slinton     if (s->class == CONST or s->class == VAR or s->class == FVAR) {
9839657Slinton 	r = s->type;
9849657Slinton     } else {
9859657Slinton 	r = s;
9869657Slinton     }
9879657Slinton  *
9889657Slinton  */
9899657Slinton     return s;
9909657Slinton }
9919657Slinton 
9929657Slinton /*
9939657Slinton  * Convert a tree to a type via a conversion operator;
9949657Slinton  * if this isn't possible generate an error.
9959657Slinton  *
9969657Slinton  * Note the tree is call by address, hence the #define below.
9979657Slinton  */
9989657Slinton 
9999657Slinton private convert(tp, typeto, op)
10009657Slinton Node *tp;
10019657Slinton Symbol typeto;
10029657Slinton Operator op;
10039657Slinton {
10049657Slinton #define tree    (*tp)
10059657Slinton 
10069657Slinton     Symbol s;
10079657Slinton 
10089657Slinton     s = rtype(tree->nodetype);
10099657Slinton     typeto = rtype(typeto);
10109657Slinton     if (compatible(typeto, t_real) and compatible(s, t_int)) {
10119657Slinton 	tree = build(op, tree);
10129657Slinton     } else if (not compatible(s, typeto)) {
10139657Slinton 	beginerrmsg();
10149657Slinton 	prtree(stderr, s);
10159657Slinton 	fprintf(stderr, " is improper type");
10169657Slinton 	enderrmsg();
10179657Slinton     } else if (op != O_NOP and s != typeto) {
10189657Slinton 	tree = build(op, tree);
10199657Slinton     }
10209657Slinton 
10219657Slinton #undef tree
10229657Slinton }
10239657Slinton 
10249657Slinton /*
10259657Slinton  * Construct a node for the dot operator.
10269657Slinton  *
10279657Slinton  * If the left operand is not a record, but rather a procedure
10289657Slinton  * or function, then we interpret the "." as referencing an
10299657Slinton  * "invisible" variable; i.e. a variable within a dynamically
10309657Slinton  * active block but not within the static scope of the current procedure.
10319657Slinton  */
10329657Slinton 
10339657Slinton public Node dot(record, fieldname)
10349657Slinton Node record;
10359657Slinton Name fieldname;
10369657Slinton {
10379657Slinton     register Node p;
10389657Slinton     register Symbol s, t;
10399657Slinton 
10409657Slinton     if (isblock(record->nodetype)) {
10419657Slinton 	find(s, fieldname) where
10429657Slinton 	    s->block == record->nodetype and
10439657Slinton 	    s->class != FIELD and s->class != TAG
10449657Slinton 	endfind(s);
10459657Slinton 	if (s == nil) {
10469657Slinton 	    beginerrmsg();
10479657Slinton 	    fprintf(stderr, "\"%s\" is not defined in ", ident(fieldname));
10489657Slinton 	    printname(stderr, record->nodetype);
10499657Slinton 	    enderrmsg();
10509657Slinton 	}
10519657Slinton 	p = new(Node);
10529657Slinton 	p->op = O_SYM;
10539657Slinton 	p->value.sym = s;
10549657Slinton 	p->nodetype = namenode(p);
10559657Slinton     } else {
10569657Slinton 	p = record;
10579657Slinton 	t = rtype(p->nodetype);
10589657Slinton 	if (t->class == PTR) {
10599657Slinton 	    s = findfield(fieldname, t->type);
10609657Slinton 	} else {
10619657Slinton 	    s = findfield(fieldname, t);
10629657Slinton 	}
10639657Slinton 	if (s == nil) {
10649657Slinton 	    beginerrmsg();
10659657Slinton 	    fprintf(stderr, "\"%s\" is not a field in ", ident(fieldname));
10669657Slinton 	    prtree(stderr, record);
10679657Slinton 	    enderrmsg();
10689657Slinton 	}
10699657Slinton 	if (t->class == PTR and not isreg(record->nodetype)) {
10709657Slinton 	    p = build(O_INDIR, record);
10719657Slinton 	}
10729657Slinton 	p = build(O_DOT, p, build(O_SYM, s));
10739657Slinton     }
10749657Slinton     return p;
10759657Slinton }
10769657Slinton 
10779657Slinton /*
10789657Slinton  * Return a tree corresponding to an array reference and do the
10799657Slinton  * error checking.
10809657Slinton  */
10819657Slinton 
10829657Slinton public Node subscript(a, slist)
10839657Slinton Node a, slist;
10849657Slinton {
1085*12547Scsvaf Symbol t;
10869657Slinton 
1087*12547Scsvaf    t = rtype(a->nodetype);
1088*12547Scsvaf    if(t->language == nil) {
1089*12547Scsvaf 	error("unknown language");
1090*12547Scsvaf    }
1091*12547Scsvaf    else {
1092*12547Scsvaf         return ( (Node)
1093*12547Scsvaf         (*language_op(t->language, L_BUILDAREF)) (a,slist)
1094*12547Scsvaf                );
1095*12547Scsvaf    }
10969657Slinton }
10979657Slinton 
10989657Slinton /*
10999657Slinton  * Evaluate a subscript index.
11009657Slinton  */
11019657Slinton 
11029657Slinton public int evalindex(s, i)
11039657Slinton Symbol s;
11049657Slinton long i;
11059657Slinton {
1106*12547Scsvaf Symbol t;
11079657Slinton 
1108*12547Scsvaf    t = rtype(s);
1109*12547Scsvaf    if(t->language == nil) {
1110*12547Scsvaf 	error("unknown language");
1111*12547Scsvaf    }
1112*12547Scsvaf    else {
1113*12547Scsvaf         return (
1114*12547Scsvaf              (*language_op(t->language, L_EVALAREF)) (s,i)
1115*12547Scsvaf                );
1116*12547Scsvaf    }
11179657Slinton }
11189657Slinton 
11199657Slinton /*
11209657Slinton  * Check to see if a tree is boolean-valued, if not it's an error.
11219657Slinton  */
11229657Slinton 
11239657Slinton public chkboolean(p)
11249657Slinton register Node p;
11259657Slinton {
11269657Slinton     if (p->nodetype != t_boolean) {
11279657Slinton 	beginerrmsg();
11289657Slinton 	fprintf(stderr, "found ");
11299657Slinton 	prtree(stderr, p);
11309657Slinton 	fprintf(stderr, ", expected boolean expression");
11319657Slinton 	enderrmsg();
11329657Slinton     }
11339657Slinton }
11349657Slinton 
11359657Slinton /*
11369657Slinton  * Check to make sure the given tree has a type of the given class.
11379657Slinton  */
11389657Slinton 
11399657Slinton private chkclass(p, class)
11409657Slinton Node p;
11419657Slinton Symclass class;
11429657Slinton {
11439657Slinton     struct Symbol tmpsym;
11449657Slinton 
11459657Slinton     tmpsym.class = class;
11469657Slinton     if (rtype(p->nodetype)->class != class) {
11479657Slinton 	beginerrmsg();
11489657Slinton 	fprintf(stderr, "\"");
11499657Slinton 	prtree(stderr, p);
11509657Slinton 	fprintf(stderr, "\" is not a %s", classname(&tmpsym));
11519657Slinton 	enderrmsg();
11529657Slinton     }
11539657Slinton }
11549657Slinton 
11559657Slinton /*
11569657Slinton  * Construct a node for the type of a string.  While we're at it,
11579657Slinton  * scan the string for '' that collapse to ', and chop off the ends.
11589657Slinton  */
11599657Slinton 
11609657Slinton private Symbol mkstring(str)
11619657Slinton String str;
11629657Slinton {
11639657Slinton     register char *p, *q;
11649657Slinton     register Symbol s;
11659657Slinton 
11669657Slinton     p = str;
11679657Slinton     q = str;
11689657Slinton     while (*p != '\0') {
11699657Slinton 	if (*p == '\\') {
11709657Slinton 	    ++p;
11719657Slinton 	}
11729657Slinton 	*q = *p;
11739657Slinton 	++p;
11749657Slinton 	++q;
11759657Slinton     }
11769657Slinton     *q = '\0';
11779657Slinton     s = newSymbol(nil, 0, ARRAY, t_char, nil);
11789657Slinton     s->language = findlanguage(".s");
11799657Slinton     s->chain = newSymbol(nil, 0, RANGE, t_int, nil);
11809657Slinton     s->chain->language = s->language;
11819657Slinton     s->chain->symvalue.rangev.lower = 1;
11829657Slinton     s->chain->symvalue.rangev.upper = p - str + 1;
11839657Slinton     return s;
11849657Slinton }
11859657Slinton 
11869657Slinton /*
11879657Slinton  * Free up the space allocated for a string type.
11889657Slinton  */
11899657Slinton 
11909657Slinton public unmkstring(s)
11919657Slinton Symbol s;
11929657Slinton {
11939657Slinton     dispose(s->chain);
11949657Slinton }
11959657Slinton 
11969657Slinton /*
11979657Slinton  * Figure out the "current" variable or function being referred to,
11989657Slinton  * this is either the active one or the most visible from the
11999657Slinton  * current scope.
12009657Slinton  */
12019657Slinton 
12029657Slinton public Symbol which(n)
12039657Slinton Name n;
12049657Slinton {
12059657Slinton     register Symbol s, p, t, f;
12069657Slinton 
12079657Slinton     find(s, n) where s->class != FIELD and s->class != TAG endfind(s);
12089657Slinton     if (s == nil) {
12099657Slinton 	s = lookup(n);
12109657Slinton     }
12119657Slinton     if (s == nil) {
12129657Slinton 	error("\"%s\" is not defined", ident(n));
12139657Slinton     } else if (s == program or isbuiltin(s)) {
12149657Slinton 	t = s;
12159657Slinton     } else {
12169657Slinton     /*
12179657Slinton      * Old way
12189657Slinton      *
12199657Slinton 	if (not isactive(program)) {
12209657Slinton 	    f = program;
12219657Slinton 	} else {
12229657Slinton 	    f = whatblock(pc);
12239657Slinton 	    if (f == nil) {
12249657Slinton 		panic("no block for addr 0x%x", pc);
12259657Slinton 	    }
12269657Slinton 	}
12279657Slinton      *
12289657Slinton      * Now start with curfunc.
12299657Slinton      */
12309657Slinton 	p = curfunc;
12319657Slinton 	do {
12329657Slinton 	    find(t, n) where
12339657Slinton 		t->block == p and t->class != FIELD and t->class != TAG
12349657Slinton 	    endfind(t);
12359657Slinton 	    p = p->block;
12369657Slinton 	} while (t == nil and p != nil);
12379657Slinton 	if (t == nil) {
12389657Slinton 	    t = s;
12399657Slinton 	}
12409657Slinton     }
12419657Slinton     return t;
12429657Slinton }
12439657Slinton 
12449657Slinton /*
12459657Slinton  * Find the symbol which is has the same name and scope as the
12469657Slinton  * given symbol but is of the given field.  Return nil if there is none.
12479657Slinton  */
12489657Slinton 
12499657Slinton public Symbol findfield(fieldname, record)
12509657Slinton Name fieldname;
12519657Slinton Symbol record;
12529657Slinton {
12539657Slinton     register Symbol t;
12549657Slinton 
12559657Slinton     t = rtype(record)->chain;
12569657Slinton     while (t != nil and t->name != fieldname) {
12579657Slinton 	t = t->chain;
12589657Slinton     }
12599657Slinton     return t;
12609657Slinton }
1261*12547Scsvaf 
1262*12547Scsvaf public Boolean getbound(s,off,type,valp)
1263*12547Scsvaf Symbol s;
1264*12547Scsvaf int off;
1265*12547Scsvaf Rangetype type;
1266*12547Scsvaf int *valp;
1267*12547Scsvaf {
1268*12547Scsvaf     Frame frp;
1269*12547Scsvaf     Address addr;
1270*12547Scsvaf     Symbol cur;
1271*12547Scsvaf 
1272*12547Scsvaf     if (not isactive(s->block)) {
1273*12547Scsvaf 	return(false);
1274*12547Scsvaf     }
1275*12547Scsvaf     cur = s->block;
1276*12547Scsvaf     while (cur != nil and cur->class == MODULE) {  /* WHY*/
1277*12547Scsvaf     		cur = cur->block;
1278*12547Scsvaf     }
1279*12547Scsvaf     if(cur == nil) {
1280*12547Scsvaf 		cur = whatblock(pc);
1281*12547Scsvaf     }
1282*12547Scsvaf     frp = findframe(cur);
1283*12547Scsvaf     if (frp == nil) {
1284*12547Scsvaf 	return(false);
1285*12547Scsvaf     }
1286*12547Scsvaf     if(type == R_TEMP) addr = locals_base(frp) + off;
1287*12547Scsvaf     else if (type == R_ARG) addr = args_base(frp) + off;
1288*12547Scsvaf     else return(false);
1289*12547Scsvaf     dread(valp,addr,sizeof(long));
1290*12547Scsvaf     return(true);
1291*12547Scsvaf }
1292