xref: /csrg-svn/old/dbx/symbols.c (revision 42687)
121625Sdist /*
238105Sbostic  * Copyright (c) 1983 The Regents of the University of California.
338105Sbostic  * All rights reserved.
438105Sbostic  *
5*42687Sbostic  * %sccs.include.redist.c%
621625Sdist  */
79657Slinton 
821625Sdist #ifndef lint
9*42687Sbostic static char sccsid[] = "@(#)symbols.c	5.8 (Berkeley) 06/01/90";
1038105Sbostic #endif /* not lint */
119657Slinton 
129657Slinton /*
139657Slinton  * Symbol management.
149657Slinton  */
159657Slinton 
169657Slinton #include "defs.h"
179657Slinton #include "symbols.h"
189657Slinton #include "languages.h"
199657Slinton #include "printsym.h"
209657Slinton #include "tree.h"
219657Slinton #include "operators.h"
229657Slinton #include "eval.h"
239657Slinton #include "mappings.h"
249657Slinton #include "events.h"
259657Slinton #include "process.h"
269657Slinton #include "runtime.h"
279657Slinton #include "machine.h"
289657Slinton #include "names.h"
299657Slinton 
309657Slinton #ifndef public
319657Slinton typedef struct Symbol *Symbol;
329657Slinton 
339657Slinton #include "machine.h"
349657Slinton #include "names.h"
359657Slinton #include "languages.h"
3618235Slinton #include "tree.h"
379657Slinton 
389657Slinton /*
399657Slinton  * Symbol classes
409657Slinton  */
419657Slinton 
429657Slinton typedef enum {
4333337Sdonn     BADUSE, CONST, TYPE, VAR, ARRAY, OPENARRAY, DYNARRAY, SUBARRAY,
4433337Sdonn     PTRFILE, RECORD, FIELD,
4512547Scsvaf     PROC, FUNC, FVAR, REF, PTR, FILET, SET, RANGE,
469657Slinton     LABEL, WITHPTR, SCAL, STR, PROG, IMPROPER, VARNT,
4716620Ssam     FPROC, FFUNC, MODULE, TAG, COMMON, EXTREF, TYPEREF
489657Slinton } Symclass;
499657Slinton 
5012547Scsvaf typedef enum { R_CONST, R_TEMP, R_ARG, R_ADJUST } Rangetype;
5112547Scsvaf 
5233337Sdonn #define INREG 0
5333337Sdonn #define STK 1
5433337Sdonn #define EXT 2
5533337Sdonn 
5640260Sdonn typedef unsigned int Storage;
5733337Sdonn 
589657Slinton struct Symbol {
599657Slinton     Name name;
609657Slinton     Language language;
6133337Sdonn     Symclass class : 8;
6233337Sdonn     Storage storage : 2;
6333337Sdonn     unsigned int level : 6;	/* for variables stored on stack only */
649657Slinton     Symbol type;
659657Slinton     Symbol chain;
669657Slinton     union {
6718235Slinton 	Node constval;		/* value of constant symbol */
689657Slinton 	int offset;		/* variable address */
699657Slinton 	long iconval;		/* integer constant value */
709657Slinton 	double fconval;		/* floating constant value */
7118235Slinton 	int ndims;		/* no. of dimensions for dynamic/sub-arrays */
729657Slinton 	struct {		/* field offset and size (both in bits) */
739657Slinton 	    int offset;
749657Slinton 	    int length;
759657Slinton 	} field;
7612547Scsvaf 	struct {		/* common offset and chain; used to relocate */
7712547Scsvaf 	    int offset;         /* vars in global BSS */
7812547Scsvaf 	    Symbol chain;
7912547Scsvaf 	} common;
809657Slinton 	struct {		/* range bounds */
8112547Scsvaf             Rangetype lowertype : 16;
8212547Scsvaf             Rangetype uppertype : 16;
839657Slinton 	    long lower;
849657Slinton 	    long upper;
859657Slinton 	} rangev;
8611865Slinton 	struct {
8711865Slinton 	    int offset : 16;	/* offset for of function value */
8816620Ssam 	    Boolean src : 1;	/* true if there is source line info */
8916620Ssam 	    Boolean inline : 1;	/* true if no separate act. rec. */
9016620Ssam 	    Boolean intern : 1; /* internal calling sequence */
9116620Ssam 	    int unused : 13;
9211865Slinton 	    Address beginaddr;	/* address of function code */
939657Slinton 	} funcv;
949657Slinton 	struct {		/* variant record info */
959657Slinton 	    int size;
969657Slinton 	    Symbol vtorec;
979657Slinton 	    Symbol vtag;
989657Slinton 	} varnt;
9916620Ssam 	String typeref;		/* type defined by "<module>:<type>" */
10016620Ssam 	Symbol extref;		/* indirect symbol for external reference */
1019657Slinton     } symvalue;
1029657Slinton     Symbol block;		/* symbol containing this symbol */
1039657Slinton     Symbol next_sym;		/* hash chain */
1049657Slinton };
1059657Slinton 
1069657Slinton /*
1079657Slinton  * Basic types.
1089657Slinton  */
1099657Slinton 
1109657Slinton Symbol t_boolean;
1119657Slinton Symbol t_char;
1129657Slinton Symbol t_int;
1139657Slinton Symbol t_real;
1149657Slinton Symbol t_nil;
11518235Slinton Symbol t_addr;
1169657Slinton 
1179657Slinton Symbol program;
1189657Slinton Symbol curfunc;
1199657Slinton 
12018235Slinton boolean showaggrs;
12118235Slinton 
1229657Slinton #define symname(s) ident(s->name)
1239657Slinton #define codeloc(f) ((f)->symvalue.funcv.beginaddr)
1249657Slinton #define isblock(s) (Boolean) ( \
1259657Slinton     s->class == FUNC or s->class == PROC or \
1269657Slinton     s->class == MODULE or s->class == PROG \
1279657Slinton )
12816620Ssam #define isroutine(s) (Boolean) ( \
12916620Ssam     s->class == FUNC or s->class == PROC \
13016620Ssam )
1319657Slinton 
13211865Slinton #define nosource(f) (not (f)->symvalue.funcv.src)
13314441Slinton #define isinline(f) ((f)->symvalue.funcv.inline)
13411865Slinton 
13533337Sdonn #define isreg(s)		(s->storage == INREG)
13624554Smckusick 
1379657Slinton #include "tree.h"
1389657Slinton 
1399657Slinton /*
1409657Slinton  * Some macros to make finding a symbol with certain attributes.
1419657Slinton  */
1429657Slinton 
1439657Slinton #define find(s, withname) \
1449657Slinton { \
1459657Slinton     s = lookup(withname); \
1469657Slinton     while (s != nil and not (s->name == (withname) and
1479657Slinton 
1489657Slinton #define where /* qualification */
1499657Slinton 
1509657Slinton #define endfind(s) )) { \
1519657Slinton 	s = s->next_sym; \
1529657Slinton     } \
1539657Slinton }
1549657Slinton 
1559657Slinton #endif
1569657Slinton 
1579657Slinton /*
1589657Slinton  * Symbol table structure currently does not support deletions.
15933337Sdonn  * Hash table size is a power of two to make hashing faster.
16033337Sdonn  * Using a non-prime is ok since we aren't doing rehashing.
1619657Slinton  */
1629657Slinton 
16333337Sdonn #define HASHTABLESIZE 8192
1649657Slinton 
1659657Slinton private Symbol hashtab[HASHTABLESIZE];
1669657Slinton 
16733337Sdonn #define hash(name) ((((unsigned) name) >> 2) & (HASHTABLESIZE - 1))
1689657Slinton 
1699657Slinton /*
1709657Slinton  * Allocate a new symbol.
1719657Slinton  */
1729657Slinton 
17333337Sdonn #define SYMBLOCKSIZE 1000
1749657Slinton 
1759657Slinton typedef struct Sympool {
1769657Slinton     struct Symbol sym[SYMBLOCKSIZE];
1779657Slinton     struct Sympool *prevpool;
1789657Slinton } *Sympool;
1799657Slinton 
1809657Slinton private Sympool sympool = nil;
1819657Slinton private Integer nleft = 0;
1829657Slinton 
1839657Slinton public Symbol symbol_alloc()
1849657Slinton {
1859657Slinton     register Sympool newpool;
1869657Slinton 
1879657Slinton     if (nleft <= 0) {
1889657Slinton 	newpool = new(Sympool);
18933337Sdonn 	bzero(newpool, sizeof(*newpool));
1909657Slinton 	newpool->prevpool = sympool;
1919657Slinton 	sympool = newpool;
1929657Slinton 	nleft = SYMBLOCKSIZE;
1939657Slinton     }
1949657Slinton     --nleft;
1959657Slinton     return &(sympool->sym[nleft]);
1969657Slinton }
1979657Slinton 
19818235Slinton public symbol_dump (func)
19912547Scsvaf Symbol func;
20012547Scsvaf {
20118235Slinton     register Symbol s;
20218235Slinton     register integer i;
20312547Scsvaf 
20418235Slinton     printf(" symbols in %s \n",symname(func));
20518235Slinton     for (i = 0; i < HASHTABLESIZE; i++) {
20618235Slinton 	for (s = hashtab[i]; s != nil; s = s->next_sym) {
20718235Slinton 	    if (s->block == func) {
20818235Slinton 		psym(s);
20918235Slinton 	    }
21018235Slinton 	}
21118235Slinton     }
21212547Scsvaf }
21312547Scsvaf 
2149657Slinton /*
2159657Slinton  * Free all the symbols currently allocated.
2169657Slinton  */
21718235Slinton 
2189657Slinton public symbol_free()
2199657Slinton {
2209657Slinton     Sympool s, t;
2219657Slinton     register Integer i;
2229657Slinton 
2239657Slinton     s = sympool;
2249657Slinton     while (s != nil) {
2259657Slinton 	t = s->prevpool;
2269657Slinton 	dispose(s);
2279657Slinton 	s = t;
2289657Slinton     }
2299657Slinton     for (i = 0; i < HASHTABLESIZE; i++) {
2309657Slinton 	hashtab[i] = nil;
2319657Slinton     }
2329657Slinton     sympool = nil;
2339657Slinton     nleft = 0;
2349657Slinton }
2359657Slinton 
2369657Slinton /*
2379657Slinton  * Create a new symbol with the given attributes.
2389657Slinton  */
2399657Slinton 
2409657Slinton public Symbol newSymbol(name, blevel, class, type, chain)
2419657Slinton Name name;
2429657Slinton Integer blevel;
2439657Slinton Symclass class;
2449657Slinton Symbol type;
2459657Slinton Symbol chain;
2469657Slinton {
2479657Slinton     register Symbol s;
2489657Slinton 
2499657Slinton     s = symbol_alloc();
2509657Slinton     s->name = name;
25118235Slinton     s->language = primlang;
25233337Sdonn     s->storage = EXT;
2539657Slinton     s->level = blevel;
2549657Slinton     s->class = class;
2559657Slinton     s->type = type;
2569657Slinton     s->chain = chain;
2579657Slinton     return s;
2589657Slinton }
2599657Slinton 
2609657Slinton /*
2619657Slinton  * Insert a symbol into the hash table.
2629657Slinton  */
2639657Slinton 
2649657Slinton public Symbol insert(name)
2659657Slinton Name name;
2669657Slinton {
2679657Slinton     register Symbol s;
2689657Slinton     register unsigned int h;
2699657Slinton 
2709657Slinton     h = hash(name);
2719657Slinton     s = symbol_alloc();
2729657Slinton     s->name = name;
2739657Slinton     s->next_sym = hashtab[h];
2749657Slinton     hashtab[h] = s;
2759657Slinton     return s;
2769657Slinton }
2779657Slinton 
2789657Slinton /*
2799657Slinton  * Symbol lookup.
2809657Slinton  */
2819657Slinton 
2829657Slinton public Symbol lookup(name)
2839657Slinton Name name;
2849657Slinton {
2859657Slinton     register Symbol s;
2869657Slinton     register unsigned int h;
2879657Slinton 
2889657Slinton     h = hash(name);
2899657Slinton     s = hashtab[h];
2909657Slinton     while (s != nil and s->name != name) {
2919657Slinton 	s = s->next_sym;
2929657Slinton     }
2939657Slinton     return s;
2949657Slinton }
2959657Slinton 
2969657Slinton /*
29716620Ssam  * Delete a symbol from the symbol table.
29816620Ssam  */
29916620Ssam 
30016620Ssam public delete (s)
30116620Ssam Symbol s;
30216620Ssam {
30316620Ssam     register Symbol t;
30416620Ssam     register unsigned int h;
30516620Ssam 
30616620Ssam     h = hash(s->name);
30716620Ssam     t = hashtab[h];
30816620Ssam     if (t == nil) {
30916620Ssam 	panic("delete of non-symbol '%s'", symname(s));
31016620Ssam     } else if (t == s) {
31116620Ssam 	hashtab[h] = s->next_sym;
31216620Ssam     } else {
31316620Ssam 	while (t->next_sym != s) {
31416620Ssam 	    t = t->next_sym;
31516620Ssam 	    if (t == nil) {
31616620Ssam 		panic("delete of non-symbol '%s'", symname(s));
31716620Ssam 	    }
31816620Ssam 	}
31916620Ssam 	t->next_sym = s->next_sym;
32016620Ssam     }
32116620Ssam }
32216620Ssam 
32316620Ssam /*
3249657Slinton  * Dump out all the variables associated with the given
32518235Slinton  * procedure, function, or program associated with the given stack frame.
3269657Slinton  *
3279657Slinton  * This is quite inefficient.  We traverse the entire symbol table
3289657Slinton  * each time we're called.  The assumption is that this routine
3299657Slinton  * won't be called frequently enough to merit improved performance.
3309657Slinton  */
3319657Slinton 
3329657Slinton public dumpvars(f, frame)
3339657Slinton Symbol f;
3349657Slinton Frame frame;
3359657Slinton {
3369657Slinton     register Integer i;
3379657Slinton     register Symbol s;
3389657Slinton 
3399657Slinton     for (i = 0; i < HASHTABLESIZE; i++) {
3409657Slinton 	for (s = hashtab[i]; s != nil; s = s->next_sym) {
3419657Slinton 	    if (container(s) == f) {
3429657Slinton 		if (should_print(s)) {
3439657Slinton 		    printv(s, frame);
3449657Slinton 		    putchar('\n');
3459657Slinton 		} else if (s->class == MODULE) {
3469657Slinton 		    dumpvars(s, frame);
3479657Slinton 		}
3489657Slinton 	    }
3499657Slinton 	}
3509657Slinton     }
3519657Slinton }
3529657Slinton 
3539657Slinton /*
3549657Slinton  * Create a builtin type.
3559657Slinton  * Builtin types are circular in that btype->type->type = btype.
3569657Slinton  */
3579657Slinton 
35818235Slinton private Symbol maketype(name, lower, upper)
3599657Slinton String name;
3609657Slinton long lower;
3619657Slinton long upper;
3629657Slinton {
3639657Slinton     register Symbol s;
36418235Slinton     Name n;
3659657Slinton 
36618235Slinton     if (name == nil) {
36718235Slinton 	n = nil;
36818235Slinton     } else {
36918235Slinton 	n = identname(name, true);
37018235Slinton     }
37118235Slinton     s = insert(n);
37216620Ssam     s->language = primlang;
37318235Slinton     s->level = 0;
37418235Slinton     s->class = TYPE;
37518235Slinton     s->type = nil;
37618235Slinton     s->chain = nil;
3779657Slinton     s->type = newSymbol(nil, 0, RANGE, s, nil);
3789657Slinton     s->type->symvalue.rangev.lower = lower;
3799657Slinton     s->type->symvalue.rangev.upper = upper;
3809657Slinton     return s;
3819657Slinton }
3829657Slinton 
3839657Slinton /*
38418235Slinton  * Create the builtin symbols.
38518235Slinton  */
38618235Slinton 
38718235Slinton public symbols_init ()
3889657Slinton {
38918235Slinton     Symbol s;
3909657Slinton 
39118235Slinton     t_boolean = maketype("$boolean", 0L, 1L);
39218235Slinton     t_int = maketype("$integer", 0x80000000L, 0x7fffffffL);
39318235Slinton     t_char = maketype("$char", 0L, 255L);
39418235Slinton     t_real = maketype("$real", 8L, 0L);
39518235Slinton     t_nil = maketype("$nil", 0L, 0L);
39618235Slinton     t_addr = insert(identname("$address", true));
39718235Slinton     t_addr->language = primlang;
39818235Slinton     t_addr->level = 0;
39918235Slinton     t_addr->class = TYPE;
40018235Slinton     t_addr->type = newSymbol(nil, 1, PTR, t_int, nil);
40118235Slinton     s = insert(identname("true", true));
40218235Slinton     s->class = CONST;
40318235Slinton     s->type = t_boolean;
40418235Slinton     s->symvalue.constval = build(O_LCON, 1L);
40518235Slinton     s->symvalue.constval->nodetype = t_boolean;
40618235Slinton     s = insert(identname("false", true));
40718235Slinton     s->class = CONST;
40818235Slinton     s->type = t_boolean;
40918235Slinton     s->symvalue.constval = build(O_LCON, 0L);
41018235Slinton     s->symvalue.constval->nodetype = t_boolean;
4119657Slinton }
4129657Slinton 
4139657Slinton /*
4149657Slinton  * Reduce type to avoid worrying about type names.
4159657Slinton  */
4169657Slinton 
4179657Slinton public Symbol rtype(type)
4189657Slinton Symbol type;
4199657Slinton {
4209657Slinton     register Symbol t;
4219657Slinton 
4229657Slinton     t = type;
4239657Slinton     if (t != nil) {
42418235Slinton 	if (t->class == VAR or t->class == CONST or
42518235Slinton 	    t->class == FIELD or t->class == REF
42618235Slinton 	) {
4279657Slinton 	    t = t->type;
4289657Slinton 	}
42916620Ssam 	if (t->class == TYPEREF) {
43016620Ssam 	    resolveRef(t);
43116620Ssam 	}
4329657Slinton 	while (t->class == TYPE or t->class == TAG) {
4339657Slinton 	    t = t->type;
43416620Ssam 	    if (t->class == TYPEREF) {
43516620Ssam 		resolveRef(t);
43616620Ssam 	    }
4379657Slinton 	}
4389657Slinton     }
4399657Slinton     return t;
4409657Slinton }
4419657Slinton 
44216620Ssam /*
44316620Ssam  * Find the end of a module name.  Return nil if there is none
44416620Ssam  * in the given string.
44516620Ssam  */
44616620Ssam 
44716620Ssam private String findModuleMark (s)
44816620Ssam String s;
44916620Ssam {
45016620Ssam     register char *p, *r;
45116620Ssam     register boolean done;
45216620Ssam 
45316620Ssam     p = s;
45416620Ssam     done = false;
45516620Ssam     do {
45616620Ssam 	if (*p == ':') {
45716620Ssam 	    done = true;
45816620Ssam 	    r = p;
45916620Ssam 	} else if (*p == '\0') {
46016620Ssam 	    done = true;
46116620Ssam 	    r = nil;
46216620Ssam 	} else {
46316620Ssam 	    ++p;
46416620Ssam 	}
46516620Ssam     } while (not done);
46616620Ssam     return r;
46716620Ssam }
46816620Ssam 
46916620Ssam /*
47016620Ssam  * Resolve a type reference by modifying to be the appropriate type.
47116620Ssam  *
47216620Ssam  * If the reference has a name, then it refers to an opaque type and
47316620Ssam  * the actual type is directly accessible.  Otherwise, we must use
47416620Ssam  * the type reference string, which is of the form "module:{module:}name".
47516620Ssam  */
47616620Ssam 
47716620Ssam public resolveRef (t)
47816620Ssam Symbol t;
47916620Ssam {
48016620Ssam     register char *p;
48116620Ssam     char *start;
48216620Ssam     Symbol s, m, outer;
48316620Ssam     Name n;
48416620Ssam 
48516620Ssam     if (t->name != nil) {
48616620Ssam 	s = t;
48716620Ssam     } else {
48816620Ssam 	start = t->symvalue.typeref;
48916620Ssam 	outer = program;
49016620Ssam 	p = findModuleMark(start);
49116620Ssam 	while (p != nil) {
49216620Ssam 	    *p = '\0';
49316620Ssam 	    n = identname(start, true);
49416620Ssam 	    find(m, n) where m->block == outer endfind(m);
49516620Ssam 	    if (m == nil) {
49616620Ssam 		p = nil;
49716620Ssam 		outer = nil;
49816620Ssam 		s = nil;
49916620Ssam 	    } else {
50016620Ssam 		outer = m;
50116620Ssam 		start = p + 1;
50216620Ssam 		p = findModuleMark(start);
50316620Ssam 	    }
50416620Ssam 	}
50516620Ssam 	if (outer != nil) {
50616620Ssam 	    n = identname(start, true);
50716620Ssam 	    find(s, n) where s->block == outer endfind(s);
50816620Ssam 	}
50916620Ssam     }
51016620Ssam     if (s != nil and s->type != nil) {
51116620Ssam 	t->name = s->type->name;
51216620Ssam 	t->class = s->type->class;
51316620Ssam 	t->type = s->type->type;
51416620Ssam 	t->chain = s->type->chain;
51516620Ssam 	t->symvalue = s->type->symvalue;
51616620Ssam 	t->block = s->type->block;
51716620Ssam     }
51816620Ssam }
51916620Ssam 
52018235Slinton public integer regnum (s)
5219657Slinton Symbol s;
5229657Slinton {
52318235Slinton     integer r;
52418235Slinton 
5259657Slinton     checkref(s);
52633337Sdonn     if (s->storage == INREG) {
52718235Slinton 	r = s->symvalue.offset;
52818235Slinton     } else {
52918235Slinton 	r = -1;
53018235Slinton     }
53118235Slinton     return r;
5329657Slinton }
5339657Slinton 
5349657Slinton public Symbol container(s)
5359657Slinton Symbol s;
5369657Slinton {
5379657Slinton     checkref(s);
5389657Slinton     return s->block;
5399657Slinton }
5409657Slinton 
54118235Slinton public Node constval(s)
54218235Slinton Symbol s;
54318235Slinton {
54418235Slinton     checkref(s);
54518235Slinton     if (s->class != CONST) {
54618235Slinton 	error("[internal error: constval(non-CONST)]");
54718235Slinton     }
54818235Slinton     return s->symvalue.constval;
54918235Slinton }
55018235Slinton 
5519657Slinton /*
5529657Slinton  * Return the object address of the given symbol.
5539657Slinton  *
5549657Slinton  * There are the following possibilities:
5559657Slinton  *
5569657Slinton  *	globals		- just take offset
5579657Slinton  *	locals		- take offset from locals base
5589657Slinton  *	arguments	- take offset from argument base
5599657Slinton  *	register	- offset is register number
5609657Slinton  */
5619657Slinton 
56233337Sdonn #define isglobal(s)		(s->storage == EXT)
56333337Sdonn #define islocaloff(s)		(s->storage == STK and s->symvalue.offset < 0)
56433337Sdonn #define isparamoff(s)		(s->storage == STK and s->symvalue.offset >= 0)
5659657Slinton 
56618235Slinton public Address address (s, frame)
5679657Slinton Symbol s;
5689657Slinton Frame frame;
5699657Slinton {
5709657Slinton     register Frame frp;
5719657Slinton     register Address addr;
5729657Slinton     register Symbol cur;
5739657Slinton 
5749657Slinton     checkref(s);
5759657Slinton     if (not isactive(s->block)) {
5769657Slinton 	error("\"%s\" is not currently defined", symname(s));
5779657Slinton     } else if (isglobal(s)) {
5789657Slinton 	addr = s->symvalue.offset;
5799657Slinton     } else {
5809657Slinton 	frp = frame;
5819657Slinton 	if (frp == nil) {
5829657Slinton 	    cur = s->block;
5839657Slinton 	    while (cur != nil and cur->class == MODULE) {
5849657Slinton 		cur = cur->block;
5859657Slinton 	    }
5869657Slinton 	    if (cur == nil) {
58718235Slinton 		frp = nil;
58818235Slinton 	    } else {
58918235Slinton 		frp = findframe(cur);
59018235Slinton 		if (frp == nil) {
59118235Slinton 		    error("[internal error: unexpected nil frame for \"%s\"]",
59218235Slinton 			symname(s)
59318235Slinton 		    );
59418235Slinton 		}
5959657Slinton 	    }
5969657Slinton 	}
5979657Slinton 	if (islocaloff(s)) {
5989657Slinton 	    addr = locals_base(frp) + s->symvalue.offset;
5999657Slinton 	} else if (isparamoff(s)) {
6009657Slinton 	    addr = args_base(frp) + s->symvalue.offset;
6019657Slinton 	} else if (isreg(s)) {
6029657Slinton 	    addr = savereg(s->symvalue.offset, frp);
6039657Slinton 	} else {
6049657Slinton 	    panic("address: bad symbol \"%s\"", symname(s));
6059657Slinton 	}
6069657Slinton     }
6079657Slinton     return addr;
6089657Slinton }
6099657Slinton 
6109657Slinton /*
6119657Slinton  * Define a symbol used to access register values.
6129657Slinton  */
6139657Slinton 
61418235Slinton public defregname (n, r)
6159657Slinton Name n;
61618235Slinton integer r;
6179657Slinton {
61818235Slinton     Symbol s;
6199657Slinton 
6209657Slinton     s = insert(n);
62118235Slinton     s->language = t_addr->language;
6229657Slinton     s->class = VAR;
62333337Sdonn     s->storage = INREG;
62433337Sdonn     s->level = 3;
62518235Slinton     s->type = t_addr;
6269657Slinton     s->symvalue.offset = r;
6279657Slinton }
6289657Slinton 
6299657Slinton /*
6309657Slinton  * Resolve an "abstract" type reference.
6319657Slinton  *
6329657Slinton  * It is possible in C to define a pointer to a type, but never define
6339657Slinton  * the type in a particular source file.  Here we try to resolve
6349657Slinton  * the type definition.  This is problematic, it is possible to
6359657Slinton  * have multiple, different definitions for the same name type.
6369657Slinton  */
6379657Slinton 
6389657Slinton public findtype(s)
6399657Slinton Symbol s;
6409657Slinton {
6419657Slinton     register Symbol t, u, prev;
6429657Slinton 
6439657Slinton     u = s;
6449657Slinton     prev = nil;
6459657Slinton     while (u != nil and u->class != BADUSE) {
6469657Slinton 	if (u->name != nil) {
6479657Slinton 	    prev = u;
6489657Slinton 	}
6499657Slinton 	u = u->type;
6509657Slinton     }
6519657Slinton     if (prev == nil) {
6529657Slinton 	error("couldn't find link to type reference");
6539657Slinton     }
65418235Slinton     t = lookup(prev->name);
65518235Slinton     while (t != nil and
65618235Slinton 	not (
65718235Slinton 	    t != prev and t->name == prev->name and
65818235Slinton 	    t->block->class == MODULE and t->class == prev->class and
65918235Slinton 	    t->type != nil and t->type->type != nil and
66018235Slinton 	    t->type->type->class != BADUSE
66118235Slinton 	)
66218235Slinton     ) {
66318235Slinton 	t = t->next_sym;
66418235Slinton     }
6659657Slinton     if (t == nil) {
6669657Slinton 	error("couldn't resolve reference");
6679657Slinton     } else {
6689657Slinton 	prev->type = t->type;
6699657Slinton     }
6709657Slinton }
6719657Slinton 
6729657Slinton /*
6739657Slinton  * Find the size in bytes of the given type.
6749657Slinton  *
6759657Slinton  * This is probably the WRONG thing to do.  The size should be kept
6769657Slinton  * as an attribute in the symbol information as is done for structures
6779657Slinton  * and fields.  I haven't gotten around to cleaning this up yet.
6789657Slinton  */
6799657Slinton 
68012547Scsvaf #define MAXUCHAR 255
68112547Scsvaf #define MAXUSHORT 65535L
6829657Slinton #define MINCHAR -128
6839657Slinton #define MAXCHAR 127
6849657Slinton #define MINSHORT -32768
6859657Slinton #define MAXSHORT 32767
6869657Slinton 
68716620Ssam public findbounds (u, lower, upper)
68816620Ssam Symbol u;
68916620Ssam long *lower, *upper;
69016620Ssam {
69116620Ssam     Rangetype lbt, ubt;
69216620Ssam     long lb, ub;
69316620Ssam 
69416620Ssam     if (u->class == RANGE) {
69516620Ssam 	lbt = u->symvalue.rangev.lowertype;
69616620Ssam 	ubt = u->symvalue.rangev.uppertype;
69716620Ssam 	lb = u->symvalue.rangev.lower;
69816620Ssam 	ub = u->symvalue.rangev.upper;
69916620Ssam 	if (lbt == R_ARG or lbt == R_TEMP) {
70016620Ssam 	    if (not getbound(u, lb, lbt, lower)) {
70116620Ssam 		error("dynamic bounds not currently available");
70216620Ssam 	    }
70316620Ssam 	} else {
70416620Ssam 	    *lower = lb;
70516620Ssam 	}
70616620Ssam 	if (ubt == R_ARG or ubt == R_TEMP) {
70716620Ssam 	    if (not getbound(u, ub, ubt, upper)) {
70816620Ssam 		error("dynamic bounds not currently available");
70916620Ssam 	    }
71016620Ssam 	} else {
71116620Ssam 	    *upper = ub;
71216620Ssam 	}
71316620Ssam     } else if (u->class == SCAL) {
71416620Ssam 	*lower = 0;
71516620Ssam 	*upper = u->symvalue.iconval - 1;
71616620Ssam     } else {
71718235Slinton 	error("[internal error: unexpected array bound type]");
71816620Ssam     }
71916620Ssam }
72016620Ssam 
72116620Ssam public integer size(sym)
72216620Ssam Symbol sym;
72316620Ssam {
72416620Ssam     register Symbol s, t, u;
72516620Ssam     register integer nel, elsize;
7269657Slinton     long lower, upper;
72716620Ssam     integer r, off, len;
7289657Slinton 
7299657Slinton     t = sym;
7309657Slinton     checkref(t);
73116620Ssam     if (t->class == TYPEREF) {
73216620Ssam 	resolveRef(t);
73316620Ssam     }
7349657Slinton     switch (t->class) {
7359657Slinton 	case RANGE:
7369657Slinton 	    lower = t->symvalue.rangev.lower;
7379657Slinton 	    upper = t->symvalue.rangev.upper;
73816620Ssam 	    if (upper == 0 and lower > 0) {
73916620Ssam 		/* real */
7409657Slinton 		r = lower;
74116620Ssam 	    } else if (lower > upper) {
74216620Ssam 		/* unsigned long */
74316620Ssam 		r = sizeof(long);
74412045Slinton 	    } else if (
74512547Scsvaf   		(lower >= MINCHAR and upper <= MAXCHAR) or
74612547Scsvaf   		(lower >= 0 and upper <= MAXUCHAR)
74712547Scsvaf   	      ) {
7489657Slinton 		r = sizeof(char);
74912547Scsvaf   	    } else if (
75012547Scsvaf   		(lower >= MINSHORT and upper <= MAXSHORT) or
75112547Scsvaf   		(lower >= 0 and upper <= MAXUSHORT)
75212547Scsvaf   	      ) {
7539657Slinton 		r = sizeof(short);
7549657Slinton 	    } else {
7559657Slinton 		r = sizeof(long);
7569657Slinton 	    }
7579657Slinton 	    break;
7589657Slinton 
7599657Slinton 	case ARRAY:
7609657Slinton 	    elsize = size(t->type);
7619657Slinton 	    nel = 1;
7629657Slinton 	    for (t = t->chain; t != nil; t = t->chain) {
76316620Ssam 		u = rtype(t);
76416620Ssam 		findbounds(u, &lower, &upper);
7659657Slinton 		nel *= (upper-lower+1);
7669657Slinton 	    }
7679657Slinton 	    r = nel*elsize;
7689657Slinton 	    break;
7699657Slinton 
77033337Sdonn 	case OPENARRAY:
77118235Slinton 	case DYNARRAY:
77218235Slinton 	    r = (t->symvalue.ndims + 1) * sizeof(Word);
77318235Slinton 	    break;
77418235Slinton 
77518235Slinton 	case SUBARRAY:
77618235Slinton 	    r = (2 * t->symvalue.ndims + 1) * sizeof(Word);
77718235Slinton 	    break;
77818235Slinton 
77912547Scsvaf 	case REF:
7809657Slinton 	case VAR:
7819657Slinton 	    r = size(t->type);
78212127Slinton 	    /*
78312127Slinton 	     *
78412045Slinton 	    if (r < sizeof(Word) and isparam(t)) {
7859657Slinton 		r = sizeof(Word);
7869657Slinton 	    }
78712547Scsvaf 	    */
7889657Slinton 	    break;
7899657Slinton 
79018235Slinton 	case FVAR:
7919657Slinton 	case CONST:
79218235Slinton 	case TAG:
7939657Slinton 	    r = size(t->type);
7949657Slinton 	    break;
7959657Slinton 
7969657Slinton 	case TYPE:
79733337Sdonn 	    /*
79833337Sdonn 	     * This causes problems on the IRIS because of the compiler bug
79933337Sdonn 	     * with stab offsets for parameters.  Not sure it's really
80033337Sdonn 	     * necessary anyway.
80133337Sdonn 	     */
80233337Sdonn #	    ifndef IRIS
8039657Slinton 	    if (t->type->class == PTR and t->type->type->class == BADUSE) {
8049657Slinton 		findtype(t);
8059657Slinton 	    }
80633337Sdonn #	    endif
8079657Slinton 	    r = size(t->type);
8089657Slinton 	    break;
8099657Slinton 
8109657Slinton 	case FIELD:
81116620Ssam 	    off = t->symvalue.field.offset;
81216620Ssam 	    len = t->symvalue.field.length;
81316620Ssam 	    r = (off + len + 7) div 8 - (off div 8);
8149657Slinton 	    break;
8159657Slinton 
8169657Slinton 	case RECORD:
8179657Slinton 	case VARNT:
8189657Slinton 	    r = t->symvalue.offset;
8199657Slinton 	    if (r == 0 and t->chain != nil) {
8209657Slinton 		panic("missing size information for record");
8219657Slinton 	    }
8229657Slinton 	    break;
8239657Slinton 
8249657Slinton 	case PTR:
82518235Slinton 	case TYPEREF:
8269657Slinton 	case FILET:
8279657Slinton 	    r = sizeof(Word);
8289657Slinton 	    break;
8299657Slinton 
8309657Slinton 	case SCAL:
83112609Slinton 	    r = sizeof(Word);
83212609Slinton 	    /*
83312609Slinton 	     *
8349657Slinton 	    if (t->symvalue.iconval > 255) {
8359657Slinton 		r = sizeof(short);
8369657Slinton 	    } else {
8379657Slinton 		r = sizeof(char);
8389657Slinton 	    }
83912609Slinton 	     *
84012609Slinton 	     */
8419657Slinton 	    break;
8429657Slinton 
8439657Slinton 	case FPROC:
8449657Slinton 	case FFUNC:
8459657Slinton 	    r = sizeof(Word);
8469657Slinton 	    break;
8479657Slinton 
8489657Slinton 	case PROC:
8499657Slinton 	case FUNC:
8509657Slinton 	case MODULE:
8519657Slinton 	case PROG:
8529657Slinton 	    r = sizeof(Symbol);
8539657Slinton 	    break;
8549657Slinton 
85516620Ssam 	case SET:
85616620Ssam 	    u = rtype(t->type);
85716620Ssam 	    switch (u->class) {
85816620Ssam 		case RANGE:
85916620Ssam 		    r = u->symvalue.rangev.upper - u->symvalue.rangev.lower + 1;
86016620Ssam 		    break;
86116620Ssam 
86216620Ssam 		case SCAL:
86316620Ssam 		    r = u->symvalue.iconval;
86416620Ssam 		    break;
86516620Ssam 
86616620Ssam 		default:
86716620Ssam 		    error("expected range for set base type");
86816620Ssam 		    break;
86916620Ssam 	    }
87016620Ssam 	    r = (r + BITSPERBYTE - 1) div BITSPERBYTE;
87116620Ssam 	    break;
87216620Ssam 
87318235Slinton 	/*
87418235Slinton 	 * These can happen in C (unfortunately) for unresolved type references
87518235Slinton 	 * Assume they are pointers.
87618235Slinton 	 */
87718235Slinton 	case BADUSE:
87818235Slinton 	    r = sizeof(Address);
87918235Slinton 	    break;
88018235Slinton 
8819657Slinton 	default:
8829657Slinton 	    if (ord(t->class) > ord(TYPEREF)) {
8839657Slinton 		panic("size: bad class (%d)", ord(t->class));
8849657Slinton 	    } else {
88518235Slinton 		fprintf(stderr, "can't compute size of a %s\n", classname(t));
8869657Slinton 	    }
88716620Ssam 	    r = 0;
88816620Ssam 	    break;
8899657Slinton     }
8909657Slinton     return r;
8919657Slinton }
8929657Slinton 
8939657Slinton /*
89418235Slinton  * Return the size associated with a symbol that takes into account
89518235Slinton  * reference parameters.  This might be better as the normal size function, but
89618235Slinton  * too many places already depend on it working the way it does.
89718235Slinton  */
89818235Slinton 
89918235Slinton public integer psize (s)
90018235Slinton Symbol s;
90118235Slinton {
90218235Slinton     integer r;
90318235Slinton     Symbol t;
90418235Slinton 
90518235Slinton     if (s->class == REF) {
90618235Slinton 	t = rtype(s->type);
90733337Sdonn 	if (t->class == OPENARRAY) {
90818235Slinton 	    r = (t->symvalue.ndims + 1) * sizeof(Word);
90918235Slinton 	} else if (t->class == SUBARRAY) {
91018235Slinton 	    r = (2 * t->symvalue.ndims + 1) * sizeof(Word);
91118235Slinton 	} else {
91218235Slinton 	    r = sizeof(Word);
91318235Slinton 	}
91418235Slinton     } else {
91518235Slinton 	r = size(s);
91618235Slinton     }
91718235Slinton     return r;
91818235Slinton }
91918235Slinton 
92018235Slinton /*
9219657Slinton  * Test if a symbol is a parameter.  This is true if there
9229657Slinton  * is a cycle from s->block to s via chain pointers.
9239657Slinton  */
9249657Slinton 
9259657Slinton public Boolean isparam(s)
9269657Slinton Symbol s;
9279657Slinton {
9289657Slinton     register Symbol t;
9299657Slinton 
9309657Slinton     t = s->block;
9319657Slinton     while (t != nil and t != s) {
9329657Slinton 	t = t->chain;
9339657Slinton     }
9349657Slinton     return (Boolean) (t != nil);
9359657Slinton }
9369657Slinton 
9379657Slinton /*
93816620Ssam  * Test if a type is an open array parameter type.
9399657Slinton  */
9409657Slinton 
94118235Slinton public boolean isopenarray (type)
94218235Slinton Symbol type;
94316620Ssam {
94418235Slinton     Symbol t;
94518235Slinton 
94618235Slinton     t = rtype(type);
94733337Sdonn     return (boolean) (t->class == OPENARRAY);
94816620Ssam }
94916620Ssam 
95016620Ssam /*
95118235Slinton  * Test if a symbol is a var parameter, i.e. has class REF.
95216620Ssam  */
95316620Ssam 
9549657Slinton public Boolean isvarparam(s)
9559657Slinton Symbol s;
9569657Slinton {
9579657Slinton     return (Boolean) (s->class == REF);
9589657Slinton }
9599657Slinton 
9609657Slinton /*
9619657Slinton  * Test if a symbol is a variable (actually any addressible quantity
9629657Slinton  * with do).
9639657Slinton  */
9649657Slinton 
9659657Slinton public Boolean isvariable(s)
96618235Slinton Symbol s;
9679657Slinton {
9689657Slinton     return (Boolean) (s->class == VAR or s->class == FVAR or s->class == REF);
9699657Slinton }
9709657Slinton 
9719657Slinton /*
97218235Slinton  * Test if a symbol is a constant.
97318235Slinton  */
97418235Slinton 
97518235Slinton public Boolean isconst(s)
97618235Slinton Symbol s;
9779657Slinton {
97818235Slinton     return (Boolean) (s->class == CONST);
9799657Slinton }
9809657Slinton 
9819657Slinton /*
9829657Slinton  * Test if a symbol is a module.
9839657Slinton  */
9849657Slinton 
9859657Slinton public Boolean ismodule(s)
9869657Slinton register Symbol s;
9879657Slinton {
9889657Slinton     return (Boolean) (s->class == MODULE);
9899657Slinton }
9909657Slinton 
9919657Slinton /*
99216620Ssam  * Mark a procedure or function as internal, meaning that it is called
99316620Ssam  * with a different calling sequence.
99416620Ssam  */
99516620Ssam 
99616620Ssam public markInternal (s)
99716620Ssam Symbol s;
99816620Ssam {
99916620Ssam     s->symvalue.funcv.intern = true;
100016620Ssam }
100116620Ssam 
100216620Ssam public boolean isinternal (s)
100316620Ssam Symbol s;
100416620Ssam {
100516620Ssam     return s->symvalue.funcv.intern;
100616620Ssam }
100716620Ssam 
100816620Ssam /*
100918235Slinton  * Decide if a field begins or ends on a bit rather than byte boundary.
101018235Slinton  */
101118235Slinton 
101218235Slinton public Boolean isbitfield(s)
101318235Slinton register Symbol s;
101418235Slinton {
101518235Slinton     boolean b;
101618235Slinton     register integer off, len;
101718235Slinton     register Symbol t;
101818235Slinton 
101918235Slinton     off = s->symvalue.field.offset;
102018235Slinton     len = s->symvalue.field.length;
102118235Slinton     if ((off mod BITSPERBYTE) != 0 or (len mod BITSPERBYTE) != 0) {
102218235Slinton 	b = true;
102318235Slinton     } else {
102418235Slinton 	t = rtype(s->type);
102518235Slinton 	b = (Boolean) (
102618235Slinton 	    (t->class == SCAL and len != (sizeof(int)*BITSPERBYTE)) or
102718235Slinton 	    len != (size(t)*BITSPERBYTE)
102818235Slinton 	);
102918235Slinton     }
103018235Slinton     return b;
103118235Slinton }
103218235Slinton 
103318235Slinton private boolean primlang_typematch (t1, t2)
103418235Slinton Symbol t1, t2;
103518235Slinton {
103618235Slinton     return (boolean) (
103718235Slinton 	(t1 == t2) or
103818235Slinton 	(
103918235Slinton 	    t1->class == RANGE and t2->class == RANGE and
104018235Slinton 	    t1->symvalue.rangev.lower == t2->symvalue.rangev.lower and
104118235Slinton 	    t1->symvalue.rangev.upper == t2->symvalue.rangev.upper
104218235Slinton 	) or (
104318235Slinton 	    t1->class == PTR and t2->class == RANGE and
104418235Slinton 	    t2->symvalue.rangev.upper >= t2->symvalue.rangev.lower
104518235Slinton 	) or (
104618235Slinton 	    t2->class == PTR and t1->class == RANGE and
104718235Slinton 	    t1->symvalue.rangev.upper >= t1->symvalue.rangev.lower
104818235Slinton 	)
104918235Slinton     );
105018235Slinton }
105118235Slinton 
105218235Slinton /*
10539657Slinton  * Test if two types match.
10549657Slinton  * Equivalent names implies a match in any language.
10559657Slinton  *
10569657Slinton  * Special symbols must be handled with care.
10579657Slinton  */
10589657Slinton 
10599657Slinton public Boolean compatible(t1, t2)
10609657Slinton register Symbol t1, t2;
10619657Slinton {
10629657Slinton     Boolean b;
106316620Ssam     Symbol rt1, rt2;
10649657Slinton 
10659657Slinton     if (t1 == t2) {
10669657Slinton 	b = true;
10679657Slinton     } else if (t1 == nil or t2 == nil) {
10689657Slinton 	b = false;
10699657Slinton     } else if (t1 == procsym) {
10709657Slinton 	b = isblock(t2);
10719657Slinton     } else if (t2 == procsym) {
10729657Slinton 	b = isblock(t1);
10739657Slinton     } else if (t1->language == nil) {
107416620Ssam 	if (t2->language == nil) {
107516620Ssam 	    b = false;
107633337Sdonn 	} else if (t2->language == primlang) {
107733337Sdonn 	    b = (boolean) primlang_typematch(rtype(t1), rtype(t2));
107816620Ssam 	} else {
107916620Ssam 	    b = (boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2);
108016620Ssam 	}
108133337Sdonn     } else if (t1->language == primlang) {
108233337Sdonn 	if (t2->language == primlang or t2->language == nil) {
108333337Sdonn 	    b = primlang_typematch(rtype(t1), rtype(t2));
108433337Sdonn 	} else {
108533337Sdonn 	    b = (boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2);
108633337Sdonn 	}
10879657Slinton     } else {
108816620Ssam 	b = (boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2);
10899657Slinton     }
10909657Slinton     return b;
10919657Slinton }
10929657Slinton 
10939657Slinton /*
10949657Slinton  * Check for a type of the given name.
10959657Slinton  */
10969657Slinton 
10979657Slinton public Boolean istypename(type, name)
10989657Slinton Symbol type;
10999657Slinton String name;
11009657Slinton {
110118235Slinton     register Symbol t;
11029657Slinton     Boolean b;
11039657Slinton 
11049657Slinton     t = type;
110518235Slinton     if (t == nil) {
110618235Slinton 	b = false;
110718235Slinton     } else {
110818235Slinton 	b = (Boolean) (
110918235Slinton 	    t->class == TYPE and streq(ident(t->name), name)
111018235Slinton 	);
111118235Slinton     }
11129657Slinton     return b;
11139657Slinton }
11149657Slinton 
11159657Slinton /*
111616620Ssam  * Determine if a (value) parameter should actually be passed by address.
111716620Ssam  */
111816620Ssam 
111916620Ssam public boolean passaddr (p, exprtype)
112016620Ssam Symbol p, exprtype;
112116620Ssam {
112216620Ssam     boolean b;
112316620Ssam     Language def;
112416620Ssam 
112516620Ssam     if (p == nil) {
112616620Ssam 	def = findlanguage(".c");
112716620Ssam 	b = (boolean) (*language_op(def, L_PASSADDR))(p, exprtype);
112816620Ssam     } else if (p->language == nil or p->language == primlang) {
112916620Ssam 	b = false;
113016620Ssam     } else if (isopenarray(p->type)) {
113116620Ssam 	b = true;
113216620Ssam     } else {
113316620Ssam 	b = (boolean) (*language_op(p->language, L_PASSADDR))(p, exprtype);
113416620Ssam     }
113516620Ssam     return b;
113616620Ssam }
113716620Ssam 
113816620Ssam /*
11399657Slinton  * Test if the name of a symbol is uniquely defined or not.
11409657Slinton  */
11419657Slinton 
11429657Slinton public Boolean isambiguous(s)
11439657Slinton register Symbol s;
11449657Slinton {
11459657Slinton     register Symbol t;
11469657Slinton 
11479657Slinton     find(t, s->name) where t != s endfind(t);
11489657Slinton     return (Boolean) (t != nil);
11499657Slinton }
11509657Slinton 
11519657Slinton typedef char *Arglist;
11529657Slinton 
11539657Slinton #define nextarg(type)  ((type *) (ap += sizeof(type)))[-1]
11549657Slinton 
11559657Slinton private Symbol mkstring();
11569657Slinton 
11579657Slinton /*
11589657Slinton  * Determine the type of a parse tree.
115918235Slinton  *
11609657Slinton  * Also make some symbol-dependent changes to the tree such as
116118235Slinton  * removing indirection for constant or register symbols.
11629657Slinton  */
11639657Slinton 
116418235Slinton public assigntypes (p)
11659657Slinton register Node p;
11669657Slinton {
11679657Slinton     register Node p1;
11689657Slinton     register Symbol s;
11699657Slinton 
11709657Slinton     switch (p->op) {
11719657Slinton 	case O_SYM:
117218235Slinton 	    p->nodetype = p->value.sym;
11739657Slinton 	    break;
11749657Slinton 
11759657Slinton 	case O_LCON:
11769657Slinton 	    p->nodetype = t_int;
11779657Slinton 	    break;
11789657Slinton 
117918235Slinton 	case O_CCON:
118018235Slinton 	    p->nodetype = t_char;
118118235Slinton 	    break;
118218235Slinton 
11839657Slinton 	case O_FCON:
11849657Slinton 	    p->nodetype = t_real;
11859657Slinton 	    break;
11869657Slinton 
11879657Slinton 	case O_SCON:
118818235Slinton 	    p->nodetype = mkstring(p->value.scon);
11899657Slinton 	    break;
11909657Slinton 
11919657Slinton 	case O_INDIR:
11929657Slinton 	    p1 = p->value.arg[0];
119318235Slinton 	    s = rtype(p1->nodetype);
119418235Slinton 	    if (s->class != PTR) {
119518235Slinton 		beginerrmsg();
119618235Slinton 		fprintf(stderr, "\"");
119718235Slinton 		prtree(stderr, p1);
119818235Slinton 		fprintf(stderr, "\" is not a pointer");
119918235Slinton 		enderrmsg();
120018235Slinton 	    }
12019657Slinton 	    p->nodetype = rtype(p1->nodetype)->type;
12029657Slinton 	    break;
12039657Slinton 
12049657Slinton 	case O_DOT:
12059657Slinton 	    p->nodetype = p->value.arg[1]->value.sym;
12069657Slinton 	    break;
12079657Slinton 
12089657Slinton 	case O_RVAL:
12099657Slinton 	    p1 = p->value.arg[0];
12109657Slinton 	    p->nodetype = p1->nodetype;
12119657Slinton 	    if (p1->op == O_SYM) {
121218235Slinton 		if (p1->nodetype->class == PROC or p->nodetype->class == FUNC) {
121318235Slinton 		    p->op = p1->op;
121418235Slinton 		    p->value.sym = p1->value.sym;
121518235Slinton 		    p->nodetype = p1->nodetype;
121618235Slinton 		    dispose(p1);
12179657Slinton 		} else if (p1->value.sym->class == CONST) {
121818235Slinton 		    p->op = p1->op;
121918235Slinton 		    p->value = p1->value;
122018235Slinton 		    p->nodetype = p1->nodetype;
122118235Slinton 		    dispose(p1);
12229657Slinton 		} else if (isreg(p1->value.sym)) {
12239657Slinton 		    p->op = O_SYM;
12249657Slinton 		    p->value.sym = p1->value.sym;
12259657Slinton 		    dispose(p1);
12269657Slinton 		}
12279657Slinton 	    } else if (p1->op == O_INDIR and p1->value.arg[0]->op == O_SYM) {
12289657Slinton 		s = p1->value.arg[0]->value.sym;
12299657Slinton 		if (isreg(s)) {
12309657Slinton 		    p1->op = O_SYM;
12319657Slinton 		    dispose(p1->value.arg[0]);
12329657Slinton 		    p1->value.sym = s;
12339657Slinton 		    p1->nodetype = s;
12349657Slinton 		}
12359657Slinton 	    }
12369657Slinton 	    break;
12379657Slinton 
123818235Slinton 	case O_COMMA:
123918235Slinton 	    p->nodetype = p->value.arg[0]->nodetype;
124018235Slinton 	    break;
124118235Slinton 
124218235Slinton 	case O_CALLPROC:
12439657Slinton 	case O_CALL:
12449657Slinton 	    p1 = p->value.arg[0];
124511171Slinton 	    p->nodetype = rtype(p1->nodetype)->type;
12469657Slinton 	    break;
12479657Slinton 
124811171Slinton 	case O_TYPERENAME:
124911171Slinton 	    p->nodetype = p->value.arg[1]->nodetype;
125011171Slinton 	    break;
125111171Slinton 
12529657Slinton 	case O_ITOF:
12539657Slinton 	    p->nodetype = t_real;
12549657Slinton 	    break;
12559657Slinton 
12569657Slinton 	case O_NEG:
12579657Slinton 	    s = p->value.arg[0]->nodetype;
12589657Slinton 	    if (not compatible(s, t_int)) {
12599657Slinton 		if (not compatible(s, t_real)) {
12609657Slinton 		    beginerrmsg();
126116620Ssam 		    fprintf(stderr, "\"");
12629657Slinton 		    prtree(stderr, p->value.arg[0]);
126316620Ssam 		    fprintf(stderr, "\" is improper type");
12649657Slinton 		    enderrmsg();
12659657Slinton 		} else {
12669657Slinton 		    p->op = O_NEGF;
12679657Slinton 		}
12689657Slinton 	    }
12699657Slinton 	    p->nodetype = s;
12709657Slinton 	    break;
12719657Slinton 
12729657Slinton 	case O_ADD:
12739657Slinton 	case O_SUB:
12749657Slinton 	case O_MUL:
127516620Ssam 	    binaryop(p, nil);
127616620Ssam 	    break;
127716620Ssam 
12789657Slinton 	case O_LT:
12799657Slinton 	case O_LE:
12809657Slinton 	case O_GT:
12819657Slinton 	case O_GE:
12829657Slinton 	case O_EQ:
12839657Slinton 	case O_NE:
128416620Ssam 	    binaryop(p, t_boolean);
12859657Slinton 	    break;
12869657Slinton 
12879657Slinton 	case O_DIVF:
12889657Slinton 	    convert(&(p->value.arg[0]), t_real, O_ITOF);
12899657Slinton 	    convert(&(p->value.arg[1]), t_real, O_ITOF);
12909657Slinton 	    p->nodetype = t_real;
12919657Slinton 	    break;
12929657Slinton 
12939657Slinton 	case O_DIV:
12949657Slinton 	case O_MOD:
12959657Slinton 	    convert(&(p->value.arg[0]), t_int, O_NOP);
12969657Slinton 	    convert(&(p->value.arg[1]), t_int, O_NOP);
12979657Slinton 	    p->nodetype = t_int;
12989657Slinton 	    break;
12999657Slinton 
13009657Slinton 	case O_AND:
13019657Slinton 	case O_OR:
13029657Slinton 	    chkboolean(p->value.arg[0]);
13039657Slinton 	    chkboolean(p->value.arg[1]);
13049657Slinton 	    p->nodetype = t_boolean;
13059657Slinton 	    break;
13069657Slinton 
13079657Slinton 	case O_QLINE:
13089657Slinton 	    p->nodetype = t_int;
13099657Slinton 	    break;
13109657Slinton 
13119657Slinton 	default:
13129657Slinton 	    p->nodetype = nil;
13139657Slinton 	    break;
13149657Slinton     }
13159657Slinton }
13169657Slinton 
13179657Slinton /*
131816620Ssam  * Process a binary arithmetic or relational operator.
131916620Ssam  * Convert from integer to real if necessary.
132016620Ssam  */
132116620Ssam 
132216620Ssam private binaryop (p, t)
132316620Ssam Node p;
132416620Ssam Symbol t;
132516620Ssam {
132616620Ssam     Node p1, p2;
132716620Ssam     Boolean t1real, t2real;
132816620Ssam     Symbol t1, t2;
132916620Ssam 
133016620Ssam     p1 = p->value.arg[0];
133116620Ssam     p2 = p->value.arg[1];
133216620Ssam     t1 = rtype(p1->nodetype);
133316620Ssam     t2 = rtype(p2->nodetype);
133416620Ssam     t1real = compatible(t1, t_real);
133516620Ssam     t2real = compatible(t2, t_real);
133616620Ssam     if (t1real or t2real) {
133716620Ssam 	p->op = (Operator) (ord(p->op) + 1);
133816620Ssam 	if (not t1real) {
133916620Ssam 	    p->value.arg[0] = build(O_ITOF, p1);
134016620Ssam 	} else if (not t2real) {
134116620Ssam 	    p->value.arg[1] = build(O_ITOF, p2);
134216620Ssam 	}
134316620Ssam 	p->nodetype = t_real;
134416620Ssam     } else {
134516620Ssam 	if (size(p1->nodetype) > sizeof(integer)) {
134616620Ssam 	    beginerrmsg();
134716620Ssam 	    fprintf(stderr, "operation not defined on \"");
134816620Ssam 	    prtree(stderr, p1);
134916620Ssam 	    fprintf(stderr, "\"");
135016620Ssam 	    enderrmsg();
135116620Ssam 	} else if (size(p2->nodetype) > sizeof(integer)) {
135216620Ssam 	    beginerrmsg();
135316620Ssam 	    fprintf(stderr, "operation not defined on \"");
135416620Ssam 	    prtree(stderr, p2);
135516620Ssam 	    fprintf(stderr, "\"");
135616620Ssam 	    enderrmsg();
135716620Ssam 	}
135816620Ssam 	p->nodetype = t_int;
135916620Ssam     }
136016620Ssam     if (t != nil) {
136116620Ssam 	p->nodetype = t;
136216620Ssam     }
136316620Ssam }
136416620Ssam 
136516620Ssam /*
13669657Slinton  * Convert a tree to a type via a conversion operator;
13679657Slinton  * if this isn't possible generate an error.
13689657Slinton  */
13699657Slinton 
13709657Slinton private convert(tp, typeto, op)
13719657Slinton Node *tp;
13729657Slinton Symbol typeto;
13739657Slinton Operator op;
13749657Slinton {
137516620Ssam     Node tree;
137616620Ssam     Symbol s, t;
13779657Slinton 
137816620Ssam     tree = *tp;
13799657Slinton     s = rtype(tree->nodetype);
138016620Ssam     t = rtype(typeto);
138116620Ssam     if (compatible(t, t_real) and compatible(s, t_int)) {
138234257Sdonn 	/* we can convert int => floating but not the reverse */
13839657Slinton 	tree = build(op, tree);
138416620Ssam     } else if (not compatible(s, t)) {
13859657Slinton 	beginerrmsg();
138616620Ssam 	prtree(stderr, tree);
138734257Sdonn 	fprintf(stderr, ": illegal type in operation");
13889657Slinton 	enderrmsg();
13899657Slinton     }
139016620Ssam     *tp = tree;
13919657Slinton }
13929657Slinton 
13939657Slinton /*
13949657Slinton  * Construct a node for the dot operator.
13959657Slinton  *
13969657Slinton  * If the left operand is not a record, but rather a procedure
13979657Slinton  * or function, then we interpret the "." as referencing an
13989657Slinton  * "invisible" variable; i.e. a variable within a dynamically
13999657Slinton  * active block but not within the static scope of the current procedure.
14009657Slinton  */
14019657Slinton 
14029657Slinton public Node dot(record, fieldname)
14039657Slinton Node record;
14049657Slinton Name fieldname;
14059657Slinton {
140618235Slinton     register Node rec, p;
14079657Slinton     register Symbol s, t;
14089657Slinton 
140918235Slinton     rec = record;
141018235Slinton     if (isblock(rec->nodetype)) {
14119657Slinton 	find(s, fieldname) where
141218235Slinton 	    s->block == rec->nodetype and
141318235Slinton 	    s->class != FIELD
14149657Slinton 	endfind(s);
14159657Slinton 	if (s == nil) {
14169657Slinton 	    beginerrmsg();
14179657Slinton 	    fprintf(stderr, "\"%s\" is not defined in ", ident(fieldname));
141818235Slinton 	    printname(stderr, rec->nodetype);
14199657Slinton 	    enderrmsg();
14209657Slinton 	}
14219657Slinton 	p = new(Node);
14229657Slinton 	p->op = O_SYM;
14239657Slinton 	p->value.sym = s;
142418235Slinton 	p->nodetype = s;
14259657Slinton     } else {
142618235Slinton 	p = rec;
14279657Slinton 	t = rtype(p->nodetype);
14289657Slinton 	if (t->class == PTR) {
14299657Slinton 	    s = findfield(fieldname, t->type);
14309657Slinton 	} else {
14319657Slinton 	    s = findfield(fieldname, t);
14329657Slinton 	}
14339657Slinton 	if (s == nil) {
14349657Slinton 	    beginerrmsg();
14359657Slinton 	    fprintf(stderr, "\"%s\" is not a field in ", ident(fieldname));
143618235Slinton 	    prtree(stderr, rec);
14379657Slinton 	    enderrmsg();
14389657Slinton 	}
143918235Slinton 	if (t->class != PTR or isreg(rec->nodetype)) {
144018235Slinton 	    p = unrval(p);
14419657Slinton 	}
144218235Slinton 	p->nodetype = t_addr;
14439657Slinton 	p = build(O_DOT, p, build(O_SYM, s));
14449657Slinton     }
144518235Slinton     return build(O_RVAL, p);
14469657Slinton }
14479657Slinton 
14489657Slinton /*
14499657Slinton  * Return a tree corresponding to an array reference and do the
14509657Slinton  * error checking.
14519657Slinton  */
14529657Slinton 
14539657Slinton public Node subscript(a, slist)
14549657Slinton Node a, slist;
14559657Slinton {
145616620Ssam     Symbol t;
145718235Slinton     Node p;
14589657Slinton 
145916620Ssam     t = rtype(a->nodetype);
146018235Slinton     if (t->language == nil or t->language == primlang) {
146118235Slinton 	p = (Node) (*language_op(findlanguage(".s"), L_BUILDAREF))(a, slist);
146216620Ssam     } else {
146318235Slinton 	p = (Node) (*language_op(t->language, L_BUILDAREF))(a, slist);
146416620Ssam     }
146518235Slinton     return build(O_RVAL, p);
14669657Slinton }
14679657Slinton 
14689657Slinton /*
14699657Slinton  * Evaluate a subscript index.
14709657Slinton  */
14719657Slinton 
147218235Slinton public int evalindex(s, base, i)
14739657Slinton Symbol s;
147418235Slinton Address base;
14759657Slinton long i;
14769657Slinton {
147716620Ssam     Symbol t;
147818235Slinton     int r;
14799657Slinton 
148016620Ssam     t = rtype(s);
148118235Slinton     if (t->language == nil or t->language == primlang) {
148218235Slinton 	r = ((*language_op(findlanguage(".s"), L_EVALAREF)) (s, base, i));
148316620Ssam     } else {
148418235Slinton 	r = ((*language_op(t->language, L_EVALAREF)) (s, base, i));
148516620Ssam     }
148618235Slinton     return r;
14879657Slinton }
14889657Slinton 
14899657Slinton /*
14909657Slinton  * Check to see if a tree is boolean-valued, if not it's an error.
14919657Slinton  */
14929657Slinton 
14939657Slinton public chkboolean(p)
14949657Slinton register Node p;
14959657Slinton {
14969657Slinton     if (p->nodetype != t_boolean) {
14979657Slinton 	beginerrmsg();
14989657Slinton 	fprintf(stderr, "found ");
14999657Slinton 	prtree(stderr, p);
15009657Slinton 	fprintf(stderr, ", expected boolean expression");
15019657Slinton 	enderrmsg();
15029657Slinton     }
15039657Slinton }
15049657Slinton 
15059657Slinton /*
150616620Ssam  * Construct a node for the type of a string.
15079657Slinton  */
15089657Slinton 
15099657Slinton private Symbol mkstring(str)
15109657Slinton String str;
15119657Slinton {
15129657Slinton     register Symbol s;
15139657Slinton 
151418235Slinton     s = newSymbol(nil, 0, ARRAY, t_char, nil);
151518235Slinton     s->chain = newSymbol(nil, 0, RANGE, t_int, nil);
151618235Slinton     s->chain->language = s->language;
151718235Slinton     s->chain->symvalue.rangev.lower = 1;
151818235Slinton     s->chain->symvalue.rangev.upper = strlen(str) + 1;
15199657Slinton     return s;
15209657Slinton }
15219657Slinton 
15229657Slinton /*
15239657Slinton  * Free up the space allocated for a string type.
15249657Slinton  */
15259657Slinton 
15269657Slinton public unmkstring(s)
15279657Slinton Symbol s;
15289657Slinton {
15299657Slinton     dispose(s->chain);
15309657Slinton }
15319657Slinton 
15329657Slinton /*
153318235Slinton  * Figure out the "current" variable or function being referred to
153418235Slinton  * by the name n.
15359657Slinton  */
15369657Slinton 
153718235Slinton private boolean stwhich(), dynwhich();
153818235Slinton 
153918235Slinton public Symbol which (n)
15409657Slinton Name n;
15419657Slinton {
154218235Slinton     Symbol s;
15439657Slinton 
154418235Slinton     s = lookup(n);
15459657Slinton     if (s == nil) {
154618235Slinton 	error("\"%s\" is not defined", ident(n));
154718235Slinton     } else if (not stwhich(&s) and isambiguous(s) and not dynwhich(&s)) {
154818235Slinton 	printf("[using ");
154918235Slinton 	printname(stdout, s);
155018235Slinton 	printf("]\n");
15519657Slinton     }
155218235Slinton     return s;
155318235Slinton }
155418235Slinton 
155518235Slinton /*
155618235Slinton  * Static search.
155718235Slinton  */
155818235Slinton 
155918235Slinton private boolean stwhich (var_s)
156018235Slinton Symbol *var_s;
156118235Slinton {
156218235Slinton     Name n;		/* name of desired symbol */
156318235Slinton     Symbol s;		/* iteration variable for symbols with name n */
156418235Slinton     Symbol f;		/* iteration variable for blocks containing s */
156518235Slinton     integer count;	/* number of levels from s->block to curfunc */
156618235Slinton     Symbol t;		/* current best answer for stwhich(n) */
156718235Slinton     integer mincount;	/* relative level for current best answer (t) */
156818235Slinton     boolean b;		/* return value, true if symbol found */
156918235Slinton 
157018235Slinton     s = *var_s;
157118235Slinton     n = s->name;
157218235Slinton     t = s;
157318235Slinton     mincount = 10000; /* force first match to set mincount */
157418235Slinton     do {
157518235Slinton 	if (s->name == n and s->class != FIELD and s->class != TAG) {
157618235Slinton 	    f = curfunc;
157718235Slinton 	    count = 0;
157818235Slinton 	    while (f != nil and f != s->block) {
157918235Slinton 		++count;
158018235Slinton 		f = f->block;
158118235Slinton 	    }
158218235Slinton 	    if (f != nil and count < mincount) {
158318235Slinton 		t = s;
158418235Slinton 		mincount = count;
158518235Slinton 		b = true;
158618235Slinton 	    }
158718235Slinton 	}
158818235Slinton 	s = s->next_sym;
158918235Slinton     } while (s != nil);
159018235Slinton     if (mincount != 10000) {
159118235Slinton 	*var_s = t;
159218235Slinton 	b = true;
15939657Slinton     } else {
159418235Slinton 	b = false;
159518235Slinton     }
159618235Slinton     return b;
159718235Slinton }
159818235Slinton 
159918235Slinton /*
160018235Slinton  * Dynamic search.
160118235Slinton  */
160218235Slinton 
160318235Slinton private boolean dynwhich (var_s)
160418235Slinton Symbol *var_s;
160518235Slinton {
160618235Slinton     Name n;		/* name of desired symbol */
160718235Slinton     Symbol s;		/* iteration variable for possible symbols */
160818235Slinton     Symbol f;		/* iteration variable for active functions */
160918235Slinton     Frame frp;		/* frame associated with stack walk */
161018235Slinton     boolean b;		/* return value */
161118235Slinton 
161218235Slinton     f = curfunc;
161318235Slinton     frp = curfuncframe();
161418235Slinton     n = (*var_s)->name;
161518235Slinton     b = false;
161618235Slinton     if (frp != nil) {
161718235Slinton 	frp = nextfunc(frp, &f);
161818235Slinton 	while (frp != nil) {
161918235Slinton 	    s = *var_s;
162018235Slinton 	    while (s != nil and
162118235Slinton 		(
162218235Slinton 		    s->name != n or s->block != f or
162318235Slinton 		    s->class == FIELD or s->class == TAG
162418235Slinton 		)
162518235Slinton 	    ) {
162618235Slinton 		s = s->next_sym;
162718235Slinton 	    }
162818235Slinton 	    if (s != nil) {
162918235Slinton 		*var_s = s;
163018235Slinton 		b = true;
163118235Slinton 		break;
163218235Slinton 	    }
163318235Slinton 	    if (f == program) {
163418235Slinton 		break;
163518235Slinton 	    }
163618235Slinton 	    frp = nextfunc(frp, &f);
16379657Slinton 	}
16389657Slinton     }
163918235Slinton     return b;
16409657Slinton }
16419657Slinton 
16429657Slinton /*
164318235Slinton  * Find the symbol that has the same name and scope as the
16449657Slinton  * given symbol but is of the given field.  Return nil if there is none.
16459657Slinton  */
16469657Slinton 
164718235Slinton public Symbol findfield (fieldname, record)
16489657Slinton Name fieldname;
16499657Slinton Symbol record;
16509657Slinton {
16519657Slinton     register Symbol t;
16529657Slinton 
16539657Slinton     t = rtype(record)->chain;
16549657Slinton     while (t != nil and t->name != fieldname) {
16559657Slinton 	t = t->chain;
16569657Slinton     }
16579657Slinton     return t;
16589657Slinton }
165912547Scsvaf 
166012547Scsvaf public Boolean getbound(s,off,type,valp)
166112547Scsvaf Symbol s;
166212547Scsvaf int off;
166312547Scsvaf Rangetype type;
166412547Scsvaf int *valp;
166512547Scsvaf {
166612547Scsvaf     Frame frp;
166712547Scsvaf     Address addr;
166812547Scsvaf     Symbol cur;
166912547Scsvaf 
167012547Scsvaf     if (not isactive(s->block)) {
167112547Scsvaf 	return(false);
167212547Scsvaf     }
167312547Scsvaf     cur = s->block;
167412547Scsvaf     while (cur != nil and cur->class == MODULE) {  /* WHY*/
167512547Scsvaf     		cur = cur->block;
167612547Scsvaf     }
167712547Scsvaf     if(cur == nil) {
167812547Scsvaf 		cur = whatblock(pc);
167912547Scsvaf     }
168012547Scsvaf     frp = findframe(cur);
168112547Scsvaf     if (frp == nil) {
168212547Scsvaf 	return(false);
168312547Scsvaf     }
168412547Scsvaf     if(type == R_TEMP) addr = locals_base(frp) + off;
168512547Scsvaf     else if (type == R_ARG) addr = args_base(frp) + off;
168612547Scsvaf     else return(false);
168712547Scsvaf     dread(valp,addr,sizeof(long));
168812547Scsvaf     return(true);
168912547Scsvaf }
1690