xref: /csrg-svn/old/dbx/symbols.c (revision 40260)
121625Sdist /*
238105Sbostic  * Copyright (c) 1983 The Regents of the University of California.
338105Sbostic  * All rights reserved.
438105Sbostic  *
538105Sbostic  * Redistribution and use in source and binary forms are permitted
638105Sbostic  * provided that the above copyright notice and this paragraph are
738105Sbostic  * duplicated in all such forms and that any documentation,
838105Sbostic  * advertising materials, and other materials related to such
938105Sbostic  * distribution and use acknowledge that the software was developed
1038105Sbostic  * by the University of California, Berkeley.  The name of the
1138105Sbostic  * University may not be used to endorse or promote products derived
1238105Sbostic  * from this software without specific prior written permission.
1338105Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1438105Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1538105Sbostic  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1621625Sdist  */
179657Slinton 
1821625Sdist #ifndef lint
19*40260Sdonn static char sccsid[] = "@(#)symbols.c	5.7 (Berkeley) 03/03/90";
2038105Sbostic #endif /* not lint */
219657Slinton 
229657Slinton /*
239657Slinton  * Symbol management.
249657Slinton  */
259657Slinton 
269657Slinton #include "defs.h"
279657Slinton #include "symbols.h"
289657Slinton #include "languages.h"
299657Slinton #include "printsym.h"
309657Slinton #include "tree.h"
319657Slinton #include "operators.h"
329657Slinton #include "eval.h"
339657Slinton #include "mappings.h"
349657Slinton #include "events.h"
359657Slinton #include "process.h"
369657Slinton #include "runtime.h"
379657Slinton #include "machine.h"
389657Slinton #include "names.h"
399657Slinton 
409657Slinton #ifndef public
419657Slinton typedef struct Symbol *Symbol;
429657Slinton 
439657Slinton #include "machine.h"
449657Slinton #include "names.h"
459657Slinton #include "languages.h"
4618235Slinton #include "tree.h"
479657Slinton 
489657Slinton /*
499657Slinton  * Symbol classes
509657Slinton  */
519657Slinton 
529657Slinton typedef enum {
5333337Sdonn     BADUSE, CONST, TYPE, VAR, ARRAY, OPENARRAY, DYNARRAY, SUBARRAY,
5433337Sdonn     PTRFILE, RECORD, FIELD,
5512547Scsvaf     PROC, FUNC, FVAR, REF, PTR, FILET, SET, RANGE,
569657Slinton     LABEL, WITHPTR, SCAL, STR, PROG, IMPROPER, VARNT,
5716620Ssam     FPROC, FFUNC, MODULE, TAG, COMMON, EXTREF, TYPEREF
589657Slinton } Symclass;
599657Slinton 
6012547Scsvaf typedef enum { R_CONST, R_TEMP, R_ARG, R_ADJUST } Rangetype;
6112547Scsvaf 
6233337Sdonn #define INREG 0
6333337Sdonn #define STK 1
6433337Sdonn #define EXT 2
6533337Sdonn 
66*40260Sdonn typedef unsigned int Storage;
6733337Sdonn 
689657Slinton struct Symbol {
699657Slinton     Name name;
709657Slinton     Language language;
7133337Sdonn     Symclass class : 8;
7233337Sdonn     Storage storage : 2;
7333337Sdonn     unsigned int level : 6;	/* for variables stored on stack only */
749657Slinton     Symbol type;
759657Slinton     Symbol chain;
769657Slinton     union {
7718235Slinton 	Node constval;		/* value of constant symbol */
789657Slinton 	int offset;		/* variable address */
799657Slinton 	long iconval;		/* integer constant value */
809657Slinton 	double fconval;		/* floating constant value */
8118235Slinton 	int ndims;		/* no. of dimensions for dynamic/sub-arrays */
829657Slinton 	struct {		/* field offset and size (both in bits) */
839657Slinton 	    int offset;
849657Slinton 	    int length;
859657Slinton 	} field;
8612547Scsvaf 	struct {		/* common offset and chain; used to relocate */
8712547Scsvaf 	    int offset;         /* vars in global BSS */
8812547Scsvaf 	    Symbol chain;
8912547Scsvaf 	} common;
909657Slinton 	struct {		/* range bounds */
9112547Scsvaf             Rangetype lowertype : 16;
9212547Scsvaf             Rangetype uppertype : 16;
939657Slinton 	    long lower;
949657Slinton 	    long upper;
959657Slinton 	} rangev;
9611865Slinton 	struct {
9711865Slinton 	    int offset : 16;	/* offset for of function value */
9816620Ssam 	    Boolean src : 1;	/* true if there is source line info */
9916620Ssam 	    Boolean inline : 1;	/* true if no separate act. rec. */
10016620Ssam 	    Boolean intern : 1; /* internal calling sequence */
10116620Ssam 	    int unused : 13;
10211865Slinton 	    Address beginaddr;	/* address of function code */
1039657Slinton 	} funcv;
1049657Slinton 	struct {		/* variant record info */
1059657Slinton 	    int size;
1069657Slinton 	    Symbol vtorec;
1079657Slinton 	    Symbol vtag;
1089657Slinton 	} varnt;
10916620Ssam 	String typeref;		/* type defined by "<module>:<type>" */
11016620Ssam 	Symbol extref;		/* indirect symbol for external reference */
1119657Slinton     } symvalue;
1129657Slinton     Symbol block;		/* symbol containing this symbol */
1139657Slinton     Symbol next_sym;		/* hash chain */
1149657Slinton };
1159657Slinton 
1169657Slinton /*
1179657Slinton  * Basic types.
1189657Slinton  */
1199657Slinton 
1209657Slinton Symbol t_boolean;
1219657Slinton Symbol t_char;
1229657Slinton Symbol t_int;
1239657Slinton Symbol t_real;
1249657Slinton Symbol t_nil;
12518235Slinton Symbol t_addr;
1269657Slinton 
1279657Slinton Symbol program;
1289657Slinton Symbol curfunc;
1299657Slinton 
13018235Slinton boolean showaggrs;
13118235Slinton 
1329657Slinton #define symname(s) ident(s->name)
1339657Slinton #define codeloc(f) ((f)->symvalue.funcv.beginaddr)
1349657Slinton #define isblock(s) (Boolean) ( \
1359657Slinton     s->class == FUNC or s->class == PROC or \
1369657Slinton     s->class == MODULE or s->class == PROG \
1379657Slinton )
13816620Ssam #define isroutine(s) (Boolean) ( \
13916620Ssam     s->class == FUNC or s->class == PROC \
14016620Ssam )
1419657Slinton 
14211865Slinton #define nosource(f) (not (f)->symvalue.funcv.src)
14314441Slinton #define isinline(f) ((f)->symvalue.funcv.inline)
14411865Slinton 
14533337Sdonn #define isreg(s)		(s->storage == INREG)
14624554Smckusick 
1479657Slinton #include "tree.h"
1489657Slinton 
1499657Slinton /*
1509657Slinton  * Some macros to make finding a symbol with certain attributes.
1519657Slinton  */
1529657Slinton 
1539657Slinton #define find(s, withname) \
1549657Slinton { \
1559657Slinton     s = lookup(withname); \
1569657Slinton     while (s != nil and not (s->name == (withname) and
1579657Slinton 
1589657Slinton #define where /* qualification */
1599657Slinton 
1609657Slinton #define endfind(s) )) { \
1619657Slinton 	s = s->next_sym; \
1629657Slinton     } \
1639657Slinton }
1649657Slinton 
1659657Slinton #endif
1669657Slinton 
1679657Slinton /*
1689657Slinton  * Symbol table structure currently does not support deletions.
16933337Sdonn  * Hash table size is a power of two to make hashing faster.
17033337Sdonn  * Using a non-prime is ok since we aren't doing rehashing.
1719657Slinton  */
1729657Slinton 
17333337Sdonn #define HASHTABLESIZE 8192
1749657Slinton 
1759657Slinton private Symbol hashtab[HASHTABLESIZE];
1769657Slinton 
17733337Sdonn #define hash(name) ((((unsigned) name) >> 2) & (HASHTABLESIZE - 1))
1789657Slinton 
1799657Slinton /*
1809657Slinton  * Allocate a new symbol.
1819657Slinton  */
1829657Slinton 
18333337Sdonn #define SYMBLOCKSIZE 1000
1849657Slinton 
1859657Slinton typedef struct Sympool {
1869657Slinton     struct Symbol sym[SYMBLOCKSIZE];
1879657Slinton     struct Sympool *prevpool;
1889657Slinton } *Sympool;
1899657Slinton 
1909657Slinton private Sympool sympool = nil;
1919657Slinton private Integer nleft = 0;
1929657Slinton 
1939657Slinton public Symbol symbol_alloc()
1949657Slinton {
1959657Slinton     register Sympool newpool;
1969657Slinton 
1979657Slinton     if (nleft <= 0) {
1989657Slinton 	newpool = new(Sympool);
19933337Sdonn 	bzero(newpool, sizeof(*newpool));
2009657Slinton 	newpool->prevpool = sympool;
2019657Slinton 	sympool = newpool;
2029657Slinton 	nleft = SYMBLOCKSIZE;
2039657Slinton     }
2049657Slinton     --nleft;
2059657Slinton     return &(sympool->sym[nleft]);
2069657Slinton }
2079657Slinton 
20818235Slinton public symbol_dump (func)
20912547Scsvaf Symbol func;
21012547Scsvaf {
21118235Slinton     register Symbol s;
21218235Slinton     register integer i;
21312547Scsvaf 
21418235Slinton     printf(" symbols in %s \n",symname(func));
21518235Slinton     for (i = 0; i < HASHTABLESIZE; i++) {
21618235Slinton 	for (s = hashtab[i]; s != nil; s = s->next_sym) {
21718235Slinton 	    if (s->block == func) {
21818235Slinton 		psym(s);
21918235Slinton 	    }
22018235Slinton 	}
22118235Slinton     }
22212547Scsvaf }
22312547Scsvaf 
2249657Slinton /*
2259657Slinton  * Free all the symbols currently allocated.
2269657Slinton  */
22718235Slinton 
2289657Slinton public symbol_free()
2299657Slinton {
2309657Slinton     Sympool s, t;
2319657Slinton     register Integer i;
2329657Slinton 
2339657Slinton     s = sympool;
2349657Slinton     while (s != nil) {
2359657Slinton 	t = s->prevpool;
2369657Slinton 	dispose(s);
2379657Slinton 	s = t;
2389657Slinton     }
2399657Slinton     for (i = 0; i < HASHTABLESIZE; i++) {
2409657Slinton 	hashtab[i] = nil;
2419657Slinton     }
2429657Slinton     sympool = nil;
2439657Slinton     nleft = 0;
2449657Slinton }
2459657Slinton 
2469657Slinton /*
2479657Slinton  * Create a new symbol with the given attributes.
2489657Slinton  */
2499657Slinton 
2509657Slinton public Symbol newSymbol(name, blevel, class, type, chain)
2519657Slinton Name name;
2529657Slinton Integer blevel;
2539657Slinton Symclass class;
2549657Slinton Symbol type;
2559657Slinton Symbol chain;
2569657Slinton {
2579657Slinton     register Symbol s;
2589657Slinton 
2599657Slinton     s = symbol_alloc();
2609657Slinton     s->name = name;
26118235Slinton     s->language = primlang;
26233337Sdonn     s->storage = EXT;
2639657Slinton     s->level = blevel;
2649657Slinton     s->class = class;
2659657Slinton     s->type = type;
2669657Slinton     s->chain = chain;
2679657Slinton     return s;
2689657Slinton }
2699657Slinton 
2709657Slinton /*
2719657Slinton  * Insert a symbol into the hash table.
2729657Slinton  */
2739657Slinton 
2749657Slinton public Symbol insert(name)
2759657Slinton Name name;
2769657Slinton {
2779657Slinton     register Symbol s;
2789657Slinton     register unsigned int h;
2799657Slinton 
2809657Slinton     h = hash(name);
2819657Slinton     s = symbol_alloc();
2829657Slinton     s->name = name;
2839657Slinton     s->next_sym = hashtab[h];
2849657Slinton     hashtab[h] = s;
2859657Slinton     return s;
2869657Slinton }
2879657Slinton 
2889657Slinton /*
2899657Slinton  * Symbol lookup.
2909657Slinton  */
2919657Slinton 
2929657Slinton public Symbol lookup(name)
2939657Slinton Name name;
2949657Slinton {
2959657Slinton     register Symbol s;
2969657Slinton     register unsigned int h;
2979657Slinton 
2989657Slinton     h = hash(name);
2999657Slinton     s = hashtab[h];
3009657Slinton     while (s != nil and s->name != name) {
3019657Slinton 	s = s->next_sym;
3029657Slinton     }
3039657Slinton     return s;
3049657Slinton }
3059657Slinton 
3069657Slinton /*
30716620Ssam  * Delete a symbol from the symbol table.
30816620Ssam  */
30916620Ssam 
31016620Ssam public delete (s)
31116620Ssam Symbol s;
31216620Ssam {
31316620Ssam     register Symbol t;
31416620Ssam     register unsigned int h;
31516620Ssam 
31616620Ssam     h = hash(s->name);
31716620Ssam     t = hashtab[h];
31816620Ssam     if (t == nil) {
31916620Ssam 	panic("delete of non-symbol '%s'", symname(s));
32016620Ssam     } else if (t == s) {
32116620Ssam 	hashtab[h] = s->next_sym;
32216620Ssam     } else {
32316620Ssam 	while (t->next_sym != s) {
32416620Ssam 	    t = t->next_sym;
32516620Ssam 	    if (t == nil) {
32616620Ssam 		panic("delete of non-symbol '%s'", symname(s));
32716620Ssam 	    }
32816620Ssam 	}
32916620Ssam 	t->next_sym = s->next_sym;
33016620Ssam     }
33116620Ssam }
33216620Ssam 
33316620Ssam /*
3349657Slinton  * Dump out all the variables associated with the given
33518235Slinton  * procedure, function, or program associated with the given stack frame.
3369657Slinton  *
3379657Slinton  * This is quite inefficient.  We traverse the entire symbol table
3389657Slinton  * each time we're called.  The assumption is that this routine
3399657Slinton  * won't be called frequently enough to merit improved performance.
3409657Slinton  */
3419657Slinton 
3429657Slinton public dumpvars(f, frame)
3439657Slinton Symbol f;
3449657Slinton Frame frame;
3459657Slinton {
3469657Slinton     register Integer i;
3479657Slinton     register Symbol s;
3489657Slinton 
3499657Slinton     for (i = 0; i < HASHTABLESIZE; i++) {
3509657Slinton 	for (s = hashtab[i]; s != nil; s = s->next_sym) {
3519657Slinton 	    if (container(s) == f) {
3529657Slinton 		if (should_print(s)) {
3539657Slinton 		    printv(s, frame);
3549657Slinton 		    putchar('\n');
3559657Slinton 		} else if (s->class == MODULE) {
3569657Slinton 		    dumpvars(s, frame);
3579657Slinton 		}
3589657Slinton 	    }
3599657Slinton 	}
3609657Slinton     }
3619657Slinton }
3629657Slinton 
3639657Slinton /*
3649657Slinton  * Create a builtin type.
3659657Slinton  * Builtin types are circular in that btype->type->type = btype.
3669657Slinton  */
3679657Slinton 
36818235Slinton private Symbol maketype(name, lower, upper)
3699657Slinton String name;
3709657Slinton long lower;
3719657Slinton long upper;
3729657Slinton {
3739657Slinton     register Symbol s;
37418235Slinton     Name n;
3759657Slinton 
37618235Slinton     if (name == nil) {
37718235Slinton 	n = nil;
37818235Slinton     } else {
37918235Slinton 	n = identname(name, true);
38018235Slinton     }
38118235Slinton     s = insert(n);
38216620Ssam     s->language = primlang;
38318235Slinton     s->level = 0;
38418235Slinton     s->class = TYPE;
38518235Slinton     s->type = nil;
38618235Slinton     s->chain = nil;
3879657Slinton     s->type = newSymbol(nil, 0, RANGE, s, nil);
3889657Slinton     s->type->symvalue.rangev.lower = lower;
3899657Slinton     s->type->symvalue.rangev.upper = upper;
3909657Slinton     return s;
3919657Slinton }
3929657Slinton 
3939657Slinton /*
39418235Slinton  * Create the builtin symbols.
39518235Slinton  */
39618235Slinton 
39718235Slinton public symbols_init ()
3989657Slinton {
39918235Slinton     Symbol s;
4009657Slinton 
40118235Slinton     t_boolean = maketype("$boolean", 0L, 1L);
40218235Slinton     t_int = maketype("$integer", 0x80000000L, 0x7fffffffL);
40318235Slinton     t_char = maketype("$char", 0L, 255L);
40418235Slinton     t_real = maketype("$real", 8L, 0L);
40518235Slinton     t_nil = maketype("$nil", 0L, 0L);
40618235Slinton     t_addr = insert(identname("$address", true));
40718235Slinton     t_addr->language = primlang;
40818235Slinton     t_addr->level = 0;
40918235Slinton     t_addr->class = TYPE;
41018235Slinton     t_addr->type = newSymbol(nil, 1, PTR, t_int, nil);
41118235Slinton     s = insert(identname("true", true));
41218235Slinton     s->class = CONST;
41318235Slinton     s->type = t_boolean;
41418235Slinton     s->symvalue.constval = build(O_LCON, 1L);
41518235Slinton     s->symvalue.constval->nodetype = t_boolean;
41618235Slinton     s = insert(identname("false", true));
41718235Slinton     s->class = CONST;
41818235Slinton     s->type = t_boolean;
41918235Slinton     s->symvalue.constval = build(O_LCON, 0L);
42018235Slinton     s->symvalue.constval->nodetype = t_boolean;
4219657Slinton }
4229657Slinton 
4239657Slinton /*
4249657Slinton  * Reduce type to avoid worrying about type names.
4259657Slinton  */
4269657Slinton 
4279657Slinton public Symbol rtype(type)
4289657Slinton Symbol type;
4299657Slinton {
4309657Slinton     register Symbol t;
4319657Slinton 
4329657Slinton     t = type;
4339657Slinton     if (t != nil) {
43418235Slinton 	if (t->class == VAR or t->class == CONST or
43518235Slinton 	    t->class == FIELD or t->class == REF
43618235Slinton 	) {
4379657Slinton 	    t = t->type;
4389657Slinton 	}
43916620Ssam 	if (t->class == TYPEREF) {
44016620Ssam 	    resolveRef(t);
44116620Ssam 	}
4429657Slinton 	while (t->class == TYPE or t->class == TAG) {
4439657Slinton 	    t = t->type;
44416620Ssam 	    if (t->class == TYPEREF) {
44516620Ssam 		resolveRef(t);
44616620Ssam 	    }
4479657Slinton 	}
4489657Slinton     }
4499657Slinton     return t;
4509657Slinton }
4519657Slinton 
45216620Ssam /*
45316620Ssam  * Find the end of a module name.  Return nil if there is none
45416620Ssam  * in the given string.
45516620Ssam  */
45616620Ssam 
45716620Ssam private String findModuleMark (s)
45816620Ssam String s;
45916620Ssam {
46016620Ssam     register char *p, *r;
46116620Ssam     register boolean done;
46216620Ssam 
46316620Ssam     p = s;
46416620Ssam     done = false;
46516620Ssam     do {
46616620Ssam 	if (*p == ':') {
46716620Ssam 	    done = true;
46816620Ssam 	    r = p;
46916620Ssam 	} else if (*p == '\0') {
47016620Ssam 	    done = true;
47116620Ssam 	    r = nil;
47216620Ssam 	} else {
47316620Ssam 	    ++p;
47416620Ssam 	}
47516620Ssam     } while (not done);
47616620Ssam     return r;
47716620Ssam }
47816620Ssam 
47916620Ssam /*
48016620Ssam  * Resolve a type reference by modifying to be the appropriate type.
48116620Ssam  *
48216620Ssam  * If the reference has a name, then it refers to an opaque type and
48316620Ssam  * the actual type is directly accessible.  Otherwise, we must use
48416620Ssam  * the type reference string, which is of the form "module:{module:}name".
48516620Ssam  */
48616620Ssam 
48716620Ssam public resolveRef (t)
48816620Ssam Symbol t;
48916620Ssam {
49016620Ssam     register char *p;
49116620Ssam     char *start;
49216620Ssam     Symbol s, m, outer;
49316620Ssam     Name n;
49416620Ssam 
49516620Ssam     if (t->name != nil) {
49616620Ssam 	s = t;
49716620Ssam     } else {
49816620Ssam 	start = t->symvalue.typeref;
49916620Ssam 	outer = program;
50016620Ssam 	p = findModuleMark(start);
50116620Ssam 	while (p != nil) {
50216620Ssam 	    *p = '\0';
50316620Ssam 	    n = identname(start, true);
50416620Ssam 	    find(m, n) where m->block == outer endfind(m);
50516620Ssam 	    if (m == nil) {
50616620Ssam 		p = nil;
50716620Ssam 		outer = nil;
50816620Ssam 		s = nil;
50916620Ssam 	    } else {
51016620Ssam 		outer = m;
51116620Ssam 		start = p + 1;
51216620Ssam 		p = findModuleMark(start);
51316620Ssam 	    }
51416620Ssam 	}
51516620Ssam 	if (outer != nil) {
51616620Ssam 	    n = identname(start, true);
51716620Ssam 	    find(s, n) where s->block == outer endfind(s);
51816620Ssam 	}
51916620Ssam     }
52016620Ssam     if (s != nil and s->type != nil) {
52116620Ssam 	t->name = s->type->name;
52216620Ssam 	t->class = s->type->class;
52316620Ssam 	t->type = s->type->type;
52416620Ssam 	t->chain = s->type->chain;
52516620Ssam 	t->symvalue = s->type->symvalue;
52616620Ssam 	t->block = s->type->block;
52716620Ssam     }
52816620Ssam }
52916620Ssam 
53018235Slinton public integer regnum (s)
5319657Slinton Symbol s;
5329657Slinton {
53318235Slinton     integer r;
53418235Slinton 
5359657Slinton     checkref(s);
53633337Sdonn     if (s->storage == INREG) {
53718235Slinton 	r = s->symvalue.offset;
53818235Slinton     } else {
53918235Slinton 	r = -1;
54018235Slinton     }
54118235Slinton     return r;
5429657Slinton }
5439657Slinton 
5449657Slinton public Symbol container(s)
5459657Slinton Symbol s;
5469657Slinton {
5479657Slinton     checkref(s);
5489657Slinton     return s->block;
5499657Slinton }
5509657Slinton 
55118235Slinton public Node constval(s)
55218235Slinton Symbol s;
55318235Slinton {
55418235Slinton     checkref(s);
55518235Slinton     if (s->class != CONST) {
55618235Slinton 	error("[internal error: constval(non-CONST)]");
55718235Slinton     }
55818235Slinton     return s->symvalue.constval;
55918235Slinton }
56018235Slinton 
5619657Slinton /*
5629657Slinton  * Return the object address of the given symbol.
5639657Slinton  *
5649657Slinton  * There are the following possibilities:
5659657Slinton  *
5669657Slinton  *	globals		- just take offset
5679657Slinton  *	locals		- take offset from locals base
5689657Slinton  *	arguments	- take offset from argument base
5699657Slinton  *	register	- offset is register number
5709657Slinton  */
5719657Slinton 
57233337Sdonn #define isglobal(s)		(s->storage == EXT)
57333337Sdonn #define islocaloff(s)		(s->storage == STK and s->symvalue.offset < 0)
57433337Sdonn #define isparamoff(s)		(s->storage == STK and s->symvalue.offset >= 0)
5759657Slinton 
57618235Slinton public Address address (s, frame)
5779657Slinton Symbol s;
5789657Slinton Frame frame;
5799657Slinton {
5809657Slinton     register Frame frp;
5819657Slinton     register Address addr;
5829657Slinton     register Symbol cur;
5839657Slinton 
5849657Slinton     checkref(s);
5859657Slinton     if (not isactive(s->block)) {
5869657Slinton 	error("\"%s\" is not currently defined", symname(s));
5879657Slinton     } else if (isglobal(s)) {
5889657Slinton 	addr = s->symvalue.offset;
5899657Slinton     } else {
5909657Slinton 	frp = frame;
5919657Slinton 	if (frp == nil) {
5929657Slinton 	    cur = s->block;
5939657Slinton 	    while (cur != nil and cur->class == MODULE) {
5949657Slinton 		cur = cur->block;
5959657Slinton 	    }
5969657Slinton 	    if (cur == nil) {
59718235Slinton 		frp = nil;
59818235Slinton 	    } else {
59918235Slinton 		frp = findframe(cur);
60018235Slinton 		if (frp == nil) {
60118235Slinton 		    error("[internal error: unexpected nil frame for \"%s\"]",
60218235Slinton 			symname(s)
60318235Slinton 		    );
60418235Slinton 		}
6059657Slinton 	    }
6069657Slinton 	}
6079657Slinton 	if (islocaloff(s)) {
6089657Slinton 	    addr = locals_base(frp) + s->symvalue.offset;
6099657Slinton 	} else if (isparamoff(s)) {
6109657Slinton 	    addr = args_base(frp) + s->symvalue.offset;
6119657Slinton 	} else if (isreg(s)) {
6129657Slinton 	    addr = savereg(s->symvalue.offset, frp);
6139657Slinton 	} else {
6149657Slinton 	    panic("address: bad symbol \"%s\"", symname(s));
6159657Slinton 	}
6169657Slinton     }
6179657Slinton     return addr;
6189657Slinton }
6199657Slinton 
6209657Slinton /*
6219657Slinton  * Define a symbol used to access register values.
6229657Slinton  */
6239657Slinton 
62418235Slinton public defregname (n, r)
6259657Slinton Name n;
62618235Slinton integer r;
6279657Slinton {
62818235Slinton     Symbol s;
6299657Slinton 
6309657Slinton     s = insert(n);
63118235Slinton     s->language = t_addr->language;
6329657Slinton     s->class = VAR;
63333337Sdonn     s->storage = INREG;
63433337Sdonn     s->level = 3;
63518235Slinton     s->type = t_addr;
6369657Slinton     s->symvalue.offset = r;
6379657Slinton }
6389657Slinton 
6399657Slinton /*
6409657Slinton  * Resolve an "abstract" type reference.
6419657Slinton  *
6429657Slinton  * It is possible in C to define a pointer to a type, but never define
6439657Slinton  * the type in a particular source file.  Here we try to resolve
6449657Slinton  * the type definition.  This is problematic, it is possible to
6459657Slinton  * have multiple, different definitions for the same name type.
6469657Slinton  */
6479657Slinton 
6489657Slinton public findtype(s)
6499657Slinton Symbol s;
6509657Slinton {
6519657Slinton     register Symbol t, u, prev;
6529657Slinton 
6539657Slinton     u = s;
6549657Slinton     prev = nil;
6559657Slinton     while (u != nil and u->class != BADUSE) {
6569657Slinton 	if (u->name != nil) {
6579657Slinton 	    prev = u;
6589657Slinton 	}
6599657Slinton 	u = u->type;
6609657Slinton     }
6619657Slinton     if (prev == nil) {
6629657Slinton 	error("couldn't find link to type reference");
6639657Slinton     }
66418235Slinton     t = lookup(prev->name);
66518235Slinton     while (t != nil and
66618235Slinton 	not (
66718235Slinton 	    t != prev and t->name == prev->name and
66818235Slinton 	    t->block->class == MODULE and t->class == prev->class and
66918235Slinton 	    t->type != nil and t->type->type != nil and
67018235Slinton 	    t->type->type->class != BADUSE
67118235Slinton 	)
67218235Slinton     ) {
67318235Slinton 	t = t->next_sym;
67418235Slinton     }
6759657Slinton     if (t == nil) {
6769657Slinton 	error("couldn't resolve reference");
6779657Slinton     } else {
6789657Slinton 	prev->type = t->type;
6799657Slinton     }
6809657Slinton }
6819657Slinton 
6829657Slinton /*
6839657Slinton  * Find the size in bytes of the given type.
6849657Slinton  *
6859657Slinton  * This is probably the WRONG thing to do.  The size should be kept
6869657Slinton  * as an attribute in the symbol information as is done for structures
6879657Slinton  * and fields.  I haven't gotten around to cleaning this up yet.
6889657Slinton  */
6899657Slinton 
69012547Scsvaf #define MAXUCHAR 255
69112547Scsvaf #define MAXUSHORT 65535L
6929657Slinton #define MINCHAR -128
6939657Slinton #define MAXCHAR 127
6949657Slinton #define MINSHORT -32768
6959657Slinton #define MAXSHORT 32767
6969657Slinton 
69716620Ssam public findbounds (u, lower, upper)
69816620Ssam Symbol u;
69916620Ssam long *lower, *upper;
70016620Ssam {
70116620Ssam     Rangetype lbt, ubt;
70216620Ssam     long lb, ub;
70316620Ssam 
70416620Ssam     if (u->class == RANGE) {
70516620Ssam 	lbt = u->symvalue.rangev.lowertype;
70616620Ssam 	ubt = u->symvalue.rangev.uppertype;
70716620Ssam 	lb = u->symvalue.rangev.lower;
70816620Ssam 	ub = u->symvalue.rangev.upper;
70916620Ssam 	if (lbt == R_ARG or lbt == R_TEMP) {
71016620Ssam 	    if (not getbound(u, lb, lbt, lower)) {
71116620Ssam 		error("dynamic bounds not currently available");
71216620Ssam 	    }
71316620Ssam 	} else {
71416620Ssam 	    *lower = lb;
71516620Ssam 	}
71616620Ssam 	if (ubt == R_ARG or ubt == R_TEMP) {
71716620Ssam 	    if (not getbound(u, ub, ubt, upper)) {
71816620Ssam 		error("dynamic bounds not currently available");
71916620Ssam 	    }
72016620Ssam 	} else {
72116620Ssam 	    *upper = ub;
72216620Ssam 	}
72316620Ssam     } else if (u->class == SCAL) {
72416620Ssam 	*lower = 0;
72516620Ssam 	*upper = u->symvalue.iconval - 1;
72616620Ssam     } else {
72718235Slinton 	error("[internal error: unexpected array bound type]");
72816620Ssam     }
72916620Ssam }
73016620Ssam 
73116620Ssam public integer size(sym)
73216620Ssam Symbol sym;
73316620Ssam {
73416620Ssam     register Symbol s, t, u;
73516620Ssam     register integer nel, elsize;
7369657Slinton     long lower, upper;
73716620Ssam     integer r, off, len;
7389657Slinton 
7399657Slinton     t = sym;
7409657Slinton     checkref(t);
74116620Ssam     if (t->class == TYPEREF) {
74216620Ssam 	resolveRef(t);
74316620Ssam     }
7449657Slinton     switch (t->class) {
7459657Slinton 	case RANGE:
7469657Slinton 	    lower = t->symvalue.rangev.lower;
7479657Slinton 	    upper = t->symvalue.rangev.upper;
74816620Ssam 	    if (upper == 0 and lower > 0) {
74916620Ssam 		/* real */
7509657Slinton 		r = lower;
75116620Ssam 	    } else if (lower > upper) {
75216620Ssam 		/* unsigned long */
75316620Ssam 		r = sizeof(long);
75412045Slinton 	    } else if (
75512547Scsvaf   		(lower >= MINCHAR and upper <= MAXCHAR) or
75612547Scsvaf   		(lower >= 0 and upper <= MAXUCHAR)
75712547Scsvaf   	      ) {
7589657Slinton 		r = sizeof(char);
75912547Scsvaf   	    } else if (
76012547Scsvaf   		(lower >= MINSHORT and upper <= MAXSHORT) or
76112547Scsvaf   		(lower >= 0 and upper <= MAXUSHORT)
76212547Scsvaf   	      ) {
7639657Slinton 		r = sizeof(short);
7649657Slinton 	    } else {
7659657Slinton 		r = sizeof(long);
7669657Slinton 	    }
7679657Slinton 	    break;
7689657Slinton 
7699657Slinton 	case ARRAY:
7709657Slinton 	    elsize = size(t->type);
7719657Slinton 	    nel = 1;
7729657Slinton 	    for (t = t->chain; t != nil; t = t->chain) {
77316620Ssam 		u = rtype(t);
77416620Ssam 		findbounds(u, &lower, &upper);
7759657Slinton 		nel *= (upper-lower+1);
7769657Slinton 	    }
7779657Slinton 	    r = nel*elsize;
7789657Slinton 	    break;
7799657Slinton 
78033337Sdonn 	case OPENARRAY:
78118235Slinton 	case DYNARRAY:
78218235Slinton 	    r = (t->symvalue.ndims + 1) * sizeof(Word);
78318235Slinton 	    break;
78418235Slinton 
78518235Slinton 	case SUBARRAY:
78618235Slinton 	    r = (2 * t->symvalue.ndims + 1) * sizeof(Word);
78718235Slinton 	    break;
78818235Slinton 
78912547Scsvaf 	case REF:
7909657Slinton 	case VAR:
7919657Slinton 	    r = size(t->type);
79212127Slinton 	    /*
79312127Slinton 	     *
79412045Slinton 	    if (r < sizeof(Word) and isparam(t)) {
7959657Slinton 		r = sizeof(Word);
7969657Slinton 	    }
79712547Scsvaf 	    */
7989657Slinton 	    break;
7999657Slinton 
80018235Slinton 	case FVAR:
8019657Slinton 	case CONST:
80218235Slinton 	case TAG:
8039657Slinton 	    r = size(t->type);
8049657Slinton 	    break;
8059657Slinton 
8069657Slinton 	case TYPE:
80733337Sdonn 	    /*
80833337Sdonn 	     * This causes problems on the IRIS because of the compiler bug
80933337Sdonn 	     * with stab offsets for parameters.  Not sure it's really
81033337Sdonn 	     * necessary anyway.
81133337Sdonn 	     */
81233337Sdonn #	    ifndef IRIS
8139657Slinton 	    if (t->type->class == PTR and t->type->type->class == BADUSE) {
8149657Slinton 		findtype(t);
8159657Slinton 	    }
81633337Sdonn #	    endif
8179657Slinton 	    r = size(t->type);
8189657Slinton 	    break;
8199657Slinton 
8209657Slinton 	case FIELD:
82116620Ssam 	    off = t->symvalue.field.offset;
82216620Ssam 	    len = t->symvalue.field.length;
82316620Ssam 	    r = (off + len + 7) div 8 - (off div 8);
8249657Slinton 	    break;
8259657Slinton 
8269657Slinton 	case RECORD:
8279657Slinton 	case VARNT:
8289657Slinton 	    r = t->symvalue.offset;
8299657Slinton 	    if (r == 0 and t->chain != nil) {
8309657Slinton 		panic("missing size information for record");
8319657Slinton 	    }
8329657Slinton 	    break;
8339657Slinton 
8349657Slinton 	case PTR:
83518235Slinton 	case TYPEREF:
8369657Slinton 	case FILET:
8379657Slinton 	    r = sizeof(Word);
8389657Slinton 	    break;
8399657Slinton 
8409657Slinton 	case SCAL:
84112609Slinton 	    r = sizeof(Word);
84212609Slinton 	    /*
84312609Slinton 	     *
8449657Slinton 	    if (t->symvalue.iconval > 255) {
8459657Slinton 		r = sizeof(short);
8469657Slinton 	    } else {
8479657Slinton 		r = sizeof(char);
8489657Slinton 	    }
84912609Slinton 	     *
85012609Slinton 	     */
8519657Slinton 	    break;
8529657Slinton 
8539657Slinton 	case FPROC:
8549657Slinton 	case FFUNC:
8559657Slinton 	    r = sizeof(Word);
8569657Slinton 	    break;
8579657Slinton 
8589657Slinton 	case PROC:
8599657Slinton 	case FUNC:
8609657Slinton 	case MODULE:
8619657Slinton 	case PROG:
8629657Slinton 	    r = sizeof(Symbol);
8639657Slinton 	    break;
8649657Slinton 
86516620Ssam 	case SET:
86616620Ssam 	    u = rtype(t->type);
86716620Ssam 	    switch (u->class) {
86816620Ssam 		case RANGE:
86916620Ssam 		    r = u->symvalue.rangev.upper - u->symvalue.rangev.lower + 1;
87016620Ssam 		    break;
87116620Ssam 
87216620Ssam 		case SCAL:
87316620Ssam 		    r = u->symvalue.iconval;
87416620Ssam 		    break;
87516620Ssam 
87616620Ssam 		default:
87716620Ssam 		    error("expected range for set base type");
87816620Ssam 		    break;
87916620Ssam 	    }
88016620Ssam 	    r = (r + BITSPERBYTE - 1) div BITSPERBYTE;
88116620Ssam 	    break;
88216620Ssam 
88318235Slinton 	/*
88418235Slinton 	 * These can happen in C (unfortunately) for unresolved type references
88518235Slinton 	 * Assume they are pointers.
88618235Slinton 	 */
88718235Slinton 	case BADUSE:
88818235Slinton 	    r = sizeof(Address);
88918235Slinton 	    break;
89018235Slinton 
8919657Slinton 	default:
8929657Slinton 	    if (ord(t->class) > ord(TYPEREF)) {
8939657Slinton 		panic("size: bad class (%d)", ord(t->class));
8949657Slinton 	    } else {
89518235Slinton 		fprintf(stderr, "can't compute size of a %s\n", classname(t));
8969657Slinton 	    }
89716620Ssam 	    r = 0;
89816620Ssam 	    break;
8999657Slinton     }
9009657Slinton     return r;
9019657Slinton }
9029657Slinton 
9039657Slinton /*
90418235Slinton  * Return the size associated with a symbol that takes into account
90518235Slinton  * reference parameters.  This might be better as the normal size function, but
90618235Slinton  * too many places already depend on it working the way it does.
90718235Slinton  */
90818235Slinton 
90918235Slinton public integer psize (s)
91018235Slinton Symbol s;
91118235Slinton {
91218235Slinton     integer r;
91318235Slinton     Symbol t;
91418235Slinton 
91518235Slinton     if (s->class == REF) {
91618235Slinton 	t = rtype(s->type);
91733337Sdonn 	if (t->class == OPENARRAY) {
91818235Slinton 	    r = (t->symvalue.ndims + 1) * sizeof(Word);
91918235Slinton 	} else if (t->class == SUBARRAY) {
92018235Slinton 	    r = (2 * t->symvalue.ndims + 1) * sizeof(Word);
92118235Slinton 	} else {
92218235Slinton 	    r = sizeof(Word);
92318235Slinton 	}
92418235Slinton     } else {
92518235Slinton 	r = size(s);
92618235Slinton     }
92718235Slinton     return r;
92818235Slinton }
92918235Slinton 
93018235Slinton /*
9319657Slinton  * Test if a symbol is a parameter.  This is true if there
9329657Slinton  * is a cycle from s->block to s via chain pointers.
9339657Slinton  */
9349657Slinton 
9359657Slinton public Boolean isparam(s)
9369657Slinton Symbol s;
9379657Slinton {
9389657Slinton     register Symbol t;
9399657Slinton 
9409657Slinton     t = s->block;
9419657Slinton     while (t != nil and t != s) {
9429657Slinton 	t = t->chain;
9439657Slinton     }
9449657Slinton     return (Boolean) (t != nil);
9459657Slinton }
9469657Slinton 
9479657Slinton /*
94816620Ssam  * Test if a type is an open array parameter type.
9499657Slinton  */
9509657Slinton 
95118235Slinton public boolean isopenarray (type)
95218235Slinton Symbol type;
95316620Ssam {
95418235Slinton     Symbol t;
95518235Slinton 
95618235Slinton     t = rtype(type);
95733337Sdonn     return (boolean) (t->class == OPENARRAY);
95816620Ssam }
95916620Ssam 
96016620Ssam /*
96118235Slinton  * Test if a symbol is a var parameter, i.e. has class REF.
96216620Ssam  */
96316620Ssam 
9649657Slinton public Boolean isvarparam(s)
9659657Slinton Symbol s;
9669657Slinton {
9679657Slinton     return (Boolean) (s->class == REF);
9689657Slinton }
9699657Slinton 
9709657Slinton /*
9719657Slinton  * Test if a symbol is a variable (actually any addressible quantity
9729657Slinton  * with do).
9739657Slinton  */
9749657Slinton 
9759657Slinton public Boolean isvariable(s)
97618235Slinton Symbol s;
9779657Slinton {
9789657Slinton     return (Boolean) (s->class == VAR or s->class == FVAR or s->class == REF);
9799657Slinton }
9809657Slinton 
9819657Slinton /*
98218235Slinton  * Test if a symbol is a constant.
98318235Slinton  */
98418235Slinton 
98518235Slinton public Boolean isconst(s)
98618235Slinton Symbol s;
9879657Slinton {
98818235Slinton     return (Boolean) (s->class == CONST);
9899657Slinton }
9909657Slinton 
9919657Slinton /*
9929657Slinton  * Test if a symbol is a module.
9939657Slinton  */
9949657Slinton 
9959657Slinton public Boolean ismodule(s)
9969657Slinton register Symbol s;
9979657Slinton {
9989657Slinton     return (Boolean) (s->class == MODULE);
9999657Slinton }
10009657Slinton 
10019657Slinton /*
100216620Ssam  * Mark a procedure or function as internal, meaning that it is called
100316620Ssam  * with a different calling sequence.
100416620Ssam  */
100516620Ssam 
100616620Ssam public markInternal (s)
100716620Ssam Symbol s;
100816620Ssam {
100916620Ssam     s->symvalue.funcv.intern = true;
101016620Ssam }
101116620Ssam 
101216620Ssam public boolean isinternal (s)
101316620Ssam Symbol s;
101416620Ssam {
101516620Ssam     return s->symvalue.funcv.intern;
101616620Ssam }
101716620Ssam 
101816620Ssam /*
101918235Slinton  * Decide if a field begins or ends on a bit rather than byte boundary.
102018235Slinton  */
102118235Slinton 
102218235Slinton public Boolean isbitfield(s)
102318235Slinton register Symbol s;
102418235Slinton {
102518235Slinton     boolean b;
102618235Slinton     register integer off, len;
102718235Slinton     register Symbol t;
102818235Slinton 
102918235Slinton     off = s->symvalue.field.offset;
103018235Slinton     len = s->symvalue.field.length;
103118235Slinton     if ((off mod BITSPERBYTE) != 0 or (len mod BITSPERBYTE) != 0) {
103218235Slinton 	b = true;
103318235Slinton     } else {
103418235Slinton 	t = rtype(s->type);
103518235Slinton 	b = (Boolean) (
103618235Slinton 	    (t->class == SCAL and len != (sizeof(int)*BITSPERBYTE)) or
103718235Slinton 	    len != (size(t)*BITSPERBYTE)
103818235Slinton 	);
103918235Slinton     }
104018235Slinton     return b;
104118235Slinton }
104218235Slinton 
104318235Slinton private boolean primlang_typematch (t1, t2)
104418235Slinton Symbol t1, t2;
104518235Slinton {
104618235Slinton     return (boolean) (
104718235Slinton 	(t1 == t2) or
104818235Slinton 	(
104918235Slinton 	    t1->class == RANGE and t2->class == RANGE and
105018235Slinton 	    t1->symvalue.rangev.lower == t2->symvalue.rangev.lower and
105118235Slinton 	    t1->symvalue.rangev.upper == t2->symvalue.rangev.upper
105218235Slinton 	) or (
105318235Slinton 	    t1->class == PTR and t2->class == RANGE and
105418235Slinton 	    t2->symvalue.rangev.upper >= t2->symvalue.rangev.lower
105518235Slinton 	) or (
105618235Slinton 	    t2->class == PTR and t1->class == RANGE and
105718235Slinton 	    t1->symvalue.rangev.upper >= t1->symvalue.rangev.lower
105818235Slinton 	)
105918235Slinton     );
106018235Slinton }
106118235Slinton 
106218235Slinton /*
10639657Slinton  * Test if two types match.
10649657Slinton  * Equivalent names implies a match in any language.
10659657Slinton  *
10669657Slinton  * Special symbols must be handled with care.
10679657Slinton  */
10689657Slinton 
10699657Slinton public Boolean compatible(t1, t2)
10709657Slinton register Symbol t1, t2;
10719657Slinton {
10729657Slinton     Boolean b;
107316620Ssam     Symbol rt1, rt2;
10749657Slinton 
10759657Slinton     if (t1 == t2) {
10769657Slinton 	b = true;
10779657Slinton     } else if (t1 == nil or t2 == nil) {
10789657Slinton 	b = false;
10799657Slinton     } else if (t1 == procsym) {
10809657Slinton 	b = isblock(t2);
10819657Slinton     } else if (t2 == procsym) {
10829657Slinton 	b = isblock(t1);
10839657Slinton     } else if (t1->language == nil) {
108416620Ssam 	if (t2->language == nil) {
108516620Ssam 	    b = false;
108633337Sdonn 	} else if (t2->language == primlang) {
108733337Sdonn 	    b = (boolean) primlang_typematch(rtype(t1), rtype(t2));
108816620Ssam 	} else {
108916620Ssam 	    b = (boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2);
109016620Ssam 	}
109133337Sdonn     } else if (t1->language == primlang) {
109233337Sdonn 	if (t2->language == primlang or t2->language == nil) {
109333337Sdonn 	    b = primlang_typematch(rtype(t1), rtype(t2));
109433337Sdonn 	} else {
109533337Sdonn 	    b = (boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2);
109633337Sdonn 	}
10979657Slinton     } else {
109816620Ssam 	b = (boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2);
10999657Slinton     }
11009657Slinton     return b;
11019657Slinton }
11029657Slinton 
11039657Slinton /*
11049657Slinton  * Check for a type of the given name.
11059657Slinton  */
11069657Slinton 
11079657Slinton public Boolean istypename(type, name)
11089657Slinton Symbol type;
11099657Slinton String name;
11109657Slinton {
111118235Slinton     register Symbol t;
11129657Slinton     Boolean b;
11139657Slinton 
11149657Slinton     t = type;
111518235Slinton     if (t == nil) {
111618235Slinton 	b = false;
111718235Slinton     } else {
111818235Slinton 	b = (Boolean) (
111918235Slinton 	    t->class == TYPE and streq(ident(t->name), name)
112018235Slinton 	);
112118235Slinton     }
11229657Slinton     return b;
11239657Slinton }
11249657Slinton 
11259657Slinton /*
112616620Ssam  * Determine if a (value) parameter should actually be passed by address.
112716620Ssam  */
112816620Ssam 
112916620Ssam public boolean passaddr (p, exprtype)
113016620Ssam Symbol p, exprtype;
113116620Ssam {
113216620Ssam     boolean b;
113316620Ssam     Language def;
113416620Ssam 
113516620Ssam     if (p == nil) {
113616620Ssam 	def = findlanguage(".c");
113716620Ssam 	b = (boolean) (*language_op(def, L_PASSADDR))(p, exprtype);
113816620Ssam     } else if (p->language == nil or p->language == primlang) {
113916620Ssam 	b = false;
114016620Ssam     } else if (isopenarray(p->type)) {
114116620Ssam 	b = true;
114216620Ssam     } else {
114316620Ssam 	b = (boolean) (*language_op(p->language, L_PASSADDR))(p, exprtype);
114416620Ssam     }
114516620Ssam     return b;
114616620Ssam }
114716620Ssam 
114816620Ssam /*
11499657Slinton  * Test if the name of a symbol is uniquely defined or not.
11509657Slinton  */
11519657Slinton 
11529657Slinton public Boolean isambiguous(s)
11539657Slinton register Symbol s;
11549657Slinton {
11559657Slinton     register Symbol t;
11569657Slinton 
11579657Slinton     find(t, s->name) where t != s endfind(t);
11589657Slinton     return (Boolean) (t != nil);
11599657Slinton }
11609657Slinton 
11619657Slinton typedef char *Arglist;
11629657Slinton 
11639657Slinton #define nextarg(type)  ((type *) (ap += sizeof(type)))[-1]
11649657Slinton 
11659657Slinton private Symbol mkstring();
11669657Slinton 
11679657Slinton /*
11689657Slinton  * Determine the type of a parse tree.
116918235Slinton  *
11709657Slinton  * Also make some symbol-dependent changes to the tree such as
117118235Slinton  * removing indirection for constant or register symbols.
11729657Slinton  */
11739657Slinton 
117418235Slinton public assigntypes (p)
11759657Slinton register Node p;
11769657Slinton {
11779657Slinton     register Node p1;
11789657Slinton     register Symbol s;
11799657Slinton 
11809657Slinton     switch (p->op) {
11819657Slinton 	case O_SYM:
118218235Slinton 	    p->nodetype = p->value.sym;
11839657Slinton 	    break;
11849657Slinton 
11859657Slinton 	case O_LCON:
11869657Slinton 	    p->nodetype = t_int;
11879657Slinton 	    break;
11889657Slinton 
118918235Slinton 	case O_CCON:
119018235Slinton 	    p->nodetype = t_char;
119118235Slinton 	    break;
119218235Slinton 
11939657Slinton 	case O_FCON:
11949657Slinton 	    p->nodetype = t_real;
11959657Slinton 	    break;
11969657Slinton 
11979657Slinton 	case O_SCON:
119818235Slinton 	    p->nodetype = mkstring(p->value.scon);
11999657Slinton 	    break;
12009657Slinton 
12019657Slinton 	case O_INDIR:
12029657Slinton 	    p1 = p->value.arg[0];
120318235Slinton 	    s = rtype(p1->nodetype);
120418235Slinton 	    if (s->class != PTR) {
120518235Slinton 		beginerrmsg();
120618235Slinton 		fprintf(stderr, "\"");
120718235Slinton 		prtree(stderr, p1);
120818235Slinton 		fprintf(stderr, "\" is not a pointer");
120918235Slinton 		enderrmsg();
121018235Slinton 	    }
12119657Slinton 	    p->nodetype = rtype(p1->nodetype)->type;
12129657Slinton 	    break;
12139657Slinton 
12149657Slinton 	case O_DOT:
12159657Slinton 	    p->nodetype = p->value.arg[1]->value.sym;
12169657Slinton 	    break;
12179657Slinton 
12189657Slinton 	case O_RVAL:
12199657Slinton 	    p1 = p->value.arg[0];
12209657Slinton 	    p->nodetype = p1->nodetype;
12219657Slinton 	    if (p1->op == O_SYM) {
122218235Slinton 		if (p1->nodetype->class == PROC or p->nodetype->class == FUNC) {
122318235Slinton 		    p->op = p1->op;
122418235Slinton 		    p->value.sym = p1->value.sym;
122518235Slinton 		    p->nodetype = p1->nodetype;
122618235Slinton 		    dispose(p1);
12279657Slinton 		} else if (p1->value.sym->class == CONST) {
122818235Slinton 		    p->op = p1->op;
122918235Slinton 		    p->value = p1->value;
123018235Slinton 		    p->nodetype = p1->nodetype;
123118235Slinton 		    dispose(p1);
12329657Slinton 		} else if (isreg(p1->value.sym)) {
12339657Slinton 		    p->op = O_SYM;
12349657Slinton 		    p->value.sym = p1->value.sym;
12359657Slinton 		    dispose(p1);
12369657Slinton 		}
12379657Slinton 	    } else if (p1->op == O_INDIR and p1->value.arg[0]->op == O_SYM) {
12389657Slinton 		s = p1->value.arg[0]->value.sym;
12399657Slinton 		if (isreg(s)) {
12409657Slinton 		    p1->op = O_SYM;
12419657Slinton 		    dispose(p1->value.arg[0]);
12429657Slinton 		    p1->value.sym = s;
12439657Slinton 		    p1->nodetype = s;
12449657Slinton 		}
12459657Slinton 	    }
12469657Slinton 	    break;
12479657Slinton 
124818235Slinton 	case O_COMMA:
124918235Slinton 	    p->nodetype = p->value.arg[0]->nodetype;
125018235Slinton 	    break;
125118235Slinton 
125218235Slinton 	case O_CALLPROC:
12539657Slinton 	case O_CALL:
12549657Slinton 	    p1 = p->value.arg[0];
125511171Slinton 	    p->nodetype = rtype(p1->nodetype)->type;
12569657Slinton 	    break;
12579657Slinton 
125811171Slinton 	case O_TYPERENAME:
125911171Slinton 	    p->nodetype = p->value.arg[1]->nodetype;
126011171Slinton 	    break;
126111171Slinton 
12629657Slinton 	case O_ITOF:
12639657Slinton 	    p->nodetype = t_real;
12649657Slinton 	    break;
12659657Slinton 
12669657Slinton 	case O_NEG:
12679657Slinton 	    s = p->value.arg[0]->nodetype;
12689657Slinton 	    if (not compatible(s, t_int)) {
12699657Slinton 		if (not compatible(s, t_real)) {
12709657Slinton 		    beginerrmsg();
127116620Ssam 		    fprintf(stderr, "\"");
12729657Slinton 		    prtree(stderr, p->value.arg[0]);
127316620Ssam 		    fprintf(stderr, "\" is improper type");
12749657Slinton 		    enderrmsg();
12759657Slinton 		} else {
12769657Slinton 		    p->op = O_NEGF;
12779657Slinton 		}
12789657Slinton 	    }
12799657Slinton 	    p->nodetype = s;
12809657Slinton 	    break;
12819657Slinton 
12829657Slinton 	case O_ADD:
12839657Slinton 	case O_SUB:
12849657Slinton 	case O_MUL:
128516620Ssam 	    binaryop(p, nil);
128616620Ssam 	    break;
128716620Ssam 
12889657Slinton 	case O_LT:
12899657Slinton 	case O_LE:
12909657Slinton 	case O_GT:
12919657Slinton 	case O_GE:
12929657Slinton 	case O_EQ:
12939657Slinton 	case O_NE:
129416620Ssam 	    binaryop(p, t_boolean);
12959657Slinton 	    break;
12969657Slinton 
12979657Slinton 	case O_DIVF:
12989657Slinton 	    convert(&(p->value.arg[0]), t_real, O_ITOF);
12999657Slinton 	    convert(&(p->value.arg[1]), t_real, O_ITOF);
13009657Slinton 	    p->nodetype = t_real;
13019657Slinton 	    break;
13029657Slinton 
13039657Slinton 	case O_DIV:
13049657Slinton 	case O_MOD:
13059657Slinton 	    convert(&(p->value.arg[0]), t_int, O_NOP);
13069657Slinton 	    convert(&(p->value.arg[1]), t_int, O_NOP);
13079657Slinton 	    p->nodetype = t_int;
13089657Slinton 	    break;
13099657Slinton 
13109657Slinton 	case O_AND:
13119657Slinton 	case O_OR:
13129657Slinton 	    chkboolean(p->value.arg[0]);
13139657Slinton 	    chkboolean(p->value.arg[1]);
13149657Slinton 	    p->nodetype = t_boolean;
13159657Slinton 	    break;
13169657Slinton 
13179657Slinton 	case O_QLINE:
13189657Slinton 	    p->nodetype = t_int;
13199657Slinton 	    break;
13209657Slinton 
13219657Slinton 	default:
13229657Slinton 	    p->nodetype = nil;
13239657Slinton 	    break;
13249657Slinton     }
13259657Slinton }
13269657Slinton 
13279657Slinton /*
132816620Ssam  * Process a binary arithmetic or relational operator.
132916620Ssam  * Convert from integer to real if necessary.
133016620Ssam  */
133116620Ssam 
133216620Ssam private binaryop (p, t)
133316620Ssam Node p;
133416620Ssam Symbol t;
133516620Ssam {
133616620Ssam     Node p1, p2;
133716620Ssam     Boolean t1real, t2real;
133816620Ssam     Symbol t1, t2;
133916620Ssam 
134016620Ssam     p1 = p->value.arg[0];
134116620Ssam     p2 = p->value.arg[1];
134216620Ssam     t1 = rtype(p1->nodetype);
134316620Ssam     t2 = rtype(p2->nodetype);
134416620Ssam     t1real = compatible(t1, t_real);
134516620Ssam     t2real = compatible(t2, t_real);
134616620Ssam     if (t1real or t2real) {
134716620Ssam 	p->op = (Operator) (ord(p->op) + 1);
134816620Ssam 	if (not t1real) {
134916620Ssam 	    p->value.arg[0] = build(O_ITOF, p1);
135016620Ssam 	} else if (not t2real) {
135116620Ssam 	    p->value.arg[1] = build(O_ITOF, p2);
135216620Ssam 	}
135316620Ssam 	p->nodetype = t_real;
135416620Ssam     } else {
135516620Ssam 	if (size(p1->nodetype) > sizeof(integer)) {
135616620Ssam 	    beginerrmsg();
135716620Ssam 	    fprintf(stderr, "operation not defined on \"");
135816620Ssam 	    prtree(stderr, p1);
135916620Ssam 	    fprintf(stderr, "\"");
136016620Ssam 	    enderrmsg();
136116620Ssam 	} else if (size(p2->nodetype) > sizeof(integer)) {
136216620Ssam 	    beginerrmsg();
136316620Ssam 	    fprintf(stderr, "operation not defined on \"");
136416620Ssam 	    prtree(stderr, p2);
136516620Ssam 	    fprintf(stderr, "\"");
136616620Ssam 	    enderrmsg();
136716620Ssam 	}
136816620Ssam 	p->nodetype = t_int;
136916620Ssam     }
137016620Ssam     if (t != nil) {
137116620Ssam 	p->nodetype = t;
137216620Ssam     }
137316620Ssam }
137416620Ssam 
137516620Ssam /*
13769657Slinton  * Convert a tree to a type via a conversion operator;
13779657Slinton  * if this isn't possible generate an error.
13789657Slinton  */
13799657Slinton 
13809657Slinton private convert(tp, typeto, op)
13819657Slinton Node *tp;
13829657Slinton Symbol typeto;
13839657Slinton Operator op;
13849657Slinton {
138516620Ssam     Node tree;
138616620Ssam     Symbol s, t;
13879657Slinton 
138816620Ssam     tree = *tp;
13899657Slinton     s = rtype(tree->nodetype);
139016620Ssam     t = rtype(typeto);
139116620Ssam     if (compatible(t, t_real) and compatible(s, t_int)) {
139234257Sdonn 	/* we can convert int => floating but not the reverse */
13939657Slinton 	tree = build(op, tree);
139416620Ssam     } else if (not compatible(s, t)) {
13959657Slinton 	beginerrmsg();
139616620Ssam 	prtree(stderr, tree);
139734257Sdonn 	fprintf(stderr, ": illegal type in operation");
13989657Slinton 	enderrmsg();
13999657Slinton     }
140016620Ssam     *tp = tree;
14019657Slinton }
14029657Slinton 
14039657Slinton /*
14049657Slinton  * Construct a node for the dot operator.
14059657Slinton  *
14069657Slinton  * If the left operand is not a record, but rather a procedure
14079657Slinton  * or function, then we interpret the "." as referencing an
14089657Slinton  * "invisible" variable; i.e. a variable within a dynamically
14099657Slinton  * active block but not within the static scope of the current procedure.
14109657Slinton  */
14119657Slinton 
14129657Slinton public Node dot(record, fieldname)
14139657Slinton Node record;
14149657Slinton Name fieldname;
14159657Slinton {
141618235Slinton     register Node rec, p;
14179657Slinton     register Symbol s, t;
14189657Slinton 
141918235Slinton     rec = record;
142018235Slinton     if (isblock(rec->nodetype)) {
14219657Slinton 	find(s, fieldname) where
142218235Slinton 	    s->block == rec->nodetype and
142318235Slinton 	    s->class != FIELD
14249657Slinton 	endfind(s);
14259657Slinton 	if (s == nil) {
14269657Slinton 	    beginerrmsg();
14279657Slinton 	    fprintf(stderr, "\"%s\" is not defined in ", ident(fieldname));
142818235Slinton 	    printname(stderr, rec->nodetype);
14299657Slinton 	    enderrmsg();
14309657Slinton 	}
14319657Slinton 	p = new(Node);
14329657Slinton 	p->op = O_SYM;
14339657Slinton 	p->value.sym = s;
143418235Slinton 	p->nodetype = s;
14359657Slinton     } else {
143618235Slinton 	p = rec;
14379657Slinton 	t = rtype(p->nodetype);
14389657Slinton 	if (t->class == PTR) {
14399657Slinton 	    s = findfield(fieldname, t->type);
14409657Slinton 	} else {
14419657Slinton 	    s = findfield(fieldname, t);
14429657Slinton 	}
14439657Slinton 	if (s == nil) {
14449657Slinton 	    beginerrmsg();
14459657Slinton 	    fprintf(stderr, "\"%s\" is not a field in ", ident(fieldname));
144618235Slinton 	    prtree(stderr, rec);
14479657Slinton 	    enderrmsg();
14489657Slinton 	}
144918235Slinton 	if (t->class != PTR or isreg(rec->nodetype)) {
145018235Slinton 	    p = unrval(p);
14519657Slinton 	}
145218235Slinton 	p->nodetype = t_addr;
14539657Slinton 	p = build(O_DOT, p, build(O_SYM, s));
14549657Slinton     }
145518235Slinton     return build(O_RVAL, p);
14569657Slinton }
14579657Slinton 
14589657Slinton /*
14599657Slinton  * Return a tree corresponding to an array reference and do the
14609657Slinton  * error checking.
14619657Slinton  */
14629657Slinton 
14639657Slinton public Node subscript(a, slist)
14649657Slinton Node a, slist;
14659657Slinton {
146616620Ssam     Symbol t;
146718235Slinton     Node p;
14689657Slinton 
146916620Ssam     t = rtype(a->nodetype);
147018235Slinton     if (t->language == nil or t->language == primlang) {
147118235Slinton 	p = (Node) (*language_op(findlanguage(".s"), L_BUILDAREF))(a, slist);
147216620Ssam     } else {
147318235Slinton 	p = (Node) (*language_op(t->language, L_BUILDAREF))(a, slist);
147416620Ssam     }
147518235Slinton     return build(O_RVAL, p);
14769657Slinton }
14779657Slinton 
14789657Slinton /*
14799657Slinton  * Evaluate a subscript index.
14809657Slinton  */
14819657Slinton 
148218235Slinton public int evalindex(s, base, i)
14839657Slinton Symbol s;
148418235Slinton Address base;
14859657Slinton long i;
14869657Slinton {
148716620Ssam     Symbol t;
148818235Slinton     int r;
14899657Slinton 
149016620Ssam     t = rtype(s);
149118235Slinton     if (t->language == nil or t->language == primlang) {
149218235Slinton 	r = ((*language_op(findlanguage(".s"), L_EVALAREF)) (s, base, i));
149316620Ssam     } else {
149418235Slinton 	r = ((*language_op(t->language, L_EVALAREF)) (s, base, i));
149516620Ssam     }
149618235Slinton     return r;
14979657Slinton }
14989657Slinton 
14999657Slinton /*
15009657Slinton  * Check to see if a tree is boolean-valued, if not it's an error.
15019657Slinton  */
15029657Slinton 
15039657Slinton public chkboolean(p)
15049657Slinton register Node p;
15059657Slinton {
15069657Slinton     if (p->nodetype != t_boolean) {
15079657Slinton 	beginerrmsg();
15089657Slinton 	fprintf(stderr, "found ");
15099657Slinton 	prtree(stderr, p);
15109657Slinton 	fprintf(stderr, ", expected boolean expression");
15119657Slinton 	enderrmsg();
15129657Slinton     }
15139657Slinton }
15149657Slinton 
15159657Slinton /*
151616620Ssam  * Construct a node for the type of a string.
15179657Slinton  */
15189657Slinton 
15199657Slinton private Symbol mkstring(str)
15209657Slinton String str;
15219657Slinton {
15229657Slinton     register Symbol s;
15239657Slinton 
152418235Slinton     s = newSymbol(nil, 0, ARRAY, t_char, nil);
152518235Slinton     s->chain = newSymbol(nil, 0, RANGE, t_int, nil);
152618235Slinton     s->chain->language = s->language;
152718235Slinton     s->chain->symvalue.rangev.lower = 1;
152818235Slinton     s->chain->symvalue.rangev.upper = strlen(str) + 1;
15299657Slinton     return s;
15309657Slinton }
15319657Slinton 
15329657Slinton /*
15339657Slinton  * Free up the space allocated for a string type.
15349657Slinton  */
15359657Slinton 
15369657Slinton public unmkstring(s)
15379657Slinton Symbol s;
15389657Slinton {
15399657Slinton     dispose(s->chain);
15409657Slinton }
15419657Slinton 
15429657Slinton /*
154318235Slinton  * Figure out the "current" variable or function being referred to
154418235Slinton  * by the name n.
15459657Slinton  */
15469657Slinton 
154718235Slinton private boolean stwhich(), dynwhich();
154818235Slinton 
154918235Slinton public Symbol which (n)
15509657Slinton Name n;
15519657Slinton {
155218235Slinton     Symbol s;
15539657Slinton 
155418235Slinton     s = lookup(n);
15559657Slinton     if (s == nil) {
155618235Slinton 	error("\"%s\" is not defined", ident(n));
155718235Slinton     } else if (not stwhich(&s) and isambiguous(s) and not dynwhich(&s)) {
155818235Slinton 	printf("[using ");
155918235Slinton 	printname(stdout, s);
156018235Slinton 	printf("]\n");
15619657Slinton     }
156218235Slinton     return s;
156318235Slinton }
156418235Slinton 
156518235Slinton /*
156618235Slinton  * Static search.
156718235Slinton  */
156818235Slinton 
156918235Slinton private boolean stwhich (var_s)
157018235Slinton Symbol *var_s;
157118235Slinton {
157218235Slinton     Name n;		/* name of desired symbol */
157318235Slinton     Symbol s;		/* iteration variable for symbols with name n */
157418235Slinton     Symbol f;		/* iteration variable for blocks containing s */
157518235Slinton     integer count;	/* number of levels from s->block to curfunc */
157618235Slinton     Symbol t;		/* current best answer for stwhich(n) */
157718235Slinton     integer mincount;	/* relative level for current best answer (t) */
157818235Slinton     boolean b;		/* return value, true if symbol found */
157918235Slinton 
158018235Slinton     s = *var_s;
158118235Slinton     n = s->name;
158218235Slinton     t = s;
158318235Slinton     mincount = 10000; /* force first match to set mincount */
158418235Slinton     do {
158518235Slinton 	if (s->name == n and s->class != FIELD and s->class != TAG) {
158618235Slinton 	    f = curfunc;
158718235Slinton 	    count = 0;
158818235Slinton 	    while (f != nil and f != s->block) {
158918235Slinton 		++count;
159018235Slinton 		f = f->block;
159118235Slinton 	    }
159218235Slinton 	    if (f != nil and count < mincount) {
159318235Slinton 		t = s;
159418235Slinton 		mincount = count;
159518235Slinton 		b = true;
159618235Slinton 	    }
159718235Slinton 	}
159818235Slinton 	s = s->next_sym;
159918235Slinton     } while (s != nil);
160018235Slinton     if (mincount != 10000) {
160118235Slinton 	*var_s = t;
160218235Slinton 	b = true;
16039657Slinton     } else {
160418235Slinton 	b = false;
160518235Slinton     }
160618235Slinton     return b;
160718235Slinton }
160818235Slinton 
160918235Slinton /*
161018235Slinton  * Dynamic search.
161118235Slinton  */
161218235Slinton 
161318235Slinton private boolean dynwhich (var_s)
161418235Slinton Symbol *var_s;
161518235Slinton {
161618235Slinton     Name n;		/* name of desired symbol */
161718235Slinton     Symbol s;		/* iteration variable for possible symbols */
161818235Slinton     Symbol f;		/* iteration variable for active functions */
161918235Slinton     Frame frp;		/* frame associated with stack walk */
162018235Slinton     boolean b;		/* return value */
162118235Slinton 
162218235Slinton     f = curfunc;
162318235Slinton     frp = curfuncframe();
162418235Slinton     n = (*var_s)->name;
162518235Slinton     b = false;
162618235Slinton     if (frp != nil) {
162718235Slinton 	frp = nextfunc(frp, &f);
162818235Slinton 	while (frp != nil) {
162918235Slinton 	    s = *var_s;
163018235Slinton 	    while (s != nil and
163118235Slinton 		(
163218235Slinton 		    s->name != n or s->block != f or
163318235Slinton 		    s->class == FIELD or s->class == TAG
163418235Slinton 		)
163518235Slinton 	    ) {
163618235Slinton 		s = s->next_sym;
163718235Slinton 	    }
163818235Slinton 	    if (s != nil) {
163918235Slinton 		*var_s = s;
164018235Slinton 		b = true;
164118235Slinton 		break;
164218235Slinton 	    }
164318235Slinton 	    if (f == program) {
164418235Slinton 		break;
164518235Slinton 	    }
164618235Slinton 	    frp = nextfunc(frp, &f);
16479657Slinton 	}
16489657Slinton     }
164918235Slinton     return b;
16509657Slinton }
16519657Slinton 
16529657Slinton /*
165318235Slinton  * Find the symbol that has the same name and scope as the
16549657Slinton  * given symbol but is of the given field.  Return nil if there is none.
16559657Slinton  */
16569657Slinton 
165718235Slinton public Symbol findfield (fieldname, record)
16589657Slinton Name fieldname;
16599657Slinton Symbol record;
16609657Slinton {
16619657Slinton     register Symbol t;
16629657Slinton 
16639657Slinton     t = rtype(record)->chain;
16649657Slinton     while (t != nil and t->name != fieldname) {
16659657Slinton 	t = t->chain;
16669657Slinton     }
16679657Slinton     return t;
16689657Slinton }
166912547Scsvaf 
167012547Scsvaf public Boolean getbound(s,off,type,valp)
167112547Scsvaf Symbol s;
167212547Scsvaf int off;
167312547Scsvaf Rangetype type;
167412547Scsvaf int *valp;
167512547Scsvaf {
167612547Scsvaf     Frame frp;
167712547Scsvaf     Address addr;
167812547Scsvaf     Symbol cur;
167912547Scsvaf 
168012547Scsvaf     if (not isactive(s->block)) {
168112547Scsvaf 	return(false);
168212547Scsvaf     }
168312547Scsvaf     cur = s->block;
168412547Scsvaf     while (cur != nil and cur->class == MODULE) {  /* WHY*/
168512547Scsvaf     		cur = cur->block;
168612547Scsvaf     }
168712547Scsvaf     if(cur == nil) {
168812547Scsvaf 		cur = whatblock(pc);
168912547Scsvaf     }
169012547Scsvaf     frp = findframe(cur);
169112547Scsvaf     if (frp == nil) {
169212547Scsvaf 	return(false);
169312547Scsvaf     }
169412547Scsvaf     if(type == R_TEMP) addr = locals_base(frp) + off;
169512547Scsvaf     else if (type == R_ARG) addr = args_base(frp) + off;
169612547Scsvaf     else return(false);
169712547Scsvaf     dread(valp,addr,sizeof(long));
169812547Scsvaf     return(true);
169912547Scsvaf }
1700