xref: /csrg-svn/old/dbx/symbols.c (revision 33337)
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*33337Sdonn static char sccsid[] = "@(#)symbols.c	5.4 (Berkeley) 01/12/88";
921625Sdist #endif not lint
109657Slinton 
11*33337Sdonn static char rcsid[] = "$Header: symbols.c,v 1.3 87/03/26 23:17:35 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 {
44*33337Sdonn     BADUSE, CONST, TYPE, VAR, ARRAY, OPENARRAY, DYNARRAY, SUBARRAY,
45*33337Sdonn     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 
53*33337Sdonn #define INREG 0
54*33337Sdonn #define STK 1
55*33337Sdonn #define EXT 2
56*33337Sdonn 
57*33337Sdonn typedef unsigned integer Storage;
58*33337Sdonn 
599657Slinton struct Symbol {
609657Slinton     Name name;
619657Slinton     Language language;
62*33337Sdonn     Symclass class : 8;
63*33337Sdonn     Storage storage : 2;
64*33337Sdonn     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 
136*33337Sdonn #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.
160*33337Sdonn  * Hash table size is a power of two to make hashing faster.
161*33337Sdonn  * Using a non-prime is ok since we aren't doing rehashing.
1629657Slinton  */
1639657Slinton 
164*33337Sdonn #define HASHTABLESIZE 8192
1659657Slinton 
1669657Slinton private Symbol hashtab[HASHTABLESIZE];
1679657Slinton 
168*33337Sdonn #define hash(name) ((((unsigned) name) >> 2) & (HASHTABLESIZE - 1))
1699657Slinton 
1709657Slinton /*
1719657Slinton  * Allocate a new symbol.
1729657Slinton  */
1739657Slinton 
174*33337Sdonn #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);
190*33337Sdonn 	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;
253*33337Sdonn     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);
527*33337Sdonn     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 
563*33337Sdonn #define isglobal(s)		(s->storage == EXT)
564*33337Sdonn #define islocaloff(s)		(s->storage == STK and s->symvalue.offset < 0)
565*33337Sdonn #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;
624*33337Sdonn     s->storage = INREG;
625*33337Sdonn     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 
771*33337Sdonn 	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:
798*33337Sdonn 	    /*
799*33337Sdonn 	     * This causes problems on the IRIS because of the compiler bug
800*33337Sdonn 	     * with stab offsets for parameters.  Not sure it's really
801*33337Sdonn 	     * necessary anyway.
802*33337Sdonn 	     */
803*33337Sdonn #	    ifndef IRIS
8049657Slinton 	    if (t->type->class == PTR and t->type->type->class == BADUSE) {
8059657Slinton 		findtype(t);
8069657Slinton 	    }
807*33337Sdonn #	    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);
908*33337Sdonn 	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);
948*33337Sdonn     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;
1077*33337Sdonn 	} else if (t2->language == primlang) {
1078*33337Sdonn 	    b = (boolean) primlang_typematch(rtype(t1), rtype(t2));
107916620Ssam 	} else {
108016620Ssam 	    b = (boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2);
108116620Ssam 	}
1082*33337Sdonn     } else if (t1->language == primlang) {
1083*33337Sdonn 	if (t2->language == primlang or t2->language == nil) {
1084*33337Sdonn 	    b = primlang_typematch(rtype(t1), rtype(t2));
1085*33337Sdonn 	} else {
1086*33337Sdonn 	    b = (boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2);
1087*33337Sdonn 	}
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  * Note the tree is call by address, hence the #define below.
13719657Slinton  */
13729657Slinton 
13739657Slinton private convert(tp, typeto, op)
13749657Slinton Node *tp;
13759657Slinton Symbol typeto;
13769657Slinton Operator op;
13779657Slinton {
137816620Ssam     Node tree;
137916620Ssam     Symbol s, t;
13809657Slinton 
138116620Ssam     tree = *tp;
13829657Slinton     s = rtype(tree->nodetype);
138316620Ssam     t = rtype(typeto);
138416620Ssam     if (compatible(t, t_real) and compatible(s, t_int)) {
13859657Slinton 	tree = build(op, tree);
138616620Ssam     } else if (not compatible(s, t)) {
13879657Slinton 	beginerrmsg();
138816620Ssam 	fprintf(stderr, "expected integer or real, found \"");
138916620Ssam 	prtree(stderr, tree);
139016620Ssam 	fprintf(stderr, "\"");
13919657Slinton 	enderrmsg();
139216620Ssam     } else if (op != O_NOP and s != t) {
13939657Slinton 	tree = build(op, tree);
13949657Slinton     }
139516620Ssam     *tp = tree;
13969657Slinton }
13979657Slinton 
13989657Slinton /*
13999657Slinton  * Construct a node for the dot operator.
14009657Slinton  *
14019657Slinton  * If the left operand is not a record, but rather a procedure
14029657Slinton  * or function, then we interpret the "." as referencing an
14039657Slinton  * "invisible" variable; i.e. a variable within a dynamically
14049657Slinton  * active block but not within the static scope of the current procedure.
14059657Slinton  */
14069657Slinton 
14079657Slinton public Node dot(record, fieldname)
14089657Slinton Node record;
14099657Slinton Name fieldname;
14109657Slinton {
141118235Slinton     register Node rec, p;
14129657Slinton     register Symbol s, t;
14139657Slinton 
141418235Slinton     rec = record;
141518235Slinton     if (isblock(rec->nodetype)) {
14169657Slinton 	find(s, fieldname) where
141718235Slinton 	    s->block == rec->nodetype and
141818235Slinton 	    s->class != FIELD
14199657Slinton 	endfind(s);
14209657Slinton 	if (s == nil) {
14219657Slinton 	    beginerrmsg();
14229657Slinton 	    fprintf(stderr, "\"%s\" is not defined in ", ident(fieldname));
142318235Slinton 	    printname(stderr, rec->nodetype);
14249657Slinton 	    enderrmsg();
14259657Slinton 	}
14269657Slinton 	p = new(Node);
14279657Slinton 	p->op = O_SYM;
14289657Slinton 	p->value.sym = s;
142918235Slinton 	p->nodetype = s;
14309657Slinton     } else {
143118235Slinton 	p = rec;
14329657Slinton 	t = rtype(p->nodetype);
14339657Slinton 	if (t->class == PTR) {
14349657Slinton 	    s = findfield(fieldname, t->type);
14359657Slinton 	} else {
14369657Slinton 	    s = findfield(fieldname, t);
14379657Slinton 	}
14389657Slinton 	if (s == nil) {
14399657Slinton 	    beginerrmsg();
14409657Slinton 	    fprintf(stderr, "\"%s\" is not a field in ", ident(fieldname));
144118235Slinton 	    prtree(stderr, rec);
14429657Slinton 	    enderrmsg();
14439657Slinton 	}
144418235Slinton 	if (t->class != PTR or isreg(rec->nodetype)) {
144518235Slinton 	    p = unrval(p);
14469657Slinton 	}
144718235Slinton 	p->nodetype = t_addr;
14489657Slinton 	p = build(O_DOT, p, build(O_SYM, s));
14499657Slinton     }
145018235Slinton     return build(O_RVAL, p);
14519657Slinton }
14529657Slinton 
14539657Slinton /*
14549657Slinton  * Return a tree corresponding to an array reference and do the
14559657Slinton  * error checking.
14569657Slinton  */
14579657Slinton 
14589657Slinton public Node subscript(a, slist)
14599657Slinton Node a, slist;
14609657Slinton {
146116620Ssam     Symbol t;
146218235Slinton     Node p;
14639657Slinton 
146416620Ssam     t = rtype(a->nodetype);
146518235Slinton     if (t->language == nil or t->language == primlang) {
146618235Slinton 	p = (Node) (*language_op(findlanguage(".s"), L_BUILDAREF))(a, slist);
146716620Ssam     } else {
146818235Slinton 	p = (Node) (*language_op(t->language, L_BUILDAREF))(a, slist);
146916620Ssam     }
147018235Slinton     return build(O_RVAL, p);
14719657Slinton }
14729657Slinton 
14739657Slinton /*
14749657Slinton  * Evaluate a subscript index.
14759657Slinton  */
14769657Slinton 
147718235Slinton public int evalindex(s, base, i)
14789657Slinton Symbol s;
147918235Slinton Address base;
14809657Slinton long i;
14819657Slinton {
148216620Ssam     Symbol t;
148318235Slinton     int r;
14849657Slinton 
148516620Ssam     t = rtype(s);
148618235Slinton     if (t->language == nil or t->language == primlang) {
148718235Slinton 	r = ((*language_op(findlanguage(".s"), L_EVALAREF)) (s, base, i));
148816620Ssam     } else {
148918235Slinton 	r = ((*language_op(t->language, L_EVALAREF)) (s, base, i));
149016620Ssam     }
149118235Slinton     return r;
14929657Slinton }
14939657Slinton 
14949657Slinton /*
14959657Slinton  * Check to see if a tree is boolean-valued, if not it's an error.
14969657Slinton  */
14979657Slinton 
14989657Slinton public chkboolean(p)
14999657Slinton register Node p;
15009657Slinton {
15019657Slinton     if (p->nodetype != t_boolean) {
15029657Slinton 	beginerrmsg();
15039657Slinton 	fprintf(stderr, "found ");
15049657Slinton 	prtree(stderr, p);
15059657Slinton 	fprintf(stderr, ", expected boolean expression");
15069657Slinton 	enderrmsg();
15079657Slinton     }
15089657Slinton }
15099657Slinton 
15109657Slinton /*
151116620Ssam  * Construct a node for the type of a string.
15129657Slinton  */
15139657Slinton 
15149657Slinton private Symbol mkstring(str)
15159657Slinton String str;
15169657Slinton {
15179657Slinton     register Symbol s;
15189657Slinton 
151918235Slinton     s = newSymbol(nil, 0, ARRAY, t_char, nil);
152018235Slinton     s->chain = newSymbol(nil, 0, RANGE, t_int, nil);
152118235Slinton     s->chain->language = s->language;
152218235Slinton     s->chain->symvalue.rangev.lower = 1;
152318235Slinton     s->chain->symvalue.rangev.upper = strlen(str) + 1;
15249657Slinton     return s;
15259657Slinton }
15269657Slinton 
15279657Slinton /*
15289657Slinton  * Free up the space allocated for a string type.
15299657Slinton  */
15309657Slinton 
15319657Slinton public unmkstring(s)
15329657Slinton Symbol s;
15339657Slinton {
15349657Slinton     dispose(s->chain);
15359657Slinton }
15369657Slinton 
15379657Slinton /*
153818235Slinton  * Figure out the "current" variable or function being referred to
153918235Slinton  * by the name n.
15409657Slinton  */
15419657Slinton 
154218235Slinton private boolean stwhich(), dynwhich();
154318235Slinton 
154418235Slinton public Symbol which (n)
15459657Slinton Name n;
15469657Slinton {
154718235Slinton     Symbol s;
15489657Slinton 
154918235Slinton     s = lookup(n);
15509657Slinton     if (s == nil) {
155118235Slinton 	error("\"%s\" is not defined", ident(n));
155218235Slinton     } else if (not stwhich(&s) and isambiguous(s) and not dynwhich(&s)) {
155318235Slinton 	printf("[using ");
155418235Slinton 	printname(stdout, s);
155518235Slinton 	printf("]\n");
15569657Slinton     }
155718235Slinton     return s;
155818235Slinton }
155918235Slinton 
156018235Slinton /*
156118235Slinton  * Static search.
156218235Slinton  */
156318235Slinton 
156418235Slinton private boolean stwhich (var_s)
156518235Slinton Symbol *var_s;
156618235Slinton {
156718235Slinton     Name n;		/* name of desired symbol */
156818235Slinton     Symbol s;		/* iteration variable for symbols with name n */
156918235Slinton     Symbol f;		/* iteration variable for blocks containing s */
157018235Slinton     integer count;	/* number of levels from s->block to curfunc */
157118235Slinton     Symbol t;		/* current best answer for stwhich(n) */
157218235Slinton     integer mincount;	/* relative level for current best answer (t) */
157318235Slinton     boolean b;		/* return value, true if symbol found */
157418235Slinton 
157518235Slinton     s = *var_s;
157618235Slinton     n = s->name;
157718235Slinton     t = s;
157818235Slinton     mincount = 10000; /* force first match to set mincount */
157918235Slinton     do {
158018235Slinton 	if (s->name == n and s->class != FIELD and s->class != TAG) {
158118235Slinton 	    f = curfunc;
158218235Slinton 	    count = 0;
158318235Slinton 	    while (f != nil and f != s->block) {
158418235Slinton 		++count;
158518235Slinton 		f = f->block;
158618235Slinton 	    }
158718235Slinton 	    if (f != nil and count < mincount) {
158818235Slinton 		t = s;
158918235Slinton 		mincount = count;
159018235Slinton 		b = true;
159118235Slinton 	    }
159218235Slinton 	}
159318235Slinton 	s = s->next_sym;
159418235Slinton     } while (s != nil);
159518235Slinton     if (mincount != 10000) {
159618235Slinton 	*var_s = t;
159718235Slinton 	b = true;
15989657Slinton     } else {
159918235Slinton 	b = false;
160018235Slinton     }
160118235Slinton     return b;
160218235Slinton }
160318235Slinton 
160418235Slinton /*
160518235Slinton  * Dynamic search.
160618235Slinton  */
160718235Slinton 
160818235Slinton private boolean dynwhich (var_s)
160918235Slinton Symbol *var_s;
161018235Slinton {
161118235Slinton     Name n;		/* name of desired symbol */
161218235Slinton     Symbol s;		/* iteration variable for possible symbols */
161318235Slinton     Symbol f;		/* iteration variable for active functions */
161418235Slinton     Frame frp;		/* frame associated with stack walk */
161518235Slinton     boolean b;		/* return value */
161618235Slinton 
161718235Slinton     f = curfunc;
161818235Slinton     frp = curfuncframe();
161918235Slinton     n = (*var_s)->name;
162018235Slinton     b = false;
162118235Slinton     if (frp != nil) {
162218235Slinton 	frp = nextfunc(frp, &f);
162318235Slinton 	while (frp != nil) {
162418235Slinton 	    s = *var_s;
162518235Slinton 	    while (s != nil and
162618235Slinton 		(
162718235Slinton 		    s->name != n or s->block != f or
162818235Slinton 		    s->class == FIELD or s->class == TAG
162918235Slinton 		)
163018235Slinton 	    ) {
163118235Slinton 		s = s->next_sym;
163218235Slinton 	    }
163318235Slinton 	    if (s != nil) {
163418235Slinton 		*var_s = s;
163518235Slinton 		b = true;
163618235Slinton 		break;
163718235Slinton 	    }
163818235Slinton 	    if (f == program) {
163918235Slinton 		break;
164018235Slinton 	    }
164118235Slinton 	    frp = nextfunc(frp, &f);
16429657Slinton 	}
16439657Slinton     }
164418235Slinton     return b;
16459657Slinton }
16469657Slinton 
16479657Slinton /*
164818235Slinton  * Find the symbol that has the same name and scope as the
16499657Slinton  * given symbol but is of the given field.  Return nil if there is none.
16509657Slinton  */
16519657Slinton 
165218235Slinton public Symbol findfield (fieldname, record)
16539657Slinton Name fieldname;
16549657Slinton Symbol record;
16559657Slinton {
16569657Slinton     register Symbol t;
16579657Slinton 
16589657Slinton     t = rtype(record)->chain;
16599657Slinton     while (t != nil and t->name != fieldname) {
16609657Slinton 	t = t->chain;
16619657Slinton     }
16629657Slinton     return t;
16639657Slinton }
166412547Scsvaf 
166512547Scsvaf public Boolean getbound(s,off,type,valp)
166612547Scsvaf Symbol s;
166712547Scsvaf int off;
166812547Scsvaf Rangetype type;
166912547Scsvaf int *valp;
167012547Scsvaf {
167112547Scsvaf     Frame frp;
167212547Scsvaf     Address addr;
167312547Scsvaf     Symbol cur;
167412547Scsvaf 
167512547Scsvaf     if (not isactive(s->block)) {
167612547Scsvaf 	return(false);
167712547Scsvaf     }
167812547Scsvaf     cur = s->block;
167912547Scsvaf     while (cur != nil and cur->class == MODULE) {  /* WHY*/
168012547Scsvaf     		cur = cur->block;
168112547Scsvaf     }
168212547Scsvaf     if(cur == nil) {
168312547Scsvaf 		cur = whatblock(pc);
168412547Scsvaf     }
168512547Scsvaf     frp = findframe(cur);
168612547Scsvaf     if (frp == nil) {
168712547Scsvaf 	return(false);
168812547Scsvaf     }
168912547Scsvaf     if(type == R_TEMP) addr = locals_base(frp) + off;
169012547Scsvaf     else if (type == R_ARG) addr = args_base(frp) + off;
169112547Scsvaf     else return(false);
169212547Scsvaf     dread(valp,addr,sizeof(long));
169312547Scsvaf     return(true);
169412547Scsvaf }
1695