xref: /csrg-svn/old/dbx/symbols.c (revision 24554)
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*24554Smckusick static char sccsid[] = "@(#)symbols.c	5.2 (Berkeley) 09/05/85";
921625Sdist #endif not lint
109657Slinton 
1118235Slinton static char rcsid[] = "$Header: symbols.c,v 1.6 84/12/26 10:42:31 linton 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 {
4418235Slinton     BADUSE, CONST, TYPE, VAR, ARRAY, DYNARRAY, SUBARRAY, PTRFILE, RECORD, FIELD,
4512547Scsvaf     PROC, FUNC, FVAR, REF, PTR, FILET, SET, RANGE,
469657Slinton     LABEL, WITHPTR, SCAL, STR, PROG, IMPROPER, VARNT,
4716620Ssam     FPROC, FFUNC, MODULE, TAG, COMMON, EXTREF, TYPEREF
489657Slinton } Symclass;
499657Slinton 
5012547Scsvaf typedef enum { R_CONST, R_TEMP, R_ARG, R_ADJUST } Rangetype;
5112547Scsvaf 
529657Slinton struct Symbol {
539657Slinton     Name name;
549657Slinton     Language language;
559657Slinton     Symclass class : 8;
569657Slinton     Integer level : 8;
579657Slinton     Symbol type;
589657Slinton     Symbol chain;
599657Slinton     union {
6018235Slinton 	Node constval;		/* value of constant symbol */
619657Slinton 	int offset;		/* variable address */
629657Slinton 	long iconval;		/* integer constant value */
639657Slinton 	double fconval;		/* floating constant value */
6418235Slinton 	int ndims;		/* no. of dimensions for dynamic/sub-arrays */
659657Slinton 	struct {		/* field offset and size (both in bits) */
669657Slinton 	    int offset;
679657Slinton 	    int length;
689657Slinton 	} field;
6912547Scsvaf 	struct {		/* common offset and chain; used to relocate */
7012547Scsvaf 	    int offset;         /* vars in global BSS */
7112547Scsvaf 	    Symbol chain;
7212547Scsvaf 	} common;
739657Slinton 	struct {		/* range bounds */
7412547Scsvaf             Rangetype lowertype : 16;
7512547Scsvaf             Rangetype uppertype : 16;
769657Slinton 	    long lower;
779657Slinton 	    long upper;
789657Slinton 	} rangev;
7911865Slinton 	struct {
8011865Slinton 	    int offset : 16;	/* offset for of function value */
8116620Ssam 	    Boolean src : 1;	/* true if there is source line info */
8216620Ssam 	    Boolean inline : 1;	/* true if no separate act. rec. */
8316620Ssam 	    Boolean intern : 1; /* internal calling sequence */
8416620Ssam 	    int unused : 13;
8511865Slinton 	    Address beginaddr;	/* address of function code */
869657Slinton 	} funcv;
879657Slinton 	struct {		/* variant record info */
889657Slinton 	    int size;
899657Slinton 	    Symbol vtorec;
909657Slinton 	    Symbol vtag;
919657Slinton 	} varnt;
9216620Ssam 	String typeref;		/* type defined by "<module>:<type>" */
9316620Ssam 	Symbol extref;		/* indirect symbol for external reference */
949657Slinton     } symvalue;
959657Slinton     Symbol block;		/* symbol containing this symbol */
969657Slinton     Symbol next_sym;		/* hash chain */
979657Slinton };
989657Slinton 
999657Slinton /*
1009657Slinton  * Basic types.
1019657Slinton  */
1029657Slinton 
1039657Slinton Symbol t_boolean;
1049657Slinton Symbol t_char;
1059657Slinton Symbol t_int;
1069657Slinton Symbol t_real;
1079657Slinton Symbol t_nil;
10818235Slinton Symbol t_addr;
1099657Slinton 
1109657Slinton Symbol program;
1119657Slinton Symbol curfunc;
1129657Slinton 
11318235Slinton boolean showaggrs;
11418235Slinton 
1159657Slinton #define symname(s) ident(s->name)
1169657Slinton #define codeloc(f) ((f)->symvalue.funcv.beginaddr)
1179657Slinton #define isblock(s) (Boolean) ( \
1189657Slinton     s->class == FUNC or s->class == PROC or \
1199657Slinton     s->class == MODULE or s->class == PROG \
1209657Slinton )
12116620Ssam #define isroutine(s) (Boolean) ( \
12216620Ssam     s->class == FUNC or s->class == PROC \
12316620Ssam )
1249657Slinton 
12511865Slinton #define nosource(f) (not (f)->symvalue.funcv.src)
12614441Slinton #define isinline(f) ((f)->symvalue.funcv.inline)
12711865Slinton 
128*24554Smckusick #define isreg(s)		(s->level < 0)
129*24554Smckusick 
1309657Slinton #include "tree.h"
1319657Slinton 
1329657Slinton /*
1339657Slinton  * Some macros to make finding a symbol with certain attributes.
1349657Slinton  */
1359657Slinton 
1369657Slinton #define find(s, withname) \
1379657Slinton { \
1389657Slinton     s = lookup(withname); \
1399657Slinton     while (s != nil and not (s->name == (withname) and
1409657Slinton 
1419657Slinton #define where /* qualification */
1429657Slinton 
1439657Slinton #define endfind(s) )) { \
1449657Slinton 	s = s->next_sym; \
1459657Slinton     } \
1469657Slinton }
1479657Slinton 
1489657Slinton #endif
1499657Slinton 
1509657Slinton /*
1519657Slinton  * Symbol table structure currently does not support deletions.
1529657Slinton  */
1539657Slinton 
1549657Slinton #define HASHTABLESIZE 2003
1559657Slinton 
1569657Slinton private Symbol hashtab[HASHTABLESIZE];
1579657Slinton 
1589657Slinton #define hash(name) ((((unsigned) name) >> 2) mod HASHTABLESIZE)
1599657Slinton 
1609657Slinton /*
1619657Slinton  * Allocate a new symbol.
1629657Slinton  */
1639657Slinton 
16411171Slinton #define SYMBLOCKSIZE 100
1659657Slinton 
1669657Slinton typedef struct Sympool {
1679657Slinton     struct Symbol sym[SYMBLOCKSIZE];
1689657Slinton     struct Sympool *prevpool;
1699657Slinton } *Sympool;
1709657Slinton 
1719657Slinton private Sympool sympool = nil;
1729657Slinton private Integer nleft = 0;
1739657Slinton 
1749657Slinton public Symbol symbol_alloc()
1759657Slinton {
1769657Slinton     register Sympool newpool;
1779657Slinton 
1789657Slinton     if (nleft <= 0) {
1799657Slinton 	newpool = new(Sympool);
18011171Slinton 	bzero(newpool, sizeof(newpool));
1819657Slinton 	newpool->prevpool = sympool;
1829657Slinton 	sympool = newpool;
1839657Slinton 	nleft = SYMBLOCKSIZE;
1849657Slinton     }
1859657Slinton     --nleft;
1869657Slinton     return &(sympool->sym[nleft]);
1879657Slinton }
1889657Slinton 
18918235Slinton public symbol_dump (func)
19012547Scsvaf Symbol func;
19112547Scsvaf {
19218235Slinton     register Symbol s;
19318235Slinton     register integer i;
19412547Scsvaf 
19518235Slinton     printf(" symbols in %s \n",symname(func));
19618235Slinton     for (i = 0; i < HASHTABLESIZE; i++) {
19718235Slinton 	for (s = hashtab[i]; s != nil; s = s->next_sym) {
19818235Slinton 	    if (s->block == func) {
19918235Slinton 		psym(s);
20018235Slinton 	    }
20118235Slinton 	}
20218235Slinton     }
20312547Scsvaf }
20412547Scsvaf 
2059657Slinton /*
2069657Slinton  * Free all the symbols currently allocated.
2079657Slinton  */
20818235Slinton 
2099657Slinton public symbol_free()
2109657Slinton {
2119657Slinton     Sympool s, t;
2129657Slinton     register Integer i;
2139657Slinton 
2149657Slinton     s = sympool;
2159657Slinton     while (s != nil) {
2169657Slinton 	t = s->prevpool;
2179657Slinton 	dispose(s);
2189657Slinton 	s = t;
2199657Slinton     }
2209657Slinton     for (i = 0; i < HASHTABLESIZE; i++) {
2219657Slinton 	hashtab[i] = nil;
2229657Slinton     }
2239657Slinton     sympool = nil;
2249657Slinton     nleft = 0;
2259657Slinton }
2269657Slinton 
2279657Slinton /*
2289657Slinton  * Create a new symbol with the given attributes.
2299657Slinton  */
2309657Slinton 
2319657Slinton public Symbol newSymbol(name, blevel, class, type, chain)
2329657Slinton Name name;
2339657Slinton Integer blevel;
2349657Slinton Symclass class;
2359657Slinton Symbol type;
2369657Slinton Symbol chain;
2379657Slinton {
2389657Slinton     register Symbol s;
2399657Slinton 
2409657Slinton     s = symbol_alloc();
2419657Slinton     s->name = name;
24218235Slinton     s->language = primlang;
2439657Slinton     s->level = blevel;
2449657Slinton     s->class = class;
2459657Slinton     s->type = type;
2469657Slinton     s->chain = chain;
2479657Slinton     return s;
2489657Slinton }
2499657Slinton 
2509657Slinton /*
2519657Slinton  * Insert a symbol into the hash table.
2529657Slinton  */
2539657Slinton 
2549657Slinton public Symbol insert(name)
2559657Slinton Name name;
2569657Slinton {
2579657Slinton     register Symbol s;
2589657Slinton     register unsigned int h;
2599657Slinton 
2609657Slinton     h = hash(name);
2619657Slinton     s = symbol_alloc();
2629657Slinton     s->name = name;
2639657Slinton     s->next_sym = hashtab[h];
2649657Slinton     hashtab[h] = s;
2659657Slinton     return s;
2669657Slinton }
2679657Slinton 
2689657Slinton /*
2699657Slinton  * Symbol lookup.
2709657Slinton  */
2719657Slinton 
2729657Slinton public Symbol lookup(name)
2739657Slinton Name name;
2749657Slinton {
2759657Slinton     register Symbol s;
2769657Slinton     register unsigned int h;
2779657Slinton 
2789657Slinton     h = hash(name);
2799657Slinton     s = hashtab[h];
2809657Slinton     while (s != nil and s->name != name) {
2819657Slinton 	s = s->next_sym;
2829657Slinton     }
2839657Slinton     return s;
2849657Slinton }
2859657Slinton 
2869657Slinton /*
28716620Ssam  * Delete a symbol from the symbol table.
28816620Ssam  */
28916620Ssam 
29016620Ssam public delete (s)
29116620Ssam Symbol s;
29216620Ssam {
29316620Ssam     register Symbol t;
29416620Ssam     register unsigned int h;
29516620Ssam 
29616620Ssam     h = hash(s->name);
29716620Ssam     t = hashtab[h];
29816620Ssam     if (t == nil) {
29916620Ssam 	panic("delete of non-symbol '%s'", symname(s));
30016620Ssam     } else if (t == s) {
30116620Ssam 	hashtab[h] = s->next_sym;
30216620Ssam     } else {
30316620Ssam 	while (t->next_sym != s) {
30416620Ssam 	    t = t->next_sym;
30516620Ssam 	    if (t == nil) {
30616620Ssam 		panic("delete of non-symbol '%s'", symname(s));
30716620Ssam 	    }
30816620Ssam 	}
30916620Ssam 	t->next_sym = s->next_sym;
31016620Ssam     }
31116620Ssam }
31216620Ssam 
31316620Ssam /*
3149657Slinton  * Dump out all the variables associated with the given
31518235Slinton  * procedure, function, or program associated with the given stack frame.
3169657Slinton  *
3179657Slinton  * This is quite inefficient.  We traverse the entire symbol table
3189657Slinton  * each time we're called.  The assumption is that this routine
3199657Slinton  * won't be called frequently enough to merit improved performance.
3209657Slinton  */
3219657Slinton 
3229657Slinton public dumpvars(f, frame)
3239657Slinton Symbol f;
3249657Slinton Frame frame;
3259657Slinton {
3269657Slinton     register Integer i;
3279657Slinton     register Symbol s;
3289657Slinton 
3299657Slinton     for (i = 0; i < HASHTABLESIZE; i++) {
3309657Slinton 	for (s = hashtab[i]; s != nil; s = s->next_sym) {
3319657Slinton 	    if (container(s) == f) {
3329657Slinton 		if (should_print(s)) {
3339657Slinton 		    printv(s, frame);
3349657Slinton 		    putchar('\n');
3359657Slinton 		} else if (s->class == MODULE) {
3369657Slinton 		    dumpvars(s, frame);
3379657Slinton 		}
3389657Slinton 	    }
3399657Slinton 	}
3409657Slinton     }
3419657Slinton }
3429657Slinton 
3439657Slinton /*
3449657Slinton  * Create a builtin type.
3459657Slinton  * Builtin types are circular in that btype->type->type = btype.
3469657Slinton  */
3479657Slinton 
34818235Slinton private Symbol maketype(name, lower, upper)
3499657Slinton String name;
3509657Slinton long lower;
3519657Slinton long upper;
3529657Slinton {
3539657Slinton     register Symbol s;
35418235Slinton     Name n;
3559657Slinton 
35618235Slinton     if (name == nil) {
35718235Slinton 	n = nil;
35818235Slinton     } else {
35918235Slinton 	n = identname(name, true);
36018235Slinton     }
36118235Slinton     s = insert(n);
36216620Ssam     s->language = primlang;
36318235Slinton     s->level = 0;
36418235Slinton     s->class = TYPE;
36518235Slinton     s->type = nil;
36618235Slinton     s->chain = nil;
3679657Slinton     s->type = newSymbol(nil, 0, RANGE, s, nil);
3689657Slinton     s->type->symvalue.rangev.lower = lower;
3699657Slinton     s->type->symvalue.rangev.upper = upper;
3709657Slinton     return s;
3719657Slinton }
3729657Slinton 
3739657Slinton /*
37418235Slinton  * Create the builtin symbols.
37518235Slinton  */
37618235Slinton 
37718235Slinton public symbols_init ()
3789657Slinton {
37918235Slinton     Symbol s;
3809657Slinton 
38118235Slinton     t_boolean = maketype("$boolean", 0L, 1L);
38218235Slinton     t_int = maketype("$integer", 0x80000000L, 0x7fffffffL);
38318235Slinton     t_char = maketype("$char", 0L, 255L);
38418235Slinton     t_real = maketype("$real", 8L, 0L);
38518235Slinton     t_nil = maketype("$nil", 0L, 0L);
38618235Slinton     t_addr = insert(identname("$address", true));
38718235Slinton     t_addr->language = primlang;
38818235Slinton     t_addr->level = 0;
38918235Slinton     t_addr->class = TYPE;
39018235Slinton     t_addr->type = newSymbol(nil, 1, PTR, t_int, nil);
39118235Slinton     s = insert(identname("true", true));
39218235Slinton     s->class = CONST;
39318235Slinton     s->type = t_boolean;
39418235Slinton     s->symvalue.constval = build(O_LCON, 1L);
39518235Slinton     s->symvalue.constval->nodetype = t_boolean;
39618235Slinton     s = insert(identname("false", true));
39718235Slinton     s->class = CONST;
39818235Slinton     s->type = t_boolean;
39918235Slinton     s->symvalue.constval = build(O_LCON, 0L);
40018235Slinton     s->symvalue.constval->nodetype = t_boolean;
4019657Slinton }
4029657Slinton 
4039657Slinton /*
4049657Slinton  * Reduce type to avoid worrying about type names.
4059657Slinton  */
4069657Slinton 
4079657Slinton public Symbol rtype(type)
4089657Slinton Symbol type;
4099657Slinton {
4109657Slinton     register Symbol t;
4119657Slinton 
4129657Slinton     t = type;
4139657Slinton     if (t != nil) {
41418235Slinton 	if (t->class == VAR or t->class == CONST or
41518235Slinton 	    t->class == FIELD or t->class == REF
41618235Slinton 	) {
4179657Slinton 	    t = t->type;
4189657Slinton 	}
41916620Ssam 	if (t->class == TYPEREF) {
42016620Ssam 	    resolveRef(t);
42116620Ssam 	}
4229657Slinton 	while (t->class == TYPE or t->class == TAG) {
4239657Slinton 	    t = t->type;
42416620Ssam 	    if (t->class == TYPEREF) {
42516620Ssam 		resolveRef(t);
42616620Ssam 	    }
4279657Slinton 	}
4289657Slinton     }
4299657Slinton     return t;
4309657Slinton }
4319657Slinton 
43216620Ssam /*
43316620Ssam  * Find the end of a module name.  Return nil if there is none
43416620Ssam  * in the given string.
43516620Ssam  */
43616620Ssam 
43716620Ssam private String findModuleMark (s)
43816620Ssam String s;
43916620Ssam {
44016620Ssam     register char *p, *r;
44116620Ssam     register boolean done;
44216620Ssam 
44316620Ssam     p = s;
44416620Ssam     done = false;
44516620Ssam     do {
44616620Ssam 	if (*p == ':') {
44716620Ssam 	    done = true;
44816620Ssam 	    r = p;
44916620Ssam 	} else if (*p == '\0') {
45016620Ssam 	    done = true;
45116620Ssam 	    r = nil;
45216620Ssam 	} else {
45316620Ssam 	    ++p;
45416620Ssam 	}
45516620Ssam     } while (not done);
45616620Ssam     return r;
45716620Ssam }
45816620Ssam 
45916620Ssam /*
46016620Ssam  * Resolve a type reference by modifying to be the appropriate type.
46116620Ssam  *
46216620Ssam  * If the reference has a name, then it refers to an opaque type and
46316620Ssam  * the actual type is directly accessible.  Otherwise, we must use
46416620Ssam  * the type reference string, which is of the form "module:{module:}name".
46516620Ssam  */
46616620Ssam 
46716620Ssam public resolveRef (t)
46816620Ssam Symbol t;
46916620Ssam {
47016620Ssam     register char *p;
47116620Ssam     char *start;
47216620Ssam     Symbol s, m, outer;
47316620Ssam     Name n;
47416620Ssam 
47516620Ssam     if (t->name != nil) {
47616620Ssam 	s = t;
47716620Ssam     } else {
47816620Ssam 	start = t->symvalue.typeref;
47916620Ssam 	outer = program;
48016620Ssam 	p = findModuleMark(start);
48116620Ssam 	while (p != nil) {
48216620Ssam 	    *p = '\0';
48316620Ssam 	    n = identname(start, true);
48416620Ssam 	    find(m, n) where m->block == outer endfind(m);
48516620Ssam 	    if (m == nil) {
48616620Ssam 		p = nil;
48716620Ssam 		outer = nil;
48816620Ssam 		s = nil;
48916620Ssam 	    } else {
49016620Ssam 		outer = m;
49116620Ssam 		start = p + 1;
49216620Ssam 		p = findModuleMark(start);
49316620Ssam 	    }
49416620Ssam 	}
49516620Ssam 	if (outer != nil) {
49616620Ssam 	    n = identname(start, true);
49716620Ssam 	    find(s, n) where s->block == outer endfind(s);
49816620Ssam 	}
49916620Ssam     }
50016620Ssam     if (s != nil and s->type != nil) {
50116620Ssam 	t->name = s->type->name;
50216620Ssam 	t->class = s->type->class;
50316620Ssam 	t->type = s->type->type;
50416620Ssam 	t->chain = s->type->chain;
50516620Ssam 	t->symvalue = s->type->symvalue;
50616620Ssam 	t->block = s->type->block;
50716620Ssam     }
50816620Ssam }
50916620Ssam 
51018235Slinton public integer regnum (s)
5119657Slinton Symbol s;
5129657Slinton {
51318235Slinton     integer r;
51418235Slinton 
5159657Slinton     checkref(s);
51618235Slinton     if (s->level < 0) {
51718235Slinton 	r = s->symvalue.offset;
51818235Slinton     } else {
51918235Slinton 	r = -1;
52018235Slinton     }
52118235Slinton     return r;
5229657Slinton }
5239657Slinton 
5249657Slinton public Symbol container(s)
5259657Slinton Symbol s;
5269657Slinton {
5279657Slinton     checkref(s);
5289657Slinton     return s->block;
5299657Slinton }
5309657Slinton 
53118235Slinton public Node constval(s)
53218235Slinton Symbol s;
53318235Slinton {
53418235Slinton     checkref(s);
53518235Slinton     if (s->class != CONST) {
53618235Slinton 	error("[internal error: constval(non-CONST)]");
53718235Slinton     }
53818235Slinton     return s->symvalue.constval;
53918235Slinton }
54018235Slinton 
5419657Slinton /*
5429657Slinton  * Return the object address of the given symbol.
5439657Slinton  *
5449657Slinton  * There are the following possibilities:
5459657Slinton  *
5469657Slinton  *	globals		- just take offset
5479657Slinton  *	locals		- take offset from locals base
5489657Slinton  *	arguments	- take offset from argument base
5499657Slinton  *	register	- offset is register number
5509657Slinton  */
5519657Slinton 
55216620Ssam #define isglobal(s)		(s->level == 1)
55316620Ssam #define islocaloff(s)		(s->level >= 2 and s->symvalue.offset < 0)
55416620Ssam #define isparamoff(s)		(s->level >= 2 and s->symvalue.offset >= 0)
5559657Slinton 
55618235Slinton public Address address (s, frame)
5579657Slinton Symbol s;
5589657Slinton Frame frame;
5599657Slinton {
5609657Slinton     register Frame frp;
5619657Slinton     register Address addr;
5629657Slinton     register Symbol cur;
5639657Slinton 
5649657Slinton     checkref(s);
5659657Slinton     if (not isactive(s->block)) {
5669657Slinton 	error("\"%s\" is not currently defined", symname(s));
5679657Slinton     } else if (isglobal(s)) {
5689657Slinton 	addr = s->symvalue.offset;
5699657Slinton     } else {
5709657Slinton 	frp = frame;
5719657Slinton 	if (frp == nil) {
5729657Slinton 	    cur = s->block;
5739657Slinton 	    while (cur != nil and cur->class == MODULE) {
5749657Slinton 		cur = cur->block;
5759657Slinton 	    }
5769657Slinton 	    if (cur == nil) {
57718235Slinton 		frp = nil;
57818235Slinton 	    } else {
57918235Slinton 		frp = findframe(cur);
58018235Slinton 		if (frp == nil) {
58118235Slinton 		    error("[internal error: unexpected nil frame for \"%s\"]",
58218235Slinton 			symname(s)
58318235Slinton 		    );
58418235Slinton 		}
5859657Slinton 	    }
5869657Slinton 	}
5879657Slinton 	if (islocaloff(s)) {
5889657Slinton 	    addr = locals_base(frp) + s->symvalue.offset;
5899657Slinton 	} else if (isparamoff(s)) {
5909657Slinton 	    addr = args_base(frp) + s->symvalue.offset;
5919657Slinton 	} else if (isreg(s)) {
5929657Slinton 	    addr = savereg(s->symvalue.offset, frp);
5939657Slinton 	} else {
5949657Slinton 	    panic("address: bad symbol \"%s\"", symname(s));
5959657Slinton 	}
5969657Slinton     }
5979657Slinton     return addr;
5989657Slinton }
5999657Slinton 
6009657Slinton /*
6019657Slinton  * Define a symbol used to access register values.
6029657Slinton  */
6039657Slinton 
60418235Slinton public defregname (n, r)
6059657Slinton Name n;
60618235Slinton integer r;
6079657Slinton {
60818235Slinton     Symbol s;
6099657Slinton 
6109657Slinton     s = insert(n);
61118235Slinton     s->language = t_addr->language;
6129657Slinton     s->class = VAR;
6139657Slinton     s->level = -3;
61418235Slinton     s->type = t_addr;
6159657Slinton     s->symvalue.offset = r;
6169657Slinton }
6179657Slinton 
6189657Slinton /*
6199657Slinton  * Resolve an "abstract" type reference.
6209657Slinton  *
6219657Slinton  * It is possible in C to define a pointer to a type, but never define
6229657Slinton  * the type in a particular source file.  Here we try to resolve
6239657Slinton  * the type definition.  This is problematic, it is possible to
6249657Slinton  * have multiple, different definitions for the same name type.
6259657Slinton  */
6269657Slinton 
6279657Slinton public findtype(s)
6289657Slinton Symbol s;
6299657Slinton {
6309657Slinton     register Symbol t, u, prev;
6319657Slinton 
6329657Slinton     u = s;
6339657Slinton     prev = nil;
6349657Slinton     while (u != nil and u->class != BADUSE) {
6359657Slinton 	if (u->name != nil) {
6369657Slinton 	    prev = u;
6379657Slinton 	}
6389657Slinton 	u = u->type;
6399657Slinton     }
6409657Slinton     if (prev == nil) {
6419657Slinton 	error("couldn't find link to type reference");
6429657Slinton     }
64318235Slinton     t = lookup(prev->name);
64418235Slinton     while (t != nil and
64518235Slinton 	not (
64618235Slinton 	    t != prev and t->name == prev->name and
64718235Slinton 	    t->block->class == MODULE and t->class == prev->class and
64818235Slinton 	    t->type != nil and t->type->type != nil and
64918235Slinton 	    t->type->type->class != BADUSE
65018235Slinton 	)
65118235Slinton     ) {
65218235Slinton 	t = t->next_sym;
65318235Slinton     }
6549657Slinton     if (t == nil) {
6559657Slinton 	error("couldn't resolve reference");
6569657Slinton     } else {
6579657Slinton 	prev->type = t->type;
6589657Slinton     }
6599657Slinton }
6609657Slinton 
6619657Slinton /*
6629657Slinton  * Find the size in bytes of the given type.
6639657Slinton  *
6649657Slinton  * This is probably the WRONG thing to do.  The size should be kept
6659657Slinton  * as an attribute in the symbol information as is done for structures
6669657Slinton  * and fields.  I haven't gotten around to cleaning this up yet.
6679657Slinton  */
6689657Slinton 
66912547Scsvaf #define MAXUCHAR 255
67012547Scsvaf #define MAXUSHORT 65535L
6719657Slinton #define MINCHAR -128
6729657Slinton #define MAXCHAR 127
6739657Slinton #define MINSHORT -32768
6749657Slinton #define MAXSHORT 32767
6759657Slinton 
67616620Ssam public findbounds (u, lower, upper)
67716620Ssam Symbol u;
67816620Ssam long *lower, *upper;
67916620Ssam {
68016620Ssam     Rangetype lbt, ubt;
68116620Ssam     long lb, ub;
68216620Ssam 
68316620Ssam     if (u->class == RANGE) {
68416620Ssam 	lbt = u->symvalue.rangev.lowertype;
68516620Ssam 	ubt = u->symvalue.rangev.uppertype;
68616620Ssam 	lb = u->symvalue.rangev.lower;
68716620Ssam 	ub = u->symvalue.rangev.upper;
68816620Ssam 	if (lbt == R_ARG or lbt == R_TEMP) {
68916620Ssam 	    if (not getbound(u, lb, lbt, lower)) {
69016620Ssam 		error("dynamic bounds not currently available");
69116620Ssam 	    }
69216620Ssam 	} else {
69316620Ssam 	    *lower = lb;
69416620Ssam 	}
69516620Ssam 	if (ubt == R_ARG or ubt == R_TEMP) {
69616620Ssam 	    if (not getbound(u, ub, ubt, upper)) {
69716620Ssam 		error("dynamic bounds not currently available");
69816620Ssam 	    }
69916620Ssam 	} else {
70016620Ssam 	    *upper = ub;
70116620Ssam 	}
70216620Ssam     } else if (u->class == SCAL) {
70316620Ssam 	*lower = 0;
70416620Ssam 	*upper = u->symvalue.iconval - 1;
70516620Ssam     } else {
70618235Slinton 	error("[internal error: unexpected array bound type]");
70716620Ssam     }
70816620Ssam }
70916620Ssam 
71016620Ssam public integer size(sym)
71116620Ssam Symbol sym;
71216620Ssam {
71316620Ssam     register Symbol s, t, u;
71416620Ssam     register integer nel, elsize;
7159657Slinton     long lower, upper;
71616620Ssam     integer r, off, len;
7179657Slinton 
7189657Slinton     t = sym;
7199657Slinton     checkref(t);
72016620Ssam     if (t->class == TYPEREF) {
72116620Ssam 	resolveRef(t);
72216620Ssam     }
7239657Slinton     switch (t->class) {
7249657Slinton 	case RANGE:
7259657Slinton 	    lower = t->symvalue.rangev.lower;
7269657Slinton 	    upper = t->symvalue.rangev.upper;
72716620Ssam 	    if (upper == 0 and lower > 0) {
72816620Ssam 		/* real */
7299657Slinton 		r = lower;
73016620Ssam 	    } else if (lower > upper) {
73116620Ssam 		/* unsigned long */
73216620Ssam 		r = sizeof(long);
73312045Slinton 	    } else if (
73412547Scsvaf   		(lower >= MINCHAR and upper <= MAXCHAR) or
73512547Scsvaf   		(lower >= 0 and upper <= MAXUCHAR)
73612547Scsvaf   	      ) {
7379657Slinton 		r = sizeof(char);
73812547Scsvaf   	    } else if (
73912547Scsvaf   		(lower >= MINSHORT and upper <= MAXSHORT) or
74012547Scsvaf   		(lower >= 0 and upper <= MAXUSHORT)
74112547Scsvaf   	      ) {
7429657Slinton 		r = sizeof(short);
7439657Slinton 	    } else {
7449657Slinton 		r = sizeof(long);
7459657Slinton 	    }
7469657Slinton 	    break;
7479657Slinton 
7489657Slinton 	case ARRAY:
7499657Slinton 	    elsize = size(t->type);
7509657Slinton 	    nel = 1;
7519657Slinton 	    for (t = t->chain; t != nil; t = t->chain) {
75216620Ssam 		u = rtype(t);
75316620Ssam 		findbounds(u, &lower, &upper);
7549657Slinton 		nel *= (upper-lower+1);
7559657Slinton 	    }
7569657Slinton 	    r = nel*elsize;
7579657Slinton 	    break;
7589657Slinton 
75918235Slinton 	case DYNARRAY:
76018235Slinton 	    r = (t->symvalue.ndims + 1) * sizeof(Word);
76118235Slinton 	    break;
76218235Slinton 
76318235Slinton 	case SUBARRAY:
76418235Slinton 	    r = (2 * t->symvalue.ndims + 1) * sizeof(Word);
76518235Slinton 	    break;
76618235Slinton 
76712547Scsvaf 	case REF:
7689657Slinton 	case VAR:
7699657Slinton 	    r = size(t->type);
77012127Slinton 	    /*
77112127Slinton 	     *
77212045Slinton 	    if (r < sizeof(Word) and isparam(t)) {
7739657Slinton 		r = sizeof(Word);
7749657Slinton 	    }
77512547Scsvaf 	    */
7769657Slinton 	    break;
7779657Slinton 
77818235Slinton 	case FVAR:
7799657Slinton 	case CONST:
78018235Slinton 	case TAG:
7819657Slinton 	    r = size(t->type);
7829657Slinton 	    break;
7839657Slinton 
7849657Slinton 	case TYPE:
7859657Slinton 	    if (t->type->class == PTR and t->type->type->class == BADUSE) {
7869657Slinton 		findtype(t);
7879657Slinton 	    }
7889657Slinton 	    r = size(t->type);
7899657Slinton 	    break;
7909657Slinton 
7919657Slinton 	case FIELD:
79216620Ssam 	    off = t->symvalue.field.offset;
79316620Ssam 	    len = t->symvalue.field.length;
79416620Ssam 	    r = (off + len + 7) div 8 - (off div 8);
7959657Slinton 	    break;
7969657Slinton 
7979657Slinton 	case RECORD:
7989657Slinton 	case VARNT:
7999657Slinton 	    r = t->symvalue.offset;
8009657Slinton 	    if (r == 0 and t->chain != nil) {
8019657Slinton 		panic("missing size information for record");
8029657Slinton 	    }
8039657Slinton 	    break;
8049657Slinton 
8059657Slinton 	case PTR:
80618235Slinton 	case TYPEREF:
8079657Slinton 	case FILET:
8089657Slinton 	    r = sizeof(Word);
8099657Slinton 	    break;
8109657Slinton 
8119657Slinton 	case SCAL:
81212609Slinton 	    r = sizeof(Word);
81312609Slinton 	    /*
81412609Slinton 	     *
8159657Slinton 	    if (t->symvalue.iconval > 255) {
8169657Slinton 		r = sizeof(short);
8179657Slinton 	    } else {
8189657Slinton 		r = sizeof(char);
8199657Slinton 	    }
82012609Slinton 	     *
82112609Slinton 	     */
8229657Slinton 	    break;
8239657Slinton 
8249657Slinton 	case FPROC:
8259657Slinton 	case FFUNC:
8269657Slinton 	    r = sizeof(Word);
8279657Slinton 	    break;
8289657Slinton 
8299657Slinton 	case PROC:
8309657Slinton 	case FUNC:
8319657Slinton 	case MODULE:
8329657Slinton 	case PROG:
8339657Slinton 	    r = sizeof(Symbol);
8349657Slinton 	    break;
8359657Slinton 
83616620Ssam 	case SET:
83716620Ssam 	    u = rtype(t->type);
83816620Ssam 	    switch (u->class) {
83916620Ssam 		case RANGE:
84016620Ssam 		    r = u->symvalue.rangev.upper - u->symvalue.rangev.lower + 1;
84116620Ssam 		    break;
84216620Ssam 
84316620Ssam 		case SCAL:
84416620Ssam 		    r = u->symvalue.iconval;
84516620Ssam 		    break;
84616620Ssam 
84716620Ssam 		default:
84816620Ssam 		    error("expected range for set base type");
84916620Ssam 		    break;
85016620Ssam 	    }
85116620Ssam 	    r = (r + BITSPERBYTE - 1) div BITSPERBYTE;
85216620Ssam 	    break;
85316620Ssam 
85418235Slinton 	/*
85518235Slinton 	 * These can happen in C (unfortunately) for unresolved type references
85618235Slinton 	 * Assume they are pointers.
85718235Slinton 	 */
85818235Slinton 	case BADUSE:
85918235Slinton 	    r = sizeof(Address);
86018235Slinton 	    break;
86118235Slinton 
8629657Slinton 	default:
8639657Slinton 	    if (ord(t->class) > ord(TYPEREF)) {
8649657Slinton 		panic("size: bad class (%d)", ord(t->class));
8659657Slinton 	    } else {
86618235Slinton 		fprintf(stderr, "can't compute size of a %s\n", classname(t));
8679657Slinton 	    }
86816620Ssam 	    r = 0;
86916620Ssam 	    break;
8709657Slinton     }
8719657Slinton     return r;
8729657Slinton }
8739657Slinton 
8749657Slinton /*
87518235Slinton  * Return the size associated with a symbol that takes into account
87618235Slinton  * reference parameters.  This might be better as the normal size function, but
87718235Slinton  * too many places already depend on it working the way it does.
87818235Slinton  */
87918235Slinton 
88018235Slinton public integer psize (s)
88118235Slinton Symbol s;
88218235Slinton {
88318235Slinton     integer r;
88418235Slinton     Symbol t;
88518235Slinton 
88618235Slinton     if (s->class == REF) {
88718235Slinton 	t = rtype(s->type);
88818235Slinton 	if (t->class == DYNARRAY) {
88918235Slinton 	    r = (t->symvalue.ndims + 1) * sizeof(Word);
89018235Slinton 	} else if (t->class == SUBARRAY) {
89118235Slinton 	    r = (2 * t->symvalue.ndims + 1) * sizeof(Word);
89218235Slinton 	} else {
89318235Slinton 	    r = sizeof(Word);
89418235Slinton 	}
89518235Slinton     } else {
89618235Slinton 	r = size(s);
89718235Slinton     }
89818235Slinton     return r;
89918235Slinton }
90018235Slinton 
90118235Slinton /*
9029657Slinton  * Test if a symbol is a parameter.  This is true if there
9039657Slinton  * is a cycle from s->block to s via chain pointers.
9049657Slinton  */
9059657Slinton 
9069657Slinton public Boolean isparam(s)
9079657Slinton Symbol s;
9089657Slinton {
9099657Slinton     register Symbol t;
9109657Slinton 
9119657Slinton     t = s->block;
9129657Slinton     while (t != nil and t != s) {
9139657Slinton 	t = t->chain;
9149657Slinton     }
9159657Slinton     return (Boolean) (t != nil);
9169657Slinton }
9179657Slinton 
9189657Slinton /*
91916620Ssam  * Test if a type is an open array parameter type.
9209657Slinton  */
9219657Slinton 
92218235Slinton public boolean isopenarray (type)
92318235Slinton Symbol type;
92416620Ssam {
92518235Slinton     Symbol t;
92618235Slinton 
92718235Slinton     t = rtype(type);
92818235Slinton     return (boolean) (t->class == DYNARRAY);
92916620Ssam }
93016620Ssam 
93116620Ssam /*
93218235Slinton  * Test if a symbol is a var parameter, i.e. has class REF.
93316620Ssam  */
93416620Ssam 
9359657Slinton public Boolean isvarparam(s)
9369657Slinton Symbol s;
9379657Slinton {
9389657Slinton     return (Boolean) (s->class == REF);
9399657Slinton }
9409657Slinton 
9419657Slinton /*
9429657Slinton  * Test if a symbol is a variable (actually any addressible quantity
9439657Slinton  * with do).
9449657Slinton  */
9459657Slinton 
9469657Slinton public Boolean isvariable(s)
94718235Slinton Symbol s;
9489657Slinton {
9499657Slinton     return (Boolean) (s->class == VAR or s->class == FVAR or s->class == REF);
9509657Slinton }
9519657Slinton 
9529657Slinton /*
95318235Slinton  * Test if a symbol is a constant.
95418235Slinton  */
95518235Slinton 
95618235Slinton public Boolean isconst(s)
95718235Slinton Symbol s;
9589657Slinton {
95918235Slinton     return (Boolean) (s->class == CONST);
9609657Slinton }
9619657Slinton 
9629657Slinton /*
9639657Slinton  * Test if a symbol is a module.
9649657Slinton  */
9659657Slinton 
9669657Slinton public Boolean ismodule(s)
9679657Slinton register Symbol s;
9689657Slinton {
9699657Slinton     return (Boolean) (s->class == MODULE);
9709657Slinton }
9719657Slinton 
9729657Slinton /*
97316620Ssam  * Mark a procedure or function as internal, meaning that it is called
97416620Ssam  * with a different calling sequence.
97516620Ssam  */
97616620Ssam 
97716620Ssam public markInternal (s)
97816620Ssam Symbol s;
97916620Ssam {
98016620Ssam     s->symvalue.funcv.intern = true;
98116620Ssam }
98216620Ssam 
98316620Ssam public boolean isinternal (s)
98416620Ssam Symbol s;
98516620Ssam {
98616620Ssam     return s->symvalue.funcv.intern;
98716620Ssam }
98816620Ssam 
98916620Ssam /*
99018235Slinton  * Decide if a field begins or ends on a bit rather than byte boundary.
99118235Slinton  */
99218235Slinton 
99318235Slinton public Boolean isbitfield(s)
99418235Slinton register Symbol s;
99518235Slinton {
99618235Slinton     boolean b;
99718235Slinton     register integer off, len;
99818235Slinton     register Symbol t;
99918235Slinton 
100018235Slinton     off = s->symvalue.field.offset;
100118235Slinton     len = s->symvalue.field.length;
100218235Slinton     if ((off mod BITSPERBYTE) != 0 or (len mod BITSPERBYTE) != 0) {
100318235Slinton 	b = true;
100418235Slinton     } else {
100518235Slinton 	t = rtype(s->type);
100618235Slinton 	b = (Boolean) (
100718235Slinton 	    (t->class == SCAL and len != (sizeof(int)*BITSPERBYTE)) or
100818235Slinton 	    len != (size(t)*BITSPERBYTE)
100918235Slinton 	);
101018235Slinton     }
101118235Slinton     return b;
101218235Slinton }
101318235Slinton 
101418235Slinton private boolean primlang_typematch (t1, t2)
101518235Slinton Symbol t1, t2;
101618235Slinton {
101718235Slinton     return (boolean) (
101818235Slinton 	(t1 == t2) or
101918235Slinton 	(
102018235Slinton 	    t1->class == RANGE and t2->class == RANGE and
102118235Slinton 	    t1->symvalue.rangev.lower == t2->symvalue.rangev.lower and
102218235Slinton 	    t1->symvalue.rangev.upper == t2->symvalue.rangev.upper
102318235Slinton 	) or (
102418235Slinton 	    t1->class == PTR and t2->class == RANGE and
102518235Slinton 	    t2->symvalue.rangev.upper >= t2->symvalue.rangev.lower
102618235Slinton 	) or (
102718235Slinton 	    t2->class == PTR and t1->class == RANGE and
102818235Slinton 	    t1->symvalue.rangev.upper >= t1->symvalue.rangev.lower
102918235Slinton 	)
103018235Slinton     );
103118235Slinton }
103218235Slinton 
103318235Slinton /*
10349657Slinton  * Test if two types match.
10359657Slinton  * Equivalent names implies a match in any language.
10369657Slinton  *
10379657Slinton  * Special symbols must be handled with care.
10389657Slinton  */
10399657Slinton 
10409657Slinton public Boolean compatible(t1, t2)
10419657Slinton register Symbol t1, t2;
10429657Slinton {
10439657Slinton     Boolean b;
104416620Ssam     Symbol rt1, rt2;
10459657Slinton 
10469657Slinton     if (t1 == t2) {
10479657Slinton 	b = true;
10489657Slinton     } else if (t1 == nil or t2 == nil) {
10499657Slinton 	b = false;
10509657Slinton     } else if (t1 == procsym) {
10519657Slinton 	b = isblock(t2);
10529657Slinton     } else if (t2 == procsym) {
10539657Slinton 	b = isblock(t1);
105416620Ssam     } else if (t1->language == primlang) {
105516620Ssam 	if (t2->language == primlang) {
105618235Slinton 	    b = primlang_typematch(rtype(t1), rtype(t2));
105716620Ssam 	} else {
105816620Ssam 	    b = (boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2);
105916620Ssam 	}
106016620Ssam     } else if (t2->language == primlang) {
106116620Ssam 	b = (boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2);
10629657Slinton     } else if (t1->language == nil) {
106316620Ssam 	if (t2->language == nil) {
106416620Ssam 	    b = false;
106516620Ssam 	} else {
106616620Ssam 	    b = (boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2);
106716620Ssam 	}
10689657Slinton     } else {
106916620Ssam 	b = (boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2);
10709657Slinton     }
10719657Slinton     return b;
10729657Slinton }
10739657Slinton 
10749657Slinton /*
10759657Slinton  * Check for a type of the given name.
10769657Slinton  */
10779657Slinton 
10789657Slinton public Boolean istypename(type, name)
10799657Slinton Symbol type;
10809657Slinton String name;
10819657Slinton {
108218235Slinton     register Symbol t;
10839657Slinton     Boolean b;
10849657Slinton 
10859657Slinton     t = type;
108618235Slinton     if (t == nil) {
108718235Slinton 	b = false;
108818235Slinton     } else {
108918235Slinton 	b = (Boolean) (
109018235Slinton 	    t->class == TYPE and streq(ident(t->name), name)
109118235Slinton 	);
109218235Slinton     }
10939657Slinton     return b;
10949657Slinton }
10959657Slinton 
10969657Slinton /*
109716620Ssam  * Determine if a (value) parameter should actually be passed by address.
109816620Ssam  */
109916620Ssam 
110016620Ssam public boolean passaddr (p, exprtype)
110116620Ssam Symbol p, exprtype;
110216620Ssam {
110316620Ssam     boolean b;
110416620Ssam     Language def;
110516620Ssam 
110616620Ssam     if (p == nil) {
110716620Ssam 	def = findlanguage(".c");
110816620Ssam 	b = (boolean) (*language_op(def, L_PASSADDR))(p, exprtype);
110916620Ssam     } else if (p->language == nil or p->language == primlang) {
111016620Ssam 	b = false;
111116620Ssam     } else if (isopenarray(p->type)) {
111216620Ssam 	b = true;
111316620Ssam     } else {
111416620Ssam 	b = (boolean) (*language_op(p->language, L_PASSADDR))(p, exprtype);
111516620Ssam     }
111616620Ssam     return b;
111716620Ssam }
111816620Ssam 
111916620Ssam /*
11209657Slinton  * Test if the name of a symbol is uniquely defined or not.
11219657Slinton  */
11229657Slinton 
11239657Slinton public Boolean isambiguous(s)
11249657Slinton register Symbol s;
11259657Slinton {
11269657Slinton     register Symbol t;
11279657Slinton 
11289657Slinton     find(t, s->name) where t != s endfind(t);
11299657Slinton     return (Boolean) (t != nil);
11309657Slinton }
11319657Slinton 
11329657Slinton typedef char *Arglist;
11339657Slinton 
11349657Slinton #define nextarg(type)  ((type *) (ap += sizeof(type)))[-1]
11359657Slinton 
11369657Slinton private Symbol mkstring();
11379657Slinton 
11389657Slinton /*
11399657Slinton  * Determine the type of a parse tree.
114018235Slinton  *
11419657Slinton  * Also make some symbol-dependent changes to the tree such as
114218235Slinton  * removing indirection for constant or register symbols.
11439657Slinton  */
11449657Slinton 
114518235Slinton public assigntypes (p)
11469657Slinton register Node p;
11479657Slinton {
11489657Slinton     register Node p1;
11499657Slinton     register Symbol s;
11509657Slinton 
11519657Slinton     switch (p->op) {
11529657Slinton 	case O_SYM:
115318235Slinton 	    p->nodetype = p->value.sym;
11549657Slinton 	    break;
11559657Slinton 
11569657Slinton 	case O_LCON:
11579657Slinton 	    p->nodetype = t_int;
11589657Slinton 	    break;
11599657Slinton 
116018235Slinton 	case O_CCON:
116118235Slinton 	    p->nodetype = t_char;
116218235Slinton 	    break;
116318235Slinton 
11649657Slinton 	case O_FCON:
11659657Slinton 	    p->nodetype = t_real;
11669657Slinton 	    break;
11679657Slinton 
11689657Slinton 	case O_SCON:
116918235Slinton 	    p->nodetype = mkstring(p->value.scon);
11709657Slinton 	    break;
11719657Slinton 
11729657Slinton 	case O_INDIR:
11739657Slinton 	    p1 = p->value.arg[0];
117418235Slinton 	    s = rtype(p1->nodetype);
117518235Slinton 	    if (s->class != PTR) {
117618235Slinton 		beginerrmsg();
117718235Slinton 		fprintf(stderr, "\"");
117818235Slinton 		prtree(stderr, p1);
117918235Slinton 		fprintf(stderr, "\" is not a pointer");
118018235Slinton 		enderrmsg();
118118235Slinton 	    }
11829657Slinton 	    p->nodetype = rtype(p1->nodetype)->type;
11839657Slinton 	    break;
11849657Slinton 
11859657Slinton 	case O_DOT:
11869657Slinton 	    p->nodetype = p->value.arg[1]->value.sym;
11879657Slinton 	    break;
11889657Slinton 
11899657Slinton 	case O_RVAL:
11909657Slinton 	    p1 = p->value.arg[0];
11919657Slinton 	    p->nodetype = p1->nodetype;
11929657Slinton 	    if (p1->op == O_SYM) {
119318235Slinton 		if (p1->nodetype->class == PROC or p->nodetype->class == FUNC) {
119418235Slinton 		    p->op = p1->op;
119518235Slinton 		    p->value.sym = p1->value.sym;
119618235Slinton 		    p->nodetype = p1->nodetype;
119718235Slinton 		    dispose(p1);
11989657Slinton 		} else if (p1->value.sym->class == CONST) {
119918235Slinton 		    p->op = p1->op;
120018235Slinton 		    p->value = p1->value;
120118235Slinton 		    p->nodetype = p1->nodetype;
120218235Slinton 		    dispose(p1);
12039657Slinton 		} else if (isreg(p1->value.sym)) {
12049657Slinton 		    p->op = O_SYM;
12059657Slinton 		    p->value.sym = p1->value.sym;
12069657Slinton 		    dispose(p1);
12079657Slinton 		}
12089657Slinton 	    } else if (p1->op == O_INDIR and p1->value.arg[0]->op == O_SYM) {
12099657Slinton 		s = p1->value.arg[0]->value.sym;
12109657Slinton 		if (isreg(s)) {
12119657Slinton 		    p1->op = O_SYM;
12129657Slinton 		    dispose(p1->value.arg[0]);
12139657Slinton 		    p1->value.sym = s;
12149657Slinton 		    p1->nodetype = s;
12159657Slinton 		}
12169657Slinton 	    }
12179657Slinton 	    break;
12189657Slinton 
121918235Slinton 	case O_COMMA:
122018235Slinton 	    p->nodetype = p->value.arg[0]->nodetype;
122118235Slinton 	    break;
122218235Slinton 
122318235Slinton 	case O_CALLPROC:
12249657Slinton 	case O_CALL:
12259657Slinton 	    p1 = p->value.arg[0];
122611171Slinton 	    p->nodetype = rtype(p1->nodetype)->type;
12279657Slinton 	    break;
12289657Slinton 
122911171Slinton 	case O_TYPERENAME:
123011171Slinton 	    p->nodetype = p->value.arg[1]->nodetype;
123111171Slinton 	    break;
123211171Slinton 
12339657Slinton 	case O_ITOF:
12349657Slinton 	    p->nodetype = t_real;
12359657Slinton 	    break;
12369657Slinton 
12379657Slinton 	case O_NEG:
12389657Slinton 	    s = p->value.arg[0]->nodetype;
12399657Slinton 	    if (not compatible(s, t_int)) {
12409657Slinton 		if (not compatible(s, t_real)) {
12419657Slinton 		    beginerrmsg();
124216620Ssam 		    fprintf(stderr, "\"");
12439657Slinton 		    prtree(stderr, p->value.arg[0]);
124416620Ssam 		    fprintf(stderr, "\" is improper type");
12459657Slinton 		    enderrmsg();
12469657Slinton 		} else {
12479657Slinton 		    p->op = O_NEGF;
12489657Slinton 		}
12499657Slinton 	    }
12509657Slinton 	    p->nodetype = s;
12519657Slinton 	    break;
12529657Slinton 
12539657Slinton 	case O_ADD:
12549657Slinton 	case O_SUB:
12559657Slinton 	case O_MUL:
125616620Ssam 	    binaryop(p, nil);
125716620Ssam 	    break;
125816620Ssam 
12599657Slinton 	case O_LT:
12609657Slinton 	case O_LE:
12619657Slinton 	case O_GT:
12629657Slinton 	case O_GE:
12639657Slinton 	case O_EQ:
12649657Slinton 	case O_NE:
126516620Ssam 	    binaryop(p, t_boolean);
12669657Slinton 	    break;
12679657Slinton 
12689657Slinton 	case O_DIVF:
12699657Slinton 	    convert(&(p->value.arg[0]), t_real, O_ITOF);
12709657Slinton 	    convert(&(p->value.arg[1]), t_real, O_ITOF);
12719657Slinton 	    p->nodetype = t_real;
12729657Slinton 	    break;
12739657Slinton 
12749657Slinton 	case O_DIV:
12759657Slinton 	case O_MOD:
12769657Slinton 	    convert(&(p->value.arg[0]), t_int, O_NOP);
12779657Slinton 	    convert(&(p->value.arg[1]), t_int, O_NOP);
12789657Slinton 	    p->nodetype = t_int;
12799657Slinton 	    break;
12809657Slinton 
12819657Slinton 	case O_AND:
12829657Slinton 	case O_OR:
12839657Slinton 	    chkboolean(p->value.arg[0]);
12849657Slinton 	    chkboolean(p->value.arg[1]);
12859657Slinton 	    p->nodetype = t_boolean;
12869657Slinton 	    break;
12879657Slinton 
12889657Slinton 	case O_QLINE:
12899657Slinton 	    p->nodetype = t_int;
12909657Slinton 	    break;
12919657Slinton 
12929657Slinton 	default:
12939657Slinton 	    p->nodetype = nil;
12949657Slinton 	    break;
12959657Slinton     }
12969657Slinton }
12979657Slinton 
12989657Slinton /*
129916620Ssam  * Process a binary arithmetic or relational operator.
130016620Ssam  * Convert from integer to real if necessary.
130116620Ssam  */
130216620Ssam 
130316620Ssam private binaryop (p, t)
130416620Ssam Node p;
130516620Ssam Symbol t;
130616620Ssam {
130716620Ssam     Node p1, p2;
130816620Ssam     Boolean t1real, t2real;
130916620Ssam     Symbol t1, t2;
131016620Ssam 
131116620Ssam     p1 = p->value.arg[0];
131216620Ssam     p2 = p->value.arg[1];
131316620Ssam     t1 = rtype(p1->nodetype);
131416620Ssam     t2 = rtype(p2->nodetype);
131516620Ssam     t1real = compatible(t1, t_real);
131616620Ssam     t2real = compatible(t2, t_real);
131716620Ssam     if (t1real or t2real) {
131816620Ssam 	p->op = (Operator) (ord(p->op) + 1);
131916620Ssam 	if (not t1real) {
132016620Ssam 	    p->value.arg[0] = build(O_ITOF, p1);
132116620Ssam 	} else if (not t2real) {
132216620Ssam 	    p->value.arg[1] = build(O_ITOF, p2);
132316620Ssam 	}
132416620Ssam 	p->nodetype = t_real;
132516620Ssam     } else {
132616620Ssam 	if (size(p1->nodetype) > sizeof(integer)) {
132716620Ssam 	    beginerrmsg();
132816620Ssam 	    fprintf(stderr, "operation not defined on \"");
132916620Ssam 	    prtree(stderr, p1);
133016620Ssam 	    fprintf(stderr, "\"");
133116620Ssam 	    enderrmsg();
133216620Ssam 	} else if (size(p2->nodetype) > sizeof(integer)) {
133316620Ssam 	    beginerrmsg();
133416620Ssam 	    fprintf(stderr, "operation not defined on \"");
133516620Ssam 	    prtree(stderr, p2);
133616620Ssam 	    fprintf(stderr, "\"");
133716620Ssam 	    enderrmsg();
133816620Ssam 	}
133916620Ssam 	p->nodetype = t_int;
134016620Ssam     }
134116620Ssam     if (t != nil) {
134216620Ssam 	p->nodetype = t;
134316620Ssam     }
134416620Ssam }
134516620Ssam 
134616620Ssam /*
13479657Slinton  * Convert a tree to a type via a conversion operator;
13489657Slinton  * if this isn't possible generate an error.
13499657Slinton  *
13509657Slinton  * Note the tree is call by address, hence the #define below.
13519657Slinton  */
13529657Slinton 
13539657Slinton private convert(tp, typeto, op)
13549657Slinton Node *tp;
13559657Slinton Symbol typeto;
13569657Slinton Operator op;
13579657Slinton {
135816620Ssam     Node tree;
135916620Ssam     Symbol s, t;
13609657Slinton 
136116620Ssam     tree = *tp;
13629657Slinton     s = rtype(tree->nodetype);
136316620Ssam     t = rtype(typeto);
136416620Ssam     if (compatible(t, t_real) and compatible(s, t_int)) {
13659657Slinton 	tree = build(op, tree);
136616620Ssam     } else if (not compatible(s, t)) {
13679657Slinton 	beginerrmsg();
136816620Ssam 	fprintf(stderr, "expected integer or real, found \"");
136916620Ssam 	prtree(stderr, tree);
137016620Ssam 	fprintf(stderr, "\"");
13719657Slinton 	enderrmsg();
137216620Ssam     } else if (op != O_NOP and s != t) {
13739657Slinton 	tree = build(op, tree);
13749657Slinton     }
137516620Ssam     *tp = tree;
13769657Slinton }
13779657Slinton 
13789657Slinton /*
13799657Slinton  * Construct a node for the dot operator.
13809657Slinton  *
13819657Slinton  * If the left operand is not a record, but rather a procedure
13829657Slinton  * or function, then we interpret the "." as referencing an
13839657Slinton  * "invisible" variable; i.e. a variable within a dynamically
13849657Slinton  * active block but not within the static scope of the current procedure.
13859657Slinton  */
13869657Slinton 
13879657Slinton public Node dot(record, fieldname)
13889657Slinton Node record;
13899657Slinton Name fieldname;
13909657Slinton {
139118235Slinton     register Node rec, p;
13929657Slinton     register Symbol s, t;
13939657Slinton 
139418235Slinton     rec = record;
139518235Slinton     if (isblock(rec->nodetype)) {
13969657Slinton 	find(s, fieldname) where
139718235Slinton 	    s->block == rec->nodetype and
139818235Slinton 	    s->class != FIELD
13999657Slinton 	endfind(s);
14009657Slinton 	if (s == nil) {
14019657Slinton 	    beginerrmsg();
14029657Slinton 	    fprintf(stderr, "\"%s\" is not defined in ", ident(fieldname));
140318235Slinton 	    printname(stderr, rec->nodetype);
14049657Slinton 	    enderrmsg();
14059657Slinton 	}
14069657Slinton 	p = new(Node);
14079657Slinton 	p->op = O_SYM;
14089657Slinton 	p->value.sym = s;
140918235Slinton 	p->nodetype = s;
14109657Slinton     } else {
141118235Slinton 	p = rec;
14129657Slinton 	t = rtype(p->nodetype);
14139657Slinton 	if (t->class == PTR) {
14149657Slinton 	    s = findfield(fieldname, t->type);
14159657Slinton 	} else {
14169657Slinton 	    s = findfield(fieldname, t);
14179657Slinton 	}
14189657Slinton 	if (s == nil) {
14199657Slinton 	    beginerrmsg();
14209657Slinton 	    fprintf(stderr, "\"%s\" is not a field in ", ident(fieldname));
142118235Slinton 	    prtree(stderr, rec);
14229657Slinton 	    enderrmsg();
14239657Slinton 	}
142418235Slinton 	if (t->class != PTR or isreg(rec->nodetype)) {
142518235Slinton 	    p = unrval(p);
14269657Slinton 	}
142718235Slinton 	p->nodetype = t_addr;
14289657Slinton 	p = build(O_DOT, p, build(O_SYM, s));
14299657Slinton     }
143018235Slinton     return build(O_RVAL, p);
14319657Slinton }
14329657Slinton 
14339657Slinton /*
14349657Slinton  * Return a tree corresponding to an array reference and do the
14359657Slinton  * error checking.
14369657Slinton  */
14379657Slinton 
14389657Slinton public Node subscript(a, slist)
14399657Slinton Node a, slist;
14409657Slinton {
144116620Ssam     Symbol t;
144218235Slinton     Node p;
14439657Slinton 
144416620Ssam     t = rtype(a->nodetype);
144518235Slinton     if (t->language == nil or t->language == primlang) {
144618235Slinton 	p = (Node) (*language_op(findlanguage(".s"), L_BUILDAREF))(a, slist);
144716620Ssam     } else {
144818235Slinton 	p = (Node) (*language_op(t->language, L_BUILDAREF))(a, slist);
144916620Ssam     }
145018235Slinton     return build(O_RVAL, p);
14519657Slinton }
14529657Slinton 
14539657Slinton /*
14549657Slinton  * Evaluate a subscript index.
14559657Slinton  */
14569657Slinton 
145718235Slinton public int evalindex(s, base, i)
14589657Slinton Symbol s;
145918235Slinton Address base;
14609657Slinton long i;
14619657Slinton {
146216620Ssam     Symbol t;
146318235Slinton     int r;
14649657Slinton 
146516620Ssam     t = rtype(s);
146618235Slinton     if (t->language == nil or t->language == primlang) {
146718235Slinton 	r = ((*language_op(findlanguage(".s"), L_EVALAREF)) (s, base, i));
146816620Ssam     } else {
146918235Slinton 	r = ((*language_op(t->language, L_EVALAREF)) (s, base, i));
147016620Ssam     }
147118235Slinton     return r;
14729657Slinton }
14739657Slinton 
14749657Slinton /*
14759657Slinton  * Check to see if a tree is boolean-valued, if not it's an error.
14769657Slinton  */
14779657Slinton 
14789657Slinton public chkboolean(p)
14799657Slinton register Node p;
14809657Slinton {
14819657Slinton     if (p->nodetype != t_boolean) {
14829657Slinton 	beginerrmsg();
14839657Slinton 	fprintf(stderr, "found ");
14849657Slinton 	prtree(stderr, p);
14859657Slinton 	fprintf(stderr, ", expected boolean expression");
14869657Slinton 	enderrmsg();
14879657Slinton     }
14889657Slinton }
14899657Slinton 
14909657Slinton /*
149116620Ssam  * Construct a node for the type of a string.
14929657Slinton  */
14939657Slinton 
14949657Slinton private Symbol mkstring(str)
14959657Slinton String str;
14969657Slinton {
14979657Slinton     register Symbol s;
14989657Slinton 
149918235Slinton     s = newSymbol(nil, 0, ARRAY, t_char, nil);
150018235Slinton     s->chain = newSymbol(nil, 0, RANGE, t_int, nil);
150118235Slinton     s->chain->language = s->language;
150218235Slinton     s->chain->symvalue.rangev.lower = 1;
150318235Slinton     s->chain->symvalue.rangev.upper = strlen(str) + 1;
15049657Slinton     return s;
15059657Slinton }
15069657Slinton 
15079657Slinton /*
15089657Slinton  * Free up the space allocated for a string type.
15099657Slinton  */
15109657Slinton 
15119657Slinton public unmkstring(s)
15129657Slinton Symbol s;
15139657Slinton {
15149657Slinton     dispose(s->chain);
15159657Slinton }
15169657Slinton 
15179657Slinton /*
151818235Slinton  * Figure out the "current" variable or function being referred to
151918235Slinton  * by the name n.
15209657Slinton  */
15219657Slinton 
152218235Slinton private boolean stwhich(), dynwhich();
152318235Slinton 
152418235Slinton public Symbol which (n)
15259657Slinton Name n;
15269657Slinton {
152718235Slinton     Symbol s;
15289657Slinton 
152918235Slinton     s = lookup(n);
15309657Slinton     if (s == nil) {
153118235Slinton 	error("\"%s\" is not defined", ident(n));
153218235Slinton     } else if (not stwhich(&s) and isambiguous(s) and not dynwhich(&s)) {
153318235Slinton 	printf("[using ");
153418235Slinton 	printname(stdout, s);
153518235Slinton 	printf("]\n");
15369657Slinton     }
153718235Slinton     return s;
153818235Slinton }
153918235Slinton 
154018235Slinton /*
154118235Slinton  * Static search.
154218235Slinton  */
154318235Slinton 
154418235Slinton private boolean stwhich (var_s)
154518235Slinton Symbol *var_s;
154618235Slinton {
154718235Slinton     Name n;		/* name of desired symbol */
154818235Slinton     Symbol s;		/* iteration variable for symbols with name n */
154918235Slinton     Symbol f;		/* iteration variable for blocks containing s */
155018235Slinton     integer count;	/* number of levels from s->block to curfunc */
155118235Slinton     Symbol t;		/* current best answer for stwhich(n) */
155218235Slinton     integer mincount;	/* relative level for current best answer (t) */
155318235Slinton     boolean b;		/* return value, true if symbol found */
155418235Slinton 
155518235Slinton     s = *var_s;
155618235Slinton     n = s->name;
155718235Slinton     t = s;
155818235Slinton     mincount = 10000; /* force first match to set mincount */
155918235Slinton     do {
156018235Slinton 	if (s->name == n and s->class != FIELD and s->class != TAG) {
156118235Slinton 	    f = curfunc;
156218235Slinton 	    count = 0;
156318235Slinton 	    while (f != nil and f != s->block) {
156418235Slinton 		++count;
156518235Slinton 		f = f->block;
156618235Slinton 	    }
156718235Slinton 	    if (f != nil and count < mincount) {
156818235Slinton 		t = s;
156918235Slinton 		mincount = count;
157018235Slinton 		b = true;
157118235Slinton 	    }
157218235Slinton 	}
157318235Slinton 	s = s->next_sym;
157418235Slinton     } while (s != nil);
157518235Slinton     if (mincount != 10000) {
157618235Slinton 	*var_s = t;
157718235Slinton 	b = true;
15789657Slinton     } else {
157918235Slinton 	b = false;
158018235Slinton     }
158118235Slinton     return b;
158218235Slinton }
158318235Slinton 
158418235Slinton /*
158518235Slinton  * Dynamic search.
158618235Slinton  */
158718235Slinton 
158818235Slinton private boolean dynwhich (var_s)
158918235Slinton Symbol *var_s;
159018235Slinton {
159118235Slinton     Name n;		/* name of desired symbol */
159218235Slinton     Symbol s;		/* iteration variable for possible symbols */
159318235Slinton     Symbol f;		/* iteration variable for active functions */
159418235Slinton     Frame frp;		/* frame associated with stack walk */
159518235Slinton     boolean b;		/* return value */
159618235Slinton 
159718235Slinton     f = curfunc;
159818235Slinton     frp = curfuncframe();
159918235Slinton     n = (*var_s)->name;
160018235Slinton     b = false;
160118235Slinton     if (frp != nil) {
160218235Slinton 	frp = nextfunc(frp, &f);
160318235Slinton 	while (frp != nil) {
160418235Slinton 	    s = *var_s;
160518235Slinton 	    while (s != nil and
160618235Slinton 		(
160718235Slinton 		    s->name != n or s->block != f or
160818235Slinton 		    s->class == FIELD or s->class == TAG
160918235Slinton 		)
161018235Slinton 	    ) {
161118235Slinton 		s = s->next_sym;
161218235Slinton 	    }
161318235Slinton 	    if (s != nil) {
161418235Slinton 		*var_s = s;
161518235Slinton 		b = true;
161618235Slinton 		break;
161718235Slinton 	    }
161818235Slinton 	    if (f == program) {
161918235Slinton 		break;
162018235Slinton 	    }
162118235Slinton 	    frp = nextfunc(frp, &f);
16229657Slinton 	}
16239657Slinton     }
162418235Slinton     return b;
16259657Slinton }
16269657Slinton 
16279657Slinton /*
162818235Slinton  * Find the symbol that has the same name and scope as the
16299657Slinton  * given symbol but is of the given field.  Return nil if there is none.
16309657Slinton  */
16319657Slinton 
163218235Slinton public Symbol findfield (fieldname, record)
16339657Slinton Name fieldname;
16349657Slinton Symbol record;
16359657Slinton {
16369657Slinton     register Symbol t;
16379657Slinton 
16389657Slinton     t = rtype(record)->chain;
16399657Slinton     while (t != nil and t->name != fieldname) {
16409657Slinton 	t = t->chain;
16419657Slinton     }
16429657Slinton     return t;
16439657Slinton }
164412547Scsvaf 
164512547Scsvaf public Boolean getbound(s,off,type,valp)
164612547Scsvaf Symbol s;
164712547Scsvaf int off;
164812547Scsvaf Rangetype type;
164912547Scsvaf int *valp;
165012547Scsvaf {
165112547Scsvaf     Frame frp;
165212547Scsvaf     Address addr;
165312547Scsvaf     Symbol cur;
165412547Scsvaf 
165512547Scsvaf     if (not isactive(s->block)) {
165612547Scsvaf 	return(false);
165712547Scsvaf     }
165812547Scsvaf     cur = s->block;
165912547Scsvaf     while (cur != nil and cur->class == MODULE) {  /* WHY*/
166012547Scsvaf     		cur = cur->block;
166112547Scsvaf     }
166212547Scsvaf     if(cur == nil) {
166312547Scsvaf 		cur = whatblock(pc);
166412547Scsvaf     }
166512547Scsvaf     frp = findframe(cur);
166612547Scsvaf     if (frp == nil) {
166712547Scsvaf 	return(false);
166812547Scsvaf     }
166912547Scsvaf     if(type == R_TEMP) addr = locals_base(frp) + off;
167012547Scsvaf     else if (type == R_ARG) addr = args_base(frp) + off;
167112547Scsvaf     else return(false);
167212547Scsvaf     dread(valp,addr,sizeof(long));
167312547Scsvaf     return(true);
167412547Scsvaf }
1675