xref: /csrg-svn/old/dbx/symbols.c (revision 21625)
1*21625Sdist /*
2*21625Sdist  * Copyright (c) 1983 Regents of the University of California.
3*21625Sdist  * All rights reserved.  The Berkeley software License Agreement
4*21625Sdist  * specifies the terms and conditions for redistribution.
5*21625Sdist  */
69657Slinton 
7*21625Sdist #ifndef lint
8*21625Sdist static char sccsid[] = "@(#)symbols.c	5.1 (Berkeley) 05/31/85";
9*21625Sdist #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 
1289657Slinton #include "tree.h"
1299657Slinton 
1309657Slinton /*
1319657Slinton  * Some macros to make finding a symbol with certain attributes.
1329657Slinton  */
1339657Slinton 
1349657Slinton #define find(s, withname) \
1359657Slinton { \
1369657Slinton     s = lookup(withname); \
1379657Slinton     while (s != nil and not (s->name == (withname) and
1389657Slinton 
1399657Slinton #define where /* qualification */
1409657Slinton 
1419657Slinton #define endfind(s) )) { \
1429657Slinton 	s = s->next_sym; \
1439657Slinton     } \
1449657Slinton }
1459657Slinton 
1469657Slinton #endif
1479657Slinton 
1489657Slinton /*
1499657Slinton  * Symbol table structure currently does not support deletions.
1509657Slinton  */
1519657Slinton 
1529657Slinton #define HASHTABLESIZE 2003
1539657Slinton 
1549657Slinton private Symbol hashtab[HASHTABLESIZE];
1559657Slinton 
1569657Slinton #define hash(name) ((((unsigned) name) >> 2) mod HASHTABLESIZE)
1579657Slinton 
1589657Slinton /*
1599657Slinton  * Allocate a new symbol.
1609657Slinton  */
1619657Slinton 
16211171Slinton #define SYMBLOCKSIZE 100
1639657Slinton 
1649657Slinton typedef struct Sympool {
1659657Slinton     struct Symbol sym[SYMBLOCKSIZE];
1669657Slinton     struct Sympool *prevpool;
1679657Slinton } *Sympool;
1689657Slinton 
1699657Slinton private Sympool sympool = nil;
1709657Slinton private Integer nleft = 0;
1719657Slinton 
1729657Slinton public Symbol symbol_alloc()
1739657Slinton {
1749657Slinton     register Sympool newpool;
1759657Slinton 
1769657Slinton     if (nleft <= 0) {
1779657Slinton 	newpool = new(Sympool);
17811171Slinton 	bzero(newpool, sizeof(newpool));
1799657Slinton 	newpool->prevpool = sympool;
1809657Slinton 	sympool = newpool;
1819657Slinton 	nleft = SYMBLOCKSIZE;
1829657Slinton     }
1839657Slinton     --nleft;
1849657Slinton     return &(sympool->sym[nleft]);
1859657Slinton }
1869657Slinton 
18718235Slinton public symbol_dump (func)
18812547Scsvaf Symbol func;
18912547Scsvaf {
19018235Slinton     register Symbol s;
19118235Slinton     register integer i;
19212547Scsvaf 
19318235Slinton     printf(" symbols in %s \n",symname(func));
19418235Slinton     for (i = 0; i < HASHTABLESIZE; i++) {
19518235Slinton 	for (s = hashtab[i]; s != nil; s = s->next_sym) {
19618235Slinton 	    if (s->block == func) {
19718235Slinton 		psym(s);
19818235Slinton 	    }
19918235Slinton 	}
20018235Slinton     }
20112547Scsvaf }
20212547Scsvaf 
2039657Slinton /*
2049657Slinton  * Free all the symbols currently allocated.
2059657Slinton  */
20618235Slinton 
2079657Slinton public symbol_free()
2089657Slinton {
2099657Slinton     Sympool s, t;
2109657Slinton     register Integer i;
2119657Slinton 
2129657Slinton     s = sympool;
2139657Slinton     while (s != nil) {
2149657Slinton 	t = s->prevpool;
2159657Slinton 	dispose(s);
2169657Slinton 	s = t;
2179657Slinton     }
2189657Slinton     for (i = 0; i < HASHTABLESIZE; i++) {
2199657Slinton 	hashtab[i] = nil;
2209657Slinton     }
2219657Slinton     sympool = nil;
2229657Slinton     nleft = 0;
2239657Slinton }
2249657Slinton 
2259657Slinton /*
2269657Slinton  * Create a new symbol with the given attributes.
2279657Slinton  */
2289657Slinton 
2299657Slinton public Symbol newSymbol(name, blevel, class, type, chain)
2309657Slinton Name name;
2319657Slinton Integer blevel;
2329657Slinton Symclass class;
2339657Slinton Symbol type;
2349657Slinton Symbol chain;
2359657Slinton {
2369657Slinton     register Symbol s;
2379657Slinton 
2389657Slinton     s = symbol_alloc();
2399657Slinton     s->name = name;
24018235Slinton     s->language = primlang;
2419657Slinton     s->level = blevel;
2429657Slinton     s->class = class;
2439657Slinton     s->type = type;
2449657Slinton     s->chain = chain;
2459657Slinton     return s;
2469657Slinton }
2479657Slinton 
2489657Slinton /*
2499657Slinton  * Insert a symbol into the hash table.
2509657Slinton  */
2519657Slinton 
2529657Slinton public Symbol insert(name)
2539657Slinton Name name;
2549657Slinton {
2559657Slinton     register Symbol s;
2569657Slinton     register unsigned int h;
2579657Slinton 
2589657Slinton     h = hash(name);
2599657Slinton     s = symbol_alloc();
2609657Slinton     s->name = name;
2619657Slinton     s->next_sym = hashtab[h];
2629657Slinton     hashtab[h] = s;
2639657Slinton     return s;
2649657Slinton }
2659657Slinton 
2669657Slinton /*
2679657Slinton  * Symbol lookup.
2689657Slinton  */
2699657Slinton 
2709657Slinton public Symbol lookup(name)
2719657Slinton Name name;
2729657Slinton {
2739657Slinton     register Symbol s;
2749657Slinton     register unsigned int h;
2759657Slinton 
2769657Slinton     h = hash(name);
2779657Slinton     s = hashtab[h];
2789657Slinton     while (s != nil and s->name != name) {
2799657Slinton 	s = s->next_sym;
2809657Slinton     }
2819657Slinton     return s;
2829657Slinton }
2839657Slinton 
2849657Slinton /*
28516620Ssam  * Delete a symbol from the symbol table.
28616620Ssam  */
28716620Ssam 
28816620Ssam public delete (s)
28916620Ssam Symbol s;
29016620Ssam {
29116620Ssam     register Symbol t;
29216620Ssam     register unsigned int h;
29316620Ssam 
29416620Ssam     h = hash(s->name);
29516620Ssam     t = hashtab[h];
29616620Ssam     if (t == nil) {
29716620Ssam 	panic("delete of non-symbol '%s'", symname(s));
29816620Ssam     } else if (t == s) {
29916620Ssam 	hashtab[h] = s->next_sym;
30016620Ssam     } else {
30116620Ssam 	while (t->next_sym != s) {
30216620Ssam 	    t = t->next_sym;
30316620Ssam 	    if (t == nil) {
30416620Ssam 		panic("delete of non-symbol '%s'", symname(s));
30516620Ssam 	    }
30616620Ssam 	}
30716620Ssam 	t->next_sym = s->next_sym;
30816620Ssam     }
30916620Ssam }
31016620Ssam 
31116620Ssam /*
3129657Slinton  * Dump out all the variables associated with the given
31318235Slinton  * procedure, function, or program associated with the given stack frame.
3149657Slinton  *
3159657Slinton  * This is quite inefficient.  We traverse the entire symbol table
3169657Slinton  * each time we're called.  The assumption is that this routine
3179657Slinton  * won't be called frequently enough to merit improved performance.
3189657Slinton  */
3199657Slinton 
3209657Slinton public dumpvars(f, frame)
3219657Slinton Symbol f;
3229657Slinton Frame frame;
3239657Slinton {
3249657Slinton     register Integer i;
3259657Slinton     register Symbol s;
3269657Slinton 
3279657Slinton     for (i = 0; i < HASHTABLESIZE; i++) {
3289657Slinton 	for (s = hashtab[i]; s != nil; s = s->next_sym) {
3299657Slinton 	    if (container(s) == f) {
3309657Slinton 		if (should_print(s)) {
3319657Slinton 		    printv(s, frame);
3329657Slinton 		    putchar('\n');
3339657Slinton 		} else if (s->class == MODULE) {
3349657Slinton 		    dumpvars(s, frame);
3359657Slinton 		}
3369657Slinton 	    }
3379657Slinton 	}
3389657Slinton     }
3399657Slinton }
3409657Slinton 
3419657Slinton /*
3429657Slinton  * Create a builtin type.
3439657Slinton  * Builtin types are circular in that btype->type->type = btype.
3449657Slinton  */
3459657Slinton 
34618235Slinton private Symbol maketype(name, lower, upper)
3479657Slinton String name;
3489657Slinton long lower;
3499657Slinton long upper;
3509657Slinton {
3519657Slinton     register Symbol s;
35218235Slinton     Name n;
3539657Slinton 
35418235Slinton     if (name == nil) {
35518235Slinton 	n = nil;
35618235Slinton     } else {
35718235Slinton 	n = identname(name, true);
35818235Slinton     }
35918235Slinton     s = insert(n);
36016620Ssam     s->language = primlang;
36118235Slinton     s->level = 0;
36218235Slinton     s->class = TYPE;
36318235Slinton     s->type = nil;
36418235Slinton     s->chain = nil;
3659657Slinton     s->type = newSymbol(nil, 0, RANGE, s, nil);
3669657Slinton     s->type->symvalue.rangev.lower = lower;
3679657Slinton     s->type->symvalue.rangev.upper = upper;
3689657Slinton     return s;
3699657Slinton }
3709657Slinton 
3719657Slinton /*
37218235Slinton  * Create the builtin symbols.
37318235Slinton  */
37418235Slinton 
37518235Slinton public symbols_init ()
3769657Slinton {
37718235Slinton     Symbol s;
3789657Slinton 
37918235Slinton     t_boolean = maketype("$boolean", 0L, 1L);
38018235Slinton     t_int = maketype("$integer", 0x80000000L, 0x7fffffffL);
38118235Slinton     t_char = maketype("$char", 0L, 255L);
38218235Slinton     t_real = maketype("$real", 8L, 0L);
38318235Slinton     t_nil = maketype("$nil", 0L, 0L);
38418235Slinton     t_addr = insert(identname("$address", true));
38518235Slinton     t_addr->language = primlang;
38618235Slinton     t_addr->level = 0;
38718235Slinton     t_addr->class = TYPE;
38818235Slinton     t_addr->type = newSymbol(nil, 1, PTR, t_int, nil);
38918235Slinton     s = insert(identname("true", true));
39018235Slinton     s->class = CONST;
39118235Slinton     s->type = t_boolean;
39218235Slinton     s->symvalue.constval = build(O_LCON, 1L);
39318235Slinton     s->symvalue.constval->nodetype = t_boolean;
39418235Slinton     s = insert(identname("false", true));
39518235Slinton     s->class = CONST;
39618235Slinton     s->type = t_boolean;
39718235Slinton     s->symvalue.constval = build(O_LCON, 0L);
39818235Slinton     s->symvalue.constval->nodetype = t_boolean;
3999657Slinton }
4009657Slinton 
4019657Slinton /*
4029657Slinton  * Reduce type to avoid worrying about type names.
4039657Slinton  */
4049657Slinton 
4059657Slinton public Symbol rtype(type)
4069657Slinton Symbol type;
4079657Slinton {
4089657Slinton     register Symbol t;
4099657Slinton 
4109657Slinton     t = type;
4119657Slinton     if (t != nil) {
41218235Slinton 	if (t->class == VAR or t->class == CONST or
41318235Slinton 	    t->class == FIELD or t->class == REF
41418235Slinton 	) {
4159657Slinton 	    t = t->type;
4169657Slinton 	}
41716620Ssam 	if (t->class == TYPEREF) {
41816620Ssam 	    resolveRef(t);
41916620Ssam 	}
4209657Slinton 	while (t->class == TYPE or t->class == TAG) {
4219657Slinton 	    t = t->type;
42216620Ssam 	    if (t->class == TYPEREF) {
42316620Ssam 		resolveRef(t);
42416620Ssam 	    }
4259657Slinton 	}
4269657Slinton     }
4279657Slinton     return t;
4289657Slinton }
4299657Slinton 
43016620Ssam /*
43116620Ssam  * Find the end of a module name.  Return nil if there is none
43216620Ssam  * in the given string.
43316620Ssam  */
43416620Ssam 
43516620Ssam private String findModuleMark (s)
43616620Ssam String s;
43716620Ssam {
43816620Ssam     register char *p, *r;
43916620Ssam     register boolean done;
44016620Ssam 
44116620Ssam     p = s;
44216620Ssam     done = false;
44316620Ssam     do {
44416620Ssam 	if (*p == ':') {
44516620Ssam 	    done = true;
44616620Ssam 	    r = p;
44716620Ssam 	} else if (*p == '\0') {
44816620Ssam 	    done = true;
44916620Ssam 	    r = nil;
45016620Ssam 	} else {
45116620Ssam 	    ++p;
45216620Ssam 	}
45316620Ssam     } while (not done);
45416620Ssam     return r;
45516620Ssam }
45616620Ssam 
45716620Ssam /*
45816620Ssam  * Resolve a type reference by modifying to be the appropriate type.
45916620Ssam  *
46016620Ssam  * If the reference has a name, then it refers to an opaque type and
46116620Ssam  * the actual type is directly accessible.  Otherwise, we must use
46216620Ssam  * the type reference string, which is of the form "module:{module:}name".
46316620Ssam  */
46416620Ssam 
46516620Ssam public resolveRef (t)
46616620Ssam Symbol t;
46716620Ssam {
46816620Ssam     register char *p;
46916620Ssam     char *start;
47016620Ssam     Symbol s, m, outer;
47116620Ssam     Name n;
47216620Ssam 
47316620Ssam     if (t->name != nil) {
47416620Ssam 	s = t;
47516620Ssam     } else {
47616620Ssam 	start = t->symvalue.typeref;
47716620Ssam 	outer = program;
47816620Ssam 	p = findModuleMark(start);
47916620Ssam 	while (p != nil) {
48016620Ssam 	    *p = '\0';
48116620Ssam 	    n = identname(start, true);
48216620Ssam 	    find(m, n) where m->block == outer endfind(m);
48316620Ssam 	    if (m == nil) {
48416620Ssam 		p = nil;
48516620Ssam 		outer = nil;
48616620Ssam 		s = nil;
48716620Ssam 	    } else {
48816620Ssam 		outer = m;
48916620Ssam 		start = p + 1;
49016620Ssam 		p = findModuleMark(start);
49116620Ssam 	    }
49216620Ssam 	}
49316620Ssam 	if (outer != nil) {
49416620Ssam 	    n = identname(start, true);
49516620Ssam 	    find(s, n) where s->block == outer endfind(s);
49616620Ssam 	}
49716620Ssam     }
49816620Ssam     if (s != nil and s->type != nil) {
49916620Ssam 	t->name = s->type->name;
50016620Ssam 	t->class = s->type->class;
50116620Ssam 	t->type = s->type->type;
50216620Ssam 	t->chain = s->type->chain;
50316620Ssam 	t->symvalue = s->type->symvalue;
50416620Ssam 	t->block = s->type->block;
50516620Ssam     }
50616620Ssam }
50716620Ssam 
50818235Slinton public integer regnum (s)
5099657Slinton Symbol s;
5109657Slinton {
51118235Slinton     integer r;
51218235Slinton 
5139657Slinton     checkref(s);
51418235Slinton     if (s->level < 0) {
51518235Slinton 	r = s->symvalue.offset;
51618235Slinton     } else {
51718235Slinton 	r = -1;
51818235Slinton     }
51918235Slinton     return r;
5209657Slinton }
5219657Slinton 
5229657Slinton public Symbol container(s)
5239657Slinton Symbol s;
5249657Slinton {
5259657Slinton     checkref(s);
5269657Slinton     return s->block;
5279657Slinton }
5289657Slinton 
52918235Slinton public Node constval(s)
53018235Slinton Symbol s;
53118235Slinton {
53218235Slinton     checkref(s);
53318235Slinton     if (s->class != CONST) {
53418235Slinton 	error("[internal error: constval(non-CONST)]");
53518235Slinton     }
53618235Slinton     return s->symvalue.constval;
53718235Slinton }
53818235Slinton 
5399657Slinton /*
5409657Slinton  * Return the object address of the given symbol.
5419657Slinton  *
5429657Slinton  * There are the following possibilities:
5439657Slinton  *
5449657Slinton  *	globals		- just take offset
5459657Slinton  *	locals		- take offset from locals base
5469657Slinton  *	arguments	- take offset from argument base
5479657Slinton  *	register	- offset is register number
5489657Slinton  */
5499657Slinton 
55016620Ssam #define isglobal(s)		(s->level == 1)
55116620Ssam #define islocaloff(s)		(s->level >= 2 and s->symvalue.offset < 0)
55216620Ssam #define isparamoff(s)		(s->level >= 2 and s->symvalue.offset >= 0)
55318235Slinton #define isreg(s)		(s->level < 0)
5549657Slinton 
55518235Slinton public Address address (s, frame)
5569657Slinton Symbol s;
5579657Slinton Frame frame;
5589657Slinton {
5599657Slinton     register Frame frp;
5609657Slinton     register Address addr;
5619657Slinton     register Symbol cur;
5629657Slinton 
5639657Slinton     checkref(s);
5649657Slinton     if (not isactive(s->block)) {
5659657Slinton 	error("\"%s\" is not currently defined", symname(s));
5669657Slinton     } else if (isglobal(s)) {
5679657Slinton 	addr = s->symvalue.offset;
5689657Slinton     } else {
5699657Slinton 	frp = frame;
5709657Slinton 	if (frp == nil) {
5719657Slinton 	    cur = s->block;
5729657Slinton 	    while (cur != nil and cur->class == MODULE) {
5739657Slinton 		cur = cur->block;
5749657Slinton 	    }
5759657Slinton 	    if (cur == nil) {
57618235Slinton 		frp = nil;
57718235Slinton 	    } else {
57818235Slinton 		frp = findframe(cur);
57918235Slinton 		if (frp == nil) {
58018235Slinton 		    error("[internal error: unexpected nil frame for \"%s\"]",
58118235Slinton 			symname(s)
58218235Slinton 		    );
58318235Slinton 		}
5849657Slinton 	    }
5859657Slinton 	}
5869657Slinton 	if (islocaloff(s)) {
5879657Slinton 	    addr = locals_base(frp) + s->symvalue.offset;
5889657Slinton 	} else if (isparamoff(s)) {
5899657Slinton 	    addr = args_base(frp) + s->symvalue.offset;
5909657Slinton 	} else if (isreg(s)) {
5919657Slinton 	    addr = savereg(s->symvalue.offset, frp);
5929657Slinton 	} else {
5939657Slinton 	    panic("address: bad symbol \"%s\"", symname(s));
5949657Slinton 	}
5959657Slinton     }
5969657Slinton     return addr;
5979657Slinton }
5989657Slinton 
5999657Slinton /*
6009657Slinton  * Define a symbol used to access register values.
6019657Slinton  */
6029657Slinton 
60318235Slinton public defregname (n, r)
6049657Slinton Name n;
60518235Slinton integer r;
6069657Slinton {
60718235Slinton     Symbol s;
6089657Slinton 
6099657Slinton     s = insert(n);
61018235Slinton     s->language = t_addr->language;
6119657Slinton     s->class = VAR;
6129657Slinton     s->level = -3;
61318235Slinton     s->type = t_addr;
6149657Slinton     s->symvalue.offset = r;
6159657Slinton }
6169657Slinton 
6179657Slinton /*
6189657Slinton  * Resolve an "abstract" type reference.
6199657Slinton  *
6209657Slinton  * It is possible in C to define a pointer to a type, but never define
6219657Slinton  * the type in a particular source file.  Here we try to resolve
6229657Slinton  * the type definition.  This is problematic, it is possible to
6239657Slinton  * have multiple, different definitions for the same name type.
6249657Slinton  */
6259657Slinton 
6269657Slinton public findtype(s)
6279657Slinton Symbol s;
6289657Slinton {
6299657Slinton     register Symbol t, u, prev;
6309657Slinton 
6319657Slinton     u = s;
6329657Slinton     prev = nil;
6339657Slinton     while (u != nil and u->class != BADUSE) {
6349657Slinton 	if (u->name != nil) {
6359657Slinton 	    prev = u;
6369657Slinton 	}
6379657Slinton 	u = u->type;
6389657Slinton     }
6399657Slinton     if (prev == nil) {
6409657Slinton 	error("couldn't find link to type reference");
6419657Slinton     }
64218235Slinton     t = lookup(prev->name);
64318235Slinton     while (t != nil and
64418235Slinton 	not (
64518235Slinton 	    t != prev and t->name == prev->name and
64618235Slinton 	    t->block->class == MODULE and t->class == prev->class and
64718235Slinton 	    t->type != nil and t->type->type != nil and
64818235Slinton 	    t->type->type->class != BADUSE
64918235Slinton 	)
65018235Slinton     ) {
65118235Slinton 	t = t->next_sym;
65218235Slinton     }
6539657Slinton     if (t == nil) {
6549657Slinton 	error("couldn't resolve reference");
6559657Slinton     } else {
6569657Slinton 	prev->type = t->type;
6579657Slinton     }
6589657Slinton }
6599657Slinton 
6609657Slinton /*
6619657Slinton  * Find the size in bytes of the given type.
6629657Slinton  *
6639657Slinton  * This is probably the WRONG thing to do.  The size should be kept
6649657Slinton  * as an attribute in the symbol information as is done for structures
6659657Slinton  * and fields.  I haven't gotten around to cleaning this up yet.
6669657Slinton  */
6679657Slinton 
66812547Scsvaf #define MAXUCHAR 255
66912547Scsvaf #define MAXUSHORT 65535L
6709657Slinton #define MINCHAR -128
6719657Slinton #define MAXCHAR 127
6729657Slinton #define MINSHORT -32768
6739657Slinton #define MAXSHORT 32767
6749657Slinton 
67516620Ssam public findbounds (u, lower, upper)
67616620Ssam Symbol u;
67716620Ssam long *lower, *upper;
67816620Ssam {
67916620Ssam     Rangetype lbt, ubt;
68016620Ssam     long lb, ub;
68116620Ssam 
68216620Ssam     if (u->class == RANGE) {
68316620Ssam 	lbt = u->symvalue.rangev.lowertype;
68416620Ssam 	ubt = u->symvalue.rangev.uppertype;
68516620Ssam 	lb = u->symvalue.rangev.lower;
68616620Ssam 	ub = u->symvalue.rangev.upper;
68716620Ssam 	if (lbt == R_ARG or lbt == R_TEMP) {
68816620Ssam 	    if (not getbound(u, lb, lbt, lower)) {
68916620Ssam 		error("dynamic bounds not currently available");
69016620Ssam 	    }
69116620Ssam 	} else {
69216620Ssam 	    *lower = lb;
69316620Ssam 	}
69416620Ssam 	if (ubt == R_ARG or ubt == R_TEMP) {
69516620Ssam 	    if (not getbound(u, ub, ubt, upper)) {
69616620Ssam 		error("dynamic bounds not currently available");
69716620Ssam 	    }
69816620Ssam 	} else {
69916620Ssam 	    *upper = ub;
70016620Ssam 	}
70116620Ssam     } else if (u->class == SCAL) {
70216620Ssam 	*lower = 0;
70316620Ssam 	*upper = u->symvalue.iconval - 1;
70416620Ssam     } else {
70518235Slinton 	error("[internal error: unexpected array bound type]");
70616620Ssam     }
70716620Ssam }
70816620Ssam 
70916620Ssam public integer size(sym)
71016620Ssam Symbol sym;
71116620Ssam {
71216620Ssam     register Symbol s, t, u;
71316620Ssam     register integer nel, elsize;
7149657Slinton     long lower, upper;
71516620Ssam     integer r, off, len;
7169657Slinton 
7179657Slinton     t = sym;
7189657Slinton     checkref(t);
71916620Ssam     if (t->class == TYPEREF) {
72016620Ssam 	resolveRef(t);
72116620Ssam     }
7229657Slinton     switch (t->class) {
7239657Slinton 	case RANGE:
7249657Slinton 	    lower = t->symvalue.rangev.lower;
7259657Slinton 	    upper = t->symvalue.rangev.upper;
72616620Ssam 	    if (upper == 0 and lower > 0) {
72716620Ssam 		/* real */
7289657Slinton 		r = lower;
72916620Ssam 	    } else if (lower > upper) {
73016620Ssam 		/* unsigned long */
73116620Ssam 		r = sizeof(long);
73212045Slinton 	    } else if (
73312547Scsvaf   		(lower >= MINCHAR and upper <= MAXCHAR) or
73412547Scsvaf   		(lower >= 0 and upper <= MAXUCHAR)
73512547Scsvaf   	      ) {
7369657Slinton 		r = sizeof(char);
73712547Scsvaf   	    } else if (
73812547Scsvaf   		(lower >= MINSHORT and upper <= MAXSHORT) or
73912547Scsvaf   		(lower >= 0 and upper <= MAXUSHORT)
74012547Scsvaf   	      ) {
7419657Slinton 		r = sizeof(short);
7429657Slinton 	    } else {
7439657Slinton 		r = sizeof(long);
7449657Slinton 	    }
7459657Slinton 	    break;
7469657Slinton 
7479657Slinton 	case ARRAY:
7489657Slinton 	    elsize = size(t->type);
7499657Slinton 	    nel = 1;
7509657Slinton 	    for (t = t->chain; t != nil; t = t->chain) {
75116620Ssam 		u = rtype(t);
75216620Ssam 		findbounds(u, &lower, &upper);
7539657Slinton 		nel *= (upper-lower+1);
7549657Slinton 	    }
7559657Slinton 	    r = nel*elsize;
7569657Slinton 	    break;
7579657Slinton 
75818235Slinton 	case DYNARRAY:
75918235Slinton 	    r = (t->symvalue.ndims + 1) * sizeof(Word);
76018235Slinton 	    break;
76118235Slinton 
76218235Slinton 	case SUBARRAY:
76318235Slinton 	    r = (2 * t->symvalue.ndims + 1) * sizeof(Word);
76418235Slinton 	    break;
76518235Slinton 
76612547Scsvaf 	case REF:
7679657Slinton 	case VAR:
7689657Slinton 	    r = size(t->type);
76912127Slinton 	    /*
77012127Slinton 	     *
77112045Slinton 	    if (r < sizeof(Word) and isparam(t)) {
7729657Slinton 		r = sizeof(Word);
7739657Slinton 	    }
77412547Scsvaf 	    */
7759657Slinton 	    break;
7769657Slinton 
77718235Slinton 	case FVAR:
7789657Slinton 	case CONST:
77918235Slinton 	case TAG:
7809657Slinton 	    r = size(t->type);
7819657Slinton 	    break;
7829657Slinton 
7839657Slinton 	case TYPE:
7849657Slinton 	    if (t->type->class == PTR and t->type->type->class == BADUSE) {
7859657Slinton 		findtype(t);
7869657Slinton 	    }
7879657Slinton 	    r = size(t->type);
7889657Slinton 	    break;
7899657Slinton 
7909657Slinton 	case FIELD:
79116620Ssam 	    off = t->symvalue.field.offset;
79216620Ssam 	    len = t->symvalue.field.length;
79316620Ssam 	    r = (off + len + 7) div 8 - (off div 8);
7949657Slinton 	    break;
7959657Slinton 
7969657Slinton 	case RECORD:
7979657Slinton 	case VARNT:
7989657Slinton 	    r = t->symvalue.offset;
7999657Slinton 	    if (r == 0 and t->chain != nil) {
8009657Slinton 		panic("missing size information for record");
8019657Slinton 	    }
8029657Slinton 	    break;
8039657Slinton 
8049657Slinton 	case PTR:
80518235Slinton 	case TYPEREF:
8069657Slinton 	case FILET:
8079657Slinton 	    r = sizeof(Word);
8089657Slinton 	    break;
8099657Slinton 
8109657Slinton 	case SCAL:
81112609Slinton 	    r = sizeof(Word);
81212609Slinton 	    /*
81312609Slinton 	     *
8149657Slinton 	    if (t->symvalue.iconval > 255) {
8159657Slinton 		r = sizeof(short);
8169657Slinton 	    } else {
8179657Slinton 		r = sizeof(char);
8189657Slinton 	    }
81912609Slinton 	     *
82012609Slinton 	     */
8219657Slinton 	    break;
8229657Slinton 
8239657Slinton 	case FPROC:
8249657Slinton 	case FFUNC:
8259657Slinton 	    r = sizeof(Word);
8269657Slinton 	    break;
8279657Slinton 
8289657Slinton 	case PROC:
8299657Slinton 	case FUNC:
8309657Slinton 	case MODULE:
8319657Slinton 	case PROG:
8329657Slinton 	    r = sizeof(Symbol);
8339657Slinton 	    break;
8349657Slinton 
83516620Ssam 	case SET:
83616620Ssam 	    u = rtype(t->type);
83716620Ssam 	    switch (u->class) {
83816620Ssam 		case RANGE:
83916620Ssam 		    r = u->symvalue.rangev.upper - u->symvalue.rangev.lower + 1;
84016620Ssam 		    break;
84116620Ssam 
84216620Ssam 		case SCAL:
84316620Ssam 		    r = u->symvalue.iconval;
84416620Ssam 		    break;
84516620Ssam 
84616620Ssam 		default:
84716620Ssam 		    error("expected range for set base type");
84816620Ssam 		    break;
84916620Ssam 	    }
85016620Ssam 	    r = (r + BITSPERBYTE - 1) div BITSPERBYTE;
85116620Ssam 	    break;
85216620Ssam 
85318235Slinton 	/*
85418235Slinton 	 * These can happen in C (unfortunately) for unresolved type references
85518235Slinton 	 * Assume they are pointers.
85618235Slinton 	 */
85718235Slinton 	case BADUSE:
85818235Slinton 	    r = sizeof(Address);
85918235Slinton 	    break;
86018235Slinton 
8619657Slinton 	default:
8629657Slinton 	    if (ord(t->class) > ord(TYPEREF)) {
8639657Slinton 		panic("size: bad class (%d)", ord(t->class));
8649657Slinton 	    } else {
86518235Slinton 		fprintf(stderr, "can't compute size of a %s\n", classname(t));
8669657Slinton 	    }
86716620Ssam 	    r = 0;
86816620Ssam 	    break;
8699657Slinton     }
8709657Slinton     return r;
8719657Slinton }
8729657Slinton 
8739657Slinton /*
87418235Slinton  * Return the size associated with a symbol that takes into account
87518235Slinton  * reference parameters.  This might be better as the normal size function, but
87618235Slinton  * too many places already depend on it working the way it does.
87718235Slinton  */
87818235Slinton 
87918235Slinton public integer psize (s)
88018235Slinton Symbol s;
88118235Slinton {
88218235Slinton     integer r;
88318235Slinton     Symbol t;
88418235Slinton 
88518235Slinton     if (s->class == REF) {
88618235Slinton 	t = rtype(s->type);
88718235Slinton 	if (t->class == DYNARRAY) {
88818235Slinton 	    r = (t->symvalue.ndims + 1) * sizeof(Word);
88918235Slinton 	} else if (t->class == SUBARRAY) {
89018235Slinton 	    r = (2 * t->symvalue.ndims + 1) * sizeof(Word);
89118235Slinton 	} else {
89218235Slinton 	    r = sizeof(Word);
89318235Slinton 	}
89418235Slinton     } else {
89518235Slinton 	r = size(s);
89618235Slinton     }
89718235Slinton     return r;
89818235Slinton }
89918235Slinton 
90018235Slinton /*
9019657Slinton  * Test if a symbol is a parameter.  This is true if there
9029657Slinton  * is a cycle from s->block to s via chain pointers.
9039657Slinton  */
9049657Slinton 
9059657Slinton public Boolean isparam(s)
9069657Slinton Symbol s;
9079657Slinton {
9089657Slinton     register Symbol t;
9099657Slinton 
9109657Slinton     t = s->block;
9119657Slinton     while (t != nil and t != s) {
9129657Slinton 	t = t->chain;
9139657Slinton     }
9149657Slinton     return (Boolean) (t != nil);
9159657Slinton }
9169657Slinton 
9179657Slinton /*
91816620Ssam  * Test if a type is an open array parameter type.
9199657Slinton  */
9209657Slinton 
92118235Slinton public boolean isopenarray (type)
92218235Slinton Symbol type;
92316620Ssam {
92418235Slinton     Symbol t;
92518235Slinton 
92618235Slinton     t = rtype(type);
92718235Slinton     return (boolean) (t->class == DYNARRAY);
92816620Ssam }
92916620Ssam 
93016620Ssam /*
93118235Slinton  * Test if a symbol is a var parameter, i.e. has class REF.
93216620Ssam  */
93316620Ssam 
9349657Slinton public Boolean isvarparam(s)
9359657Slinton Symbol s;
9369657Slinton {
9379657Slinton     return (Boolean) (s->class == REF);
9389657Slinton }
9399657Slinton 
9409657Slinton /*
9419657Slinton  * Test if a symbol is a variable (actually any addressible quantity
9429657Slinton  * with do).
9439657Slinton  */
9449657Slinton 
9459657Slinton public Boolean isvariable(s)
94618235Slinton Symbol s;
9479657Slinton {
9489657Slinton     return (Boolean) (s->class == VAR or s->class == FVAR or s->class == REF);
9499657Slinton }
9509657Slinton 
9519657Slinton /*
95218235Slinton  * Test if a symbol is a constant.
95318235Slinton  */
95418235Slinton 
95518235Slinton public Boolean isconst(s)
95618235Slinton Symbol s;
9579657Slinton {
95818235Slinton     return (Boolean) (s->class == CONST);
9599657Slinton }
9609657Slinton 
9619657Slinton /*
9629657Slinton  * Test if a symbol is a module.
9639657Slinton  */
9649657Slinton 
9659657Slinton public Boolean ismodule(s)
9669657Slinton register Symbol s;
9679657Slinton {
9689657Slinton     return (Boolean) (s->class == MODULE);
9699657Slinton }
9709657Slinton 
9719657Slinton /*
97216620Ssam  * Mark a procedure or function as internal, meaning that it is called
97316620Ssam  * with a different calling sequence.
97416620Ssam  */
97516620Ssam 
97616620Ssam public markInternal (s)
97716620Ssam Symbol s;
97816620Ssam {
97916620Ssam     s->symvalue.funcv.intern = true;
98016620Ssam }
98116620Ssam 
98216620Ssam public boolean isinternal (s)
98316620Ssam Symbol s;
98416620Ssam {
98516620Ssam     return s->symvalue.funcv.intern;
98616620Ssam }
98716620Ssam 
98816620Ssam /*
98918235Slinton  * Decide if a field begins or ends on a bit rather than byte boundary.
99018235Slinton  */
99118235Slinton 
99218235Slinton public Boolean isbitfield(s)
99318235Slinton register Symbol s;
99418235Slinton {
99518235Slinton     boolean b;
99618235Slinton     register integer off, len;
99718235Slinton     register Symbol t;
99818235Slinton 
99918235Slinton     off = s->symvalue.field.offset;
100018235Slinton     len = s->symvalue.field.length;
100118235Slinton     if ((off mod BITSPERBYTE) != 0 or (len mod BITSPERBYTE) != 0) {
100218235Slinton 	b = true;
100318235Slinton     } else {
100418235Slinton 	t = rtype(s->type);
100518235Slinton 	b = (Boolean) (
100618235Slinton 	    (t->class == SCAL and len != (sizeof(int)*BITSPERBYTE)) or
100718235Slinton 	    len != (size(t)*BITSPERBYTE)
100818235Slinton 	);
100918235Slinton     }
101018235Slinton     return b;
101118235Slinton }
101218235Slinton 
101318235Slinton private boolean primlang_typematch (t1, t2)
101418235Slinton Symbol t1, t2;
101518235Slinton {
101618235Slinton     return (boolean) (
101718235Slinton 	(t1 == t2) or
101818235Slinton 	(
101918235Slinton 	    t1->class == RANGE and t2->class == RANGE and
102018235Slinton 	    t1->symvalue.rangev.lower == t2->symvalue.rangev.lower and
102118235Slinton 	    t1->symvalue.rangev.upper == t2->symvalue.rangev.upper
102218235Slinton 	) or (
102318235Slinton 	    t1->class == PTR and t2->class == RANGE and
102418235Slinton 	    t2->symvalue.rangev.upper >= t2->symvalue.rangev.lower
102518235Slinton 	) or (
102618235Slinton 	    t2->class == PTR and t1->class == RANGE and
102718235Slinton 	    t1->symvalue.rangev.upper >= t1->symvalue.rangev.lower
102818235Slinton 	)
102918235Slinton     );
103018235Slinton }
103118235Slinton 
103218235Slinton /*
10339657Slinton  * Test if two types match.
10349657Slinton  * Equivalent names implies a match in any language.
10359657Slinton  *
10369657Slinton  * Special symbols must be handled with care.
10379657Slinton  */
10389657Slinton 
10399657Slinton public Boolean compatible(t1, t2)
10409657Slinton register Symbol t1, t2;
10419657Slinton {
10429657Slinton     Boolean b;
104316620Ssam     Symbol rt1, rt2;
10449657Slinton 
10459657Slinton     if (t1 == t2) {
10469657Slinton 	b = true;
10479657Slinton     } else if (t1 == nil or t2 == nil) {
10489657Slinton 	b = false;
10499657Slinton     } else if (t1 == procsym) {
10509657Slinton 	b = isblock(t2);
10519657Slinton     } else if (t2 == procsym) {
10529657Slinton 	b = isblock(t1);
105316620Ssam     } else if (t1->language == primlang) {
105416620Ssam 	if (t2->language == primlang) {
105518235Slinton 	    b = primlang_typematch(rtype(t1), rtype(t2));
105616620Ssam 	} else {
105716620Ssam 	    b = (boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2);
105816620Ssam 	}
105916620Ssam     } else if (t2->language == primlang) {
106016620Ssam 	b = (boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2);
10619657Slinton     } else if (t1->language == nil) {
106216620Ssam 	if (t2->language == nil) {
106316620Ssam 	    b = false;
106416620Ssam 	} else {
106516620Ssam 	    b = (boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2);
106616620Ssam 	}
10679657Slinton     } else {
106816620Ssam 	b = (boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2);
10699657Slinton     }
10709657Slinton     return b;
10719657Slinton }
10729657Slinton 
10739657Slinton /*
10749657Slinton  * Check for a type of the given name.
10759657Slinton  */
10769657Slinton 
10779657Slinton public Boolean istypename(type, name)
10789657Slinton Symbol type;
10799657Slinton String name;
10809657Slinton {
108118235Slinton     register Symbol t;
10829657Slinton     Boolean b;
10839657Slinton 
10849657Slinton     t = type;
108518235Slinton     if (t == nil) {
108618235Slinton 	b = false;
108718235Slinton     } else {
108818235Slinton 	b = (Boolean) (
108918235Slinton 	    t->class == TYPE and streq(ident(t->name), name)
109018235Slinton 	);
109118235Slinton     }
10929657Slinton     return b;
10939657Slinton }
10949657Slinton 
10959657Slinton /*
109616620Ssam  * Determine if a (value) parameter should actually be passed by address.
109716620Ssam  */
109816620Ssam 
109916620Ssam public boolean passaddr (p, exprtype)
110016620Ssam Symbol p, exprtype;
110116620Ssam {
110216620Ssam     boolean b;
110316620Ssam     Language def;
110416620Ssam 
110516620Ssam     if (p == nil) {
110616620Ssam 	def = findlanguage(".c");
110716620Ssam 	b = (boolean) (*language_op(def, L_PASSADDR))(p, exprtype);
110816620Ssam     } else if (p->language == nil or p->language == primlang) {
110916620Ssam 	b = false;
111016620Ssam     } else if (isopenarray(p->type)) {
111116620Ssam 	b = true;
111216620Ssam     } else {
111316620Ssam 	b = (boolean) (*language_op(p->language, L_PASSADDR))(p, exprtype);
111416620Ssam     }
111516620Ssam     return b;
111616620Ssam }
111716620Ssam 
111816620Ssam /*
11199657Slinton  * Test if the name of a symbol is uniquely defined or not.
11209657Slinton  */
11219657Slinton 
11229657Slinton public Boolean isambiguous(s)
11239657Slinton register Symbol s;
11249657Slinton {
11259657Slinton     register Symbol t;
11269657Slinton 
11279657Slinton     find(t, s->name) where t != s endfind(t);
11289657Slinton     return (Boolean) (t != nil);
11299657Slinton }
11309657Slinton 
11319657Slinton typedef char *Arglist;
11329657Slinton 
11339657Slinton #define nextarg(type)  ((type *) (ap += sizeof(type)))[-1]
11349657Slinton 
11359657Slinton private Symbol mkstring();
11369657Slinton 
11379657Slinton /*
11389657Slinton  * Determine the type of a parse tree.
113918235Slinton  *
11409657Slinton  * Also make some symbol-dependent changes to the tree such as
114118235Slinton  * removing indirection for constant or register symbols.
11429657Slinton  */
11439657Slinton 
114418235Slinton public assigntypes (p)
11459657Slinton register Node p;
11469657Slinton {
11479657Slinton     register Node p1;
11489657Slinton     register Symbol s;
11499657Slinton 
11509657Slinton     switch (p->op) {
11519657Slinton 	case O_SYM:
115218235Slinton 	    p->nodetype = p->value.sym;
11539657Slinton 	    break;
11549657Slinton 
11559657Slinton 	case O_LCON:
11569657Slinton 	    p->nodetype = t_int;
11579657Slinton 	    break;
11589657Slinton 
115918235Slinton 	case O_CCON:
116018235Slinton 	    p->nodetype = t_char;
116118235Slinton 	    break;
116218235Slinton 
11639657Slinton 	case O_FCON:
11649657Slinton 	    p->nodetype = t_real;
11659657Slinton 	    break;
11669657Slinton 
11679657Slinton 	case O_SCON:
116818235Slinton 	    p->nodetype = mkstring(p->value.scon);
11699657Slinton 	    break;
11709657Slinton 
11719657Slinton 	case O_INDIR:
11729657Slinton 	    p1 = p->value.arg[0];
117318235Slinton 	    s = rtype(p1->nodetype);
117418235Slinton 	    if (s->class != PTR) {
117518235Slinton 		beginerrmsg();
117618235Slinton 		fprintf(stderr, "\"");
117718235Slinton 		prtree(stderr, p1);
117818235Slinton 		fprintf(stderr, "\" is not a pointer");
117918235Slinton 		enderrmsg();
118018235Slinton 	    }
11819657Slinton 	    p->nodetype = rtype(p1->nodetype)->type;
11829657Slinton 	    break;
11839657Slinton 
11849657Slinton 	case O_DOT:
11859657Slinton 	    p->nodetype = p->value.arg[1]->value.sym;
11869657Slinton 	    break;
11879657Slinton 
11889657Slinton 	case O_RVAL:
11899657Slinton 	    p1 = p->value.arg[0];
11909657Slinton 	    p->nodetype = p1->nodetype;
11919657Slinton 	    if (p1->op == O_SYM) {
119218235Slinton 		if (p1->nodetype->class == PROC or p->nodetype->class == FUNC) {
119318235Slinton 		    p->op = p1->op;
119418235Slinton 		    p->value.sym = p1->value.sym;
119518235Slinton 		    p->nodetype = p1->nodetype;
119618235Slinton 		    dispose(p1);
11979657Slinton 		} else if (p1->value.sym->class == CONST) {
119818235Slinton 		    p->op = p1->op;
119918235Slinton 		    p->value = p1->value;
120018235Slinton 		    p->nodetype = p1->nodetype;
120118235Slinton 		    dispose(p1);
12029657Slinton 		} else if (isreg(p1->value.sym)) {
12039657Slinton 		    p->op = O_SYM;
12049657Slinton 		    p->value.sym = p1->value.sym;
12059657Slinton 		    dispose(p1);
12069657Slinton 		}
12079657Slinton 	    } else if (p1->op == O_INDIR and p1->value.arg[0]->op == O_SYM) {
12089657Slinton 		s = p1->value.arg[0]->value.sym;
12099657Slinton 		if (isreg(s)) {
12109657Slinton 		    p1->op = O_SYM;
12119657Slinton 		    dispose(p1->value.arg[0]);
12129657Slinton 		    p1->value.sym = s;
12139657Slinton 		    p1->nodetype = s;
12149657Slinton 		}
12159657Slinton 	    }
12169657Slinton 	    break;
12179657Slinton 
121818235Slinton 	case O_COMMA:
121918235Slinton 	    p->nodetype = p->value.arg[0]->nodetype;
122018235Slinton 	    break;
122118235Slinton 
122218235Slinton 	case O_CALLPROC:
12239657Slinton 	case O_CALL:
12249657Slinton 	    p1 = p->value.arg[0];
122511171Slinton 	    p->nodetype = rtype(p1->nodetype)->type;
12269657Slinton 	    break;
12279657Slinton 
122811171Slinton 	case O_TYPERENAME:
122911171Slinton 	    p->nodetype = p->value.arg[1]->nodetype;
123011171Slinton 	    break;
123111171Slinton 
12329657Slinton 	case O_ITOF:
12339657Slinton 	    p->nodetype = t_real;
12349657Slinton 	    break;
12359657Slinton 
12369657Slinton 	case O_NEG:
12379657Slinton 	    s = p->value.arg[0]->nodetype;
12389657Slinton 	    if (not compatible(s, t_int)) {
12399657Slinton 		if (not compatible(s, t_real)) {
12409657Slinton 		    beginerrmsg();
124116620Ssam 		    fprintf(stderr, "\"");
12429657Slinton 		    prtree(stderr, p->value.arg[0]);
124316620Ssam 		    fprintf(stderr, "\" is improper type");
12449657Slinton 		    enderrmsg();
12459657Slinton 		} else {
12469657Slinton 		    p->op = O_NEGF;
12479657Slinton 		}
12489657Slinton 	    }
12499657Slinton 	    p->nodetype = s;
12509657Slinton 	    break;
12519657Slinton 
12529657Slinton 	case O_ADD:
12539657Slinton 	case O_SUB:
12549657Slinton 	case O_MUL:
125516620Ssam 	    binaryop(p, nil);
125616620Ssam 	    break;
125716620Ssam 
12589657Slinton 	case O_LT:
12599657Slinton 	case O_LE:
12609657Slinton 	case O_GT:
12619657Slinton 	case O_GE:
12629657Slinton 	case O_EQ:
12639657Slinton 	case O_NE:
126416620Ssam 	    binaryop(p, t_boolean);
12659657Slinton 	    break;
12669657Slinton 
12679657Slinton 	case O_DIVF:
12689657Slinton 	    convert(&(p->value.arg[0]), t_real, O_ITOF);
12699657Slinton 	    convert(&(p->value.arg[1]), t_real, O_ITOF);
12709657Slinton 	    p->nodetype = t_real;
12719657Slinton 	    break;
12729657Slinton 
12739657Slinton 	case O_DIV:
12749657Slinton 	case O_MOD:
12759657Slinton 	    convert(&(p->value.arg[0]), t_int, O_NOP);
12769657Slinton 	    convert(&(p->value.arg[1]), t_int, O_NOP);
12779657Slinton 	    p->nodetype = t_int;
12789657Slinton 	    break;
12799657Slinton 
12809657Slinton 	case O_AND:
12819657Slinton 	case O_OR:
12829657Slinton 	    chkboolean(p->value.arg[0]);
12839657Slinton 	    chkboolean(p->value.arg[1]);
12849657Slinton 	    p->nodetype = t_boolean;
12859657Slinton 	    break;
12869657Slinton 
12879657Slinton 	case O_QLINE:
12889657Slinton 	    p->nodetype = t_int;
12899657Slinton 	    break;
12909657Slinton 
12919657Slinton 	default:
12929657Slinton 	    p->nodetype = nil;
12939657Slinton 	    break;
12949657Slinton     }
12959657Slinton }
12969657Slinton 
12979657Slinton /*
129816620Ssam  * Process a binary arithmetic or relational operator.
129916620Ssam  * Convert from integer to real if necessary.
130016620Ssam  */
130116620Ssam 
130216620Ssam private binaryop (p, t)
130316620Ssam Node p;
130416620Ssam Symbol t;
130516620Ssam {
130616620Ssam     Node p1, p2;
130716620Ssam     Boolean t1real, t2real;
130816620Ssam     Symbol t1, t2;
130916620Ssam 
131016620Ssam     p1 = p->value.arg[0];
131116620Ssam     p2 = p->value.arg[1];
131216620Ssam     t1 = rtype(p1->nodetype);
131316620Ssam     t2 = rtype(p2->nodetype);
131416620Ssam     t1real = compatible(t1, t_real);
131516620Ssam     t2real = compatible(t2, t_real);
131616620Ssam     if (t1real or t2real) {
131716620Ssam 	p->op = (Operator) (ord(p->op) + 1);
131816620Ssam 	if (not t1real) {
131916620Ssam 	    p->value.arg[0] = build(O_ITOF, p1);
132016620Ssam 	} else if (not t2real) {
132116620Ssam 	    p->value.arg[1] = build(O_ITOF, p2);
132216620Ssam 	}
132316620Ssam 	p->nodetype = t_real;
132416620Ssam     } else {
132516620Ssam 	if (size(p1->nodetype) > sizeof(integer)) {
132616620Ssam 	    beginerrmsg();
132716620Ssam 	    fprintf(stderr, "operation not defined on \"");
132816620Ssam 	    prtree(stderr, p1);
132916620Ssam 	    fprintf(stderr, "\"");
133016620Ssam 	    enderrmsg();
133116620Ssam 	} else if (size(p2->nodetype) > sizeof(integer)) {
133216620Ssam 	    beginerrmsg();
133316620Ssam 	    fprintf(stderr, "operation not defined on \"");
133416620Ssam 	    prtree(stderr, p2);
133516620Ssam 	    fprintf(stderr, "\"");
133616620Ssam 	    enderrmsg();
133716620Ssam 	}
133816620Ssam 	p->nodetype = t_int;
133916620Ssam     }
134016620Ssam     if (t != nil) {
134116620Ssam 	p->nodetype = t;
134216620Ssam     }
134316620Ssam }
134416620Ssam 
134516620Ssam /*
13469657Slinton  * Convert a tree to a type via a conversion operator;
13479657Slinton  * if this isn't possible generate an error.
13489657Slinton  *
13499657Slinton  * Note the tree is call by address, hence the #define below.
13509657Slinton  */
13519657Slinton 
13529657Slinton private convert(tp, typeto, op)
13539657Slinton Node *tp;
13549657Slinton Symbol typeto;
13559657Slinton Operator op;
13569657Slinton {
135716620Ssam     Node tree;
135816620Ssam     Symbol s, t;
13599657Slinton 
136016620Ssam     tree = *tp;
13619657Slinton     s = rtype(tree->nodetype);
136216620Ssam     t = rtype(typeto);
136316620Ssam     if (compatible(t, t_real) and compatible(s, t_int)) {
13649657Slinton 	tree = build(op, tree);
136516620Ssam     } else if (not compatible(s, t)) {
13669657Slinton 	beginerrmsg();
136716620Ssam 	fprintf(stderr, "expected integer or real, found \"");
136816620Ssam 	prtree(stderr, tree);
136916620Ssam 	fprintf(stderr, "\"");
13709657Slinton 	enderrmsg();
137116620Ssam     } else if (op != O_NOP and s != t) {
13729657Slinton 	tree = build(op, tree);
13739657Slinton     }
137416620Ssam     *tp = tree;
13759657Slinton }
13769657Slinton 
13779657Slinton /*
13789657Slinton  * Construct a node for the dot operator.
13799657Slinton  *
13809657Slinton  * If the left operand is not a record, but rather a procedure
13819657Slinton  * or function, then we interpret the "." as referencing an
13829657Slinton  * "invisible" variable; i.e. a variable within a dynamically
13839657Slinton  * active block but not within the static scope of the current procedure.
13849657Slinton  */
13859657Slinton 
13869657Slinton public Node dot(record, fieldname)
13879657Slinton Node record;
13889657Slinton Name fieldname;
13899657Slinton {
139018235Slinton     register Node rec, p;
13919657Slinton     register Symbol s, t;
13929657Slinton 
139318235Slinton     rec = record;
139418235Slinton     if (isblock(rec->nodetype)) {
13959657Slinton 	find(s, fieldname) where
139618235Slinton 	    s->block == rec->nodetype and
139718235Slinton 	    s->class != FIELD
13989657Slinton 	endfind(s);
13999657Slinton 	if (s == nil) {
14009657Slinton 	    beginerrmsg();
14019657Slinton 	    fprintf(stderr, "\"%s\" is not defined in ", ident(fieldname));
140218235Slinton 	    printname(stderr, rec->nodetype);
14039657Slinton 	    enderrmsg();
14049657Slinton 	}
14059657Slinton 	p = new(Node);
14069657Slinton 	p->op = O_SYM;
14079657Slinton 	p->value.sym = s;
140818235Slinton 	p->nodetype = s;
14099657Slinton     } else {
141018235Slinton 	p = rec;
14119657Slinton 	t = rtype(p->nodetype);
14129657Slinton 	if (t->class == PTR) {
14139657Slinton 	    s = findfield(fieldname, t->type);
14149657Slinton 	} else {
14159657Slinton 	    s = findfield(fieldname, t);
14169657Slinton 	}
14179657Slinton 	if (s == nil) {
14189657Slinton 	    beginerrmsg();
14199657Slinton 	    fprintf(stderr, "\"%s\" is not a field in ", ident(fieldname));
142018235Slinton 	    prtree(stderr, rec);
14219657Slinton 	    enderrmsg();
14229657Slinton 	}
142318235Slinton 	if (t->class != PTR or isreg(rec->nodetype)) {
142418235Slinton 	    p = unrval(p);
14259657Slinton 	}
142618235Slinton 	p->nodetype = t_addr;
14279657Slinton 	p = build(O_DOT, p, build(O_SYM, s));
14289657Slinton     }
142918235Slinton     return build(O_RVAL, p);
14309657Slinton }
14319657Slinton 
14329657Slinton /*
14339657Slinton  * Return a tree corresponding to an array reference and do the
14349657Slinton  * error checking.
14359657Slinton  */
14369657Slinton 
14379657Slinton public Node subscript(a, slist)
14389657Slinton Node a, slist;
14399657Slinton {
144016620Ssam     Symbol t;
144118235Slinton     Node p;
14429657Slinton 
144316620Ssam     t = rtype(a->nodetype);
144418235Slinton     if (t->language == nil or t->language == primlang) {
144518235Slinton 	p = (Node) (*language_op(findlanguage(".s"), L_BUILDAREF))(a, slist);
144616620Ssam     } else {
144718235Slinton 	p = (Node) (*language_op(t->language, L_BUILDAREF))(a, slist);
144816620Ssam     }
144918235Slinton     return build(O_RVAL, p);
14509657Slinton }
14519657Slinton 
14529657Slinton /*
14539657Slinton  * Evaluate a subscript index.
14549657Slinton  */
14559657Slinton 
145618235Slinton public int evalindex(s, base, i)
14579657Slinton Symbol s;
145818235Slinton Address base;
14599657Slinton long i;
14609657Slinton {
146116620Ssam     Symbol t;
146218235Slinton     int r;
14639657Slinton 
146416620Ssam     t = rtype(s);
146518235Slinton     if (t->language == nil or t->language == primlang) {
146618235Slinton 	r = ((*language_op(findlanguage(".s"), L_EVALAREF)) (s, base, i));
146716620Ssam     } else {
146818235Slinton 	r = ((*language_op(t->language, L_EVALAREF)) (s, base, i));
146916620Ssam     }
147018235Slinton     return r;
14719657Slinton }
14729657Slinton 
14739657Slinton /*
14749657Slinton  * Check to see if a tree is boolean-valued, if not it's an error.
14759657Slinton  */
14769657Slinton 
14779657Slinton public chkboolean(p)
14789657Slinton register Node p;
14799657Slinton {
14809657Slinton     if (p->nodetype != t_boolean) {
14819657Slinton 	beginerrmsg();
14829657Slinton 	fprintf(stderr, "found ");
14839657Slinton 	prtree(stderr, p);
14849657Slinton 	fprintf(stderr, ", expected boolean expression");
14859657Slinton 	enderrmsg();
14869657Slinton     }
14879657Slinton }
14889657Slinton 
14899657Slinton /*
149016620Ssam  * Construct a node for the type of a string.
14919657Slinton  */
14929657Slinton 
14939657Slinton private Symbol mkstring(str)
14949657Slinton String str;
14959657Slinton {
14969657Slinton     register Symbol s;
14979657Slinton 
149818235Slinton     s = newSymbol(nil, 0, ARRAY, t_char, nil);
149918235Slinton     s->chain = newSymbol(nil, 0, RANGE, t_int, nil);
150018235Slinton     s->chain->language = s->language;
150118235Slinton     s->chain->symvalue.rangev.lower = 1;
150218235Slinton     s->chain->symvalue.rangev.upper = strlen(str) + 1;
15039657Slinton     return s;
15049657Slinton }
15059657Slinton 
15069657Slinton /*
15079657Slinton  * Free up the space allocated for a string type.
15089657Slinton  */
15099657Slinton 
15109657Slinton public unmkstring(s)
15119657Slinton Symbol s;
15129657Slinton {
15139657Slinton     dispose(s->chain);
15149657Slinton }
15159657Slinton 
15169657Slinton /*
151718235Slinton  * Figure out the "current" variable or function being referred to
151818235Slinton  * by the name n.
15199657Slinton  */
15209657Slinton 
152118235Slinton private boolean stwhich(), dynwhich();
152218235Slinton 
152318235Slinton public Symbol which (n)
15249657Slinton Name n;
15259657Slinton {
152618235Slinton     Symbol s;
15279657Slinton 
152818235Slinton     s = lookup(n);
15299657Slinton     if (s == nil) {
153018235Slinton 	error("\"%s\" is not defined", ident(n));
153118235Slinton     } else if (not stwhich(&s) and isambiguous(s) and not dynwhich(&s)) {
153218235Slinton 	printf("[using ");
153318235Slinton 	printname(stdout, s);
153418235Slinton 	printf("]\n");
15359657Slinton     }
153618235Slinton     return s;
153718235Slinton }
153818235Slinton 
153918235Slinton /*
154018235Slinton  * Static search.
154118235Slinton  */
154218235Slinton 
154318235Slinton private boolean stwhich (var_s)
154418235Slinton Symbol *var_s;
154518235Slinton {
154618235Slinton     Name n;		/* name of desired symbol */
154718235Slinton     Symbol s;		/* iteration variable for symbols with name n */
154818235Slinton     Symbol f;		/* iteration variable for blocks containing s */
154918235Slinton     integer count;	/* number of levels from s->block to curfunc */
155018235Slinton     Symbol t;		/* current best answer for stwhich(n) */
155118235Slinton     integer mincount;	/* relative level for current best answer (t) */
155218235Slinton     boolean b;		/* return value, true if symbol found */
155318235Slinton 
155418235Slinton     s = *var_s;
155518235Slinton     n = s->name;
155618235Slinton     t = s;
155718235Slinton     mincount = 10000; /* force first match to set mincount */
155818235Slinton     do {
155918235Slinton 	if (s->name == n and s->class != FIELD and s->class != TAG) {
156018235Slinton 	    f = curfunc;
156118235Slinton 	    count = 0;
156218235Slinton 	    while (f != nil and f != s->block) {
156318235Slinton 		++count;
156418235Slinton 		f = f->block;
156518235Slinton 	    }
156618235Slinton 	    if (f != nil and count < mincount) {
156718235Slinton 		t = s;
156818235Slinton 		mincount = count;
156918235Slinton 		b = true;
157018235Slinton 	    }
157118235Slinton 	}
157218235Slinton 	s = s->next_sym;
157318235Slinton     } while (s != nil);
157418235Slinton     if (mincount != 10000) {
157518235Slinton 	*var_s = t;
157618235Slinton 	b = true;
15779657Slinton     } else {
157818235Slinton 	b = false;
157918235Slinton     }
158018235Slinton     return b;
158118235Slinton }
158218235Slinton 
158318235Slinton /*
158418235Slinton  * Dynamic search.
158518235Slinton  */
158618235Slinton 
158718235Slinton private boolean dynwhich (var_s)
158818235Slinton Symbol *var_s;
158918235Slinton {
159018235Slinton     Name n;		/* name of desired symbol */
159118235Slinton     Symbol s;		/* iteration variable for possible symbols */
159218235Slinton     Symbol f;		/* iteration variable for active functions */
159318235Slinton     Frame frp;		/* frame associated with stack walk */
159418235Slinton     boolean b;		/* return value */
159518235Slinton 
159618235Slinton     f = curfunc;
159718235Slinton     frp = curfuncframe();
159818235Slinton     n = (*var_s)->name;
159918235Slinton     b = false;
160018235Slinton     if (frp != nil) {
160118235Slinton 	frp = nextfunc(frp, &f);
160218235Slinton 	while (frp != nil) {
160318235Slinton 	    s = *var_s;
160418235Slinton 	    while (s != nil and
160518235Slinton 		(
160618235Slinton 		    s->name != n or s->block != f or
160718235Slinton 		    s->class == FIELD or s->class == TAG
160818235Slinton 		)
160918235Slinton 	    ) {
161018235Slinton 		s = s->next_sym;
161118235Slinton 	    }
161218235Slinton 	    if (s != nil) {
161318235Slinton 		*var_s = s;
161418235Slinton 		b = true;
161518235Slinton 		break;
161618235Slinton 	    }
161718235Slinton 	    if (f == program) {
161818235Slinton 		break;
161918235Slinton 	    }
162018235Slinton 	    frp = nextfunc(frp, &f);
16219657Slinton 	}
16229657Slinton     }
162318235Slinton     return b;
16249657Slinton }
16259657Slinton 
16269657Slinton /*
162718235Slinton  * Find the symbol that has the same name and scope as the
16289657Slinton  * given symbol but is of the given field.  Return nil if there is none.
16299657Slinton  */
16309657Slinton 
163118235Slinton public Symbol findfield (fieldname, record)
16329657Slinton Name fieldname;
16339657Slinton Symbol record;
16349657Slinton {
16359657Slinton     register Symbol t;
16369657Slinton 
16379657Slinton     t = rtype(record)->chain;
16389657Slinton     while (t != nil and t->name != fieldname) {
16399657Slinton 	t = t->chain;
16409657Slinton     }
16419657Slinton     return t;
16429657Slinton }
164312547Scsvaf 
164412547Scsvaf public Boolean getbound(s,off,type,valp)
164512547Scsvaf Symbol s;
164612547Scsvaf int off;
164712547Scsvaf Rangetype type;
164812547Scsvaf int *valp;
164912547Scsvaf {
165012547Scsvaf     Frame frp;
165112547Scsvaf     Address addr;
165212547Scsvaf     Symbol cur;
165312547Scsvaf 
165412547Scsvaf     if (not isactive(s->block)) {
165512547Scsvaf 	return(false);
165612547Scsvaf     }
165712547Scsvaf     cur = s->block;
165812547Scsvaf     while (cur != nil and cur->class == MODULE) {  /* WHY*/
165912547Scsvaf     		cur = cur->block;
166012547Scsvaf     }
166112547Scsvaf     if(cur == nil) {
166212547Scsvaf 		cur = whatblock(pc);
166312547Scsvaf     }
166412547Scsvaf     frp = findframe(cur);
166512547Scsvaf     if (frp == nil) {
166612547Scsvaf 	return(false);
166712547Scsvaf     }
166812547Scsvaf     if(type == R_TEMP) addr = locals_base(frp) + off;
166912547Scsvaf     else if (type == R_ARG) addr = args_base(frp) + off;
167012547Scsvaf     else return(false);
167112547Scsvaf     dread(valp,addr,sizeof(long));
167212547Scsvaf     return(true);
167312547Scsvaf }
1674