xref: /csrg-svn/old/dbx/symbols.c (revision 34257)
121625Sdist /*
221625Sdist  * Copyright (c) 1983 Regents of the University of California.
321625Sdist  * All rights reserved.  The Berkeley software License Agreement
421625Sdist  * specifies the terms and conditions for redistribution.
521625Sdist  */
69657Slinton 
721625Sdist #ifndef lint
8*34257Sdonn static char sccsid[] = "@(#)symbols.c	5.5 (Berkeley) 05/11/88";
921625Sdist #endif not lint
109657Slinton 
11*34257Sdonn static char rcsid[] = "$Header: symbols.c,v 1.4 88/04/02 01:29:03 donn Exp $";
1218235Slinton 
139657Slinton /*
149657Slinton  * Symbol management.
159657Slinton  */
169657Slinton 
179657Slinton #include "defs.h"
189657Slinton #include "symbols.h"
199657Slinton #include "languages.h"
209657Slinton #include "printsym.h"
219657Slinton #include "tree.h"
229657Slinton #include "operators.h"
239657Slinton #include "eval.h"
249657Slinton #include "mappings.h"
259657Slinton #include "events.h"
269657Slinton #include "process.h"
279657Slinton #include "runtime.h"
289657Slinton #include "machine.h"
299657Slinton #include "names.h"
309657Slinton 
319657Slinton #ifndef public
329657Slinton typedef struct Symbol *Symbol;
339657Slinton 
349657Slinton #include "machine.h"
359657Slinton #include "names.h"
369657Slinton #include "languages.h"
3718235Slinton #include "tree.h"
389657Slinton 
399657Slinton /*
409657Slinton  * Symbol classes
419657Slinton  */
429657Slinton 
439657Slinton typedef enum {
4433337Sdonn     BADUSE, CONST, TYPE, VAR, ARRAY, OPENARRAY, DYNARRAY, SUBARRAY,
4533337Sdonn     PTRFILE, RECORD, FIELD,
4612547Scsvaf     PROC, FUNC, FVAR, REF, PTR, FILET, SET, RANGE,
479657Slinton     LABEL, WITHPTR, SCAL, STR, PROG, IMPROPER, VARNT,
4816620Ssam     FPROC, FFUNC, MODULE, TAG, COMMON, EXTREF, TYPEREF
499657Slinton } Symclass;
509657Slinton 
5112547Scsvaf typedef enum { R_CONST, R_TEMP, R_ARG, R_ADJUST } Rangetype;
5212547Scsvaf 
5333337Sdonn #define INREG 0
5433337Sdonn #define STK 1
5533337Sdonn #define EXT 2
5633337Sdonn 
5733337Sdonn typedef unsigned integer Storage;
5833337Sdonn 
599657Slinton struct Symbol {
609657Slinton     Name name;
619657Slinton     Language language;
6233337Sdonn     Symclass class : 8;
6333337Sdonn     Storage storage : 2;
6433337Sdonn     unsigned int level : 6;	/* for variables stored on stack only */
659657Slinton     Symbol type;
669657Slinton     Symbol chain;
679657Slinton     union {
6818235Slinton 	Node constval;		/* value of constant symbol */
699657Slinton 	int offset;		/* variable address */
709657Slinton 	long iconval;		/* integer constant value */
719657Slinton 	double fconval;		/* floating constant value */
7218235Slinton 	int ndims;		/* no. of dimensions for dynamic/sub-arrays */
739657Slinton 	struct {		/* field offset and size (both in bits) */
749657Slinton 	    int offset;
759657Slinton 	    int length;
769657Slinton 	} field;
7712547Scsvaf 	struct {		/* common offset and chain; used to relocate */
7812547Scsvaf 	    int offset;         /* vars in global BSS */
7912547Scsvaf 	    Symbol chain;
8012547Scsvaf 	} common;
819657Slinton 	struct {		/* range bounds */
8212547Scsvaf             Rangetype lowertype : 16;
8312547Scsvaf             Rangetype uppertype : 16;
849657Slinton 	    long lower;
859657Slinton 	    long upper;
869657Slinton 	} rangev;
8711865Slinton 	struct {
8811865Slinton 	    int offset : 16;	/* offset for of function value */
8916620Ssam 	    Boolean src : 1;	/* true if there is source line info */
9016620Ssam 	    Boolean inline : 1;	/* true if no separate act. rec. */
9116620Ssam 	    Boolean intern : 1; /* internal calling sequence */
9216620Ssam 	    int unused : 13;
9311865Slinton 	    Address beginaddr;	/* address of function code */
949657Slinton 	} funcv;
959657Slinton 	struct {		/* variant record info */
969657Slinton 	    int size;
979657Slinton 	    Symbol vtorec;
989657Slinton 	    Symbol vtag;
999657Slinton 	} varnt;
10016620Ssam 	String typeref;		/* type defined by "<module>:<type>" */
10116620Ssam 	Symbol extref;		/* indirect symbol for external reference */
1029657Slinton     } symvalue;
1039657Slinton     Symbol block;		/* symbol containing this symbol */
1049657Slinton     Symbol next_sym;		/* hash chain */
1059657Slinton };
1069657Slinton 
1079657Slinton /*
1089657Slinton  * Basic types.
1099657Slinton  */
1109657Slinton 
1119657Slinton Symbol t_boolean;
1129657Slinton Symbol t_char;
1139657Slinton Symbol t_int;
1149657Slinton Symbol t_real;
1159657Slinton Symbol t_nil;
11618235Slinton Symbol t_addr;
1179657Slinton 
1189657Slinton Symbol program;
1199657Slinton Symbol curfunc;
1209657Slinton 
12118235Slinton boolean showaggrs;
12218235Slinton 
1239657Slinton #define symname(s) ident(s->name)
1249657Slinton #define codeloc(f) ((f)->symvalue.funcv.beginaddr)
1259657Slinton #define isblock(s) (Boolean) ( \
1269657Slinton     s->class == FUNC or s->class == PROC or \
1279657Slinton     s->class == MODULE or s->class == PROG \
1289657Slinton )
12916620Ssam #define isroutine(s) (Boolean) ( \
13016620Ssam     s->class == FUNC or s->class == PROC \
13116620Ssam )
1329657Slinton 
13311865Slinton #define nosource(f) (not (f)->symvalue.funcv.src)
13414441Slinton #define isinline(f) ((f)->symvalue.funcv.inline)
13511865Slinton 
13633337Sdonn #define isreg(s)		(s->storage == INREG)
13724554Smckusick 
1389657Slinton #include "tree.h"
1399657Slinton 
1409657Slinton /*
1419657Slinton  * Some macros to make finding a symbol with certain attributes.
1429657Slinton  */
1439657Slinton 
1449657Slinton #define find(s, withname) \
1459657Slinton { \
1469657Slinton     s = lookup(withname); \
1479657Slinton     while (s != nil and not (s->name == (withname) and
1489657Slinton 
1499657Slinton #define where /* qualification */
1509657Slinton 
1519657Slinton #define endfind(s) )) { \
1529657Slinton 	s = s->next_sym; \
1539657Slinton     } \
1549657Slinton }
1559657Slinton 
1569657Slinton #endif
1579657Slinton 
1589657Slinton /*
1599657Slinton  * Symbol table structure currently does not support deletions.
16033337Sdonn  * Hash table size is a power of two to make hashing faster.
16133337Sdonn  * Using a non-prime is ok since we aren't doing rehashing.
1629657Slinton  */
1639657Slinton 
16433337Sdonn #define HASHTABLESIZE 8192
1659657Slinton 
1669657Slinton private Symbol hashtab[HASHTABLESIZE];
1679657Slinton 
16833337Sdonn #define hash(name) ((((unsigned) name) >> 2) & (HASHTABLESIZE - 1))
1699657Slinton 
1709657Slinton /*
1719657Slinton  * Allocate a new symbol.
1729657Slinton  */
1739657Slinton 
17433337Sdonn #define SYMBLOCKSIZE 1000
1759657Slinton 
1769657Slinton typedef struct Sympool {
1779657Slinton     struct Symbol sym[SYMBLOCKSIZE];
1789657Slinton     struct Sympool *prevpool;
1799657Slinton } *Sympool;
1809657Slinton 
1819657Slinton private Sympool sympool = nil;
1829657Slinton private Integer nleft = 0;
1839657Slinton 
1849657Slinton public Symbol symbol_alloc()
1859657Slinton {
1869657Slinton     register Sympool newpool;
1879657Slinton 
1889657Slinton     if (nleft <= 0) {
1899657Slinton 	newpool = new(Sympool);
19033337Sdonn 	bzero(newpool, sizeof(*newpool));
1919657Slinton 	newpool->prevpool = sympool;
1929657Slinton 	sympool = newpool;
1939657Slinton 	nleft = SYMBLOCKSIZE;
1949657Slinton     }
1959657Slinton     --nleft;
1969657Slinton     return &(sympool->sym[nleft]);
1979657Slinton }
1989657Slinton 
19918235Slinton public symbol_dump (func)
20012547Scsvaf Symbol func;
20112547Scsvaf {
20218235Slinton     register Symbol s;
20318235Slinton     register integer i;
20412547Scsvaf 
20518235Slinton     printf(" symbols in %s \n",symname(func));
20618235Slinton     for (i = 0; i < HASHTABLESIZE; i++) {
20718235Slinton 	for (s = hashtab[i]; s != nil; s = s->next_sym) {
20818235Slinton 	    if (s->block == func) {
20918235Slinton 		psym(s);
21018235Slinton 	    }
21118235Slinton 	}
21218235Slinton     }
21312547Scsvaf }
21412547Scsvaf 
2159657Slinton /*
2169657Slinton  * Free all the symbols currently allocated.
2179657Slinton  */
21818235Slinton 
2199657Slinton public symbol_free()
2209657Slinton {
2219657Slinton     Sympool s, t;
2229657Slinton     register Integer i;
2239657Slinton 
2249657Slinton     s = sympool;
2259657Slinton     while (s != nil) {
2269657Slinton 	t = s->prevpool;
2279657Slinton 	dispose(s);
2289657Slinton 	s = t;
2299657Slinton     }
2309657Slinton     for (i = 0; i < HASHTABLESIZE; i++) {
2319657Slinton 	hashtab[i] = nil;
2329657Slinton     }
2339657Slinton     sympool = nil;
2349657Slinton     nleft = 0;
2359657Slinton }
2369657Slinton 
2379657Slinton /*
2389657Slinton  * Create a new symbol with the given attributes.
2399657Slinton  */
2409657Slinton 
2419657Slinton public Symbol newSymbol(name, blevel, class, type, chain)
2429657Slinton Name name;
2439657Slinton Integer blevel;
2449657Slinton Symclass class;
2459657Slinton Symbol type;
2469657Slinton Symbol chain;
2479657Slinton {
2489657Slinton     register Symbol s;
2499657Slinton 
2509657Slinton     s = symbol_alloc();
2519657Slinton     s->name = name;
25218235Slinton     s->language = primlang;
25333337Sdonn     s->storage = EXT;
2549657Slinton     s->level = blevel;
2559657Slinton     s->class = class;
2569657Slinton     s->type = type;
2579657Slinton     s->chain = chain;
2589657Slinton     return s;
2599657Slinton }
2609657Slinton 
2619657Slinton /*
2629657Slinton  * Insert a symbol into the hash table.
2639657Slinton  */
2649657Slinton 
2659657Slinton public Symbol insert(name)
2669657Slinton Name name;
2679657Slinton {
2689657Slinton     register Symbol s;
2699657Slinton     register unsigned int h;
2709657Slinton 
2719657Slinton     h = hash(name);
2729657Slinton     s = symbol_alloc();
2739657Slinton     s->name = name;
2749657Slinton     s->next_sym = hashtab[h];
2759657Slinton     hashtab[h] = s;
2769657Slinton     return s;
2779657Slinton }
2789657Slinton 
2799657Slinton /*
2809657Slinton  * Symbol lookup.
2819657Slinton  */
2829657Slinton 
2839657Slinton public Symbol lookup(name)
2849657Slinton Name name;
2859657Slinton {
2869657Slinton     register Symbol s;
2879657Slinton     register unsigned int h;
2889657Slinton 
2899657Slinton     h = hash(name);
2909657Slinton     s = hashtab[h];
2919657Slinton     while (s != nil and s->name != name) {
2929657Slinton 	s = s->next_sym;
2939657Slinton     }
2949657Slinton     return s;
2959657Slinton }
2969657Slinton 
2979657Slinton /*
29816620Ssam  * Delete a symbol from the symbol table.
29916620Ssam  */
30016620Ssam 
30116620Ssam public delete (s)
30216620Ssam Symbol s;
30316620Ssam {
30416620Ssam     register Symbol t;
30516620Ssam     register unsigned int h;
30616620Ssam 
30716620Ssam     h = hash(s->name);
30816620Ssam     t = hashtab[h];
30916620Ssam     if (t == nil) {
31016620Ssam 	panic("delete of non-symbol '%s'", symname(s));
31116620Ssam     } else if (t == s) {
31216620Ssam 	hashtab[h] = s->next_sym;
31316620Ssam     } else {
31416620Ssam 	while (t->next_sym != s) {
31516620Ssam 	    t = t->next_sym;
31616620Ssam 	    if (t == nil) {
31716620Ssam 		panic("delete of non-symbol '%s'", symname(s));
31816620Ssam 	    }
31916620Ssam 	}
32016620Ssam 	t->next_sym = s->next_sym;
32116620Ssam     }
32216620Ssam }
32316620Ssam 
32416620Ssam /*
3259657Slinton  * Dump out all the variables associated with the given
32618235Slinton  * procedure, function, or program associated with the given stack frame.
3279657Slinton  *
3289657Slinton  * This is quite inefficient.  We traverse the entire symbol table
3299657Slinton  * each time we're called.  The assumption is that this routine
3309657Slinton  * won't be called frequently enough to merit improved performance.
3319657Slinton  */
3329657Slinton 
3339657Slinton public dumpvars(f, frame)
3349657Slinton Symbol f;
3359657Slinton Frame frame;
3369657Slinton {
3379657Slinton     register Integer i;
3389657Slinton     register Symbol s;
3399657Slinton 
3409657Slinton     for (i = 0; i < HASHTABLESIZE; i++) {
3419657Slinton 	for (s = hashtab[i]; s != nil; s = s->next_sym) {
3429657Slinton 	    if (container(s) == f) {
3439657Slinton 		if (should_print(s)) {
3449657Slinton 		    printv(s, frame);
3459657Slinton 		    putchar('\n');
3469657Slinton 		} else if (s->class == MODULE) {
3479657Slinton 		    dumpvars(s, frame);
3489657Slinton 		}
3499657Slinton 	    }
3509657Slinton 	}
3519657Slinton     }
3529657Slinton }
3539657Slinton 
3549657Slinton /*
3559657Slinton  * Create a builtin type.
3569657Slinton  * Builtin types are circular in that btype->type->type = btype.
3579657Slinton  */
3589657Slinton 
35918235Slinton private Symbol maketype(name, lower, upper)
3609657Slinton String name;
3619657Slinton long lower;
3629657Slinton long upper;
3639657Slinton {
3649657Slinton     register Symbol s;
36518235Slinton     Name n;
3669657Slinton 
36718235Slinton     if (name == nil) {
36818235Slinton 	n = nil;
36918235Slinton     } else {
37018235Slinton 	n = identname(name, true);
37118235Slinton     }
37218235Slinton     s = insert(n);
37316620Ssam     s->language = primlang;
37418235Slinton     s->level = 0;
37518235Slinton     s->class = TYPE;
37618235Slinton     s->type = nil;
37718235Slinton     s->chain = nil;
3789657Slinton     s->type = newSymbol(nil, 0, RANGE, s, nil);
3799657Slinton     s->type->symvalue.rangev.lower = lower;
3809657Slinton     s->type->symvalue.rangev.upper = upper;
3819657Slinton     return s;
3829657Slinton }
3839657Slinton 
3849657Slinton /*
38518235Slinton  * Create the builtin symbols.
38618235Slinton  */
38718235Slinton 
38818235Slinton public symbols_init ()
3899657Slinton {
39018235Slinton     Symbol s;
3919657Slinton 
39218235Slinton     t_boolean = maketype("$boolean", 0L, 1L);
39318235Slinton     t_int = maketype("$integer", 0x80000000L, 0x7fffffffL);
39418235Slinton     t_char = maketype("$char", 0L, 255L);
39518235Slinton     t_real = maketype("$real", 8L, 0L);
39618235Slinton     t_nil = maketype("$nil", 0L, 0L);
39718235Slinton     t_addr = insert(identname("$address", true));
39818235Slinton     t_addr->language = primlang;
39918235Slinton     t_addr->level = 0;
40018235Slinton     t_addr->class = TYPE;
40118235Slinton     t_addr->type = newSymbol(nil, 1, PTR, t_int, nil);
40218235Slinton     s = insert(identname("true", true));
40318235Slinton     s->class = CONST;
40418235Slinton     s->type = t_boolean;
40518235Slinton     s->symvalue.constval = build(O_LCON, 1L);
40618235Slinton     s->symvalue.constval->nodetype = t_boolean;
40718235Slinton     s = insert(identname("false", true));
40818235Slinton     s->class = CONST;
40918235Slinton     s->type = t_boolean;
41018235Slinton     s->symvalue.constval = build(O_LCON, 0L);
41118235Slinton     s->symvalue.constval->nodetype = t_boolean;
4129657Slinton }
4139657Slinton 
4149657Slinton /*
4159657Slinton  * Reduce type to avoid worrying about type names.
4169657Slinton  */
4179657Slinton 
4189657Slinton public Symbol rtype(type)
4199657Slinton Symbol type;
4209657Slinton {
4219657Slinton     register Symbol t;
4229657Slinton 
4239657Slinton     t = type;
4249657Slinton     if (t != nil) {
42518235Slinton 	if (t->class == VAR or t->class == CONST or
42618235Slinton 	    t->class == FIELD or t->class == REF
42718235Slinton 	) {
4289657Slinton 	    t = t->type;
4299657Slinton 	}
43016620Ssam 	if (t->class == TYPEREF) {
43116620Ssam 	    resolveRef(t);
43216620Ssam 	}
4339657Slinton 	while (t->class == TYPE or t->class == TAG) {
4349657Slinton 	    t = t->type;
43516620Ssam 	    if (t->class == TYPEREF) {
43616620Ssam 		resolveRef(t);
43716620Ssam 	    }
4389657Slinton 	}
4399657Slinton     }
4409657Slinton     return t;
4419657Slinton }
4429657Slinton 
44316620Ssam /*
44416620Ssam  * Find the end of a module name.  Return nil if there is none
44516620Ssam  * in the given string.
44616620Ssam  */
44716620Ssam 
44816620Ssam private String findModuleMark (s)
44916620Ssam String s;
45016620Ssam {
45116620Ssam     register char *p, *r;
45216620Ssam     register boolean done;
45316620Ssam 
45416620Ssam     p = s;
45516620Ssam     done = false;
45616620Ssam     do {
45716620Ssam 	if (*p == ':') {
45816620Ssam 	    done = true;
45916620Ssam 	    r = p;
46016620Ssam 	} else if (*p == '\0') {
46116620Ssam 	    done = true;
46216620Ssam 	    r = nil;
46316620Ssam 	} else {
46416620Ssam 	    ++p;
46516620Ssam 	}
46616620Ssam     } while (not done);
46716620Ssam     return r;
46816620Ssam }
46916620Ssam 
47016620Ssam /*
47116620Ssam  * Resolve a type reference by modifying to be the appropriate type.
47216620Ssam  *
47316620Ssam  * If the reference has a name, then it refers to an opaque type and
47416620Ssam  * the actual type is directly accessible.  Otherwise, we must use
47516620Ssam  * the type reference string, which is of the form "module:{module:}name".
47616620Ssam  */
47716620Ssam 
47816620Ssam public resolveRef (t)
47916620Ssam Symbol t;
48016620Ssam {
48116620Ssam     register char *p;
48216620Ssam     char *start;
48316620Ssam     Symbol s, m, outer;
48416620Ssam     Name n;
48516620Ssam 
48616620Ssam     if (t->name != nil) {
48716620Ssam 	s = t;
48816620Ssam     } else {
48916620Ssam 	start = t->symvalue.typeref;
49016620Ssam 	outer = program;
49116620Ssam 	p = findModuleMark(start);
49216620Ssam 	while (p != nil) {
49316620Ssam 	    *p = '\0';
49416620Ssam 	    n = identname(start, true);
49516620Ssam 	    find(m, n) where m->block == outer endfind(m);
49616620Ssam 	    if (m == nil) {
49716620Ssam 		p = nil;
49816620Ssam 		outer = nil;
49916620Ssam 		s = nil;
50016620Ssam 	    } else {
50116620Ssam 		outer = m;
50216620Ssam 		start = p + 1;
50316620Ssam 		p = findModuleMark(start);
50416620Ssam 	    }
50516620Ssam 	}
50616620Ssam 	if (outer != nil) {
50716620Ssam 	    n = identname(start, true);
50816620Ssam 	    find(s, n) where s->block == outer endfind(s);
50916620Ssam 	}
51016620Ssam     }
51116620Ssam     if (s != nil and s->type != nil) {
51216620Ssam 	t->name = s->type->name;
51316620Ssam 	t->class = s->type->class;
51416620Ssam 	t->type = s->type->type;
51516620Ssam 	t->chain = s->type->chain;
51616620Ssam 	t->symvalue = s->type->symvalue;
51716620Ssam 	t->block = s->type->block;
51816620Ssam     }
51916620Ssam }
52016620Ssam 
52118235Slinton public integer regnum (s)
5229657Slinton Symbol s;
5239657Slinton {
52418235Slinton     integer r;
52518235Slinton 
5269657Slinton     checkref(s);
52733337Sdonn     if (s->storage == INREG) {
52818235Slinton 	r = s->symvalue.offset;
52918235Slinton     } else {
53018235Slinton 	r = -1;
53118235Slinton     }
53218235Slinton     return r;
5339657Slinton }
5349657Slinton 
5359657Slinton public Symbol container(s)
5369657Slinton Symbol s;
5379657Slinton {
5389657Slinton     checkref(s);
5399657Slinton     return s->block;
5409657Slinton }
5419657Slinton 
54218235Slinton public Node constval(s)
54318235Slinton Symbol s;
54418235Slinton {
54518235Slinton     checkref(s);
54618235Slinton     if (s->class != CONST) {
54718235Slinton 	error("[internal error: constval(non-CONST)]");
54818235Slinton     }
54918235Slinton     return s->symvalue.constval;
55018235Slinton }
55118235Slinton 
5529657Slinton /*
5539657Slinton  * Return the object address of the given symbol.
5549657Slinton  *
5559657Slinton  * There are the following possibilities:
5569657Slinton  *
5579657Slinton  *	globals		- just take offset
5589657Slinton  *	locals		- take offset from locals base
5599657Slinton  *	arguments	- take offset from argument base
5609657Slinton  *	register	- offset is register number
5619657Slinton  */
5629657Slinton 
56333337Sdonn #define isglobal(s)		(s->storage == EXT)
56433337Sdonn #define islocaloff(s)		(s->storage == STK and s->symvalue.offset < 0)
56533337Sdonn #define isparamoff(s)		(s->storage == STK and s->symvalue.offset >= 0)
5669657Slinton 
56718235Slinton public Address address (s, frame)
5689657Slinton Symbol s;
5699657Slinton Frame frame;
5709657Slinton {
5719657Slinton     register Frame frp;
5729657Slinton     register Address addr;
5739657Slinton     register Symbol cur;
5749657Slinton 
5759657Slinton     checkref(s);
5769657Slinton     if (not isactive(s->block)) {
5779657Slinton 	error("\"%s\" is not currently defined", symname(s));
5789657Slinton     } else if (isglobal(s)) {
5799657Slinton 	addr = s->symvalue.offset;
5809657Slinton     } else {
5819657Slinton 	frp = frame;
5829657Slinton 	if (frp == nil) {
5839657Slinton 	    cur = s->block;
5849657Slinton 	    while (cur != nil and cur->class == MODULE) {
5859657Slinton 		cur = cur->block;
5869657Slinton 	    }
5879657Slinton 	    if (cur == nil) {
58818235Slinton 		frp = nil;
58918235Slinton 	    } else {
59018235Slinton 		frp = findframe(cur);
59118235Slinton 		if (frp == nil) {
59218235Slinton 		    error("[internal error: unexpected nil frame for \"%s\"]",
59318235Slinton 			symname(s)
59418235Slinton 		    );
59518235Slinton 		}
5969657Slinton 	    }
5979657Slinton 	}
5989657Slinton 	if (islocaloff(s)) {
5999657Slinton 	    addr = locals_base(frp) + s->symvalue.offset;
6009657Slinton 	} else if (isparamoff(s)) {
6019657Slinton 	    addr = args_base(frp) + s->symvalue.offset;
6029657Slinton 	} else if (isreg(s)) {
6039657Slinton 	    addr = savereg(s->symvalue.offset, frp);
6049657Slinton 	} else {
6059657Slinton 	    panic("address: bad symbol \"%s\"", symname(s));
6069657Slinton 	}
6079657Slinton     }
6089657Slinton     return addr;
6099657Slinton }
6109657Slinton 
6119657Slinton /*
6129657Slinton  * Define a symbol used to access register values.
6139657Slinton  */
6149657Slinton 
61518235Slinton public defregname (n, r)
6169657Slinton Name n;
61718235Slinton integer r;
6189657Slinton {
61918235Slinton     Symbol s;
6209657Slinton 
6219657Slinton     s = insert(n);
62218235Slinton     s->language = t_addr->language;
6239657Slinton     s->class = VAR;
62433337Sdonn     s->storage = INREG;
62533337Sdonn     s->level = 3;
62618235Slinton     s->type = t_addr;
6279657Slinton     s->symvalue.offset = r;
6289657Slinton }
6299657Slinton 
6309657Slinton /*
6319657Slinton  * Resolve an "abstract" type reference.
6329657Slinton  *
6339657Slinton  * It is possible in C to define a pointer to a type, but never define
6349657Slinton  * the type in a particular source file.  Here we try to resolve
6359657Slinton  * the type definition.  This is problematic, it is possible to
6369657Slinton  * have multiple, different definitions for the same name type.
6379657Slinton  */
6389657Slinton 
6399657Slinton public findtype(s)
6409657Slinton Symbol s;
6419657Slinton {
6429657Slinton     register Symbol t, u, prev;
6439657Slinton 
6449657Slinton     u = s;
6459657Slinton     prev = nil;
6469657Slinton     while (u != nil and u->class != BADUSE) {
6479657Slinton 	if (u->name != nil) {
6489657Slinton 	    prev = u;
6499657Slinton 	}
6509657Slinton 	u = u->type;
6519657Slinton     }
6529657Slinton     if (prev == nil) {
6539657Slinton 	error("couldn't find link to type reference");
6549657Slinton     }
65518235Slinton     t = lookup(prev->name);
65618235Slinton     while (t != nil and
65718235Slinton 	not (
65818235Slinton 	    t != prev and t->name == prev->name and
65918235Slinton 	    t->block->class == MODULE and t->class == prev->class and
66018235Slinton 	    t->type != nil and t->type->type != nil and
66118235Slinton 	    t->type->type->class != BADUSE
66218235Slinton 	)
66318235Slinton     ) {
66418235Slinton 	t = t->next_sym;
66518235Slinton     }
6669657Slinton     if (t == nil) {
6679657Slinton 	error("couldn't resolve reference");
6689657Slinton     } else {
6699657Slinton 	prev->type = t->type;
6709657Slinton     }
6719657Slinton }
6729657Slinton 
6739657Slinton /*
6749657Slinton  * Find the size in bytes of the given type.
6759657Slinton  *
6769657Slinton  * This is probably the WRONG thing to do.  The size should be kept
6779657Slinton  * as an attribute in the symbol information as is done for structures
6789657Slinton  * and fields.  I haven't gotten around to cleaning this up yet.
6799657Slinton  */
6809657Slinton 
68112547Scsvaf #define MAXUCHAR 255
68212547Scsvaf #define MAXUSHORT 65535L
6839657Slinton #define MINCHAR -128
6849657Slinton #define MAXCHAR 127
6859657Slinton #define MINSHORT -32768
6869657Slinton #define MAXSHORT 32767
6879657Slinton 
68816620Ssam public findbounds (u, lower, upper)
68916620Ssam Symbol u;
69016620Ssam long *lower, *upper;
69116620Ssam {
69216620Ssam     Rangetype lbt, ubt;
69316620Ssam     long lb, ub;
69416620Ssam 
69516620Ssam     if (u->class == RANGE) {
69616620Ssam 	lbt = u->symvalue.rangev.lowertype;
69716620Ssam 	ubt = u->symvalue.rangev.uppertype;
69816620Ssam 	lb = u->symvalue.rangev.lower;
69916620Ssam 	ub = u->symvalue.rangev.upper;
70016620Ssam 	if (lbt == R_ARG or lbt == R_TEMP) {
70116620Ssam 	    if (not getbound(u, lb, lbt, lower)) {
70216620Ssam 		error("dynamic bounds not currently available");
70316620Ssam 	    }
70416620Ssam 	} else {
70516620Ssam 	    *lower = lb;
70616620Ssam 	}
70716620Ssam 	if (ubt == R_ARG or ubt == R_TEMP) {
70816620Ssam 	    if (not getbound(u, ub, ubt, upper)) {
70916620Ssam 		error("dynamic bounds not currently available");
71016620Ssam 	    }
71116620Ssam 	} else {
71216620Ssam 	    *upper = ub;
71316620Ssam 	}
71416620Ssam     } else if (u->class == SCAL) {
71516620Ssam 	*lower = 0;
71616620Ssam 	*upper = u->symvalue.iconval - 1;
71716620Ssam     } else {
71818235Slinton 	error("[internal error: unexpected array bound type]");
71916620Ssam     }
72016620Ssam }
72116620Ssam 
72216620Ssam public integer size(sym)
72316620Ssam Symbol sym;
72416620Ssam {
72516620Ssam     register Symbol s, t, u;
72616620Ssam     register integer nel, elsize;
7279657Slinton     long lower, upper;
72816620Ssam     integer r, off, len;
7299657Slinton 
7309657Slinton     t = sym;
7319657Slinton     checkref(t);
73216620Ssam     if (t->class == TYPEREF) {
73316620Ssam 	resolveRef(t);
73416620Ssam     }
7359657Slinton     switch (t->class) {
7369657Slinton 	case RANGE:
7379657Slinton 	    lower = t->symvalue.rangev.lower;
7389657Slinton 	    upper = t->symvalue.rangev.upper;
73916620Ssam 	    if (upper == 0 and lower > 0) {
74016620Ssam 		/* real */
7419657Slinton 		r = lower;
74216620Ssam 	    } else if (lower > upper) {
74316620Ssam 		/* unsigned long */
74416620Ssam 		r = sizeof(long);
74512045Slinton 	    } else if (
74612547Scsvaf   		(lower >= MINCHAR and upper <= MAXCHAR) or
74712547Scsvaf   		(lower >= 0 and upper <= MAXUCHAR)
74812547Scsvaf   	      ) {
7499657Slinton 		r = sizeof(char);
75012547Scsvaf   	    } else if (
75112547Scsvaf   		(lower >= MINSHORT and upper <= MAXSHORT) or
75212547Scsvaf   		(lower >= 0 and upper <= MAXUSHORT)
75312547Scsvaf   	      ) {
7549657Slinton 		r = sizeof(short);
7559657Slinton 	    } else {
7569657Slinton 		r = sizeof(long);
7579657Slinton 	    }
7589657Slinton 	    break;
7599657Slinton 
7609657Slinton 	case ARRAY:
7619657Slinton 	    elsize = size(t->type);
7629657Slinton 	    nel = 1;
7639657Slinton 	    for (t = t->chain; t != nil; t = t->chain) {
76416620Ssam 		u = rtype(t);
76516620Ssam 		findbounds(u, &lower, &upper);
7669657Slinton 		nel *= (upper-lower+1);
7679657Slinton 	    }
7689657Slinton 	    r = nel*elsize;
7699657Slinton 	    break;
7709657Slinton 
77133337Sdonn 	case OPENARRAY:
77218235Slinton 	case DYNARRAY:
77318235Slinton 	    r = (t->symvalue.ndims + 1) * sizeof(Word);
77418235Slinton 	    break;
77518235Slinton 
77618235Slinton 	case SUBARRAY:
77718235Slinton 	    r = (2 * t->symvalue.ndims + 1) * sizeof(Word);
77818235Slinton 	    break;
77918235Slinton 
78012547Scsvaf 	case REF:
7819657Slinton 	case VAR:
7829657Slinton 	    r = size(t->type);
78312127Slinton 	    /*
78412127Slinton 	     *
78512045Slinton 	    if (r < sizeof(Word) and isparam(t)) {
7869657Slinton 		r = sizeof(Word);
7879657Slinton 	    }
78812547Scsvaf 	    */
7899657Slinton 	    break;
7909657Slinton 
79118235Slinton 	case FVAR:
7929657Slinton 	case CONST:
79318235Slinton 	case TAG:
7949657Slinton 	    r = size(t->type);
7959657Slinton 	    break;
7969657Slinton 
7979657Slinton 	case TYPE:
79833337Sdonn 	    /*
79933337Sdonn 	     * This causes problems on the IRIS because of the compiler bug
80033337Sdonn 	     * with stab offsets for parameters.  Not sure it's really
80133337Sdonn 	     * necessary anyway.
80233337Sdonn 	     */
80333337Sdonn #	    ifndef IRIS
8049657Slinton 	    if (t->type->class == PTR and t->type->type->class == BADUSE) {
8059657Slinton 		findtype(t);
8069657Slinton 	    }
80733337Sdonn #	    endif
8089657Slinton 	    r = size(t->type);
8099657Slinton 	    break;
8109657Slinton 
8119657Slinton 	case FIELD:
81216620Ssam 	    off = t->symvalue.field.offset;
81316620Ssam 	    len = t->symvalue.field.length;
81416620Ssam 	    r = (off + len + 7) div 8 - (off div 8);
8159657Slinton 	    break;
8169657Slinton 
8179657Slinton 	case RECORD:
8189657Slinton 	case VARNT:
8199657Slinton 	    r = t->symvalue.offset;
8209657Slinton 	    if (r == 0 and t->chain != nil) {
8219657Slinton 		panic("missing size information for record");
8229657Slinton 	    }
8239657Slinton 	    break;
8249657Slinton 
8259657Slinton 	case PTR:
82618235Slinton 	case TYPEREF:
8279657Slinton 	case FILET:
8289657Slinton 	    r = sizeof(Word);
8299657Slinton 	    break;
8309657Slinton 
8319657Slinton 	case SCAL:
83212609Slinton 	    r = sizeof(Word);
83312609Slinton 	    /*
83412609Slinton 	     *
8359657Slinton 	    if (t->symvalue.iconval > 255) {
8369657Slinton 		r = sizeof(short);
8379657Slinton 	    } else {
8389657Slinton 		r = sizeof(char);
8399657Slinton 	    }
84012609Slinton 	     *
84112609Slinton 	     */
8429657Slinton 	    break;
8439657Slinton 
8449657Slinton 	case FPROC:
8459657Slinton 	case FFUNC:
8469657Slinton 	    r = sizeof(Word);
8479657Slinton 	    break;
8489657Slinton 
8499657Slinton 	case PROC:
8509657Slinton 	case FUNC:
8519657Slinton 	case MODULE:
8529657Slinton 	case PROG:
8539657Slinton 	    r = sizeof(Symbol);
8549657Slinton 	    break;
8559657Slinton 
85616620Ssam 	case SET:
85716620Ssam 	    u = rtype(t->type);
85816620Ssam 	    switch (u->class) {
85916620Ssam 		case RANGE:
86016620Ssam 		    r = u->symvalue.rangev.upper - u->symvalue.rangev.lower + 1;
86116620Ssam 		    break;
86216620Ssam 
86316620Ssam 		case SCAL:
86416620Ssam 		    r = u->symvalue.iconval;
86516620Ssam 		    break;
86616620Ssam 
86716620Ssam 		default:
86816620Ssam 		    error("expected range for set base type");
86916620Ssam 		    break;
87016620Ssam 	    }
87116620Ssam 	    r = (r + BITSPERBYTE - 1) div BITSPERBYTE;
87216620Ssam 	    break;
87316620Ssam 
87418235Slinton 	/*
87518235Slinton 	 * These can happen in C (unfortunately) for unresolved type references
87618235Slinton 	 * Assume they are pointers.
87718235Slinton 	 */
87818235Slinton 	case BADUSE:
87918235Slinton 	    r = sizeof(Address);
88018235Slinton 	    break;
88118235Slinton 
8829657Slinton 	default:
8839657Slinton 	    if (ord(t->class) > ord(TYPEREF)) {
8849657Slinton 		panic("size: bad class (%d)", ord(t->class));
8859657Slinton 	    } else {
88618235Slinton 		fprintf(stderr, "can't compute size of a %s\n", classname(t));
8879657Slinton 	    }
88816620Ssam 	    r = 0;
88916620Ssam 	    break;
8909657Slinton     }
8919657Slinton     return r;
8929657Slinton }
8939657Slinton 
8949657Slinton /*
89518235Slinton  * Return the size associated with a symbol that takes into account
89618235Slinton  * reference parameters.  This might be better as the normal size function, but
89718235Slinton  * too many places already depend on it working the way it does.
89818235Slinton  */
89918235Slinton 
90018235Slinton public integer psize (s)
90118235Slinton Symbol s;
90218235Slinton {
90318235Slinton     integer r;
90418235Slinton     Symbol t;
90518235Slinton 
90618235Slinton     if (s->class == REF) {
90718235Slinton 	t = rtype(s->type);
90833337Sdonn 	if (t->class == OPENARRAY) {
90918235Slinton 	    r = (t->symvalue.ndims + 1) * sizeof(Word);
91018235Slinton 	} else if (t->class == SUBARRAY) {
91118235Slinton 	    r = (2 * t->symvalue.ndims + 1) * sizeof(Word);
91218235Slinton 	} else {
91318235Slinton 	    r = sizeof(Word);
91418235Slinton 	}
91518235Slinton     } else {
91618235Slinton 	r = size(s);
91718235Slinton     }
91818235Slinton     return r;
91918235Slinton }
92018235Slinton 
92118235Slinton /*
9229657Slinton  * Test if a symbol is a parameter.  This is true if there
9239657Slinton  * is a cycle from s->block to s via chain pointers.
9249657Slinton  */
9259657Slinton 
9269657Slinton public Boolean isparam(s)
9279657Slinton Symbol s;
9289657Slinton {
9299657Slinton     register Symbol t;
9309657Slinton 
9319657Slinton     t = s->block;
9329657Slinton     while (t != nil and t != s) {
9339657Slinton 	t = t->chain;
9349657Slinton     }
9359657Slinton     return (Boolean) (t != nil);
9369657Slinton }
9379657Slinton 
9389657Slinton /*
93916620Ssam  * Test if a type is an open array parameter type.
9409657Slinton  */
9419657Slinton 
94218235Slinton public boolean isopenarray (type)
94318235Slinton Symbol type;
94416620Ssam {
94518235Slinton     Symbol t;
94618235Slinton 
94718235Slinton     t = rtype(type);
94833337Sdonn     return (boolean) (t->class == OPENARRAY);
94916620Ssam }
95016620Ssam 
95116620Ssam /*
95218235Slinton  * Test if a symbol is a var parameter, i.e. has class REF.
95316620Ssam  */
95416620Ssam 
9559657Slinton public Boolean isvarparam(s)
9569657Slinton Symbol s;
9579657Slinton {
9589657Slinton     return (Boolean) (s->class == REF);
9599657Slinton }
9609657Slinton 
9619657Slinton /*
9629657Slinton  * Test if a symbol is a variable (actually any addressible quantity
9639657Slinton  * with do).
9649657Slinton  */
9659657Slinton 
9669657Slinton public Boolean isvariable(s)
96718235Slinton Symbol s;
9689657Slinton {
9699657Slinton     return (Boolean) (s->class == VAR or s->class == FVAR or s->class == REF);
9709657Slinton }
9719657Slinton 
9729657Slinton /*
97318235Slinton  * Test if a symbol is a constant.
97418235Slinton  */
97518235Slinton 
97618235Slinton public Boolean isconst(s)
97718235Slinton Symbol s;
9789657Slinton {
97918235Slinton     return (Boolean) (s->class == CONST);
9809657Slinton }
9819657Slinton 
9829657Slinton /*
9839657Slinton  * Test if a symbol is a module.
9849657Slinton  */
9859657Slinton 
9869657Slinton public Boolean ismodule(s)
9879657Slinton register Symbol s;
9889657Slinton {
9899657Slinton     return (Boolean) (s->class == MODULE);
9909657Slinton }
9919657Slinton 
9929657Slinton /*
99316620Ssam  * Mark a procedure or function as internal, meaning that it is called
99416620Ssam  * with a different calling sequence.
99516620Ssam  */
99616620Ssam 
99716620Ssam public markInternal (s)
99816620Ssam Symbol s;
99916620Ssam {
100016620Ssam     s->symvalue.funcv.intern = true;
100116620Ssam }
100216620Ssam 
100316620Ssam public boolean isinternal (s)
100416620Ssam Symbol s;
100516620Ssam {
100616620Ssam     return s->symvalue.funcv.intern;
100716620Ssam }
100816620Ssam 
100916620Ssam /*
101018235Slinton  * Decide if a field begins or ends on a bit rather than byte boundary.
101118235Slinton  */
101218235Slinton 
101318235Slinton public Boolean isbitfield(s)
101418235Slinton register Symbol s;
101518235Slinton {
101618235Slinton     boolean b;
101718235Slinton     register integer off, len;
101818235Slinton     register Symbol t;
101918235Slinton 
102018235Slinton     off = s->symvalue.field.offset;
102118235Slinton     len = s->symvalue.field.length;
102218235Slinton     if ((off mod BITSPERBYTE) != 0 or (len mod BITSPERBYTE) != 0) {
102318235Slinton 	b = true;
102418235Slinton     } else {
102518235Slinton 	t = rtype(s->type);
102618235Slinton 	b = (Boolean) (
102718235Slinton 	    (t->class == SCAL and len != (sizeof(int)*BITSPERBYTE)) or
102818235Slinton 	    len != (size(t)*BITSPERBYTE)
102918235Slinton 	);
103018235Slinton     }
103118235Slinton     return b;
103218235Slinton }
103318235Slinton 
103418235Slinton private boolean primlang_typematch (t1, t2)
103518235Slinton Symbol t1, t2;
103618235Slinton {
103718235Slinton     return (boolean) (
103818235Slinton 	(t1 == t2) or
103918235Slinton 	(
104018235Slinton 	    t1->class == RANGE and t2->class == RANGE and
104118235Slinton 	    t1->symvalue.rangev.lower == t2->symvalue.rangev.lower and
104218235Slinton 	    t1->symvalue.rangev.upper == t2->symvalue.rangev.upper
104318235Slinton 	) or (
104418235Slinton 	    t1->class == PTR and t2->class == RANGE and
104518235Slinton 	    t2->symvalue.rangev.upper >= t2->symvalue.rangev.lower
104618235Slinton 	) or (
104718235Slinton 	    t2->class == PTR and t1->class == RANGE and
104818235Slinton 	    t1->symvalue.rangev.upper >= t1->symvalue.rangev.lower
104918235Slinton 	)
105018235Slinton     );
105118235Slinton }
105218235Slinton 
105318235Slinton /*
10549657Slinton  * Test if two types match.
10559657Slinton  * Equivalent names implies a match in any language.
10569657Slinton  *
10579657Slinton  * Special symbols must be handled with care.
10589657Slinton  */
10599657Slinton 
10609657Slinton public Boolean compatible(t1, t2)
10619657Slinton register Symbol t1, t2;
10629657Slinton {
10639657Slinton     Boolean b;
106416620Ssam     Symbol rt1, rt2;
10659657Slinton 
10669657Slinton     if (t1 == t2) {
10679657Slinton 	b = true;
10689657Slinton     } else if (t1 == nil or t2 == nil) {
10699657Slinton 	b = false;
10709657Slinton     } else if (t1 == procsym) {
10719657Slinton 	b = isblock(t2);
10729657Slinton     } else if (t2 == procsym) {
10739657Slinton 	b = isblock(t1);
10749657Slinton     } else if (t1->language == nil) {
107516620Ssam 	if (t2->language == nil) {
107616620Ssam 	    b = false;
107733337Sdonn 	} else if (t2->language == primlang) {
107833337Sdonn 	    b = (boolean) primlang_typematch(rtype(t1), rtype(t2));
107916620Ssam 	} else {
108016620Ssam 	    b = (boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2);
108116620Ssam 	}
108233337Sdonn     } else if (t1->language == primlang) {
108333337Sdonn 	if (t2->language == primlang or t2->language == nil) {
108433337Sdonn 	    b = primlang_typematch(rtype(t1), rtype(t2));
108533337Sdonn 	} else {
108633337Sdonn 	    b = (boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2);
108733337Sdonn 	}
10889657Slinton     } else {
108916620Ssam 	b = (boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2);
10909657Slinton     }
10919657Slinton     return b;
10929657Slinton }
10939657Slinton 
10949657Slinton /*
10959657Slinton  * Check for a type of the given name.
10969657Slinton  */
10979657Slinton 
10989657Slinton public Boolean istypename(type, name)
10999657Slinton Symbol type;
11009657Slinton String name;
11019657Slinton {
110218235Slinton     register Symbol t;
11039657Slinton     Boolean b;
11049657Slinton 
11059657Slinton     t = type;
110618235Slinton     if (t == nil) {
110718235Slinton 	b = false;
110818235Slinton     } else {
110918235Slinton 	b = (Boolean) (
111018235Slinton 	    t->class == TYPE and streq(ident(t->name), name)
111118235Slinton 	);
111218235Slinton     }
11139657Slinton     return b;
11149657Slinton }
11159657Slinton 
11169657Slinton /*
111716620Ssam  * Determine if a (value) parameter should actually be passed by address.
111816620Ssam  */
111916620Ssam 
112016620Ssam public boolean passaddr (p, exprtype)
112116620Ssam Symbol p, exprtype;
112216620Ssam {
112316620Ssam     boolean b;
112416620Ssam     Language def;
112516620Ssam 
112616620Ssam     if (p == nil) {
112716620Ssam 	def = findlanguage(".c");
112816620Ssam 	b = (boolean) (*language_op(def, L_PASSADDR))(p, exprtype);
112916620Ssam     } else if (p->language == nil or p->language == primlang) {
113016620Ssam 	b = false;
113116620Ssam     } else if (isopenarray(p->type)) {
113216620Ssam 	b = true;
113316620Ssam     } else {
113416620Ssam 	b = (boolean) (*language_op(p->language, L_PASSADDR))(p, exprtype);
113516620Ssam     }
113616620Ssam     return b;
113716620Ssam }
113816620Ssam 
113916620Ssam /*
11409657Slinton  * Test if the name of a symbol is uniquely defined or not.
11419657Slinton  */
11429657Slinton 
11439657Slinton public Boolean isambiguous(s)
11449657Slinton register Symbol s;
11459657Slinton {
11469657Slinton     register Symbol t;
11479657Slinton 
11489657Slinton     find(t, s->name) where t != s endfind(t);
11499657Slinton     return (Boolean) (t != nil);
11509657Slinton }
11519657Slinton 
11529657Slinton typedef char *Arglist;
11539657Slinton 
11549657Slinton #define nextarg(type)  ((type *) (ap += sizeof(type)))[-1]
11559657Slinton 
11569657Slinton private Symbol mkstring();
11579657Slinton 
11589657Slinton /*
11599657Slinton  * Determine the type of a parse tree.
116018235Slinton  *
11619657Slinton  * Also make some symbol-dependent changes to the tree such as
116218235Slinton  * removing indirection for constant or register symbols.
11639657Slinton  */
11649657Slinton 
116518235Slinton public assigntypes (p)
11669657Slinton register Node p;
11679657Slinton {
11689657Slinton     register Node p1;
11699657Slinton     register Symbol s;
11709657Slinton 
11719657Slinton     switch (p->op) {
11729657Slinton 	case O_SYM:
117318235Slinton 	    p->nodetype = p->value.sym;
11749657Slinton 	    break;
11759657Slinton 
11769657Slinton 	case O_LCON:
11779657Slinton 	    p->nodetype = t_int;
11789657Slinton 	    break;
11799657Slinton 
118018235Slinton 	case O_CCON:
118118235Slinton 	    p->nodetype = t_char;
118218235Slinton 	    break;
118318235Slinton 
11849657Slinton 	case O_FCON:
11859657Slinton 	    p->nodetype = t_real;
11869657Slinton 	    break;
11879657Slinton 
11889657Slinton 	case O_SCON:
118918235Slinton 	    p->nodetype = mkstring(p->value.scon);
11909657Slinton 	    break;
11919657Slinton 
11929657Slinton 	case O_INDIR:
11939657Slinton 	    p1 = p->value.arg[0];
119418235Slinton 	    s = rtype(p1->nodetype);
119518235Slinton 	    if (s->class != PTR) {
119618235Slinton 		beginerrmsg();
119718235Slinton 		fprintf(stderr, "\"");
119818235Slinton 		prtree(stderr, p1);
119918235Slinton 		fprintf(stderr, "\" is not a pointer");
120018235Slinton 		enderrmsg();
120118235Slinton 	    }
12029657Slinton 	    p->nodetype = rtype(p1->nodetype)->type;
12039657Slinton 	    break;
12049657Slinton 
12059657Slinton 	case O_DOT:
12069657Slinton 	    p->nodetype = p->value.arg[1]->value.sym;
12079657Slinton 	    break;
12089657Slinton 
12099657Slinton 	case O_RVAL:
12109657Slinton 	    p1 = p->value.arg[0];
12119657Slinton 	    p->nodetype = p1->nodetype;
12129657Slinton 	    if (p1->op == O_SYM) {
121318235Slinton 		if (p1->nodetype->class == PROC or p->nodetype->class == FUNC) {
121418235Slinton 		    p->op = p1->op;
121518235Slinton 		    p->value.sym = p1->value.sym;
121618235Slinton 		    p->nodetype = p1->nodetype;
121718235Slinton 		    dispose(p1);
12189657Slinton 		} else if (p1->value.sym->class == CONST) {
121918235Slinton 		    p->op = p1->op;
122018235Slinton 		    p->value = p1->value;
122118235Slinton 		    p->nodetype = p1->nodetype;
122218235Slinton 		    dispose(p1);
12239657Slinton 		} else if (isreg(p1->value.sym)) {
12249657Slinton 		    p->op = O_SYM;
12259657Slinton 		    p->value.sym = p1->value.sym;
12269657Slinton 		    dispose(p1);
12279657Slinton 		}
12289657Slinton 	    } else if (p1->op == O_INDIR and p1->value.arg[0]->op == O_SYM) {
12299657Slinton 		s = p1->value.arg[0]->value.sym;
12309657Slinton 		if (isreg(s)) {
12319657Slinton 		    p1->op = O_SYM;
12329657Slinton 		    dispose(p1->value.arg[0]);
12339657Slinton 		    p1->value.sym = s;
12349657Slinton 		    p1->nodetype = s;
12359657Slinton 		}
12369657Slinton 	    }
12379657Slinton 	    break;
12389657Slinton 
123918235Slinton 	case O_COMMA:
124018235Slinton 	    p->nodetype = p->value.arg[0]->nodetype;
124118235Slinton 	    break;
124218235Slinton 
124318235Slinton 	case O_CALLPROC:
12449657Slinton 	case O_CALL:
12459657Slinton 	    p1 = p->value.arg[0];
124611171Slinton 	    p->nodetype = rtype(p1->nodetype)->type;
12479657Slinton 	    break;
12489657Slinton 
124911171Slinton 	case O_TYPERENAME:
125011171Slinton 	    p->nodetype = p->value.arg[1]->nodetype;
125111171Slinton 	    break;
125211171Slinton 
12539657Slinton 	case O_ITOF:
12549657Slinton 	    p->nodetype = t_real;
12559657Slinton 	    break;
12569657Slinton 
12579657Slinton 	case O_NEG:
12589657Slinton 	    s = p->value.arg[0]->nodetype;
12599657Slinton 	    if (not compatible(s, t_int)) {
12609657Slinton 		if (not compatible(s, t_real)) {
12619657Slinton 		    beginerrmsg();
126216620Ssam 		    fprintf(stderr, "\"");
12639657Slinton 		    prtree(stderr, p->value.arg[0]);
126416620Ssam 		    fprintf(stderr, "\" is improper type");
12659657Slinton 		    enderrmsg();
12669657Slinton 		} else {
12679657Slinton 		    p->op = O_NEGF;
12689657Slinton 		}
12699657Slinton 	    }
12709657Slinton 	    p->nodetype = s;
12719657Slinton 	    break;
12729657Slinton 
12739657Slinton 	case O_ADD:
12749657Slinton 	case O_SUB:
12759657Slinton 	case O_MUL:
127616620Ssam 	    binaryop(p, nil);
127716620Ssam 	    break;
127816620Ssam 
12799657Slinton 	case O_LT:
12809657Slinton 	case O_LE:
12819657Slinton 	case O_GT:
12829657Slinton 	case O_GE:
12839657Slinton 	case O_EQ:
12849657Slinton 	case O_NE:
128516620Ssam 	    binaryop(p, t_boolean);
12869657Slinton 	    break;
12879657Slinton 
12889657Slinton 	case O_DIVF:
12899657Slinton 	    convert(&(p->value.arg[0]), t_real, O_ITOF);
12909657Slinton 	    convert(&(p->value.arg[1]), t_real, O_ITOF);
12919657Slinton 	    p->nodetype = t_real;
12929657Slinton 	    break;
12939657Slinton 
12949657Slinton 	case O_DIV:
12959657Slinton 	case O_MOD:
12969657Slinton 	    convert(&(p->value.arg[0]), t_int, O_NOP);
12979657Slinton 	    convert(&(p->value.arg[1]), t_int, O_NOP);
12989657Slinton 	    p->nodetype = t_int;
12999657Slinton 	    break;
13009657Slinton 
13019657Slinton 	case O_AND:
13029657Slinton 	case O_OR:
13039657Slinton 	    chkboolean(p->value.arg[0]);
13049657Slinton 	    chkboolean(p->value.arg[1]);
13059657Slinton 	    p->nodetype = t_boolean;
13069657Slinton 	    break;
13079657Slinton 
13089657Slinton 	case O_QLINE:
13099657Slinton 	    p->nodetype = t_int;
13109657Slinton 	    break;
13119657Slinton 
13129657Slinton 	default:
13139657Slinton 	    p->nodetype = nil;
13149657Slinton 	    break;
13159657Slinton     }
13169657Slinton }
13179657Slinton 
13189657Slinton /*
131916620Ssam  * Process a binary arithmetic or relational operator.
132016620Ssam  * Convert from integer to real if necessary.
132116620Ssam  */
132216620Ssam 
132316620Ssam private binaryop (p, t)
132416620Ssam Node p;
132516620Ssam Symbol t;
132616620Ssam {
132716620Ssam     Node p1, p2;
132816620Ssam     Boolean t1real, t2real;
132916620Ssam     Symbol t1, t2;
133016620Ssam 
133116620Ssam     p1 = p->value.arg[0];
133216620Ssam     p2 = p->value.arg[1];
133316620Ssam     t1 = rtype(p1->nodetype);
133416620Ssam     t2 = rtype(p2->nodetype);
133516620Ssam     t1real = compatible(t1, t_real);
133616620Ssam     t2real = compatible(t2, t_real);
133716620Ssam     if (t1real or t2real) {
133816620Ssam 	p->op = (Operator) (ord(p->op) + 1);
133916620Ssam 	if (not t1real) {
134016620Ssam 	    p->value.arg[0] = build(O_ITOF, p1);
134116620Ssam 	} else if (not t2real) {
134216620Ssam 	    p->value.arg[1] = build(O_ITOF, p2);
134316620Ssam 	}
134416620Ssam 	p->nodetype = t_real;
134516620Ssam     } else {
134616620Ssam 	if (size(p1->nodetype) > sizeof(integer)) {
134716620Ssam 	    beginerrmsg();
134816620Ssam 	    fprintf(stderr, "operation not defined on \"");
134916620Ssam 	    prtree(stderr, p1);
135016620Ssam 	    fprintf(stderr, "\"");
135116620Ssam 	    enderrmsg();
135216620Ssam 	} else if (size(p2->nodetype) > sizeof(integer)) {
135316620Ssam 	    beginerrmsg();
135416620Ssam 	    fprintf(stderr, "operation not defined on \"");
135516620Ssam 	    prtree(stderr, p2);
135616620Ssam 	    fprintf(stderr, "\"");
135716620Ssam 	    enderrmsg();
135816620Ssam 	}
135916620Ssam 	p->nodetype = t_int;
136016620Ssam     }
136116620Ssam     if (t != nil) {
136216620Ssam 	p->nodetype = t;
136316620Ssam     }
136416620Ssam }
136516620Ssam 
136616620Ssam /*
13679657Slinton  * Convert a tree to a type via a conversion operator;
13689657Slinton  * if this isn't possible generate an error.
13699657Slinton  */
13709657Slinton 
13719657Slinton private convert(tp, typeto, op)
13729657Slinton Node *tp;
13739657Slinton Symbol typeto;
13749657Slinton Operator op;
13759657Slinton {
137616620Ssam     Node tree;
137716620Ssam     Symbol s, t;
13789657Slinton 
137916620Ssam     tree = *tp;
13809657Slinton     s = rtype(tree->nodetype);
138116620Ssam     t = rtype(typeto);
138216620Ssam     if (compatible(t, t_real) and compatible(s, t_int)) {
1383*34257Sdonn 	/* we can convert int => floating but not the reverse */
13849657Slinton 	tree = build(op, tree);
138516620Ssam     } else if (not compatible(s, t)) {
13869657Slinton 	beginerrmsg();
138716620Ssam 	prtree(stderr, tree);
1388*34257Sdonn 	fprintf(stderr, ": illegal type in operation");
13899657Slinton 	enderrmsg();
13909657Slinton     }
139116620Ssam     *tp = tree;
13929657Slinton }
13939657Slinton 
13949657Slinton /*
13959657Slinton  * Construct a node for the dot operator.
13969657Slinton  *
13979657Slinton  * If the left operand is not a record, but rather a procedure
13989657Slinton  * or function, then we interpret the "." as referencing an
13999657Slinton  * "invisible" variable; i.e. a variable within a dynamically
14009657Slinton  * active block but not within the static scope of the current procedure.
14019657Slinton  */
14029657Slinton 
14039657Slinton public Node dot(record, fieldname)
14049657Slinton Node record;
14059657Slinton Name fieldname;
14069657Slinton {
140718235Slinton     register Node rec, p;
14089657Slinton     register Symbol s, t;
14099657Slinton 
141018235Slinton     rec = record;
141118235Slinton     if (isblock(rec->nodetype)) {
14129657Slinton 	find(s, fieldname) where
141318235Slinton 	    s->block == rec->nodetype and
141418235Slinton 	    s->class != FIELD
14159657Slinton 	endfind(s);
14169657Slinton 	if (s == nil) {
14179657Slinton 	    beginerrmsg();
14189657Slinton 	    fprintf(stderr, "\"%s\" is not defined in ", ident(fieldname));
141918235Slinton 	    printname(stderr, rec->nodetype);
14209657Slinton 	    enderrmsg();
14219657Slinton 	}
14229657Slinton 	p = new(Node);
14239657Slinton 	p->op = O_SYM;
14249657Slinton 	p->value.sym = s;
142518235Slinton 	p->nodetype = s;
14269657Slinton     } else {
142718235Slinton 	p = rec;
14289657Slinton 	t = rtype(p->nodetype);
14299657Slinton 	if (t->class == PTR) {
14309657Slinton 	    s = findfield(fieldname, t->type);
14319657Slinton 	} else {
14329657Slinton 	    s = findfield(fieldname, t);
14339657Slinton 	}
14349657Slinton 	if (s == nil) {
14359657Slinton 	    beginerrmsg();
14369657Slinton 	    fprintf(stderr, "\"%s\" is not a field in ", ident(fieldname));
143718235Slinton 	    prtree(stderr, rec);
14389657Slinton 	    enderrmsg();
14399657Slinton 	}
144018235Slinton 	if (t->class != PTR or isreg(rec->nodetype)) {
144118235Slinton 	    p = unrval(p);
14429657Slinton 	}
144318235Slinton 	p->nodetype = t_addr;
14449657Slinton 	p = build(O_DOT, p, build(O_SYM, s));
14459657Slinton     }
144618235Slinton     return build(O_RVAL, p);
14479657Slinton }
14489657Slinton 
14499657Slinton /*
14509657Slinton  * Return a tree corresponding to an array reference and do the
14519657Slinton  * error checking.
14529657Slinton  */
14539657Slinton 
14549657Slinton public Node subscript(a, slist)
14559657Slinton Node a, slist;
14569657Slinton {
145716620Ssam     Symbol t;
145818235Slinton     Node p;
14599657Slinton 
146016620Ssam     t = rtype(a->nodetype);
146118235Slinton     if (t->language == nil or t->language == primlang) {
146218235Slinton 	p = (Node) (*language_op(findlanguage(".s"), L_BUILDAREF))(a, slist);
146316620Ssam     } else {
146418235Slinton 	p = (Node) (*language_op(t->language, L_BUILDAREF))(a, slist);
146516620Ssam     }
146618235Slinton     return build(O_RVAL, p);
14679657Slinton }
14689657Slinton 
14699657Slinton /*
14709657Slinton  * Evaluate a subscript index.
14719657Slinton  */
14729657Slinton 
147318235Slinton public int evalindex(s, base, i)
14749657Slinton Symbol s;
147518235Slinton Address base;
14769657Slinton long i;
14779657Slinton {
147816620Ssam     Symbol t;
147918235Slinton     int r;
14809657Slinton 
148116620Ssam     t = rtype(s);
148218235Slinton     if (t->language == nil or t->language == primlang) {
148318235Slinton 	r = ((*language_op(findlanguage(".s"), L_EVALAREF)) (s, base, i));
148416620Ssam     } else {
148518235Slinton 	r = ((*language_op(t->language, L_EVALAREF)) (s, base, i));
148616620Ssam     }
148718235Slinton     return r;
14889657Slinton }
14899657Slinton 
14909657Slinton /*
14919657Slinton  * Check to see if a tree is boolean-valued, if not it's an error.
14929657Slinton  */
14939657Slinton 
14949657Slinton public chkboolean(p)
14959657Slinton register Node p;
14969657Slinton {
14979657Slinton     if (p->nodetype != t_boolean) {
14989657Slinton 	beginerrmsg();
14999657Slinton 	fprintf(stderr, "found ");
15009657Slinton 	prtree(stderr, p);
15019657Slinton 	fprintf(stderr, ", expected boolean expression");
15029657Slinton 	enderrmsg();
15039657Slinton     }
15049657Slinton }
15059657Slinton 
15069657Slinton /*
150716620Ssam  * Construct a node for the type of a string.
15089657Slinton  */
15099657Slinton 
15109657Slinton private Symbol mkstring(str)
15119657Slinton String str;
15129657Slinton {
15139657Slinton     register Symbol s;
15149657Slinton 
151518235Slinton     s = newSymbol(nil, 0, ARRAY, t_char, nil);
151618235Slinton     s->chain = newSymbol(nil, 0, RANGE, t_int, nil);
151718235Slinton     s->chain->language = s->language;
151818235Slinton     s->chain->symvalue.rangev.lower = 1;
151918235Slinton     s->chain->symvalue.rangev.upper = strlen(str) + 1;
15209657Slinton     return s;
15219657Slinton }
15229657Slinton 
15239657Slinton /*
15249657Slinton  * Free up the space allocated for a string type.
15259657Slinton  */
15269657Slinton 
15279657Slinton public unmkstring(s)
15289657Slinton Symbol s;
15299657Slinton {
15309657Slinton     dispose(s->chain);
15319657Slinton }
15329657Slinton 
15339657Slinton /*
153418235Slinton  * Figure out the "current" variable or function being referred to
153518235Slinton  * by the name n.
15369657Slinton  */
15379657Slinton 
153818235Slinton private boolean stwhich(), dynwhich();
153918235Slinton 
154018235Slinton public Symbol which (n)
15419657Slinton Name n;
15429657Slinton {
154318235Slinton     Symbol s;
15449657Slinton 
154518235Slinton     s = lookup(n);
15469657Slinton     if (s == nil) {
154718235Slinton 	error("\"%s\" is not defined", ident(n));
154818235Slinton     } else if (not stwhich(&s) and isambiguous(s) and not dynwhich(&s)) {
154918235Slinton 	printf("[using ");
155018235Slinton 	printname(stdout, s);
155118235Slinton 	printf("]\n");
15529657Slinton     }
155318235Slinton     return s;
155418235Slinton }
155518235Slinton 
155618235Slinton /*
155718235Slinton  * Static search.
155818235Slinton  */
155918235Slinton 
156018235Slinton private boolean stwhich (var_s)
156118235Slinton Symbol *var_s;
156218235Slinton {
156318235Slinton     Name n;		/* name of desired symbol */
156418235Slinton     Symbol s;		/* iteration variable for symbols with name n */
156518235Slinton     Symbol f;		/* iteration variable for blocks containing s */
156618235Slinton     integer count;	/* number of levels from s->block to curfunc */
156718235Slinton     Symbol t;		/* current best answer for stwhich(n) */
156818235Slinton     integer mincount;	/* relative level for current best answer (t) */
156918235Slinton     boolean b;		/* return value, true if symbol found */
157018235Slinton 
157118235Slinton     s = *var_s;
157218235Slinton     n = s->name;
157318235Slinton     t = s;
157418235Slinton     mincount = 10000; /* force first match to set mincount */
157518235Slinton     do {
157618235Slinton 	if (s->name == n and s->class != FIELD and s->class != TAG) {
157718235Slinton 	    f = curfunc;
157818235Slinton 	    count = 0;
157918235Slinton 	    while (f != nil and f != s->block) {
158018235Slinton 		++count;
158118235Slinton 		f = f->block;
158218235Slinton 	    }
158318235Slinton 	    if (f != nil and count < mincount) {
158418235Slinton 		t = s;
158518235Slinton 		mincount = count;
158618235Slinton 		b = true;
158718235Slinton 	    }
158818235Slinton 	}
158918235Slinton 	s = s->next_sym;
159018235Slinton     } while (s != nil);
159118235Slinton     if (mincount != 10000) {
159218235Slinton 	*var_s = t;
159318235Slinton 	b = true;
15949657Slinton     } else {
159518235Slinton 	b = false;
159618235Slinton     }
159718235Slinton     return b;
159818235Slinton }
159918235Slinton 
160018235Slinton /*
160118235Slinton  * Dynamic search.
160218235Slinton  */
160318235Slinton 
160418235Slinton private boolean dynwhich (var_s)
160518235Slinton Symbol *var_s;
160618235Slinton {
160718235Slinton     Name n;		/* name of desired symbol */
160818235Slinton     Symbol s;		/* iteration variable for possible symbols */
160918235Slinton     Symbol f;		/* iteration variable for active functions */
161018235Slinton     Frame frp;		/* frame associated with stack walk */
161118235Slinton     boolean b;		/* return value */
161218235Slinton 
161318235Slinton     f = curfunc;
161418235Slinton     frp = curfuncframe();
161518235Slinton     n = (*var_s)->name;
161618235Slinton     b = false;
161718235Slinton     if (frp != nil) {
161818235Slinton 	frp = nextfunc(frp, &f);
161918235Slinton 	while (frp != nil) {
162018235Slinton 	    s = *var_s;
162118235Slinton 	    while (s != nil and
162218235Slinton 		(
162318235Slinton 		    s->name != n or s->block != f or
162418235Slinton 		    s->class == FIELD or s->class == TAG
162518235Slinton 		)
162618235Slinton 	    ) {
162718235Slinton 		s = s->next_sym;
162818235Slinton 	    }
162918235Slinton 	    if (s != nil) {
163018235Slinton 		*var_s = s;
163118235Slinton 		b = true;
163218235Slinton 		break;
163318235Slinton 	    }
163418235Slinton 	    if (f == program) {
163518235Slinton 		break;
163618235Slinton 	    }
163718235Slinton 	    frp = nextfunc(frp, &f);
16389657Slinton 	}
16399657Slinton     }
164018235Slinton     return b;
16419657Slinton }
16429657Slinton 
16439657Slinton /*
164418235Slinton  * Find the symbol that has the same name and scope as the
16459657Slinton  * given symbol but is of the given field.  Return nil if there is none.
16469657Slinton  */
16479657Slinton 
164818235Slinton public Symbol findfield (fieldname, record)
16499657Slinton Name fieldname;
16509657Slinton Symbol record;
16519657Slinton {
16529657Slinton     register Symbol t;
16539657Slinton 
16549657Slinton     t = rtype(record)->chain;
16559657Slinton     while (t != nil and t->name != fieldname) {
16569657Slinton 	t = t->chain;
16579657Slinton     }
16589657Slinton     return t;
16599657Slinton }
166012547Scsvaf 
166112547Scsvaf public Boolean getbound(s,off,type,valp)
166212547Scsvaf Symbol s;
166312547Scsvaf int off;
166412547Scsvaf Rangetype type;
166512547Scsvaf int *valp;
166612547Scsvaf {
166712547Scsvaf     Frame frp;
166812547Scsvaf     Address addr;
166912547Scsvaf     Symbol cur;
167012547Scsvaf 
167112547Scsvaf     if (not isactive(s->block)) {
167212547Scsvaf 	return(false);
167312547Scsvaf     }
167412547Scsvaf     cur = s->block;
167512547Scsvaf     while (cur != nil and cur->class == MODULE) {  /* WHY*/
167612547Scsvaf     		cur = cur->block;
167712547Scsvaf     }
167812547Scsvaf     if(cur == nil) {
167912547Scsvaf 		cur = whatblock(pc);
168012547Scsvaf     }
168112547Scsvaf     frp = findframe(cur);
168212547Scsvaf     if (frp == nil) {
168312547Scsvaf 	return(false);
168412547Scsvaf     }
168512547Scsvaf     if(type == R_TEMP) addr = locals_base(frp) + off;
168612547Scsvaf     else if (type == R_ARG) addr = args_base(frp) + off;
168712547Scsvaf     else return(false);
168812547Scsvaf     dread(valp,addr,sizeof(long));
168912547Scsvaf     return(true);
169012547Scsvaf }
1691