xref: /csrg-svn/old/dbx/symbols.c (revision 18235)
19657Slinton /* Copyright (c) 1982 Regents of the University of California */
29657Slinton 
3*18235Slinton static	char sccsid[] = "@(#)symbols.c	1.17 (Berkeley) 03/01/85";
49657Slinton 
5*18235Slinton static char rcsid[] = "$Header: symbols.c,v 1.6 84/12/26 10:42:31 linton Exp $";
6*18235Slinton 
79657Slinton /*
89657Slinton  * Symbol management.
99657Slinton  */
109657Slinton 
119657Slinton #include "defs.h"
129657Slinton #include "symbols.h"
139657Slinton #include "languages.h"
149657Slinton #include "printsym.h"
159657Slinton #include "tree.h"
169657Slinton #include "operators.h"
179657Slinton #include "eval.h"
189657Slinton #include "mappings.h"
199657Slinton #include "events.h"
209657Slinton #include "process.h"
219657Slinton #include "runtime.h"
229657Slinton #include "machine.h"
239657Slinton #include "names.h"
249657Slinton 
259657Slinton #ifndef public
269657Slinton typedef struct Symbol *Symbol;
279657Slinton 
289657Slinton #include "machine.h"
299657Slinton #include "names.h"
309657Slinton #include "languages.h"
31*18235Slinton #include "tree.h"
329657Slinton 
339657Slinton /*
349657Slinton  * Symbol classes
359657Slinton  */
369657Slinton 
379657Slinton typedef enum {
38*18235Slinton     BADUSE, CONST, TYPE, VAR, ARRAY, DYNARRAY, SUBARRAY, PTRFILE, RECORD, FIELD,
3912547Scsvaf     PROC, FUNC, FVAR, REF, PTR, FILET, SET, RANGE,
409657Slinton     LABEL, WITHPTR, SCAL, STR, PROG, IMPROPER, VARNT,
4116620Ssam     FPROC, FFUNC, MODULE, TAG, COMMON, EXTREF, TYPEREF
429657Slinton } Symclass;
439657Slinton 
4412547Scsvaf typedef enum { R_CONST, R_TEMP, R_ARG, R_ADJUST } Rangetype;
4512547Scsvaf 
469657Slinton struct Symbol {
479657Slinton     Name name;
489657Slinton     Language language;
499657Slinton     Symclass class : 8;
509657Slinton     Integer level : 8;
519657Slinton     Symbol type;
529657Slinton     Symbol chain;
539657Slinton     union {
54*18235Slinton 	Node constval;		/* value of constant symbol */
559657Slinton 	int offset;		/* variable address */
569657Slinton 	long iconval;		/* integer constant value */
579657Slinton 	double fconval;		/* floating constant value */
58*18235Slinton 	int ndims;		/* no. of dimensions for dynamic/sub-arrays */
599657Slinton 	struct {		/* field offset and size (both in bits) */
609657Slinton 	    int offset;
619657Slinton 	    int length;
629657Slinton 	} field;
6312547Scsvaf 	struct {		/* common offset and chain; used to relocate */
6412547Scsvaf 	    int offset;         /* vars in global BSS */
6512547Scsvaf 	    Symbol chain;
6612547Scsvaf 	} common;
679657Slinton 	struct {		/* range bounds */
6812547Scsvaf             Rangetype lowertype : 16;
6912547Scsvaf             Rangetype uppertype : 16;
709657Slinton 	    long lower;
719657Slinton 	    long upper;
729657Slinton 	} rangev;
7311865Slinton 	struct {
7411865Slinton 	    int offset : 16;	/* offset for of function value */
7516620Ssam 	    Boolean src : 1;	/* true if there is source line info */
7616620Ssam 	    Boolean inline : 1;	/* true if no separate act. rec. */
7716620Ssam 	    Boolean intern : 1; /* internal calling sequence */
7816620Ssam 	    int unused : 13;
7911865Slinton 	    Address beginaddr;	/* address of function code */
809657Slinton 	} funcv;
819657Slinton 	struct {		/* variant record info */
829657Slinton 	    int size;
839657Slinton 	    Symbol vtorec;
849657Slinton 	    Symbol vtag;
859657Slinton 	} varnt;
8616620Ssam 	String typeref;		/* type defined by "<module>:<type>" */
8716620Ssam 	Symbol extref;		/* indirect symbol for external reference */
889657Slinton     } symvalue;
899657Slinton     Symbol block;		/* symbol containing this symbol */
909657Slinton     Symbol next_sym;		/* hash chain */
919657Slinton };
929657Slinton 
939657Slinton /*
949657Slinton  * Basic types.
959657Slinton  */
969657Slinton 
979657Slinton Symbol t_boolean;
989657Slinton Symbol t_char;
999657Slinton Symbol t_int;
1009657Slinton Symbol t_real;
1019657Slinton Symbol t_nil;
102*18235Slinton Symbol t_addr;
1039657Slinton 
1049657Slinton Symbol program;
1059657Slinton Symbol curfunc;
1069657Slinton 
107*18235Slinton boolean showaggrs;
108*18235Slinton 
1099657Slinton #define symname(s) ident(s->name)
1109657Slinton #define codeloc(f) ((f)->symvalue.funcv.beginaddr)
1119657Slinton #define isblock(s) (Boolean) ( \
1129657Slinton     s->class == FUNC or s->class == PROC or \
1139657Slinton     s->class == MODULE or s->class == PROG \
1149657Slinton )
11516620Ssam #define isroutine(s) (Boolean) ( \
11616620Ssam     s->class == FUNC or s->class == PROC \
11716620Ssam )
1189657Slinton 
11911865Slinton #define nosource(f) (not (f)->symvalue.funcv.src)
12014441Slinton #define isinline(f) ((f)->symvalue.funcv.inline)
12111865Slinton 
1229657Slinton #include "tree.h"
1239657Slinton 
1249657Slinton /*
1259657Slinton  * Some macros to make finding a symbol with certain attributes.
1269657Slinton  */
1279657Slinton 
1289657Slinton #define find(s, withname) \
1299657Slinton { \
1309657Slinton     s = lookup(withname); \
1319657Slinton     while (s != nil and not (s->name == (withname) and
1329657Slinton 
1339657Slinton #define where /* qualification */
1349657Slinton 
1359657Slinton #define endfind(s) )) { \
1369657Slinton 	s = s->next_sym; \
1379657Slinton     } \
1389657Slinton }
1399657Slinton 
1409657Slinton #endif
1419657Slinton 
1429657Slinton /*
1439657Slinton  * Symbol table structure currently does not support deletions.
1449657Slinton  */
1459657Slinton 
1469657Slinton #define HASHTABLESIZE 2003
1479657Slinton 
1489657Slinton private Symbol hashtab[HASHTABLESIZE];
1499657Slinton 
1509657Slinton #define hash(name) ((((unsigned) name) >> 2) mod HASHTABLESIZE)
1519657Slinton 
1529657Slinton /*
1539657Slinton  * Allocate a new symbol.
1549657Slinton  */
1559657Slinton 
15611171Slinton #define SYMBLOCKSIZE 100
1579657Slinton 
1589657Slinton typedef struct Sympool {
1599657Slinton     struct Symbol sym[SYMBLOCKSIZE];
1609657Slinton     struct Sympool *prevpool;
1619657Slinton } *Sympool;
1629657Slinton 
1639657Slinton private Sympool sympool = nil;
1649657Slinton private Integer nleft = 0;
1659657Slinton 
1669657Slinton public Symbol symbol_alloc()
1679657Slinton {
1689657Slinton     register Sympool newpool;
1699657Slinton 
1709657Slinton     if (nleft <= 0) {
1719657Slinton 	newpool = new(Sympool);
17211171Slinton 	bzero(newpool, sizeof(newpool));
1739657Slinton 	newpool->prevpool = sympool;
1749657Slinton 	sympool = newpool;
1759657Slinton 	nleft = SYMBLOCKSIZE;
1769657Slinton     }
1779657Slinton     --nleft;
1789657Slinton     return &(sympool->sym[nleft]);
1799657Slinton }
1809657Slinton 
181*18235Slinton public symbol_dump (func)
18212547Scsvaf Symbol func;
18312547Scsvaf {
184*18235Slinton     register Symbol s;
185*18235Slinton     register integer i;
18612547Scsvaf 
187*18235Slinton     printf(" symbols in %s \n",symname(func));
188*18235Slinton     for (i = 0; i < HASHTABLESIZE; i++) {
189*18235Slinton 	for (s = hashtab[i]; s != nil; s = s->next_sym) {
190*18235Slinton 	    if (s->block == func) {
191*18235Slinton 		psym(s);
192*18235Slinton 	    }
193*18235Slinton 	}
194*18235Slinton     }
19512547Scsvaf }
19612547Scsvaf 
1979657Slinton /*
1989657Slinton  * Free all the symbols currently allocated.
1999657Slinton  */
200*18235Slinton 
2019657Slinton public symbol_free()
2029657Slinton {
2039657Slinton     Sympool s, t;
2049657Slinton     register Integer i;
2059657Slinton 
2069657Slinton     s = sympool;
2079657Slinton     while (s != nil) {
2089657Slinton 	t = s->prevpool;
2099657Slinton 	dispose(s);
2109657Slinton 	s = t;
2119657Slinton     }
2129657Slinton     for (i = 0; i < HASHTABLESIZE; i++) {
2139657Slinton 	hashtab[i] = nil;
2149657Slinton     }
2159657Slinton     sympool = nil;
2169657Slinton     nleft = 0;
2179657Slinton }
2189657Slinton 
2199657Slinton /*
2209657Slinton  * Create a new symbol with the given attributes.
2219657Slinton  */
2229657Slinton 
2239657Slinton public Symbol newSymbol(name, blevel, class, type, chain)
2249657Slinton Name name;
2259657Slinton Integer blevel;
2269657Slinton Symclass class;
2279657Slinton Symbol type;
2289657Slinton Symbol chain;
2299657Slinton {
2309657Slinton     register Symbol s;
2319657Slinton 
2329657Slinton     s = symbol_alloc();
2339657Slinton     s->name = name;
234*18235Slinton     s->language = primlang;
2359657Slinton     s->level = blevel;
2369657Slinton     s->class = class;
2379657Slinton     s->type = type;
2389657Slinton     s->chain = chain;
2399657Slinton     return s;
2409657Slinton }
2419657Slinton 
2429657Slinton /*
2439657Slinton  * Insert a symbol into the hash table.
2449657Slinton  */
2459657Slinton 
2469657Slinton public Symbol insert(name)
2479657Slinton Name name;
2489657Slinton {
2499657Slinton     register Symbol s;
2509657Slinton     register unsigned int h;
2519657Slinton 
2529657Slinton     h = hash(name);
2539657Slinton     s = symbol_alloc();
2549657Slinton     s->name = name;
2559657Slinton     s->next_sym = hashtab[h];
2569657Slinton     hashtab[h] = s;
2579657Slinton     return s;
2589657Slinton }
2599657Slinton 
2609657Slinton /*
2619657Slinton  * Symbol lookup.
2629657Slinton  */
2639657Slinton 
2649657Slinton public Symbol lookup(name)
2659657Slinton Name name;
2669657Slinton {
2679657Slinton     register Symbol s;
2689657Slinton     register unsigned int h;
2699657Slinton 
2709657Slinton     h = hash(name);
2719657Slinton     s = hashtab[h];
2729657Slinton     while (s != nil and s->name != name) {
2739657Slinton 	s = s->next_sym;
2749657Slinton     }
2759657Slinton     return s;
2769657Slinton }
2779657Slinton 
2789657Slinton /*
27916620Ssam  * Delete a symbol from the symbol table.
28016620Ssam  */
28116620Ssam 
28216620Ssam public delete (s)
28316620Ssam Symbol s;
28416620Ssam {
28516620Ssam     register Symbol t;
28616620Ssam     register unsigned int h;
28716620Ssam 
28816620Ssam     h = hash(s->name);
28916620Ssam     t = hashtab[h];
29016620Ssam     if (t == nil) {
29116620Ssam 	panic("delete of non-symbol '%s'", symname(s));
29216620Ssam     } else if (t == s) {
29316620Ssam 	hashtab[h] = s->next_sym;
29416620Ssam     } else {
29516620Ssam 	while (t->next_sym != s) {
29616620Ssam 	    t = t->next_sym;
29716620Ssam 	    if (t == nil) {
29816620Ssam 		panic("delete of non-symbol '%s'", symname(s));
29916620Ssam 	    }
30016620Ssam 	}
30116620Ssam 	t->next_sym = s->next_sym;
30216620Ssam     }
30316620Ssam }
30416620Ssam 
30516620Ssam /*
3069657Slinton  * Dump out all the variables associated with the given
307*18235Slinton  * procedure, function, or program associated with the given stack frame.
3089657Slinton  *
3099657Slinton  * This is quite inefficient.  We traverse the entire symbol table
3109657Slinton  * each time we're called.  The assumption is that this routine
3119657Slinton  * won't be called frequently enough to merit improved performance.
3129657Slinton  */
3139657Slinton 
3149657Slinton public dumpvars(f, frame)
3159657Slinton Symbol f;
3169657Slinton Frame frame;
3179657Slinton {
3189657Slinton     register Integer i;
3199657Slinton     register Symbol s;
3209657Slinton 
3219657Slinton     for (i = 0; i < HASHTABLESIZE; i++) {
3229657Slinton 	for (s = hashtab[i]; s != nil; s = s->next_sym) {
3239657Slinton 	    if (container(s) == f) {
3249657Slinton 		if (should_print(s)) {
3259657Slinton 		    printv(s, frame);
3269657Slinton 		    putchar('\n');
3279657Slinton 		} else if (s->class == MODULE) {
3289657Slinton 		    dumpvars(s, frame);
3299657Slinton 		}
3309657Slinton 	    }
3319657Slinton 	}
3329657Slinton     }
3339657Slinton }
3349657Slinton 
3359657Slinton /*
3369657Slinton  * Create a builtin type.
3379657Slinton  * Builtin types are circular in that btype->type->type = btype.
3389657Slinton  */
3399657Slinton 
340*18235Slinton private Symbol maketype(name, lower, upper)
3419657Slinton String name;
3429657Slinton long lower;
3439657Slinton long upper;
3449657Slinton {
3459657Slinton     register Symbol s;
346*18235Slinton     Name n;
3479657Slinton 
348*18235Slinton     if (name == nil) {
349*18235Slinton 	n = nil;
350*18235Slinton     } else {
351*18235Slinton 	n = identname(name, true);
352*18235Slinton     }
353*18235Slinton     s = insert(n);
35416620Ssam     s->language = primlang;
355*18235Slinton     s->level = 0;
356*18235Slinton     s->class = TYPE;
357*18235Slinton     s->type = nil;
358*18235Slinton     s->chain = nil;
3599657Slinton     s->type = newSymbol(nil, 0, RANGE, s, nil);
3609657Slinton     s->type->symvalue.rangev.lower = lower;
3619657Slinton     s->type->symvalue.rangev.upper = upper;
3629657Slinton     return s;
3639657Slinton }
3649657Slinton 
3659657Slinton /*
366*18235Slinton  * Create the builtin symbols.
367*18235Slinton  */
368*18235Slinton 
369*18235Slinton public symbols_init ()
3709657Slinton {
371*18235Slinton     Symbol s;
3729657Slinton 
373*18235Slinton     t_boolean = maketype("$boolean", 0L, 1L);
374*18235Slinton     t_int = maketype("$integer", 0x80000000L, 0x7fffffffL);
375*18235Slinton     t_char = maketype("$char", 0L, 255L);
376*18235Slinton     t_real = maketype("$real", 8L, 0L);
377*18235Slinton     t_nil = maketype("$nil", 0L, 0L);
378*18235Slinton     t_addr = insert(identname("$address", true));
379*18235Slinton     t_addr->language = primlang;
380*18235Slinton     t_addr->level = 0;
381*18235Slinton     t_addr->class = TYPE;
382*18235Slinton     t_addr->type = newSymbol(nil, 1, PTR, t_int, nil);
383*18235Slinton     s = insert(identname("true", true));
384*18235Slinton     s->class = CONST;
385*18235Slinton     s->type = t_boolean;
386*18235Slinton     s->symvalue.constval = build(O_LCON, 1L);
387*18235Slinton     s->symvalue.constval->nodetype = t_boolean;
388*18235Slinton     s = insert(identname("false", true));
389*18235Slinton     s->class = CONST;
390*18235Slinton     s->type = t_boolean;
391*18235Slinton     s->symvalue.constval = build(O_LCON, 0L);
392*18235Slinton     s->symvalue.constval->nodetype = t_boolean;
3939657Slinton }
3949657Slinton 
3959657Slinton /*
3969657Slinton  * Reduce type to avoid worrying about type names.
3979657Slinton  */
3989657Slinton 
3999657Slinton public Symbol rtype(type)
4009657Slinton Symbol type;
4019657Slinton {
4029657Slinton     register Symbol t;
4039657Slinton 
4049657Slinton     t = type;
4059657Slinton     if (t != nil) {
406*18235Slinton 	if (t->class == VAR or t->class == CONST or
407*18235Slinton 	    t->class == FIELD or t->class == REF
408*18235Slinton 	) {
4099657Slinton 	    t = t->type;
4109657Slinton 	}
41116620Ssam 	if (t->class == TYPEREF) {
41216620Ssam 	    resolveRef(t);
41316620Ssam 	}
4149657Slinton 	while (t->class == TYPE or t->class == TAG) {
4159657Slinton 	    t = t->type;
41616620Ssam 	    if (t->class == TYPEREF) {
41716620Ssam 		resolveRef(t);
41816620Ssam 	    }
4199657Slinton 	}
4209657Slinton     }
4219657Slinton     return t;
4229657Slinton }
4239657Slinton 
42416620Ssam /*
42516620Ssam  * Find the end of a module name.  Return nil if there is none
42616620Ssam  * in the given string.
42716620Ssam  */
42816620Ssam 
42916620Ssam private String findModuleMark (s)
43016620Ssam String s;
43116620Ssam {
43216620Ssam     register char *p, *r;
43316620Ssam     register boolean done;
43416620Ssam 
43516620Ssam     p = s;
43616620Ssam     done = false;
43716620Ssam     do {
43816620Ssam 	if (*p == ':') {
43916620Ssam 	    done = true;
44016620Ssam 	    r = p;
44116620Ssam 	} else if (*p == '\0') {
44216620Ssam 	    done = true;
44316620Ssam 	    r = nil;
44416620Ssam 	} else {
44516620Ssam 	    ++p;
44616620Ssam 	}
44716620Ssam     } while (not done);
44816620Ssam     return r;
44916620Ssam }
45016620Ssam 
45116620Ssam /*
45216620Ssam  * Resolve a type reference by modifying to be the appropriate type.
45316620Ssam  *
45416620Ssam  * If the reference has a name, then it refers to an opaque type and
45516620Ssam  * the actual type is directly accessible.  Otherwise, we must use
45616620Ssam  * the type reference string, which is of the form "module:{module:}name".
45716620Ssam  */
45816620Ssam 
45916620Ssam public resolveRef (t)
46016620Ssam Symbol t;
46116620Ssam {
46216620Ssam     register char *p;
46316620Ssam     char *start;
46416620Ssam     Symbol s, m, outer;
46516620Ssam     Name n;
46616620Ssam 
46716620Ssam     if (t->name != nil) {
46816620Ssam 	s = t;
46916620Ssam     } else {
47016620Ssam 	start = t->symvalue.typeref;
47116620Ssam 	outer = program;
47216620Ssam 	p = findModuleMark(start);
47316620Ssam 	while (p != nil) {
47416620Ssam 	    *p = '\0';
47516620Ssam 	    n = identname(start, true);
47616620Ssam 	    find(m, n) where m->block == outer endfind(m);
47716620Ssam 	    if (m == nil) {
47816620Ssam 		p = nil;
47916620Ssam 		outer = nil;
48016620Ssam 		s = nil;
48116620Ssam 	    } else {
48216620Ssam 		outer = m;
48316620Ssam 		start = p + 1;
48416620Ssam 		p = findModuleMark(start);
48516620Ssam 	    }
48616620Ssam 	}
48716620Ssam 	if (outer != nil) {
48816620Ssam 	    n = identname(start, true);
48916620Ssam 	    find(s, n) where s->block == outer endfind(s);
49016620Ssam 	}
49116620Ssam     }
49216620Ssam     if (s != nil and s->type != nil) {
49316620Ssam 	t->name = s->type->name;
49416620Ssam 	t->class = s->type->class;
49516620Ssam 	t->type = s->type->type;
49616620Ssam 	t->chain = s->type->chain;
49716620Ssam 	t->symvalue = s->type->symvalue;
49816620Ssam 	t->block = s->type->block;
49916620Ssam     }
50016620Ssam }
50116620Ssam 
502*18235Slinton public integer regnum (s)
5039657Slinton Symbol s;
5049657Slinton {
505*18235Slinton     integer r;
506*18235Slinton 
5079657Slinton     checkref(s);
508*18235Slinton     if (s->level < 0) {
509*18235Slinton 	r = s->symvalue.offset;
510*18235Slinton     } else {
511*18235Slinton 	r = -1;
512*18235Slinton     }
513*18235Slinton     return r;
5149657Slinton }
5159657Slinton 
5169657Slinton public Symbol container(s)
5179657Slinton Symbol s;
5189657Slinton {
5199657Slinton     checkref(s);
5209657Slinton     return s->block;
5219657Slinton }
5229657Slinton 
523*18235Slinton public Node constval(s)
524*18235Slinton Symbol s;
525*18235Slinton {
526*18235Slinton     checkref(s);
527*18235Slinton     if (s->class != CONST) {
528*18235Slinton 	error("[internal error: constval(non-CONST)]");
529*18235Slinton     }
530*18235Slinton     return s->symvalue.constval;
531*18235Slinton }
532*18235Slinton 
5339657Slinton /*
5349657Slinton  * Return the object address of the given symbol.
5359657Slinton  *
5369657Slinton  * There are the following possibilities:
5379657Slinton  *
5389657Slinton  *	globals		- just take offset
5399657Slinton  *	locals		- take offset from locals base
5409657Slinton  *	arguments	- take offset from argument base
5419657Slinton  *	register	- offset is register number
5429657Slinton  */
5439657Slinton 
54416620Ssam #define isglobal(s)		(s->level == 1)
54516620Ssam #define islocaloff(s)		(s->level >= 2 and s->symvalue.offset < 0)
54616620Ssam #define isparamoff(s)		(s->level >= 2 and s->symvalue.offset >= 0)
547*18235Slinton #define isreg(s)		(s->level < 0)
5489657Slinton 
549*18235Slinton public Address address (s, frame)
5509657Slinton Symbol s;
5519657Slinton Frame frame;
5529657Slinton {
5539657Slinton     register Frame frp;
5549657Slinton     register Address addr;
5559657Slinton     register Symbol cur;
5569657Slinton 
5579657Slinton     checkref(s);
5589657Slinton     if (not isactive(s->block)) {
5599657Slinton 	error("\"%s\" is not currently defined", symname(s));
5609657Slinton     } else if (isglobal(s)) {
5619657Slinton 	addr = s->symvalue.offset;
5629657Slinton     } else {
5639657Slinton 	frp = frame;
5649657Slinton 	if (frp == nil) {
5659657Slinton 	    cur = s->block;
5669657Slinton 	    while (cur != nil and cur->class == MODULE) {
5679657Slinton 		cur = cur->block;
5689657Slinton 	    }
5699657Slinton 	    if (cur == nil) {
570*18235Slinton 		frp = nil;
571*18235Slinton 	    } else {
572*18235Slinton 		frp = findframe(cur);
573*18235Slinton 		if (frp == nil) {
574*18235Slinton 		    error("[internal error: unexpected nil frame for \"%s\"]",
575*18235Slinton 			symname(s)
576*18235Slinton 		    );
577*18235Slinton 		}
5789657Slinton 	    }
5799657Slinton 	}
5809657Slinton 	if (islocaloff(s)) {
5819657Slinton 	    addr = locals_base(frp) + s->symvalue.offset;
5829657Slinton 	} else if (isparamoff(s)) {
5839657Slinton 	    addr = args_base(frp) + s->symvalue.offset;
5849657Slinton 	} else if (isreg(s)) {
5859657Slinton 	    addr = savereg(s->symvalue.offset, frp);
5869657Slinton 	} else {
5879657Slinton 	    panic("address: bad symbol \"%s\"", symname(s));
5889657Slinton 	}
5899657Slinton     }
5909657Slinton     return addr;
5919657Slinton }
5929657Slinton 
5939657Slinton /*
5949657Slinton  * Define a symbol used to access register values.
5959657Slinton  */
5969657Slinton 
597*18235Slinton public defregname (n, r)
5989657Slinton Name n;
599*18235Slinton integer r;
6009657Slinton {
601*18235Slinton     Symbol s;
6029657Slinton 
6039657Slinton     s = insert(n);
604*18235Slinton     s->language = t_addr->language;
6059657Slinton     s->class = VAR;
6069657Slinton     s->level = -3;
607*18235Slinton     s->type = t_addr;
6089657Slinton     s->symvalue.offset = r;
6099657Slinton }
6109657Slinton 
6119657Slinton /*
6129657Slinton  * Resolve an "abstract" type reference.
6139657Slinton  *
6149657Slinton  * It is possible in C to define a pointer to a type, but never define
6159657Slinton  * the type in a particular source file.  Here we try to resolve
6169657Slinton  * the type definition.  This is problematic, it is possible to
6179657Slinton  * have multiple, different definitions for the same name type.
6189657Slinton  */
6199657Slinton 
6209657Slinton public findtype(s)
6219657Slinton Symbol s;
6229657Slinton {
6239657Slinton     register Symbol t, u, prev;
6249657Slinton 
6259657Slinton     u = s;
6269657Slinton     prev = nil;
6279657Slinton     while (u != nil and u->class != BADUSE) {
6289657Slinton 	if (u->name != nil) {
6299657Slinton 	    prev = u;
6309657Slinton 	}
6319657Slinton 	u = u->type;
6329657Slinton     }
6339657Slinton     if (prev == nil) {
6349657Slinton 	error("couldn't find link to type reference");
6359657Slinton     }
636*18235Slinton     t = lookup(prev->name);
637*18235Slinton     while (t != nil and
638*18235Slinton 	not (
639*18235Slinton 	    t != prev and t->name == prev->name and
640*18235Slinton 	    t->block->class == MODULE and t->class == prev->class and
641*18235Slinton 	    t->type != nil and t->type->type != nil and
642*18235Slinton 	    t->type->type->class != BADUSE
643*18235Slinton 	)
644*18235Slinton     ) {
645*18235Slinton 	t = t->next_sym;
646*18235Slinton     }
6479657Slinton     if (t == nil) {
6489657Slinton 	error("couldn't resolve reference");
6499657Slinton     } else {
6509657Slinton 	prev->type = t->type;
6519657Slinton     }
6529657Slinton }
6539657Slinton 
6549657Slinton /*
6559657Slinton  * Find the size in bytes of the given type.
6569657Slinton  *
6579657Slinton  * This is probably the WRONG thing to do.  The size should be kept
6589657Slinton  * as an attribute in the symbol information as is done for structures
6599657Slinton  * and fields.  I haven't gotten around to cleaning this up yet.
6609657Slinton  */
6619657Slinton 
66212547Scsvaf #define MAXUCHAR 255
66312547Scsvaf #define MAXUSHORT 65535L
6649657Slinton #define MINCHAR -128
6659657Slinton #define MAXCHAR 127
6669657Slinton #define MINSHORT -32768
6679657Slinton #define MAXSHORT 32767
6689657Slinton 
66916620Ssam public findbounds (u, lower, upper)
67016620Ssam Symbol u;
67116620Ssam long *lower, *upper;
67216620Ssam {
67316620Ssam     Rangetype lbt, ubt;
67416620Ssam     long lb, ub;
67516620Ssam 
67616620Ssam     if (u->class == RANGE) {
67716620Ssam 	lbt = u->symvalue.rangev.lowertype;
67816620Ssam 	ubt = u->symvalue.rangev.uppertype;
67916620Ssam 	lb = u->symvalue.rangev.lower;
68016620Ssam 	ub = u->symvalue.rangev.upper;
68116620Ssam 	if (lbt == R_ARG or lbt == R_TEMP) {
68216620Ssam 	    if (not getbound(u, lb, lbt, lower)) {
68316620Ssam 		error("dynamic bounds not currently available");
68416620Ssam 	    }
68516620Ssam 	} else {
68616620Ssam 	    *lower = lb;
68716620Ssam 	}
68816620Ssam 	if (ubt == R_ARG or ubt == R_TEMP) {
68916620Ssam 	    if (not getbound(u, ub, ubt, upper)) {
69016620Ssam 		error("dynamic bounds not currently available");
69116620Ssam 	    }
69216620Ssam 	} else {
69316620Ssam 	    *upper = ub;
69416620Ssam 	}
69516620Ssam     } else if (u->class == SCAL) {
69616620Ssam 	*lower = 0;
69716620Ssam 	*upper = u->symvalue.iconval - 1;
69816620Ssam     } else {
699*18235Slinton 	error("[internal error: unexpected array bound type]");
70016620Ssam     }
70116620Ssam }
70216620Ssam 
70316620Ssam public integer size(sym)
70416620Ssam Symbol sym;
70516620Ssam {
70616620Ssam     register Symbol s, t, u;
70716620Ssam     register integer nel, elsize;
7089657Slinton     long lower, upper;
70916620Ssam     integer r, off, len;
7109657Slinton 
7119657Slinton     t = sym;
7129657Slinton     checkref(t);
71316620Ssam     if (t->class == TYPEREF) {
71416620Ssam 	resolveRef(t);
71516620Ssam     }
7169657Slinton     switch (t->class) {
7179657Slinton 	case RANGE:
7189657Slinton 	    lower = t->symvalue.rangev.lower;
7199657Slinton 	    upper = t->symvalue.rangev.upper;
72016620Ssam 	    if (upper == 0 and lower > 0) {
72116620Ssam 		/* real */
7229657Slinton 		r = lower;
72316620Ssam 	    } else if (lower > upper) {
72416620Ssam 		/* unsigned long */
72516620Ssam 		r = sizeof(long);
72612045Slinton 	    } else if (
72712547Scsvaf   		(lower >= MINCHAR and upper <= MAXCHAR) or
72812547Scsvaf   		(lower >= 0 and upper <= MAXUCHAR)
72912547Scsvaf   	      ) {
7309657Slinton 		r = sizeof(char);
73112547Scsvaf   	    } else if (
73212547Scsvaf   		(lower >= MINSHORT and upper <= MAXSHORT) or
73312547Scsvaf   		(lower >= 0 and upper <= MAXUSHORT)
73412547Scsvaf   	      ) {
7359657Slinton 		r = sizeof(short);
7369657Slinton 	    } else {
7379657Slinton 		r = sizeof(long);
7389657Slinton 	    }
7399657Slinton 	    break;
7409657Slinton 
7419657Slinton 	case ARRAY:
7429657Slinton 	    elsize = size(t->type);
7439657Slinton 	    nel = 1;
7449657Slinton 	    for (t = t->chain; t != nil; t = t->chain) {
74516620Ssam 		u = rtype(t);
74616620Ssam 		findbounds(u, &lower, &upper);
7479657Slinton 		nel *= (upper-lower+1);
7489657Slinton 	    }
7499657Slinton 	    r = nel*elsize;
7509657Slinton 	    break;
7519657Slinton 
752*18235Slinton 	case DYNARRAY:
753*18235Slinton 	    r = (t->symvalue.ndims + 1) * sizeof(Word);
754*18235Slinton 	    break;
755*18235Slinton 
756*18235Slinton 	case SUBARRAY:
757*18235Slinton 	    r = (2 * t->symvalue.ndims + 1) * sizeof(Word);
758*18235Slinton 	    break;
759*18235Slinton 
76012547Scsvaf 	case REF:
7619657Slinton 	case VAR:
7629657Slinton 	    r = size(t->type);
76312127Slinton 	    /*
76412127Slinton 	     *
76512045Slinton 	    if (r < sizeof(Word) and isparam(t)) {
7669657Slinton 		r = sizeof(Word);
7679657Slinton 	    }
76812547Scsvaf 	    */
7699657Slinton 	    break;
7709657Slinton 
771*18235Slinton 	case FVAR:
7729657Slinton 	case CONST:
773*18235Slinton 	case TAG:
7749657Slinton 	    r = size(t->type);
7759657Slinton 	    break;
7769657Slinton 
7779657Slinton 	case TYPE:
7789657Slinton 	    if (t->type->class == PTR and t->type->type->class == BADUSE) {
7799657Slinton 		findtype(t);
7809657Slinton 	    }
7819657Slinton 	    r = size(t->type);
7829657Slinton 	    break;
7839657Slinton 
7849657Slinton 	case FIELD:
78516620Ssam 	    off = t->symvalue.field.offset;
78616620Ssam 	    len = t->symvalue.field.length;
78716620Ssam 	    r = (off + len + 7) div 8 - (off div 8);
7889657Slinton 	    break;
7899657Slinton 
7909657Slinton 	case RECORD:
7919657Slinton 	case VARNT:
7929657Slinton 	    r = t->symvalue.offset;
7939657Slinton 	    if (r == 0 and t->chain != nil) {
7949657Slinton 		panic("missing size information for record");
7959657Slinton 	    }
7969657Slinton 	    break;
7979657Slinton 
7989657Slinton 	case PTR:
799*18235Slinton 	case TYPEREF:
8009657Slinton 	case FILET:
8019657Slinton 	    r = sizeof(Word);
8029657Slinton 	    break;
8039657Slinton 
8049657Slinton 	case SCAL:
80512609Slinton 	    r = sizeof(Word);
80612609Slinton 	    /*
80712609Slinton 	     *
8089657Slinton 	    if (t->symvalue.iconval > 255) {
8099657Slinton 		r = sizeof(short);
8109657Slinton 	    } else {
8119657Slinton 		r = sizeof(char);
8129657Slinton 	    }
81312609Slinton 	     *
81412609Slinton 	     */
8159657Slinton 	    break;
8169657Slinton 
8179657Slinton 	case FPROC:
8189657Slinton 	case FFUNC:
8199657Slinton 	    r = sizeof(Word);
8209657Slinton 	    break;
8219657Slinton 
8229657Slinton 	case PROC:
8239657Slinton 	case FUNC:
8249657Slinton 	case MODULE:
8259657Slinton 	case PROG:
8269657Slinton 	    r = sizeof(Symbol);
8279657Slinton 	    break;
8289657Slinton 
82916620Ssam 	case SET:
83016620Ssam 	    u = rtype(t->type);
83116620Ssam 	    switch (u->class) {
83216620Ssam 		case RANGE:
83316620Ssam 		    r = u->symvalue.rangev.upper - u->symvalue.rangev.lower + 1;
83416620Ssam 		    break;
83516620Ssam 
83616620Ssam 		case SCAL:
83716620Ssam 		    r = u->symvalue.iconval;
83816620Ssam 		    break;
83916620Ssam 
84016620Ssam 		default:
84116620Ssam 		    error("expected range for set base type");
84216620Ssam 		    break;
84316620Ssam 	    }
84416620Ssam 	    r = (r + BITSPERBYTE - 1) div BITSPERBYTE;
84516620Ssam 	    break;
84616620Ssam 
847*18235Slinton 	/*
848*18235Slinton 	 * These can happen in C (unfortunately) for unresolved type references
849*18235Slinton 	 * Assume they are pointers.
850*18235Slinton 	 */
851*18235Slinton 	case BADUSE:
852*18235Slinton 	    r = sizeof(Address);
853*18235Slinton 	    break;
854*18235Slinton 
8559657Slinton 	default:
8569657Slinton 	    if (ord(t->class) > ord(TYPEREF)) {
8579657Slinton 		panic("size: bad class (%d)", ord(t->class));
8589657Slinton 	    } else {
859*18235Slinton 		fprintf(stderr, "can't compute size of a %s\n", classname(t));
8609657Slinton 	    }
86116620Ssam 	    r = 0;
86216620Ssam 	    break;
8639657Slinton     }
8649657Slinton     return r;
8659657Slinton }
8669657Slinton 
8679657Slinton /*
868*18235Slinton  * Return the size associated with a symbol that takes into account
869*18235Slinton  * reference parameters.  This might be better as the normal size function, but
870*18235Slinton  * too many places already depend on it working the way it does.
871*18235Slinton  */
872*18235Slinton 
873*18235Slinton public integer psize (s)
874*18235Slinton Symbol s;
875*18235Slinton {
876*18235Slinton     integer r;
877*18235Slinton     Symbol t;
878*18235Slinton 
879*18235Slinton     if (s->class == REF) {
880*18235Slinton 	t = rtype(s->type);
881*18235Slinton 	if (t->class == DYNARRAY) {
882*18235Slinton 	    r = (t->symvalue.ndims + 1) * sizeof(Word);
883*18235Slinton 	} else if (t->class == SUBARRAY) {
884*18235Slinton 	    r = (2 * t->symvalue.ndims + 1) * sizeof(Word);
885*18235Slinton 	} else {
886*18235Slinton 	    r = sizeof(Word);
887*18235Slinton 	}
888*18235Slinton     } else {
889*18235Slinton 	r = size(s);
890*18235Slinton     }
891*18235Slinton     return r;
892*18235Slinton }
893*18235Slinton 
894*18235Slinton /*
8959657Slinton  * Test if a symbol is a parameter.  This is true if there
8969657Slinton  * is a cycle from s->block to s via chain pointers.
8979657Slinton  */
8989657Slinton 
8999657Slinton public Boolean isparam(s)
9009657Slinton Symbol s;
9019657Slinton {
9029657Slinton     register Symbol t;
9039657Slinton 
9049657Slinton     t = s->block;
9059657Slinton     while (t != nil and t != s) {
9069657Slinton 	t = t->chain;
9079657Slinton     }
9089657Slinton     return (Boolean) (t != nil);
9099657Slinton }
9109657Slinton 
9119657Slinton /*
91216620Ssam  * Test if a type is an open array parameter type.
9139657Slinton  */
9149657Slinton 
915*18235Slinton public boolean isopenarray (type)
916*18235Slinton Symbol type;
91716620Ssam {
918*18235Slinton     Symbol t;
919*18235Slinton 
920*18235Slinton     t = rtype(type);
921*18235Slinton     return (boolean) (t->class == DYNARRAY);
92216620Ssam }
92316620Ssam 
92416620Ssam /*
925*18235Slinton  * Test if a symbol is a var parameter, i.e. has class REF.
92616620Ssam  */
92716620Ssam 
9289657Slinton public Boolean isvarparam(s)
9299657Slinton Symbol s;
9309657Slinton {
9319657Slinton     return (Boolean) (s->class == REF);
9329657Slinton }
9339657Slinton 
9349657Slinton /*
9359657Slinton  * Test if a symbol is a variable (actually any addressible quantity
9369657Slinton  * with do).
9379657Slinton  */
9389657Slinton 
9399657Slinton public Boolean isvariable(s)
940*18235Slinton Symbol s;
9419657Slinton {
9429657Slinton     return (Boolean) (s->class == VAR or s->class == FVAR or s->class == REF);
9439657Slinton }
9449657Slinton 
9459657Slinton /*
946*18235Slinton  * Test if a symbol is a constant.
947*18235Slinton  */
948*18235Slinton 
949*18235Slinton public Boolean isconst(s)
950*18235Slinton Symbol s;
9519657Slinton {
952*18235Slinton     return (Boolean) (s->class == CONST);
9539657Slinton }
9549657Slinton 
9559657Slinton /*
9569657Slinton  * Test if a symbol is a module.
9579657Slinton  */
9589657Slinton 
9599657Slinton public Boolean ismodule(s)
9609657Slinton register Symbol s;
9619657Slinton {
9629657Slinton     return (Boolean) (s->class == MODULE);
9639657Slinton }
9649657Slinton 
9659657Slinton /*
96616620Ssam  * Mark a procedure or function as internal, meaning that it is called
96716620Ssam  * with a different calling sequence.
96816620Ssam  */
96916620Ssam 
97016620Ssam public markInternal (s)
97116620Ssam Symbol s;
97216620Ssam {
97316620Ssam     s->symvalue.funcv.intern = true;
97416620Ssam }
97516620Ssam 
97616620Ssam public boolean isinternal (s)
97716620Ssam Symbol s;
97816620Ssam {
97916620Ssam     return s->symvalue.funcv.intern;
98016620Ssam }
98116620Ssam 
98216620Ssam /*
983*18235Slinton  * Decide if a field begins or ends on a bit rather than byte boundary.
984*18235Slinton  */
985*18235Slinton 
986*18235Slinton public Boolean isbitfield(s)
987*18235Slinton register Symbol s;
988*18235Slinton {
989*18235Slinton     boolean b;
990*18235Slinton     register integer off, len;
991*18235Slinton     register Symbol t;
992*18235Slinton 
993*18235Slinton     off = s->symvalue.field.offset;
994*18235Slinton     len = s->symvalue.field.length;
995*18235Slinton     if ((off mod BITSPERBYTE) != 0 or (len mod BITSPERBYTE) != 0) {
996*18235Slinton 	b = true;
997*18235Slinton     } else {
998*18235Slinton 	t = rtype(s->type);
999*18235Slinton 	b = (Boolean) (
1000*18235Slinton 	    (t->class == SCAL and len != (sizeof(int)*BITSPERBYTE)) or
1001*18235Slinton 	    len != (size(t)*BITSPERBYTE)
1002*18235Slinton 	);
1003*18235Slinton     }
1004*18235Slinton     return b;
1005*18235Slinton }
1006*18235Slinton 
1007*18235Slinton private boolean primlang_typematch (t1, t2)
1008*18235Slinton Symbol t1, t2;
1009*18235Slinton {
1010*18235Slinton     return (boolean) (
1011*18235Slinton 	(t1 == t2) or
1012*18235Slinton 	(
1013*18235Slinton 	    t1->class == RANGE and t2->class == RANGE and
1014*18235Slinton 	    t1->symvalue.rangev.lower == t2->symvalue.rangev.lower and
1015*18235Slinton 	    t1->symvalue.rangev.upper == t2->symvalue.rangev.upper
1016*18235Slinton 	) or (
1017*18235Slinton 	    t1->class == PTR and t2->class == RANGE and
1018*18235Slinton 	    t2->symvalue.rangev.upper >= t2->symvalue.rangev.lower
1019*18235Slinton 	) or (
1020*18235Slinton 	    t2->class == PTR and t1->class == RANGE and
1021*18235Slinton 	    t1->symvalue.rangev.upper >= t1->symvalue.rangev.lower
1022*18235Slinton 	)
1023*18235Slinton     );
1024*18235Slinton }
1025*18235Slinton 
1026*18235Slinton /*
10279657Slinton  * Test if two types match.
10289657Slinton  * Equivalent names implies a match in any language.
10299657Slinton  *
10309657Slinton  * Special symbols must be handled with care.
10319657Slinton  */
10329657Slinton 
10339657Slinton public Boolean compatible(t1, t2)
10349657Slinton register Symbol t1, t2;
10359657Slinton {
10369657Slinton     Boolean b;
103716620Ssam     Symbol rt1, rt2;
10389657Slinton 
10399657Slinton     if (t1 == t2) {
10409657Slinton 	b = true;
10419657Slinton     } else if (t1 == nil or t2 == nil) {
10429657Slinton 	b = false;
10439657Slinton     } else if (t1 == procsym) {
10449657Slinton 	b = isblock(t2);
10459657Slinton     } else if (t2 == procsym) {
10469657Slinton 	b = isblock(t1);
104716620Ssam     } else if (t1->language == primlang) {
104816620Ssam 	if (t2->language == primlang) {
1049*18235Slinton 	    b = primlang_typematch(rtype(t1), rtype(t2));
105016620Ssam 	} else {
105116620Ssam 	    b = (boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2);
105216620Ssam 	}
105316620Ssam     } else if (t2->language == primlang) {
105416620Ssam 	b = (boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2);
10559657Slinton     } else if (t1->language == nil) {
105616620Ssam 	if (t2->language == nil) {
105716620Ssam 	    b = false;
105816620Ssam 	} else {
105916620Ssam 	    b = (boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2);
106016620Ssam 	}
10619657Slinton     } else {
106216620Ssam 	b = (boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2);
10639657Slinton     }
10649657Slinton     return b;
10659657Slinton }
10669657Slinton 
10679657Slinton /*
10689657Slinton  * Check for a type of the given name.
10699657Slinton  */
10709657Slinton 
10719657Slinton public Boolean istypename(type, name)
10729657Slinton Symbol type;
10739657Slinton String name;
10749657Slinton {
1075*18235Slinton     register Symbol t;
10769657Slinton     Boolean b;
10779657Slinton 
10789657Slinton     t = type;
1079*18235Slinton     if (t == nil) {
1080*18235Slinton 	b = false;
1081*18235Slinton     } else {
1082*18235Slinton 	b = (Boolean) (
1083*18235Slinton 	    t->class == TYPE and streq(ident(t->name), name)
1084*18235Slinton 	);
1085*18235Slinton     }
10869657Slinton     return b;
10879657Slinton }
10889657Slinton 
10899657Slinton /*
109016620Ssam  * Determine if a (value) parameter should actually be passed by address.
109116620Ssam  */
109216620Ssam 
109316620Ssam public boolean passaddr (p, exprtype)
109416620Ssam Symbol p, exprtype;
109516620Ssam {
109616620Ssam     boolean b;
109716620Ssam     Language def;
109816620Ssam 
109916620Ssam     if (p == nil) {
110016620Ssam 	def = findlanguage(".c");
110116620Ssam 	b = (boolean) (*language_op(def, L_PASSADDR))(p, exprtype);
110216620Ssam     } else if (p->language == nil or p->language == primlang) {
110316620Ssam 	b = false;
110416620Ssam     } else if (isopenarray(p->type)) {
110516620Ssam 	b = true;
110616620Ssam     } else {
110716620Ssam 	b = (boolean) (*language_op(p->language, L_PASSADDR))(p, exprtype);
110816620Ssam     }
110916620Ssam     return b;
111016620Ssam }
111116620Ssam 
111216620Ssam /*
11139657Slinton  * Test if the name of a symbol is uniquely defined or not.
11149657Slinton  */
11159657Slinton 
11169657Slinton public Boolean isambiguous(s)
11179657Slinton register Symbol s;
11189657Slinton {
11199657Slinton     register Symbol t;
11209657Slinton 
11219657Slinton     find(t, s->name) where t != s endfind(t);
11229657Slinton     return (Boolean) (t != nil);
11239657Slinton }
11249657Slinton 
11259657Slinton typedef char *Arglist;
11269657Slinton 
11279657Slinton #define nextarg(type)  ((type *) (ap += sizeof(type)))[-1]
11289657Slinton 
11299657Slinton private Symbol mkstring();
11309657Slinton 
11319657Slinton /*
11329657Slinton  * Determine the type of a parse tree.
1133*18235Slinton  *
11349657Slinton  * Also make some symbol-dependent changes to the tree such as
1135*18235Slinton  * removing indirection for constant or register symbols.
11369657Slinton  */
11379657Slinton 
1138*18235Slinton public assigntypes (p)
11399657Slinton register Node p;
11409657Slinton {
11419657Slinton     register Node p1;
11429657Slinton     register Symbol s;
11439657Slinton 
11449657Slinton     switch (p->op) {
11459657Slinton 	case O_SYM:
1146*18235Slinton 	    p->nodetype = p->value.sym;
11479657Slinton 	    break;
11489657Slinton 
11499657Slinton 	case O_LCON:
11509657Slinton 	    p->nodetype = t_int;
11519657Slinton 	    break;
11529657Slinton 
1153*18235Slinton 	case O_CCON:
1154*18235Slinton 	    p->nodetype = t_char;
1155*18235Slinton 	    break;
1156*18235Slinton 
11579657Slinton 	case O_FCON:
11589657Slinton 	    p->nodetype = t_real;
11599657Slinton 	    break;
11609657Slinton 
11619657Slinton 	case O_SCON:
1162*18235Slinton 	    p->nodetype = mkstring(p->value.scon);
11639657Slinton 	    break;
11649657Slinton 
11659657Slinton 	case O_INDIR:
11669657Slinton 	    p1 = p->value.arg[0];
1167*18235Slinton 	    s = rtype(p1->nodetype);
1168*18235Slinton 	    if (s->class != PTR) {
1169*18235Slinton 		beginerrmsg();
1170*18235Slinton 		fprintf(stderr, "\"");
1171*18235Slinton 		prtree(stderr, p1);
1172*18235Slinton 		fprintf(stderr, "\" is not a pointer");
1173*18235Slinton 		enderrmsg();
1174*18235Slinton 	    }
11759657Slinton 	    p->nodetype = rtype(p1->nodetype)->type;
11769657Slinton 	    break;
11779657Slinton 
11789657Slinton 	case O_DOT:
11799657Slinton 	    p->nodetype = p->value.arg[1]->value.sym;
11809657Slinton 	    break;
11819657Slinton 
11829657Slinton 	case O_RVAL:
11839657Slinton 	    p1 = p->value.arg[0];
11849657Slinton 	    p->nodetype = p1->nodetype;
11859657Slinton 	    if (p1->op == O_SYM) {
1186*18235Slinton 		if (p1->nodetype->class == PROC or p->nodetype->class == FUNC) {
1187*18235Slinton 		    p->op = p1->op;
1188*18235Slinton 		    p->value.sym = p1->value.sym;
1189*18235Slinton 		    p->nodetype = p1->nodetype;
1190*18235Slinton 		    dispose(p1);
11919657Slinton 		} else if (p1->value.sym->class == CONST) {
1192*18235Slinton 		    p->op = p1->op;
1193*18235Slinton 		    p->value = p1->value;
1194*18235Slinton 		    p->nodetype = p1->nodetype;
1195*18235Slinton 		    dispose(p1);
11969657Slinton 		} else if (isreg(p1->value.sym)) {
11979657Slinton 		    p->op = O_SYM;
11989657Slinton 		    p->value.sym = p1->value.sym;
11999657Slinton 		    dispose(p1);
12009657Slinton 		}
12019657Slinton 	    } else if (p1->op == O_INDIR and p1->value.arg[0]->op == O_SYM) {
12029657Slinton 		s = p1->value.arg[0]->value.sym;
12039657Slinton 		if (isreg(s)) {
12049657Slinton 		    p1->op = O_SYM;
12059657Slinton 		    dispose(p1->value.arg[0]);
12069657Slinton 		    p1->value.sym = s;
12079657Slinton 		    p1->nodetype = s;
12089657Slinton 		}
12099657Slinton 	    }
12109657Slinton 	    break;
12119657Slinton 
1212*18235Slinton 	case O_COMMA:
1213*18235Slinton 	    p->nodetype = p->value.arg[0]->nodetype;
1214*18235Slinton 	    break;
1215*18235Slinton 
1216*18235Slinton 	case O_CALLPROC:
12179657Slinton 	case O_CALL:
12189657Slinton 	    p1 = p->value.arg[0];
121911171Slinton 	    p->nodetype = rtype(p1->nodetype)->type;
12209657Slinton 	    break;
12219657Slinton 
122211171Slinton 	case O_TYPERENAME:
122311171Slinton 	    p->nodetype = p->value.arg[1]->nodetype;
122411171Slinton 	    break;
122511171Slinton 
12269657Slinton 	case O_ITOF:
12279657Slinton 	    p->nodetype = t_real;
12289657Slinton 	    break;
12299657Slinton 
12309657Slinton 	case O_NEG:
12319657Slinton 	    s = p->value.arg[0]->nodetype;
12329657Slinton 	    if (not compatible(s, t_int)) {
12339657Slinton 		if (not compatible(s, t_real)) {
12349657Slinton 		    beginerrmsg();
123516620Ssam 		    fprintf(stderr, "\"");
12369657Slinton 		    prtree(stderr, p->value.arg[0]);
123716620Ssam 		    fprintf(stderr, "\" is improper type");
12389657Slinton 		    enderrmsg();
12399657Slinton 		} else {
12409657Slinton 		    p->op = O_NEGF;
12419657Slinton 		}
12429657Slinton 	    }
12439657Slinton 	    p->nodetype = s;
12449657Slinton 	    break;
12459657Slinton 
12469657Slinton 	case O_ADD:
12479657Slinton 	case O_SUB:
12489657Slinton 	case O_MUL:
124916620Ssam 	    binaryop(p, nil);
125016620Ssam 	    break;
125116620Ssam 
12529657Slinton 	case O_LT:
12539657Slinton 	case O_LE:
12549657Slinton 	case O_GT:
12559657Slinton 	case O_GE:
12569657Slinton 	case O_EQ:
12579657Slinton 	case O_NE:
125816620Ssam 	    binaryop(p, t_boolean);
12599657Slinton 	    break;
12609657Slinton 
12619657Slinton 	case O_DIVF:
12629657Slinton 	    convert(&(p->value.arg[0]), t_real, O_ITOF);
12639657Slinton 	    convert(&(p->value.arg[1]), t_real, O_ITOF);
12649657Slinton 	    p->nodetype = t_real;
12659657Slinton 	    break;
12669657Slinton 
12679657Slinton 	case O_DIV:
12689657Slinton 	case O_MOD:
12699657Slinton 	    convert(&(p->value.arg[0]), t_int, O_NOP);
12709657Slinton 	    convert(&(p->value.arg[1]), t_int, O_NOP);
12719657Slinton 	    p->nodetype = t_int;
12729657Slinton 	    break;
12739657Slinton 
12749657Slinton 	case O_AND:
12759657Slinton 	case O_OR:
12769657Slinton 	    chkboolean(p->value.arg[0]);
12779657Slinton 	    chkboolean(p->value.arg[1]);
12789657Slinton 	    p->nodetype = t_boolean;
12799657Slinton 	    break;
12809657Slinton 
12819657Slinton 	case O_QLINE:
12829657Slinton 	    p->nodetype = t_int;
12839657Slinton 	    break;
12849657Slinton 
12859657Slinton 	default:
12869657Slinton 	    p->nodetype = nil;
12879657Slinton 	    break;
12889657Slinton     }
12899657Slinton }
12909657Slinton 
12919657Slinton /*
129216620Ssam  * Process a binary arithmetic or relational operator.
129316620Ssam  * Convert from integer to real if necessary.
129416620Ssam  */
129516620Ssam 
129616620Ssam private binaryop (p, t)
129716620Ssam Node p;
129816620Ssam Symbol t;
129916620Ssam {
130016620Ssam     Node p1, p2;
130116620Ssam     Boolean t1real, t2real;
130216620Ssam     Symbol t1, t2;
130316620Ssam 
130416620Ssam     p1 = p->value.arg[0];
130516620Ssam     p2 = p->value.arg[1];
130616620Ssam     t1 = rtype(p1->nodetype);
130716620Ssam     t2 = rtype(p2->nodetype);
130816620Ssam     t1real = compatible(t1, t_real);
130916620Ssam     t2real = compatible(t2, t_real);
131016620Ssam     if (t1real or t2real) {
131116620Ssam 	p->op = (Operator) (ord(p->op) + 1);
131216620Ssam 	if (not t1real) {
131316620Ssam 	    p->value.arg[0] = build(O_ITOF, p1);
131416620Ssam 	} else if (not t2real) {
131516620Ssam 	    p->value.arg[1] = build(O_ITOF, p2);
131616620Ssam 	}
131716620Ssam 	p->nodetype = t_real;
131816620Ssam     } else {
131916620Ssam 	if (size(p1->nodetype) > sizeof(integer)) {
132016620Ssam 	    beginerrmsg();
132116620Ssam 	    fprintf(stderr, "operation not defined on \"");
132216620Ssam 	    prtree(stderr, p1);
132316620Ssam 	    fprintf(stderr, "\"");
132416620Ssam 	    enderrmsg();
132516620Ssam 	} else if (size(p2->nodetype) > sizeof(integer)) {
132616620Ssam 	    beginerrmsg();
132716620Ssam 	    fprintf(stderr, "operation not defined on \"");
132816620Ssam 	    prtree(stderr, p2);
132916620Ssam 	    fprintf(stderr, "\"");
133016620Ssam 	    enderrmsg();
133116620Ssam 	}
133216620Ssam 	p->nodetype = t_int;
133316620Ssam     }
133416620Ssam     if (t != nil) {
133516620Ssam 	p->nodetype = t;
133616620Ssam     }
133716620Ssam }
133816620Ssam 
133916620Ssam /*
13409657Slinton  * Convert a tree to a type via a conversion operator;
13419657Slinton  * if this isn't possible generate an error.
13429657Slinton  *
13439657Slinton  * Note the tree is call by address, hence the #define below.
13449657Slinton  */
13459657Slinton 
13469657Slinton private convert(tp, typeto, op)
13479657Slinton Node *tp;
13489657Slinton Symbol typeto;
13499657Slinton Operator op;
13509657Slinton {
135116620Ssam     Node tree;
135216620Ssam     Symbol s, t;
13539657Slinton 
135416620Ssam     tree = *tp;
13559657Slinton     s = rtype(tree->nodetype);
135616620Ssam     t = rtype(typeto);
135716620Ssam     if (compatible(t, t_real) and compatible(s, t_int)) {
13589657Slinton 	tree = build(op, tree);
135916620Ssam     } else if (not compatible(s, t)) {
13609657Slinton 	beginerrmsg();
136116620Ssam 	fprintf(stderr, "expected integer or real, found \"");
136216620Ssam 	prtree(stderr, tree);
136316620Ssam 	fprintf(stderr, "\"");
13649657Slinton 	enderrmsg();
136516620Ssam     } else if (op != O_NOP and s != t) {
13669657Slinton 	tree = build(op, tree);
13679657Slinton     }
136816620Ssam     *tp = tree;
13699657Slinton }
13709657Slinton 
13719657Slinton /*
13729657Slinton  * Construct a node for the dot operator.
13739657Slinton  *
13749657Slinton  * If the left operand is not a record, but rather a procedure
13759657Slinton  * or function, then we interpret the "." as referencing an
13769657Slinton  * "invisible" variable; i.e. a variable within a dynamically
13779657Slinton  * active block but not within the static scope of the current procedure.
13789657Slinton  */
13799657Slinton 
13809657Slinton public Node dot(record, fieldname)
13819657Slinton Node record;
13829657Slinton Name fieldname;
13839657Slinton {
1384*18235Slinton     register Node rec, p;
13859657Slinton     register Symbol s, t;
13869657Slinton 
1387*18235Slinton     rec = record;
1388*18235Slinton     if (isblock(rec->nodetype)) {
13899657Slinton 	find(s, fieldname) where
1390*18235Slinton 	    s->block == rec->nodetype and
1391*18235Slinton 	    s->class != FIELD
13929657Slinton 	endfind(s);
13939657Slinton 	if (s == nil) {
13949657Slinton 	    beginerrmsg();
13959657Slinton 	    fprintf(stderr, "\"%s\" is not defined in ", ident(fieldname));
1396*18235Slinton 	    printname(stderr, rec->nodetype);
13979657Slinton 	    enderrmsg();
13989657Slinton 	}
13999657Slinton 	p = new(Node);
14009657Slinton 	p->op = O_SYM;
14019657Slinton 	p->value.sym = s;
1402*18235Slinton 	p->nodetype = s;
14039657Slinton     } else {
1404*18235Slinton 	p = rec;
14059657Slinton 	t = rtype(p->nodetype);
14069657Slinton 	if (t->class == PTR) {
14079657Slinton 	    s = findfield(fieldname, t->type);
14089657Slinton 	} else {
14099657Slinton 	    s = findfield(fieldname, t);
14109657Slinton 	}
14119657Slinton 	if (s == nil) {
14129657Slinton 	    beginerrmsg();
14139657Slinton 	    fprintf(stderr, "\"%s\" is not a field in ", ident(fieldname));
1414*18235Slinton 	    prtree(stderr, rec);
14159657Slinton 	    enderrmsg();
14169657Slinton 	}
1417*18235Slinton 	if (t->class != PTR or isreg(rec->nodetype)) {
1418*18235Slinton 	    p = unrval(p);
14199657Slinton 	}
1420*18235Slinton 	p->nodetype = t_addr;
14219657Slinton 	p = build(O_DOT, p, build(O_SYM, s));
14229657Slinton     }
1423*18235Slinton     return build(O_RVAL, p);
14249657Slinton }
14259657Slinton 
14269657Slinton /*
14279657Slinton  * Return a tree corresponding to an array reference and do the
14289657Slinton  * error checking.
14299657Slinton  */
14309657Slinton 
14319657Slinton public Node subscript(a, slist)
14329657Slinton Node a, slist;
14339657Slinton {
143416620Ssam     Symbol t;
1435*18235Slinton     Node p;
14369657Slinton 
143716620Ssam     t = rtype(a->nodetype);
1438*18235Slinton     if (t->language == nil or t->language == primlang) {
1439*18235Slinton 	p = (Node) (*language_op(findlanguage(".s"), L_BUILDAREF))(a, slist);
144016620Ssam     } else {
1441*18235Slinton 	p = (Node) (*language_op(t->language, L_BUILDAREF))(a, slist);
144216620Ssam     }
1443*18235Slinton     return build(O_RVAL, p);
14449657Slinton }
14459657Slinton 
14469657Slinton /*
14479657Slinton  * Evaluate a subscript index.
14489657Slinton  */
14499657Slinton 
1450*18235Slinton public int evalindex(s, base, i)
14519657Slinton Symbol s;
1452*18235Slinton Address base;
14539657Slinton long i;
14549657Slinton {
145516620Ssam     Symbol t;
1456*18235Slinton     int r;
14579657Slinton 
145816620Ssam     t = rtype(s);
1459*18235Slinton     if (t->language == nil or t->language == primlang) {
1460*18235Slinton 	r = ((*language_op(findlanguage(".s"), L_EVALAREF)) (s, base, i));
146116620Ssam     } else {
1462*18235Slinton 	r = ((*language_op(t->language, L_EVALAREF)) (s, base, i));
146316620Ssam     }
1464*18235Slinton     return r;
14659657Slinton }
14669657Slinton 
14679657Slinton /*
14689657Slinton  * Check to see if a tree is boolean-valued, if not it's an error.
14699657Slinton  */
14709657Slinton 
14719657Slinton public chkboolean(p)
14729657Slinton register Node p;
14739657Slinton {
14749657Slinton     if (p->nodetype != t_boolean) {
14759657Slinton 	beginerrmsg();
14769657Slinton 	fprintf(stderr, "found ");
14779657Slinton 	prtree(stderr, p);
14789657Slinton 	fprintf(stderr, ", expected boolean expression");
14799657Slinton 	enderrmsg();
14809657Slinton     }
14819657Slinton }
14829657Slinton 
14839657Slinton /*
148416620Ssam  * Construct a node for the type of a string.
14859657Slinton  */
14869657Slinton 
14879657Slinton private Symbol mkstring(str)
14889657Slinton String str;
14899657Slinton {
14909657Slinton     register Symbol s;
14919657Slinton 
1492*18235Slinton     s = newSymbol(nil, 0, ARRAY, t_char, nil);
1493*18235Slinton     s->chain = newSymbol(nil, 0, RANGE, t_int, nil);
1494*18235Slinton     s->chain->language = s->language;
1495*18235Slinton     s->chain->symvalue.rangev.lower = 1;
1496*18235Slinton     s->chain->symvalue.rangev.upper = strlen(str) + 1;
14979657Slinton     return s;
14989657Slinton }
14999657Slinton 
15009657Slinton /*
15019657Slinton  * Free up the space allocated for a string type.
15029657Slinton  */
15039657Slinton 
15049657Slinton public unmkstring(s)
15059657Slinton Symbol s;
15069657Slinton {
15079657Slinton     dispose(s->chain);
15089657Slinton }
15099657Slinton 
15109657Slinton /*
1511*18235Slinton  * Figure out the "current" variable or function being referred to
1512*18235Slinton  * by the name n.
15139657Slinton  */
15149657Slinton 
1515*18235Slinton private boolean stwhich(), dynwhich();
1516*18235Slinton 
1517*18235Slinton public Symbol which (n)
15189657Slinton Name n;
15199657Slinton {
1520*18235Slinton     Symbol s;
15219657Slinton 
1522*18235Slinton     s = lookup(n);
15239657Slinton     if (s == nil) {
1524*18235Slinton 	error("\"%s\" is not defined", ident(n));
1525*18235Slinton     } else if (not stwhich(&s) and isambiguous(s) and not dynwhich(&s)) {
1526*18235Slinton 	printf("[using ");
1527*18235Slinton 	printname(stdout, s);
1528*18235Slinton 	printf("]\n");
15299657Slinton     }
1530*18235Slinton     return s;
1531*18235Slinton }
1532*18235Slinton 
1533*18235Slinton /*
1534*18235Slinton  * Static search.
1535*18235Slinton  */
1536*18235Slinton 
1537*18235Slinton private boolean stwhich (var_s)
1538*18235Slinton Symbol *var_s;
1539*18235Slinton {
1540*18235Slinton     Name n;		/* name of desired symbol */
1541*18235Slinton     Symbol s;		/* iteration variable for symbols with name n */
1542*18235Slinton     Symbol f;		/* iteration variable for blocks containing s */
1543*18235Slinton     integer count;	/* number of levels from s->block to curfunc */
1544*18235Slinton     Symbol t;		/* current best answer for stwhich(n) */
1545*18235Slinton     integer mincount;	/* relative level for current best answer (t) */
1546*18235Slinton     boolean b;		/* return value, true if symbol found */
1547*18235Slinton 
1548*18235Slinton     s = *var_s;
1549*18235Slinton     n = s->name;
1550*18235Slinton     t = s;
1551*18235Slinton     mincount = 10000; /* force first match to set mincount */
1552*18235Slinton     do {
1553*18235Slinton 	if (s->name == n and s->class != FIELD and s->class != TAG) {
1554*18235Slinton 	    f = curfunc;
1555*18235Slinton 	    count = 0;
1556*18235Slinton 	    while (f != nil and f != s->block) {
1557*18235Slinton 		++count;
1558*18235Slinton 		f = f->block;
1559*18235Slinton 	    }
1560*18235Slinton 	    if (f != nil and count < mincount) {
1561*18235Slinton 		t = s;
1562*18235Slinton 		mincount = count;
1563*18235Slinton 		b = true;
1564*18235Slinton 	    }
1565*18235Slinton 	}
1566*18235Slinton 	s = s->next_sym;
1567*18235Slinton     } while (s != nil);
1568*18235Slinton     if (mincount != 10000) {
1569*18235Slinton 	*var_s = t;
1570*18235Slinton 	b = true;
15719657Slinton     } else {
1572*18235Slinton 	b = false;
1573*18235Slinton     }
1574*18235Slinton     return b;
1575*18235Slinton }
1576*18235Slinton 
1577*18235Slinton /*
1578*18235Slinton  * Dynamic search.
1579*18235Slinton  */
1580*18235Slinton 
1581*18235Slinton private boolean dynwhich (var_s)
1582*18235Slinton Symbol *var_s;
1583*18235Slinton {
1584*18235Slinton     Name n;		/* name of desired symbol */
1585*18235Slinton     Symbol s;		/* iteration variable for possible symbols */
1586*18235Slinton     Symbol f;		/* iteration variable for active functions */
1587*18235Slinton     Frame frp;		/* frame associated with stack walk */
1588*18235Slinton     boolean b;		/* return value */
1589*18235Slinton 
1590*18235Slinton     f = curfunc;
1591*18235Slinton     frp = curfuncframe();
1592*18235Slinton     n = (*var_s)->name;
1593*18235Slinton     b = false;
1594*18235Slinton     if (frp != nil) {
1595*18235Slinton 	frp = nextfunc(frp, &f);
1596*18235Slinton 	while (frp != nil) {
1597*18235Slinton 	    s = *var_s;
1598*18235Slinton 	    while (s != nil and
1599*18235Slinton 		(
1600*18235Slinton 		    s->name != n or s->block != f or
1601*18235Slinton 		    s->class == FIELD or s->class == TAG
1602*18235Slinton 		)
1603*18235Slinton 	    ) {
1604*18235Slinton 		s = s->next_sym;
1605*18235Slinton 	    }
1606*18235Slinton 	    if (s != nil) {
1607*18235Slinton 		*var_s = s;
1608*18235Slinton 		b = true;
1609*18235Slinton 		break;
1610*18235Slinton 	    }
1611*18235Slinton 	    if (f == program) {
1612*18235Slinton 		break;
1613*18235Slinton 	    }
1614*18235Slinton 	    frp = nextfunc(frp, &f);
16159657Slinton 	}
16169657Slinton     }
1617*18235Slinton     return b;
16189657Slinton }
16199657Slinton 
16209657Slinton /*
1621*18235Slinton  * Find the symbol that has the same name and scope as the
16229657Slinton  * given symbol but is of the given field.  Return nil if there is none.
16239657Slinton  */
16249657Slinton 
1625*18235Slinton public Symbol findfield (fieldname, record)
16269657Slinton Name fieldname;
16279657Slinton Symbol record;
16289657Slinton {
16299657Slinton     register Symbol t;
16309657Slinton 
16319657Slinton     t = rtype(record)->chain;
16329657Slinton     while (t != nil and t->name != fieldname) {
16339657Slinton 	t = t->chain;
16349657Slinton     }
16359657Slinton     return t;
16369657Slinton }
163712547Scsvaf 
163812547Scsvaf public Boolean getbound(s,off,type,valp)
163912547Scsvaf Symbol s;
164012547Scsvaf int off;
164112547Scsvaf Rangetype type;
164212547Scsvaf int *valp;
164312547Scsvaf {
164412547Scsvaf     Frame frp;
164512547Scsvaf     Address addr;
164612547Scsvaf     Symbol cur;
164712547Scsvaf 
164812547Scsvaf     if (not isactive(s->block)) {
164912547Scsvaf 	return(false);
165012547Scsvaf     }
165112547Scsvaf     cur = s->block;
165212547Scsvaf     while (cur != nil and cur->class == MODULE) {  /* WHY*/
165312547Scsvaf     		cur = cur->block;
165412547Scsvaf     }
165512547Scsvaf     if(cur == nil) {
165612547Scsvaf 		cur = whatblock(pc);
165712547Scsvaf     }
165812547Scsvaf     frp = findframe(cur);
165912547Scsvaf     if (frp == nil) {
166012547Scsvaf 	return(false);
166112547Scsvaf     }
166212547Scsvaf     if(type == R_TEMP) addr = locals_base(frp) + off;
166312547Scsvaf     else if (type == R_ARG) addr = args_base(frp) + off;
166412547Scsvaf     else return(false);
166512547Scsvaf     dread(valp,addr,sizeof(long));
166612547Scsvaf     return(true);
166712547Scsvaf }
1668