xref: /csrg-svn/old/dbx/symbols.c (revision 14441)
19657Slinton /* Copyright (c) 1982 Regents of the University of California */
29657Slinton 
3*14441Slinton static char sccsid[] = "@(#)symbols.c 1.10 08/10/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,
3612547Scsvaf     PROC, FUNC, FVAR, REF, PTR, FILET, SET, RANGE,
379657Slinton     LABEL, WITHPTR, SCAL, STR, PROG, IMPROPER, VARNT,
3812547Scsvaf     FPROC, FFUNC, MODULE, TAG, COMMON, TYPEREF
399657Slinton } Symclass;
409657Slinton 
4112547Scsvaf typedef enum { R_CONST, R_TEMP, R_ARG, R_ADJUST } Rangetype;
4212547Scsvaf 
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;
5812547Scsvaf 	struct {		/* common offset and chain; used to relocate */
5912547Scsvaf 	    int offset;         /* vars in global BSS */
6012547Scsvaf 	    Symbol chain;
6112547Scsvaf 	} common;
629657Slinton 	struct {		/* range bounds */
6312547Scsvaf             Rangetype lowertype : 16;
6412547Scsvaf             Rangetype uppertype : 16;
659657Slinton 	    long lower;
669657Slinton 	    long upper;
679657Slinton 	} rangev;
6811865Slinton 	struct {
6911865Slinton 	    int offset : 16;	/* offset for of function value */
70*14441Slinton 	    Boolean src : 8;	/* true if there is source line info */
71*14441Slinton 	    Boolean inline : 8;	/* true if no separate act. rec. */
7211865Slinton 	    Address beginaddr;	/* address of function code */
739657Slinton 	} funcv;
749657Slinton 	struct {		/* variant record info */
759657Slinton 	    int size;
769657Slinton 	    Symbol vtorec;
779657Slinton 	    Symbol vtag;
789657Slinton 	} varnt;
799657Slinton     } symvalue;
809657Slinton     Symbol block;		/* symbol containing this symbol */
819657Slinton     Symbol next_sym;		/* hash chain */
829657Slinton };
839657Slinton 
849657Slinton /*
859657Slinton  * Basic types.
869657Slinton  */
879657Slinton 
889657Slinton Symbol t_boolean;
899657Slinton Symbol t_char;
909657Slinton Symbol t_int;
919657Slinton Symbol t_real;
929657Slinton Symbol t_nil;
939657Slinton 
949657Slinton Symbol program;
959657Slinton Symbol curfunc;
969657Slinton 
979657Slinton #define symname(s) ident(s->name)
989657Slinton #define codeloc(f) ((f)->symvalue.funcv.beginaddr)
999657Slinton #define isblock(s) (Boolean) ( \
1009657Slinton     s->class == FUNC or s->class == PROC or \
1019657Slinton     s->class == MODULE or s->class == PROG \
1029657Slinton )
1039657Slinton 
10411865Slinton #define nosource(f) (not (f)->symvalue.funcv.src)
105*14441Slinton #define isinline(f) ((f)->symvalue.funcv.inline)
10611865Slinton 
1079657Slinton #include "tree.h"
1089657Slinton 
1099657Slinton /*
1109657Slinton  * Some macros to make finding a symbol with certain attributes.
1119657Slinton  */
1129657Slinton 
1139657Slinton #define find(s, withname) \
1149657Slinton { \
1159657Slinton     s = lookup(withname); \
1169657Slinton     while (s != nil and not (s->name == (withname) and
1179657Slinton 
1189657Slinton #define where /* qualification */
1199657Slinton 
1209657Slinton #define endfind(s) )) { \
1219657Slinton 	s = s->next_sym; \
1229657Slinton     } \
1239657Slinton }
1249657Slinton 
1259657Slinton #endif
1269657Slinton 
1279657Slinton /*
1289657Slinton  * Symbol table structure currently does not support deletions.
1299657Slinton  */
1309657Slinton 
1319657Slinton #define HASHTABLESIZE 2003
1329657Slinton 
1339657Slinton private Symbol hashtab[HASHTABLESIZE];
1349657Slinton 
1359657Slinton #define hash(name) ((((unsigned) name) >> 2) mod HASHTABLESIZE)
1369657Slinton 
1379657Slinton /*
1389657Slinton  * Allocate a new symbol.
1399657Slinton  */
1409657Slinton 
14111171Slinton #define SYMBLOCKSIZE 100
1429657Slinton 
1439657Slinton typedef struct Sympool {
1449657Slinton     struct Symbol sym[SYMBLOCKSIZE];
1459657Slinton     struct Sympool *prevpool;
1469657Slinton } *Sympool;
1479657Slinton 
1489657Slinton private Sympool sympool = nil;
1499657Slinton private Integer nleft = 0;
1509657Slinton 
1519657Slinton public Symbol symbol_alloc()
1529657Slinton {
1539657Slinton     register Sympool newpool;
1549657Slinton 
1559657Slinton     if (nleft <= 0) {
1569657Slinton 	newpool = new(Sympool);
15711171Slinton 	bzero(newpool, sizeof(newpool));
1589657Slinton 	newpool->prevpool = sympool;
1599657Slinton 	sympool = newpool;
1609657Slinton 	nleft = SYMBLOCKSIZE;
1619657Slinton     }
1629657Slinton     --nleft;
1639657Slinton     return &(sympool->sym[nleft]);
1649657Slinton }
1659657Slinton 
16612547Scsvaf 
16712547Scsvaf public symbol_dump(func)
16812547Scsvaf Symbol func;
16912547Scsvaf {
17012547Scsvaf   register Symbol s;
17112547Scsvaf   register Integer i;
17212547Scsvaf 
17312547Scsvaf 	printf(" symbols in %s \n",symname(func));
17412547Scsvaf 	for(i=0; i< HASHTABLESIZE; i++)
17512547Scsvaf 	   for(s=hashtab[i]; s != nil; s=s->next_sym)  {
17612547Scsvaf 		if (s->block == func) psym(s);
17712547Scsvaf 		}
17812547Scsvaf }
17912547Scsvaf 
1809657Slinton /*
1819657Slinton  * Free all the symbols currently allocated.
1829657Slinton  */
1839657Slinton public symbol_free()
1849657Slinton {
1859657Slinton     Sympool s, t;
1869657Slinton     register Integer i;
1879657Slinton 
1889657Slinton     s = sympool;
1899657Slinton     while (s != nil) {
1909657Slinton 	t = s->prevpool;
1919657Slinton 	dispose(s);
1929657Slinton 	s = t;
1939657Slinton     }
1949657Slinton     for (i = 0; i < HASHTABLESIZE; i++) {
1959657Slinton 	hashtab[i] = nil;
1969657Slinton     }
1979657Slinton     sympool = nil;
1989657Slinton     nleft = 0;
1999657Slinton }
2009657Slinton 
2019657Slinton /*
2029657Slinton  * Create a new symbol with the given attributes.
2039657Slinton  */
2049657Slinton 
2059657Slinton public Symbol newSymbol(name, blevel, class, type, chain)
2069657Slinton Name name;
2079657Slinton Integer blevel;
2089657Slinton Symclass class;
2099657Slinton Symbol type;
2109657Slinton Symbol chain;
2119657Slinton {
2129657Slinton     register Symbol s;
2139657Slinton 
2149657Slinton     s = symbol_alloc();
2159657Slinton     s->name = name;
2169657Slinton     s->level = blevel;
2179657Slinton     s->class = class;
2189657Slinton     s->type = type;
2199657Slinton     s->chain = chain;
2209657Slinton     return s;
2219657Slinton }
2229657Slinton 
2239657Slinton /*
2249657Slinton  * Insert a symbol into the hash table.
2259657Slinton  */
2269657Slinton 
2279657Slinton public Symbol insert(name)
2289657Slinton Name name;
2299657Slinton {
2309657Slinton     register Symbol s;
2319657Slinton     register unsigned int h;
2329657Slinton 
2339657Slinton     h = hash(name);
2349657Slinton     s = symbol_alloc();
2359657Slinton     s->name = name;
2369657Slinton     s->next_sym = hashtab[h];
2379657Slinton     hashtab[h] = s;
2389657Slinton     return s;
2399657Slinton }
2409657Slinton 
2419657Slinton /*
2429657Slinton  * Symbol lookup.
2439657Slinton  */
2449657Slinton 
2459657Slinton public Symbol lookup(name)
2469657Slinton Name name;
2479657Slinton {
2489657Slinton     register Symbol s;
2499657Slinton     register unsigned int h;
2509657Slinton 
2519657Slinton     h = hash(name);
2529657Slinton     s = hashtab[h];
2539657Slinton     while (s != nil and s->name != name) {
2549657Slinton 	s = s->next_sym;
2559657Slinton     }
2569657Slinton     return s;
2579657Slinton }
2589657Slinton 
2599657Slinton /*
2609657Slinton  * Dump out all the variables associated with the given
2619657Slinton  * procedure, function, or program at the given recursive level.
2629657Slinton  *
2639657Slinton  * This is quite inefficient.  We traverse the entire symbol table
2649657Slinton  * each time we're called.  The assumption is that this routine
2659657Slinton  * won't be called frequently enough to merit improved performance.
2669657Slinton  */
2679657Slinton 
2689657Slinton public dumpvars(f, frame)
2699657Slinton Symbol f;
2709657Slinton Frame frame;
2719657Slinton {
2729657Slinton     register Integer i;
2739657Slinton     register Symbol s;
2749657Slinton 
2759657Slinton     for (i = 0; i < HASHTABLESIZE; i++) {
2769657Slinton 	for (s = hashtab[i]; s != nil; s = s->next_sym) {
2779657Slinton 	    if (container(s) == f) {
2789657Slinton 		if (should_print(s)) {
2799657Slinton 		    printv(s, frame);
2809657Slinton 		    putchar('\n');
2819657Slinton 		} else if (s->class == MODULE) {
2829657Slinton 		    dumpvars(s, frame);
2839657Slinton 		}
2849657Slinton 	    }
2859657Slinton 	}
2869657Slinton     }
2879657Slinton }
2889657Slinton 
2899657Slinton /*
2909657Slinton  * Create a builtin type.
2919657Slinton  * Builtin types are circular in that btype->type->type = btype.
2929657Slinton  */
2939657Slinton 
2949657Slinton public Symbol maketype(name, lower, upper)
2959657Slinton String name;
2969657Slinton long lower;
2979657Slinton long upper;
2989657Slinton {
2999657Slinton     register Symbol s;
3009657Slinton 
3019657Slinton     s = newSymbol(identname(name, true), 0, TYPE, nil, nil);
3029657Slinton     s->language = findlanguage(".c");
3039657Slinton     s->type = newSymbol(nil, 0, RANGE, s, nil);
3049657Slinton     s->type->symvalue.rangev.lower = lower;
3059657Slinton     s->type->symvalue.rangev.upper = upper;
3069657Slinton     return s;
3079657Slinton }
3089657Slinton 
3099657Slinton /*
3109657Slinton  * These functions are now compiled inline.
3119657Slinton  *
3129657Slinton  * public String symname(s)
3139657Slinton Symbol s;
3149657Slinton {
3159657Slinton     checkref(s);
3169657Slinton     return ident(s->name);
3179657Slinton }
3189657Slinton 
3199657Slinton  *
3209657Slinton  * public Address codeloc(f)
3219657Slinton Symbol f;
3229657Slinton {
3239657Slinton     checkref(f);
3249657Slinton     if (not isblock(f)) {
3259657Slinton 	panic("codeloc: \"%s\" is not a block", ident(f->name));
3269657Slinton     }
3279657Slinton     return f->symvalue.funcv.beginaddr;
3289657Slinton }
3299657Slinton  *
3309657Slinton  */
3319657Slinton 
3329657Slinton /*
3339657Slinton  * Reduce type to avoid worrying about type names.
3349657Slinton  */
3359657Slinton 
3369657Slinton public Symbol rtype(type)
3379657Slinton Symbol type;
3389657Slinton {
3399657Slinton     register Symbol t;
3409657Slinton 
3419657Slinton     t = type;
3429657Slinton     if (t != nil) {
34312547Scsvaf 	if (t->class == VAR or t->class == FIELD or t->class == REF ) {
3449657Slinton 	    t = t->type;
3459657Slinton 	}
3469657Slinton 	while (t->class == TYPE or t->class == TAG) {
3479657Slinton 	    t = t->type;
3489657Slinton 	}
3499657Slinton     }
3509657Slinton     return t;
3519657Slinton }
3529657Slinton 
3539657Slinton public Integer level(s)
3549657Slinton Symbol s;
3559657Slinton {
3569657Slinton     checkref(s);
3579657Slinton     return s->level;
3589657Slinton }
3599657Slinton 
3609657Slinton public Symbol container(s)
3619657Slinton Symbol s;
3629657Slinton {
3639657Slinton     checkref(s);
3649657Slinton     return s->block;
3659657Slinton }
3669657Slinton 
3679657Slinton /*
3689657Slinton  * Return the object address of the given symbol.
3699657Slinton  *
3709657Slinton  * There are the following possibilities:
3719657Slinton  *
3729657Slinton  *	globals		- just take offset
3739657Slinton  *	locals		- take offset from locals base
3749657Slinton  *	arguments	- take offset from argument base
3759657Slinton  *	register	- offset is register number
3769657Slinton  */
3779657Slinton 
3789657Slinton #define isglobal(s)		(s->level == 1 or s->level == 2)
3799657Slinton #define islocaloff(s)		(s->level >= 3 and s->symvalue.offset < 0)
3809657Slinton #define isparamoff(s)		(s->level >= 3 and s->symvalue.offset >= 0)
3819657Slinton #define isreg(s)		(s->level < 0)
3829657Slinton 
3839657Slinton public Address address(s, frame)
3849657Slinton Symbol s;
3859657Slinton Frame frame;
3869657Slinton {
3879657Slinton     register Frame frp;
3889657Slinton     register Address addr;
3899657Slinton     register Symbol cur;
3909657Slinton 
3919657Slinton     checkref(s);
3929657Slinton     if (not isactive(s->block)) {
3939657Slinton 	error("\"%s\" is not currently defined", symname(s));
3949657Slinton     } else if (isglobal(s)) {
3959657Slinton 	addr = s->symvalue.offset;
3969657Slinton     } else {
3979657Slinton 	frp = frame;
3989657Slinton 	if (frp == nil) {
3999657Slinton 	    cur = s->block;
4009657Slinton 	    while (cur != nil and cur->class == MODULE) {
4019657Slinton 		cur = cur->block;
4029657Slinton 	    }
4039657Slinton 	    if (cur == nil) {
4049657Slinton 		cur = whatblock(pc);
4059657Slinton 	    }
4069657Slinton 	    frp = findframe(cur);
4079657Slinton 	    if (frp == nil) {
4089657Slinton 		panic("unexpected nil frame for \"%s\"", symname(s));
4099657Slinton 	    }
4109657Slinton 	}
4119657Slinton 	if (islocaloff(s)) {
4129657Slinton 	    addr = locals_base(frp) + s->symvalue.offset;
4139657Slinton 	} else if (isparamoff(s)) {
4149657Slinton 	    addr = args_base(frp) + s->symvalue.offset;
4159657Slinton 	} else if (isreg(s)) {
4169657Slinton 	    addr = savereg(s->symvalue.offset, frp);
4179657Slinton 	} else {
4189657Slinton 	    panic("address: bad symbol \"%s\"", symname(s));
4199657Slinton 	}
4209657Slinton     }
4219657Slinton     return addr;
4229657Slinton }
4239657Slinton 
4249657Slinton /*
4259657Slinton  * Define a symbol used to access register values.
4269657Slinton  */
4279657Slinton 
4289657Slinton public defregname(n, r)
4299657Slinton Name n;
4309657Slinton Integer r;
4319657Slinton {
4329657Slinton     register Symbol s, t;
4339657Slinton 
4349657Slinton     s = insert(n);
4359657Slinton     t = newSymbol(nil, 0, PTR, t_int, nil);
4369657Slinton     t->language = findlanguage(".s");
4379657Slinton     s->language = t->language;
4389657Slinton     s->class = VAR;
4399657Slinton     s->level = -3;
4409657Slinton     s->type = t;
4419657Slinton     s->block = program;
4429657Slinton     s->symvalue.offset = r;
4439657Slinton }
4449657Slinton 
4459657Slinton /*
4469657Slinton  * Resolve an "abstract" type reference.
4479657Slinton  *
4489657Slinton  * It is possible in C to define a pointer to a type, but never define
4499657Slinton  * the type in a particular source file.  Here we try to resolve
4509657Slinton  * the type definition.  This is problematic, it is possible to
4519657Slinton  * have multiple, different definitions for the same name type.
4529657Slinton  */
4539657Slinton 
4549657Slinton public findtype(s)
4559657Slinton Symbol s;
4569657Slinton {
4579657Slinton     register Symbol t, u, prev;
4589657Slinton 
4599657Slinton     u = s;
4609657Slinton     prev = nil;
4619657Slinton     while (u != nil and u->class != BADUSE) {
4629657Slinton 	if (u->name != nil) {
4639657Slinton 	    prev = u;
4649657Slinton 	}
4659657Slinton 	u = u->type;
4669657Slinton     }
4679657Slinton     if (prev == nil) {
4689657Slinton 	error("couldn't find link to type reference");
4699657Slinton     }
4709657Slinton     find(t, prev->name) where
4719657Slinton 	t->type != nil and t->class == prev->class and
4729657Slinton 	t->type->class != BADUSE and t->block->class == MODULE
4739657Slinton     endfind(t);
4749657Slinton     if (t == nil) {
4759657Slinton 	error("couldn't resolve reference");
4769657Slinton     } else {
4779657Slinton 	prev->type = t->type;
4789657Slinton     }
4799657Slinton }
4809657Slinton 
4819657Slinton /*
4829657Slinton  * Find the size in bytes of the given type.
4839657Slinton  *
4849657Slinton  * This is probably the WRONG thing to do.  The size should be kept
4859657Slinton  * as an attribute in the symbol information as is done for structures
4869657Slinton  * and fields.  I haven't gotten around to cleaning this up yet.
4879657Slinton  */
4889657Slinton 
48912547Scsvaf #define MAXUCHAR 255
49012547Scsvaf #define MAXUSHORT 65535L
4919657Slinton #define MINCHAR -128
4929657Slinton #define MAXCHAR 127
4939657Slinton #define MINSHORT -32768
4949657Slinton #define MAXSHORT 32767
4959657Slinton 
4969657Slinton public Integer size(sym)
4979657Slinton Symbol sym;
4989657Slinton {
4999657Slinton     register Symbol s, t;
5009657Slinton     register int nel, elsize;
5019657Slinton     long lower, upper;
5029657Slinton     int r;
5039657Slinton 
5049657Slinton     t = sym;
5059657Slinton     checkref(t);
5069657Slinton     switch (t->class) {
5079657Slinton 	case RANGE:
5089657Slinton 	    lower = t->symvalue.rangev.lower;
5099657Slinton 	    upper = t->symvalue.rangev.upper;
5109657Slinton 	    if (upper == 0 and lower > 0) {		/* real */
5119657Slinton 		r = lower;
51212045Slinton 	    } else if (
51312547Scsvaf   		(lower >= MINCHAR and upper <= MAXCHAR) or
51412547Scsvaf   		(lower >= 0 and upper <= MAXUCHAR)
51512547Scsvaf   	      ) {
5169657Slinton 		r = sizeof(char);
51712547Scsvaf   	    } else if (
51812547Scsvaf   		(lower >= MINSHORT and upper <= MAXSHORT) or
51912547Scsvaf   		(lower >= 0 and upper <= MAXUSHORT)
52012547Scsvaf   	      ) {
5219657Slinton 		r = sizeof(short);
5229657Slinton 	    } else {
5239657Slinton 		r = sizeof(long);
5249657Slinton 	    }
5259657Slinton 	    break;
5269657Slinton 
5279657Slinton 	case ARRAY:
5289657Slinton 	    elsize = size(t->type);
5299657Slinton 	    nel = 1;
5309657Slinton 	    for (t = t->chain; t != nil; t = t->chain) {
53112609Slinton 		if (t->symvalue.rangev.lowertype == R_ARG or
53212609Slinton 		  t->symvalue.rangev.lowertype == R_TEMP)  {
53312609Slinton 		    if (not getbound(t, t->symvalue.rangev.lower,
53412609Slinton 		      t->symvalue.rangev.lowertype, &lower)) {
53512609Slinton 			error("dynamic bounds not currently available");
53612609Slinton 		    }
53712609Slinton 		} else {
53812609Slinton 		    lower = t->symvalue.rangev.lower;
53912547Scsvaf 		}
54012609Slinton 		if (t->symvalue.rangev.uppertype == R_ARG or
54112609Slinton 		  t->symvalue.rangev.uppertype == R_TEMP) {
54212609Slinton 		    if (not getbound(t, t->symvalue.rangev.upper,
54312609Slinton 		      t->symvalue.rangev.uppertype, &upper)) {
54412609Slinton 			error("dynamic bounds nor currently available");
54512609Slinton 		    }
54612609Slinton 		} else {
54712609Slinton 		    upper = t->symvalue.rangev.upper;
54812547Scsvaf 		}
5499657Slinton 		nel *= (upper-lower+1);
5509657Slinton 	    }
5519657Slinton 	    r = nel*elsize;
5529657Slinton 	    break;
5539657Slinton 
55412547Scsvaf 	case REF:
5559657Slinton 	case VAR:
5569657Slinton 	case FVAR:
5579657Slinton 	    r = size(t->type);
55812127Slinton 	    /*
55912127Slinton 	     *
56012045Slinton 	    if (r < sizeof(Word) and isparam(t)) {
5619657Slinton 		r = sizeof(Word);
5629657Slinton 	    }
56312547Scsvaf 	    */
5649657Slinton 	    break;
5659657Slinton 
5669657Slinton 	case CONST:
5679657Slinton 	    r = size(t->type);
5689657Slinton 	    break;
5699657Slinton 
5709657Slinton 	case TYPE:
5719657Slinton 	    if (t->type->class == PTR and t->type->type->class == BADUSE) {
5729657Slinton 		findtype(t);
5739657Slinton 	    }
5749657Slinton 	    r = size(t->type);
5759657Slinton 	    break;
5769657Slinton 
5779657Slinton 	case TAG:
5789657Slinton 	    r = size(t->type);
5799657Slinton 	    break;
5809657Slinton 
5819657Slinton 	case FIELD:
5829657Slinton 	    r = (t->symvalue.field.length + 7) div 8;
5839657Slinton 	    break;
5849657Slinton 
5859657Slinton 	case RECORD:
5869657Slinton 	case VARNT:
5879657Slinton 	    r = t->symvalue.offset;
5889657Slinton 	    if (r == 0 and t->chain != nil) {
5899657Slinton 		panic("missing size information for record");
5909657Slinton 	    }
5919657Slinton 	    break;
5929657Slinton 
5939657Slinton 	case PTR:
5949657Slinton 	case FILET:
5959657Slinton 	    r = sizeof(Word);
5969657Slinton 	    break;
5979657Slinton 
5989657Slinton 	case SCAL:
59912609Slinton 	    r = sizeof(Word);
60012609Slinton 	    /*
60112609Slinton 	     *
6029657Slinton 	    if (t->symvalue.iconval > 255) {
6039657Slinton 		r = sizeof(short);
6049657Slinton 	    } else {
6059657Slinton 		r = sizeof(char);
6069657Slinton 	    }
60712609Slinton 	     *
60812609Slinton 	     */
6099657Slinton 	    break;
6109657Slinton 
6119657Slinton 	case FPROC:
6129657Slinton 	case FFUNC:
6139657Slinton 	    r = sizeof(Word);
6149657Slinton 	    break;
6159657Slinton 
6169657Slinton 	case PROC:
6179657Slinton 	case FUNC:
6189657Slinton 	case MODULE:
6199657Slinton 	case PROG:
6209657Slinton 	    r = sizeof(Symbol);
6219657Slinton 	    break;
6229657Slinton 
6239657Slinton 	default:
6249657Slinton 	    if (ord(t->class) > ord(TYPEREF)) {
6259657Slinton 		panic("size: bad class (%d)", ord(t->class));
6269657Slinton 	    } else {
6279657Slinton 		error("improper operation on a %s", classname(t));
6289657Slinton 	    }
6299657Slinton 	    /* NOTREACHED */
6309657Slinton     }
6319657Slinton     return r;
6329657Slinton }
6339657Slinton 
6349657Slinton /*
6359657Slinton  * Test if a symbol is a parameter.  This is true if there
6369657Slinton  * is a cycle from s->block to s via chain pointers.
6379657Slinton  */
6389657Slinton 
6399657Slinton public Boolean isparam(s)
6409657Slinton Symbol s;
6419657Slinton {
6429657Slinton     register Symbol t;
6439657Slinton 
6449657Slinton     t = s->block;
6459657Slinton     while (t != nil and t != s) {
6469657Slinton 	t = t->chain;
6479657Slinton     }
6489657Slinton     return (Boolean) (t != nil);
6499657Slinton }
6509657Slinton 
6519657Slinton /*
6529657Slinton  * Test if a symbol is a var parameter, i.e. has class REF.
6539657Slinton  */
6549657Slinton 
6559657Slinton public Boolean isvarparam(s)
6569657Slinton Symbol s;
6579657Slinton {
6589657Slinton     return (Boolean) (s->class == REF);
6599657Slinton }
6609657Slinton 
6619657Slinton /*
6629657Slinton  * Test if a symbol is a variable (actually any addressible quantity
6639657Slinton  * with do).
6649657Slinton  */
6659657Slinton 
6669657Slinton public Boolean isvariable(s)
6679657Slinton register Symbol s;
6689657Slinton {
6699657Slinton     return (Boolean) (s->class == VAR or s->class == FVAR or s->class == REF);
6709657Slinton }
6719657Slinton 
6729657Slinton /*
6739657Slinton  * Test if a symbol is a block, e.g. function, procedure, or the
6749657Slinton  * main program.
6759657Slinton  *
6769657Slinton  * This function is now expanded inline for efficiency.
6779657Slinton  *
6789657Slinton  * public Boolean isblock(s)
6799657Slinton register Symbol s;
6809657Slinton {
6819657Slinton     return (Boolean) (
6829657Slinton 	s->class == FUNC or s->class == PROC or
6839657Slinton 	s->class == MODULE or s->class == PROG
6849657Slinton     );
6859657Slinton }
6869657Slinton  *
6879657Slinton  */
6889657Slinton 
6899657Slinton /*
6909657Slinton  * Test if a symbol is a module.
6919657Slinton  */
6929657Slinton 
6939657Slinton public Boolean ismodule(s)
6949657Slinton register Symbol s;
6959657Slinton {
6969657Slinton     return (Boolean) (s->class == MODULE);
6979657Slinton }
6989657Slinton 
6999657Slinton /*
7009657Slinton  * Test if a symbol is builtin, that is, a predefined type or
7019657Slinton  * reserved word.
7029657Slinton  */
7039657Slinton 
7049657Slinton public Boolean isbuiltin(s)
7059657Slinton register Symbol s;
7069657Slinton {
7079657Slinton     return (Boolean) (s->level == 0 and s->class != PROG and s->class != VAR);
7089657Slinton }
7099657Slinton 
7109657Slinton /*
7119657Slinton  * Test if two types match.
7129657Slinton  * Equivalent names implies a match in any language.
7139657Slinton  *
7149657Slinton  * Special symbols must be handled with care.
7159657Slinton  */
7169657Slinton 
7179657Slinton public Boolean compatible(t1, t2)
7189657Slinton register Symbol t1, t2;
7199657Slinton {
7209657Slinton     Boolean b;
7219657Slinton 
7229657Slinton     if (t1 == t2) {
7239657Slinton 	b = true;
7249657Slinton     } else if (t1 == nil or t2 == nil) {
7259657Slinton 	b = false;
7269657Slinton     } else if (t1 == procsym) {
7279657Slinton 	b = isblock(t2);
7289657Slinton     } else if (t2 == procsym) {
7299657Slinton 	b = isblock(t1);
7309657Slinton     } else if (t1->language == nil) {
7319657Slinton 	b = (Boolean) (t2->language == nil or
7329657Slinton 	    (*language_op(t2->language, L_TYPEMATCH))(t1, t2));
73312547Scsvaf     } else if (t2->language == nil) {
73412547Scsvaf 	b = (Boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2);
73512547Scsvaf     } else if ( isbuiltin(t1) or isbuiltin(t1->type) ) {
73612547Scsvaf 	b = (Boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2);
7379657Slinton     } else {
7389657Slinton 	b = (Boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2);
7399657Slinton     }
7409657Slinton     return b;
7419657Slinton }
7429657Slinton 
7439657Slinton /*
7449657Slinton  * Check for a type of the given name.
7459657Slinton  */
7469657Slinton 
7479657Slinton public Boolean istypename(type, name)
7489657Slinton Symbol type;
7499657Slinton String name;
7509657Slinton {
7519657Slinton     Symbol t;
7529657Slinton     Boolean b;
7539657Slinton 
7549657Slinton     t = type;
7559657Slinton     checkref(t);
7569657Slinton     b = (Boolean) (
7579657Slinton 	t->class == TYPE and t->name == identname(name, true)
7589657Slinton     );
7599657Slinton     return b;
7609657Slinton }
7619657Slinton 
7629657Slinton /*
7639657Slinton  * Test if the name of a symbol is uniquely defined or not.
7649657Slinton  */
7659657Slinton 
7669657Slinton public Boolean isambiguous(s)
7679657Slinton register Symbol s;
7689657Slinton {
7699657Slinton     register Symbol t;
7709657Slinton 
7719657Slinton     find(t, s->name) where t != s endfind(t);
7729657Slinton     return (Boolean) (t != nil);
7739657Slinton }
7749657Slinton 
7759657Slinton typedef char *Arglist;
7769657Slinton 
7779657Slinton #define nextarg(type)  ((type *) (ap += sizeof(type)))[-1]
7789657Slinton 
7799657Slinton private Symbol mkstring();
7809657Slinton private Symbol namenode();
7819657Slinton 
7829657Slinton /*
7839657Slinton  * Determine the type of a parse tree.
7849657Slinton  * Also make some symbol-dependent changes to the tree such as
7859657Slinton  * changing removing RVAL nodes for constant symbols.
7869657Slinton  */
7879657Slinton 
7889657Slinton public assigntypes(p)
7899657Slinton register Node p;
7909657Slinton {
7919657Slinton     register Node p1;
7929657Slinton     register Symbol s;
7939657Slinton 
7949657Slinton     switch (p->op) {
7959657Slinton 	case O_SYM:
7969657Slinton 	    p->nodetype = namenode(p);
7979657Slinton 	    break;
7989657Slinton 
7999657Slinton 	case O_LCON:
8009657Slinton 	    p->nodetype = t_int;
8019657Slinton 	    break;
8029657Slinton 
8039657Slinton 	case O_FCON:
8049657Slinton 	    p->nodetype = t_real;
8059657Slinton 	    break;
8069657Slinton 
8079657Slinton 	case O_SCON:
8089657Slinton 	    p->value.scon = strdup(p->value.scon);
8099657Slinton 	    s = mkstring(p->value.scon);
8109657Slinton 	    if (s == t_char) {
8119657Slinton 		p->op = O_LCON;
8129657Slinton 		p->value.lcon = p->value.scon[0];
8139657Slinton 	    }
8149657Slinton 	    p->nodetype = s;
8159657Slinton 	    break;
8169657Slinton 
8179657Slinton 	case O_INDIR:
8189657Slinton 	    p1 = p->value.arg[0];
8199657Slinton 	    chkclass(p1, PTR);
8209657Slinton 	    p->nodetype = rtype(p1->nodetype)->type;
8219657Slinton 	    break;
8229657Slinton 
8239657Slinton 	case O_DOT:
8249657Slinton 	    p->nodetype = p->value.arg[1]->value.sym;
8259657Slinton 	    break;
8269657Slinton 
8279657Slinton 	case O_RVAL:
8289657Slinton 	    p1 = p->value.arg[0];
8299657Slinton 	    p->nodetype = p1->nodetype;
8309657Slinton 	    if (p1->op == O_SYM) {
8319657Slinton 		if (p1->nodetype->class == FUNC) {
8329657Slinton 		    p->op = O_CALL;
8339657Slinton 		    p->value.arg[1] = nil;
8349657Slinton 		} else if (p1->value.sym->class == CONST) {
8359657Slinton 		    if (compatible(p1->value.sym->type, t_real)) {
8369657Slinton 			p->op = O_FCON;
8379657Slinton 			p->value.fcon = p1->value.sym->symvalue.fconval;
8389657Slinton 			p->nodetype = t_real;
8399657Slinton 			dispose(p1);
8409657Slinton 		    } else {
8419657Slinton 			p->op = O_LCON;
8429657Slinton 			p->value.lcon = p1->value.sym->symvalue.iconval;
8439657Slinton 			p->nodetype = p1->value.sym->type;
8449657Slinton 			dispose(p1);
8459657Slinton 		    }
8469657Slinton 		} else if (isreg(p1->value.sym)) {
8479657Slinton 		    p->op = O_SYM;
8489657Slinton 		    p->value.sym = p1->value.sym;
8499657Slinton 		    dispose(p1);
8509657Slinton 		}
8519657Slinton 	    } else if (p1->op == O_INDIR and p1->value.arg[0]->op == O_SYM) {
8529657Slinton 		s = p1->value.arg[0]->value.sym;
8539657Slinton 		if (isreg(s)) {
8549657Slinton 		    p1->op = O_SYM;
8559657Slinton 		    dispose(p1->value.arg[0]);
8569657Slinton 		    p1->value.sym = s;
8579657Slinton 		    p1->nodetype = s;
8589657Slinton 		}
8599657Slinton 	    }
8609657Slinton 	    break;
8619657Slinton 
8629657Slinton 	/*
8639657Slinton 	 * Perform a cast if the call is of the form "type(expr)".
8649657Slinton 	 */
8659657Slinton 	case O_CALL:
8669657Slinton 	    p1 = p->value.arg[0];
86711171Slinton 	    p->nodetype = rtype(p1->nodetype)->type;
8689657Slinton 	    break;
8699657Slinton 
87011171Slinton 	case O_TYPERENAME:
87111171Slinton 	    p->nodetype = p->value.arg[1]->nodetype;
87211171Slinton 	    break;
87311171Slinton 
8749657Slinton 	case O_ITOF:
8759657Slinton 	    p->nodetype = t_real;
8769657Slinton 	    break;
8779657Slinton 
8789657Slinton 	case O_NEG:
8799657Slinton 	    s = p->value.arg[0]->nodetype;
8809657Slinton 	    if (not compatible(s, t_int)) {
8819657Slinton 		if (not compatible(s, t_real)) {
8829657Slinton 		    beginerrmsg();
8839657Slinton 		    prtree(stderr, p->value.arg[0]);
8849657Slinton 		    fprintf(stderr, "is improper type");
8859657Slinton 		    enderrmsg();
8869657Slinton 		} else {
8879657Slinton 		    p->op = O_NEGF;
8889657Slinton 		}
8899657Slinton 	    }
8909657Slinton 	    p->nodetype = s;
8919657Slinton 	    break;
8929657Slinton 
8939657Slinton 	case O_ADD:
8949657Slinton 	case O_SUB:
8959657Slinton 	case O_MUL:
8969657Slinton 	case O_LT:
8979657Slinton 	case O_LE:
8989657Slinton 	case O_GT:
8999657Slinton 	case O_GE:
9009657Slinton 	case O_EQ:
9019657Slinton 	case O_NE:
9029657Slinton 	{
9039657Slinton 	    Boolean t1real, t2real;
9049657Slinton 	    Symbol t1, t2;
9059657Slinton 
9069657Slinton 	    t1 = rtype(p->value.arg[0]->nodetype);
9079657Slinton 	    t2 = rtype(p->value.arg[1]->nodetype);
9089657Slinton 	    t1real = compatible(t1, t_real);
9099657Slinton 	    t2real = compatible(t2, t_real);
9109657Slinton 	    if (t1real or t2real) {
9119657Slinton 		p->op = (Operator) (ord(p->op) + 1);
9129657Slinton 		if (not t1real) {
9139657Slinton 		    p->value.arg[0] = build(O_ITOF, p->value.arg[0]);
9149657Slinton 		} else if (not t2real) {
9159657Slinton 		    p->value.arg[1] = build(O_ITOF, p->value.arg[1]);
9169657Slinton 		}
9179657Slinton 	    } else {
9189657Slinton 		if (t1real) {
9199657Slinton 		    convert(&(p->value.arg[0]), t_int, O_NOP);
9209657Slinton 		}
9219657Slinton 		if (t2real) {
9229657Slinton 		    convert(&(p->value.arg[1]), t_int, O_NOP);
9239657Slinton 		}
9249657Slinton 	    }
9259657Slinton 	    if (ord(p->op) >= ord(O_LT)) {
9269657Slinton 		p->nodetype = t_boolean;
9279657Slinton 	    } else {
9289657Slinton 		if (t1real or t2real) {
9299657Slinton 		    p->nodetype = t_real;
9309657Slinton 		} else {
9319657Slinton 		    p->nodetype = t_int;
9329657Slinton 		}
9339657Slinton 	    }
9349657Slinton 	    break;
9359657Slinton 	}
9369657Slinton 
9379657Slinton 	case O_DIVF:
9389657Slinton 	    convert(&(p->value.arg[0]), t_real, O_ITOF);
9399657Slinton 	    convert(&(p->value.arg[1]), t_real, O_ITOF);
9409657Slinton 	    p->nodetype = t_real;
9419657Slinton 	    break;
9429657Slinton 
9439657Slinton 	case O_DIV:
9449657Slinton 	case O_MOD:
9459657Slinton 	    convert(&(p->value.arg[0]), t_int, O_NOP);
9469657Slinton 	    convert(&(p->value.arg[1]), t_int, O_NOP);
9479657Slinton 	    p->nodetype = t_int;
9489657Slinton 	    break;
9499657Slinton 
9509657Slinton 	case O_AND:
9519657Slinton 	case O_OR:
9529657Slinton 	    chkboolean(p->value.arg[0]);
9539657Slinton 	    chkboolean(p->value.arg[1]);
9549657Slinton 	    p->nodetype = t_boolean;
9559657Slinton 	    break;
9569657Slinton 
9579657Slinton 	case O_QLINE:
9589657Slinton 	    p->nodetype = t_int;
9599657Slinton 	    break;
9609657Slinton 
9619657Slinton 	default:
9629657Slinton 	    p->nodetype = nil;
9639657Slinton 	    break;
9649657Slinton     }
9659657Slinton }
9669657Slinton 
9679657Slinton /*
9689657Slinton  * Create a node for a name.  The symbol for the name has already
9699657Slinton  * been chosen, either implicitly with "which" or explicitly from
9709657Slinton  * the dot routine.
9719657Slinton  */
9729657Slinton 
9739657Slinton private Symbol namenode(p)
9749657Slinton Node p;
9759657Slinton {
9769657Slinton     register Symbol r, s;
9779657Slinton     register Node np;
9789657Slinton 
9799657Slinton     s = p->value.sym;
9809657Slinton     if (s->class == REF) {
9819657Slinton 	np = new(Node);
9829657Slinton 	np->op = p->op;
9839657Slinton 	np->nodetype = s;
9849657Slinton 	np->value.sym = s;
9859657Slinton 	p->op = O_INDIR;
9869657Slinton 	p->value.arg[0] = np;
9879657Slinton     }
9889657Slinton /*
9899657Slinton  * Old way
9909657Slinton  *
9919657Slinton     if (s->class == CONST or s->class == VAR or s->class == FVAR) {
9929657Slinton 	r = s->type;
9939657Slinton     } else {
9949657Slinton 	r = s;
9959657Slinton     }
9969657Slinton  *
9979657Slinton  */
9989657Slinton     return s;
9999657Slinton }
10009657Slinton 
10019657Slinton /*
10029657Slinton  * Convert a tree to a type via a conversion operator;
10039657Slinton  * if this isn't possible generate an error.
10049657Slinton  *
10059657Slinton  * Note the tree is call by address, hence the #define below.
10069657Slinton  */
10079657Slinton 
10089657Slinton private convert(tp, typeto, op)
10099657Slinton Node *tp;
10109657Slinton Symbol typeto;
10119657Slinton Operator op;
10129657Slinton {
10139657Slinton #define tree    (*tp)
10149657Slinton 
10159657Slinton     Symbol s;
10169657Slinton 
10179657Slinton     s = rtype(tree->nodetype);
10189657Slinton     typeto = rtype(typeto);
10199657Slinton     if (compatible(typeto, t_real) and compatible(s, t_int)) {
10209657Slinton 	tree = build(op, tree);
10219657Slinton     } else if (not compatible(s, typeto)) {
10229657Slinton 	beginerrmsg();
10239657Slinton 	prtree(stderr, s);
10249657Slinton 	fprintf(stderr, " is improper type");
10259657Slinton 	enderrmsg();
10269657Slinton     } else if (op != O_NOP and s != typeto) {
10279657Slinton 	tree = build(op, tree);
10289657Slinton     }
10299657Slinton 
10309657Slinton #undef tree
10319657Slinton }
10329657Slinton 
10339657Slinton /*
10349657Slinton  * Construct a node for the dot operator.
10359657Slinton  *
10369657Slinton  * If the left operand is not a record, but rather a procedure
10379657Slinton  * or function, then we interpret the "." as referencing an
10389657Slinton  * "invisible" variable; i.e. a variable within a dynamically
10399657Slinton  * active block but not within the static scope of the current procedure.
10409657Slinton  */
10419657Slinton 
10429657Slinton public Node dot(record, fieldname)
10439657Slinton Node record;
10449657Slinton Name fieldname;
10459657Slinton {
10469657Slinton     register Node p;
10479657Slinton     register Symbol s, t;
10489657Slinton 
10499657Slinton     if (isblock(record->nodetype)) {
10509657Slinton 	find(s, fieldname) where
10519657Slinton 	    s->block == record->nodetype and
10529657Slinton 	    s->class != FIELD and s->class != TAG
10539657Slinton 	endfind(s);
10549657Slinton 	if (s == nil) {
10559657Slinton 	    beginerrmsg();
10569657Slinton 	    fprintf(stderr, "\"%s\" is not defined in ", ident(fieldname));
10579657Slinton 	    printname(stderr, record->nodetype);
10589657Slinton 	    enderrmsg();
10599657Slinton 	}
10609657Slinton 	p = new(Node);
10619657Slinton 	p->op = O_SYM;
10629657Slinton 	p->value.sym = s;
10639657Slinton 	p->nodetype = namenode(p);
10649657Slinton     } else {
10659657Slinton 	p = record;
10669657Slinton 	t = rtype(p->nodetype);
10679657Slinton 	if (t->class == PTR) {
10689657Slinton 	    s = findfield(fieldname, t->type);
10699657Slinton 	} else {
10709657Slinton 	    s = findfield(fieldname, t);
10719657Slinton 	}
10729657Slinton 	if (s == nil) {
10739657Slinton 	    beginerrmsg();
10749657Slinton 	    fprintf(stderr, "\"%s\" is not a field in ", ident(fieldname));
10759657Slinton 	    prtree(stderr, record);
10769657Slinton 	    enderrmsg();
10779657Slinton 	}
10789657Slinton 	if (t->class == PTR and not isreg(record->nodetype)) {
10799657Slinton 	    p = build(O_INDIR, record);
10809657Slinton 	}
10819657Slinton 	p = build(O_DOT, p, build(O_SYM, s));
10829657Slinton     }
10839657Slinton     return p;
10849657Slinton }
10859657Slinton 
10869657Slinton /*
10879657Slinton  * Return a tree corresponding to an array reference and do the
10889657Slinton  * error checking.
10899657Slinton  */
10909657Slinton 
10919657Slinton public Node subscript(a, slist)
10929657Slinton Node a, slist;
10939657Slinton {
109412547Scsvaf Symbol t;
10959657Slinton 
109612547Scsvaf    t = rtype(a->nodetype);
109712547Scsvaf    if(t->language == nil) {
109812547Scsvaf 	error("unknown language");
109912547Scsvaf    }
110012547Scsvaf    else {
110112547Scsvaf         return ( (Node)
110212547Scsvaf         (*language_op(t->language, L_BUILDAREF)) (a,slist)
110312547Scsvaf                );
110412547Scsvaf    }
11059657Slinton }
11069657Slinton 
11079657Slinton /*
11089657Slinton  * Evaluate a subscript index.
11099657Slinton  */
11109657Slinton 
11119657Slinton public int evalindex(s, i)
11129657Slinton Symbol s;
11139657Slinton long i;
11149657Slinton {
111512547Scsvaf Symbol t;
11169657Slinton 
111712547Scsvaf    t = rtype(s);
111812547Scsvaf    if(t->language == nil) {
111912547Scsvaf 	error("unknown language");
112012547Scsvaf    }
112112547Scsvaf    else {
112212547Scsvaf         return (
112312547Scsvaf              (*language_op(t->language, L_EVALAREF)) (s,i)
112412547Scsvaf                );
112512547Scsvaf    }
11269657Slinton }
11279657Slinton 
11289657Slinton /*
11299657Slinton  * Check to see if a tree is boolean-valued, if not it's an error.
11309657Slinton  */
11319657Slinton 
11329657Slinton public chkboolean(p)
11339657Slinton register Node p;
11349657Slinton {
11359657Slinton     if (p->nodetype != t_boolean) {
11369657Slinton 	beginerrmsg();
11379657Slinton 	fprintf(stderr, "found ");
11389657Slinton 	prtree(stderr, p);
11399657Slinton 	fprintf(stderr, ", expected boolean expression");
11409657Slinton 	enderrmsg();
11419657Slinton     }
11429657Slinton }
11439657Slinton 
11449657Slinton /*
11459657Slinton  * Check to make sure the given tree has a type of the given class.
11469657Slinton  */
11479657Slinton 
11489657Slinton private chkclass(p, class)
11499657Slinton Node p;
11509657Slinton Symclass class;
11519657Slinton {
11529657Slinton     struct Symbol tmpsym;
11539657Slinton 
11549657Slinton     tmpsym.class = class;
11559657Slinton     if (rtype(p->nodetype)->class != class) {
11569657Slinton 	beginerrmsg();
11579657Slinton 	fprintf(stderr, "\"");
11589657Slinton 	prtree(stderr, p);
11599657Slinton 	fprintf(stderr, "\" is not a %s", classname(&tmpsym));
11609657Slinton 	enderrmsg();
11619657Slinton     }
11629657Slinton }
11639657Slinton 
11649657Slinton /*
11659657Slinton  * Construct a node for the type of a string.  While we're at it,
11669657Slinton  * scan the string for '' that collapse to ', and chop off the ends.
11679657Slinton  */
11689657Slinton 
11699657Slinton private Symbol mkstring(str)
11709657Slinton String str;
11719657Slinton {
11729657Slinton     register char *p, *q;
11739657Slinton     register Symbol s;
11749657Slinton 
11759657Slinton     p = str;
11769657Slinton     q = str;
11779657Slinton     while (*p != '\0') {
11789657Slinton 	if (*p == '\\') {
11799657Slinton 	    ++p;
11809657Slinton 	}
11819657Slinton 	*q = *p;
11829657Slinton 	++p;
11839657Slinton 	++q;
11849657Slinton     }
11859657Slinton     *q = '\0';
11869657Slinton     s = newSymbol(nil, 0, ARRAY, t_char, nil);
11879657Slinton     s->language = findlanguage(".s");
11889657Slinton     s->chain = newSymbol(nil, 0, RANGE, t_int, nil);
11899657Slinton     s->chain->language = s->language;
11909657Slinton     s->chain->symvalue.rangev.lower = 1;
11919657Slinton     s->chain->symvalue.rangev.upper = p - str + 1;
11929657Slinton     return s;
11939657Slinton }
11949657Slinton 
11959657Slinton /*
11969657Slinton  * Free up the space allocated for a string type.
11979657Slinton  */
11989657Slinton 
11999657Slinton public unmkstring(s)
12009657Slinton Symbol s;
12019657Slinton {
12029657Slinton     dispose(s->chain);
12039657Slinton }
12049657Slinton 
12059657Slinton /*
12069657Slinton  * Figure out the "current" variable or function being referred to,
12079657Slinton  * this is either the active one or the most visible from the
12089657Slinton  * current scope.
12099657Slinton  */
12109657Slinton 
12119657Slinton public Symbol which(n)
12129657Slinton Name n;
12139657Slinton {
12149657Slinton     register Symbol s, p, t, f;
12159657Slinton 
12169657Slinton     find(s, n) where s->class != FIELD and s->class != TAG endfind(s);
12179657Slinton     if (s == nil) {
12189657Slinton 	s = lookup(n);
12199657Slinton     }
12209657Slinton     if (s == nil) {
12219657Slinton 	error("\"%s\" is not defined", ident(n));
12229657Slinton     } else if (s == program or isbuiltin(s)) {
12239657Slinton 	t = s;
12249657Slinton     } else {
12259657Slinton     /*
12269657Slinton      * Old way
12279657Slinton      *
12289657Slinton 	if (not isactive(program)) {
12299657Slinton 	    f = program;
12309657Slinton 	} else {
12319657Slinton 	    f = whatblock(pc);
12329657Slinton 	    if (f == nil) {
12339657Slinton 		panic("no block for addr 0x%x", pc);
12349657Slinton 	    }
12359657Slinton 	}
12369657Slinton      *
12379657Slinton      * Now start with curfunc.
12389657Slinton      */
12399657Slinton 	p = curfunc;
12409657Slinton 	do {
12419657Slinton 	    find(t, n) where
12429657Slinton 		t->block == p and t->class != FIELD and t->class != TAG
12439657Slinton 	    endfind(t);
12449657Slinton 	    p = p->block;
12459657Slinton 	} while (t == nil and p != nil);
12469657Slinton 	if (t == nil) {
12479657Slinton 	    t = s;
12489657Slinton 	}
12499657Slinton     }
12509657Slinton     return t;
12519657Slinton }
12529657Slinton 
12539657Slinton /*
12549657Slinton  * Find the symbol which is has the same name and scope as the
12559657Slinton  * given symbol but is of the given field.  Return nil if there is none.
12569657Slinton  */
12579657Slinton 
12589657Slinton public Symbol findfield(fieldname, record)
12599657Slinton Name fieldname;
12609657Slinton Symbol record;
12619657Slinton {
12629657Slinton     register Symbol t;
12639657Slinton 
12649657Slinton     t = rtype(record)->chain;
12659657Slinton     while (t != nil and t->name != fieldname) {
12669657Slinton 	t = t->chain;
12679657Slinton     }
12689657Slinton     return t;
12699657Slinton }
127012547Scsvaf 
127112547Scsvaf public Boolean getbound(s,off,type,valp)
127212547Scsvaf Symbol s;
127312547Scsvaf int off;
127412547Scsvaf Rangetype type;
127512547Scsvaf int *valp;
127612547Scsvaf {
127712547Scsvaf     Frame frp;
127812547Scsvaf     Address addr;
127912547Scsvaf     Symbol cur;
128012547Scsvaf 
128112547Scsvaf     if (not isactive(s->block)) {
128212547Scsvaf 	return(false);
128312547Scsvaf     }
128412547Scsvaf     cur = s->block;
128512547Scsvaf     while (cur != nil and cur->class == MODULE) {  /* WHY*/
128612547Scsvaf     		cur = cur->block;
128712547Scsvaf     }
128812547Scsvaf     if(cur == nil) {
128912547Scsvaf 		cur = whatblock(pc);
129012547Scsvaf     }
129112547Scsvaf     frp = findframe(cur);
129212547Scsvaf     if (frp == nil) {
129312547Scsvaf 	return(false);
129412547Scsvaf     }
129512547Scsvaf     if(type == R_TEMP) addr = locals_base(frp) + off;
129612547Scsvaf     else if (type == R_ARG) addr = args_base(frp) + off;
129712547Scsvaf     else return(false);
129812547Scsvaf     dread(valp,addr,sizeof(long));
129912547Scsvaf     return(true);
130012547Scsvaf }
1301