xref: /csrg-svn/old/dbx/symbols.c (revision 9657)
1*9657Slinton /* Copyright (c) 1982 Regents of the University of California */
2*9657Slinton 
3*9657Slinton static char sccsid[] = "@(#)@(#)symbols.c 1.1 12/15/82";
4*9657Slinton 
5*9657Slinton /*
6*9657Slinton  * Symbol management.
7*9657Slinton  */
8*9657Slinton 
9*9657Slinton #include "defs.h"
10*9657Slinton #include "symbols.h"
11*9657Slinton #include "languages.h"
12*9657Slinton #include "printsym.h"
13*9657Slinton #include "tree.h"
14*9657Slinton #include "operators.h"
15*9657Slinton #include "eval.h"
16*9657Slinton #include "mappings.h"
17*9657Slinton #include "events.h"
18*9657Slinton #include "process.h"
19*9657Slinton #include "runtime.h"
20*9657Slinton #include "machine.h"
21*9657Slinton #include "names.h"
22*9657Slinton 
23*9657Slinton #ifndef public
24*9657Slinton typedef struct Symbol *Symbol;
25*9657Slinton 
26*9657Slinton #include "machine.h"
27*9657Slinton #include "names.h"
28*9657Slinton #include "languages.h"
29*9657Slinton 
30*9657Slinton /*
31*9657Slinton  * Symbol classes
32*9657Slinton  */
33*9657Slinton 
34*9657Slinton typedef enum {
35*9657Slinton     BADUSE, CONST, TYPE, VAR, ARRAY, PTRFILE, RECORD, FIELD,
36*9657Slinton     PROC, FUNC, FVAR, REF, PTR, FILET, SET, RANGE,
37*9657Slinton     LABEL, WITHPTR, SCAL, STR, PROG, IMPROPER, VARNT,
38*9657Slinton     FPROC, FFUNC, MODULE, TYPEREF, TAG
39*9657Slinton } Symclass;
40*9657Slinton 
41*9657Slinton struct Symbol {
42*9657Slinton     Name name;
43*9657Slinton     Language language;
44*9657Slinton     Symclass class : 8;
45*9657Slinton     Integer level : 8;
46*9657Slinton     Symbol type;
47*9657Slinton     Symbol chain;
48*9657Slinton     union {
49*9657Slinton 	int offset;		/* variable address */
50*9657Slinton 	long iconval;		/* integer constant value */
51*9657Slinton 	double fconval;		/* floating constant value */
52*9657Slinton 	struct {		/* field offset and size (both in bits) */
53*9657Slinton 	    int offset;
54*9657Slinton 	    int length;
55*9657Slinton 	} field;
56*9657Slinton 	struct {		/* range bounds */
57*9657Slinton 	    long lower;
58*9657Slinton 	    long upper;
59*9657Slinton 	} rangev;
60*9657Slinton 	struct {		/* address of function value, code */
61*9657Slinton 	    int offset;
62*9657Slinton 	    Address beginaddr;
63*9657Slinton 	} funcv;
64*9657Slinton 	struct {		/* variant record info */
65*9657Slinton 	    int size;
66*9657Slinton 	    Symbol vtorec;
67*9657Slinton 	    Symbol vtag;
68*9657Slinton 	} varnt;
69*9657Slinton     } symvalue;
70*9657Slinton     Symbol block;		/* symbol containing this symbol */
71*9657Slinton     Symbol next_sym;		/* hash chain */
72*9657Slinton };
73*9657Slinton 
74*9657Slinton /*
75*9657Slinton  * Basic types.
76*9657Slinton  */
77*9657Slinton 
78*9657Slinton Symbol t_boolean;
79*9657Slinton Symbol t_char;
80*9657Slinton Symbol t_int;
81*9657Slinton Symbol t_real;
82*9657Slinton Symbol t_nil;
83*9657Slinton 
84*9657Slinton Symbol program;
85*9657Slinton Symbol curfunc;
86*9657Slinton 
87*9657Slinton #define symname(s) ident(s->name)
88*9657Slinton #define codeloc(f) ((f)->symvalue.funcv.beginaddr)
89*9657Slinton #define isblock(s) (Boolean) ( \
90*9657Slinton     s->class == FUNC or s->class == PROC or \
91*9657Slinton     s->class == MODULE or s->class == PROG \
92*9657Slinton )
93*9657Slinton 
94*9657Slinton #include "tree.h"
95*9657Slinton 
96*9657Slinton /*
97*9657Slinton  * Some macros to make finding a symbol with certain attributes.
98*9657Slinton  */
99*9657Slinton 
100*9657Slinton #define find(s, withname) \
101*9657Slinton { \
102*9657Slinton     s = lookup(withname); \
103*9657Slinton     while (s != nil and not (s->name == (withname) and
104*9657Slinton 
105*9657Slinton #define where /* qualification */
106*9657Slinton 
107*9657Slinton #define endfind(s) )) { \
108*9657Slinton 	s = s->next_sym; \
109*9657Slinton     } \
110*9657Slinton }
111*9657Slinton 
112*9657Slinton #endif
113*9657Slinton 
114*9657Slinton /*
115*9657Slinton  * Symbol table structure currently does not support deletions.
116*9657Slinton  */
117*9657Slinton 
118*9657Slinton #define HASHTABLESIZE 2003
119*9657Slinton 
120*9657Slinton private Symbol hashtab[HASHTABLESIZE];
121*9657Slinton 
122*9657Slinton #define hash(name) ((((unsigned) name) >> 2) mod HASHTABLESIZE)
123*9657Slinton 
124*9657Slinton /*
125*9657Slinton  * Allocate a new symbol.
126*9657Slinton  */
127*9657Slinton 
128*9657Slinton #define SYMBLOCKSIZE 1000
129*9657Slinton 
130*9657Slinton typedef struct Sympool {
131*9657Slinton     struct Symbol sym[SYMBLOCKSIZE];
132*9657Slinton     struct Sympool *prevpool;
133*9657Slinton } *Sympool;
134*9657Slinton 
135*9657Slinton private Sympool sympool = nil;
136*9657Slinton private Integer nleft = 0;
137*9657Slinton private struct Sympool zeropool;
138*9657Slinton 
139*9657Slinton public Symbol symbol_alloc()
140*9657Slinton {
141*9657Slinton     register Sympool newpool;
142*9657Slinton 
143*9657Slinton     if (nleft <= 0) {
144*9657Slinton 	newpool = new(Sympool);
145*9657Slinton 	*newpool = zeropool;
146*9657Slinton 	newpool->prevpool = sympool;
147*9657Slinton 	sympool = newpool;
148*9657Slinton 	nleft = SYMBLOCKSIZE;
149*9657Slinton     }
150*9657Slinton     --nleft;
151*9657Slinton     return &(sympool->sym[nleft]);
152*9657Slinton }
153*9657Slinton 
154*9657Slinton /*
155*9657Slinton  * Free all the symbols currently allocated.
156*9657Slinton  */
157*9657Slinton 
158*9657Slinton public symbol_free()
159*9657Slinton {
160*9657Slinton     Sympool s, t;
161*9657Slinton     register Integer i;
162*9657Slinton 
163*9657Slinton     s = sympool;
164*9657Slinton     while (s != nil) {
165*9657Slinton 	t = s->prevpool;
166*9657Slinton 	dispose(s);
167*9657Slinton 	s = t;
168*9657Slinton     }
169*9657Slinton     for (i = 0; i < HASHTABLESIZE; i++) {
170*9657Slinton 	hashtab[i] = nil;
171*9657Slinton     }
172*9657Slinton     sympool = nil;
173*9657Slinton     nleft = 0;
174*9657Slinton }
175*9657Slinton 
176*9657Slinton /*
177*9657Slinton  * Create a new symbol with the given attributes.
178*9657Slinton  */
179*9657Slinton 
180*9657Slinton public Symbol newSymbol(name, blevel, class, type, chain)
181*9657Slinton Name name;
182*9657Slinton Integer blevel;
183*9657Slinton Symclass class;
184*9657Slinton Symbol type;
185*9657Slinton Symbol chain;
186*9657Slinton {
187*9657Slinton     register Symbol s;
188*9657Slinton 
189*9657Slinton     s = symbol_alloc();
190*9657Slinton     s->name = name;
191*9657Slinton     s->level = blevel;
192*9657Slinton     s->class = class;
193*9657Slinton     s->type = type;
194*9657Slinton     s->chain = chain;
195*9657Slinton     return s;
196*9657Slinton }
197*9657Slinton 
198*9657Slinton /*
199*9657Slinton  * Insert a symbol into the hash table.
200*9657Slinton  */
201*9657Slinton 
202*9657Slinton public Symbol insert(name)
203*9657Slinton Name name;
204*9657Slinton {
205*9657Slinton     register Symbol s;
206*9657Slinton     register unsigned int h;
207*9657Slinton 
208*9657Slinton     h = hash(name);
209*9657Slinton     s = symbol_alloc();
210*9657Slinton     s->name = name;
211*9657Slinton     s->next_sym = hashtab[h];
212*9657Slinton     hashtab[h] = s;
213*9657Slinton     return s;
214*9657Slinton }
215*9657Slinton 
216*9657Slinton /*
217*9657Slinton  * Symbol lookup.
218*9657Slinton  */
219*9657Slinton 
220*9657Slinton public Symbol lookup(name)
221*9657Slinton Name name;
222*9657Slinton {
223*9657Slinton     register Symbol s;
224*9657Slinton     register unsigned int h;
225*9657Slinton 
226*9657Slinton     h = hash(name);
227*9657Slinton     s = hashtab[h];
228*9657Slinton     while (s != nil and s->name != name) {
229*9657Slinton 	s = s->next_sym;
230*9657Slinton     }
231*9657Slinton     return s;
232*9657Slinton }
233*9657Slinton 
234*9657Slinton /*
235*9657Slinton  * Dump out all the variables associated with the given
236*9657Slinton  * procedure, function, or program at the given recursive level.
237*9657Slinton  *
238*9657Slinton  * This is quite inefficient.  We traverse the entire symbol table
239*9657Slinton  * each time we're called.  The assumption is that this routine
240*9657Slinton  * won't be called frequently enough to merit improved performance.
241*9657Slinton  */
242*9657Slinton 
243*9657Slinton public dumpvars(f, frame)
244*9657Slinton Symbol f;
245*9657Slinton Frame frame;
246*9657Slinton {
247*9657Slinton     register Integer i;
248*9657Slinton     register Symbol s;
249*9657Slinton 
250*9657Slinton     for (i = 0; i < HASHTABLESIZE; i++) {
251*9657Slinton 	for (s = hashtab[i]; s != nil; s = s->next_sym) {
252*9657Slinton 	    if (container(s) == f) {
253*9657Slinton 		if (should_print(s)) {
254*9657Slinton 		    printv(s, frame);
255*9657Slinton 		    putchar('\n');
256*9657Slinton 		} else if (s->class == MODULE) {
257*9657Slinton 		    dumpvars(s, frame);
258*9657Slinton 		}
259*9657Slinton 	    }
260*9657Slinton 	}
261*9657Slinton     }
262*9657Slinton }
263*9657Slinton 
264*9657Slinton /*
265*9657Slinton  * Create a builtin type.
266*9657Slinton  * Builtin types are circular in that btype->type->type = btype.
267*9657Slinton  */
268*9657Slinton 
269*9657Slinton public Symbol maketype(name, lower, upper)
270*9657Slinton String name;
271*9657Slinton long lower;
272*9657Slinton long upper;
273*9657Slinton {
274*9657Slinton     register Symbol s;
275*9657Slinton 
276*9657Slinton     s = newSymbol(identname(name, true), 0, TYPE, nil, nil);
277*9657Slinton     s->language = findlanguage(".c");
278*9657Slinton     s->type = newSymbol(nil, 0, RANGE, s, nil);
279*9657Slinton     s->type->symvalue.rangev.lower = lower;
280*9657Slinton     s->type->symvalue.rangev.upper = upper;
281*9657Slinton     return s;
282*9657Slinton }
283*9657Slinton 
284*9657Slinton /*
285*9657Slinton  * These functions are now compiled inline.
286*9657Slinton  *
287*9657Slinton  * public String symname(s)
288*9657Slinton Symbol s;
289*9657Slinton {
290*9657Slinton     checkref(s);
291*9657Slinton     return ident(s->name);
292*9657Slinton }
293*9657Slinton 
294*9657Slinton  *
295*9657Slinton  * public Address codeloc(f)
296*9657Slinton Symbol f;
297*9657Slinton {
298*9657Slinton     checkref(f);
299*9657Slinton     if (not isblock(f)) {
300*9657Slinton 	panic("codeloc: \"%s\" is not a block", ident(f->name));
301*9657Slinton     }
302*9657Slinton     return f->symvalue.funcv.beginaddr;
303*9657Slinton }
304*9657Slinton  *
305*9657Slinton  */
306*9657Slinton 
307*9657Slinton /*
308*9657Slinton  * Reduce type to avoid worrying about type names.
309*9657Slinton  */
310*9657Slinton 
311*9657Slinton public Symbol rtype(type)
312*9657Slinton Symbol type;
313*9657Slinton {
314*9657Slinton     register Symbol t;
315*9657Slinton 
316*9657Slinton     t = type;
317*9657Slinton     if (t != nil) {
318*9657Slinton 	if (t->class == VAR or t->class == FIELD) {
319*9657Slinton 	    t = t->type;
320*9657Slinton 	}
321*9657Slinton 	while (t->class == TYPE or t->class == TAG) {
322*9657Slinton 	    t = t->type;
323*9657Slinton 	}
324*9657Slinton     }
325*9657Slinton     return t;
326*9657Slinton }
327*9657Slinton 
328*9657Slinton public Integer level(s)
329*9657Slinton Symbol s;
330*9657Slinton {
331*9657Slinton     checkref(s);
332*9657Slinton     return s->level;
333*9657Slinton }
334*9657Slinton 
335*9657Slinton public Symbol container(s)
336*9657Slinton Symbol s;
337*9657Slinton {
338*9657Slinton     checkref(s);
339*9657Slinton     return s->block;
340*9657Slinton }
341*9657Slinton 
342*9657Slinton /*
343*9657Slinton  * Return the object address of the given symbol.
344*9657Slinton  *
345*9657Slinton  * There are the following possibilities:
346*9657Slinton  *
347*9657Slinton  *	globals		- just take offset
348*9657Slinton  *	locals		- take offset from locals base
349*9657Slinton  *	arguments	- take offset from argument base
350*9657Slinton  *	register	- offset is register number
351*9657Slinton  */
352*9657Slinton 
353*9657Slinton #define isglobal(s)		(s->level == 1 or s->level == 2)
354*9657Slinton #define islocaloff(s)		(s->level >= 3 and s->symvalue.offset < 0)
355*9657Slinton #define isparamoff(s)		(s->level >= 3 and s->symvalue.offset >= 0)
356*9657Slinton #define isreg(s)		(s->level < 0)
357*9657Slinton 
358*9657Slinton public Address address(s, frame)
359*9657Slinton Symbol s;
360*9657Slinton Frame frame;
361*9657Slinton {
362*9657Slinton     register Frame frp;
363*9657Slinton     register Address addr;
364*9657Slinton     register Symbol cur;
365*9657Slinton 
366*9657Slinton     checkref(s);
367*9657Slinton     if (not isactive(s->block)) {
368*9657Slinton 	error("\"%s\" is not currently defined", symname(s));
369*9657Slinton     } else if (isglobal(s)) {
370*9657Slinton 	addr = s->symvalue.offset;
371*9657Slinton     } else {
372*9657Slinton 	frp = frame;
373*9657Slinton 	if (frp == nil) {
374*9657Slinton 	    cur = s->block;
375*9657Slinton 	    while (cur != nil and cur->class == MODULE) {
376*9657Slinton 		cur = cur->block;
377*9657Slinton 	    }
378*9657Slinton 	    if (cur == nil) {
379*9657Slinton 		cur = whatblock(pc);
380*9657Slinton 	    }
381*9657Slinton 	    frp = findframe(cur);
382*9657Slinton 	    if (frp == nil) {
383*9657Slinton 		panic("unexpected nil frame for \"%s\"", symname(s));
384*9657Slinton 	    }
385*9657Slinton 	}
386*9657Slinton 	if (islocaloff(s)) {
387*9657Slinton 	    addr = locals_base(frp) + s->symvalue.offset;
388*9657Slinton 	} else if (isparamoff(s)) {
389*9657Slinton 	    addr = args_base(frp) + s->symvalue.offset;
390*9657Slinton 	} else if (isreg(s)) {
391*9657Slinton 	    addr = savereg(s->symvalue.offset, frp);
392*9657Slinton 	} else {
393*9657Slinton 	    panic("address: bad symbol \"%s\"", symname(s));
394*9657Slinton 	}
395*9657Slinton     }
396*9657Slinton     return addr;
397*9657Slinton }
398*9657Slinton 
399*9657Slinton /*
400*9657Slinton  * Define a symbol used to access register values.
401*9657Slinton  */
402*9657Slinton 
403*9657Slinton public defregname(n, r)
404*9657Slinton Name n;
405*9657Slinton Integer r;
406*9657Slinton {
407*9657Slinton     register Symbol s, t;
408*9657Slinton 
409*9657Slinton     s = insert(n);
410*9657Slinton     t = newSymbol(nil, 0, PTR, t_int, nil);
411*9657Slinton     t->language = findlanguage(".s");
412*9657Slinton     s->language = t->language;
413*9657Slinton     s->class = VAR;
414*9657Slinton     s->level = -3;
415*9657Slinton     s->type = t;
416*9657Slinton     s->block = program;
417*9657Slinton     s->symvalue.offset = r;
418*9657Slinton }
419*9657Slinton 
420*9657Slinton /*
421*9657Slinton  * Resolve an "abstract" type reference.
422*9657Slinton  *
423*9657Slinton  * It is possible in C to define a pointer to a type, but never define
424*9657Slinton  * the type in a particular source file.  Here we try to resolve
425*9657Slinton  * the type definition.  This is problematic, it is possible to
426*9657Slinton  * have multiple, different definitions for the same name type.
427*9657Slinton  */
428*9657Slinton 
429*9657Slinton public findtype(s)
430*9657Slinton Symbol s;
431*9657Slinton {
432*9657Slinton     register Symbol t, u, prev;
433*9657Slinton 
434*9657Slinton     u = s;
435*9657Slinton     prev = nil;
436*9657Slinton     while (u != nil and u->class != BADUSE) {
437*9657Slinton 	if (u->name != nil) {
438*9657Slinton 	    prev = u;
439*9657Slinton 	}
440*9657Slinton 	u = u->type;
441*9657Slinton     }
442*9657Slinton     if (prev == nil) {
443*9657Slinton 	error("couldn't find link to type reference");
444*9657Slinton     }
445*9657Slinton     find(t, prev->name) where
446*9657Slinton 	t->type != nil and t->class == prev->class and
447*9657Slinton 	t->type->class != BADUSE and t->block->class == MODULE
448*9657Slinton     endfind(t);
449*9657Slinton     if (t == nil) {
450*9657Slinton 	error("couldn't resolve reference");
451*9657Slinton     } else {
452*9657Slinton 	prev->type = t->type;
453*9657Slinton     }
454*9657Slinton }
455*9657Slinton 
456*9657Slinton /*
457*9657Slinton  * Find the size in bytes of the given type.
458*9657Slinton  *
459*9657Slinton  * This is probably the WRONG thing to do.  The size should be kept
460*9657Slinton  * as an attribute in the symbol information as is done for structures
461*9657Slinton  * and fields.  I haven't gotten around to cleaning this up yet.
462*9657Slinton  */
463*9657Slinton 
464*9657Slinton #define MINCHAR -128
465*9657Slinton #define MAXCHAR 127
466*9657Slinton #define MINSHORT -32768
467*9657Slinton #define MAXSHORT 32767
468*9657Slinton 
469*9657Slinton public Integer size(sym)
470*9657Slinton Symbol sym;
471*9657Slinton {
472*9657Slinton     register Symbol s, t;
473*9657Slinton     register int nel, elsize;
474*9657Slinton     long lower, upper;
475*9657Slinton     int r;
476*9657Slinton 
477*9657Slinton     t = sym;
478*9657Slinton     checkref(t);
479*9657Slinton     switch (t->class) {
480*9657Slinton 	case RANGE:
481*9657Slinton 	    lower = t->symvalue.rangev.lower;
482*9657Slinton 	    upper = t->symvalue.rangev.upper;
483*9657Slinton 	    if (upper == 0 and lower > 0) {		/* real */
484*9657Slinton 		r = lower;
485*9657Slinton 	    } else if (lower >= MINCHAR and upper <= MAXCHAR) {
486*9657Slinton 		r = sizeof(char);
487*9657Slinton 	    } else if (lower >= MINSHORT and upper <= MAXSHORT) {
488*9657Slinton 		r = sizeof(short);
489*9657Slinton 	    } else {
490*9657Slinton 		r = sizeof(long);
491*9657Slinton 	    }
492*9657Slinton 	    break;
493*9657Slinton 
494*9657Slinton 	case ARRAY:
495*9657Slinton 	    elsize = size(t->type);
496*9657Slinton 	    nel = 1;
497*9657Slinton 	    for (t = t->chain; t != nil; t = t->chain) {
498*9657Slinton 		s = rtype(t);
499*9657Slinton 		lower = s->symvalue.rangev.lower;
500*9657Slinton 		upper = s->symvalue.rangev.upper;
501*9657Slinton 		nel *= (upper-lower+1);
502*9657Slinton 	    }
503*9657Slinton 	    r = nel*elsize;
504*9657Slinton 	    break;
505*9657Slinton 
506*9657Slinton 	case VAR:
507*9657Slinton 	case FVAR:
508*9657Slinton 	    r = size(t->type);
509*9657Slinton 	    if (r < sizeof(Word)) {
510*9657Slinton 		r = sizeof(Word);
511*9657Slinton 	    }
512*9657Slinton 	    break;
513*9657Slinton 
514*9657Slinton 	case CONST:
515*9657Slinton 	    r = size(t->type);
516*9657Slinton 	    break;
517*9657Slinton 
518*9657Slinton 	case TYPE:
519*9657Slinton 	    if (t->type->class == PTR and t->type->type->class == BADUSE) {
520*9657Slinton 		findtype(t);
521*9657Slinton 	    }
522*9657Slinton 	    r = size(t->type);
523*9657Slinton 	    break;
524*9657Slinton 
525*9657Slinton 	case TAG:
526*9657Slinton 	    r = size(t->type);
527*9657Slinton 	    break;
528*9657Slinton 
529*9657Slinton 	case FIELD:
530*9657Slinton 	    r = (t->symvalue.field.length + 7) div 8;
531*9657Slinton 	    break;
532*9657Slinton 
533*9657Slinton 	case RECORD:
534*9657Slinton 	case VARNT:
535*9657Slinton 	    r = t->symvalue.offset;
536*9657Slinton 	    if (r == 0 and t->chain != nil) {
537*9657Slinton 		panic("missing size information for record");
538*9657Slinton 	    }
539*9657Slinton 	    break;
540*9657Slinton 
541*9657Slinton 	case PTR:
542*9657Slinton 	case REF:
543*9657Slinton 	case FILET:
544*9657Slinton 	    r = sizeof(Word);
545*9657Slinton 	    break;
546*9657Slinton 
547*9657Slinton 	case SCAL:
548*9657Slinton 	    if (t->symvalue.iconval > 255) {
549*9657Slinton 		r = sizeof(short);
550*9657Slinton 	    } else {
551*9657Slinton 		r = sizeof(char);
552*9657Slinton 	    }
553*9657Slinton 	    break;
554*9657Slinton 
555*9657Slinton 	case FPROC:
556*9657Slinton 	case FFUNC:
557*9657Slinton 	    r = sizeof(Word);
558*9657Slinton 	    break;
559*9657Slinton 
560*9657Slinton 	case PROC:
561*9657Slinton 	case FUNC:
562*9657Slinton 	case MODULE:
563*9657Slinton 	case PROG:
564*9657Slinton 	    r = sizeof(Symbol);
565*9657Slinton 	    break;
566*9657Slinton 
567*9657Slinton 	default:
568*9657Slinton 	    if (ord(t->class) > ord(TYPEREF)) {
569*9657Slinton 		panic("size: bad class (%d)", ord(t->class));
570*9657Slinton 	    } else {
571*9657Slinton 		error("improper operation on a %s", classname(t));
572*9657Slinton 	    }
573*9657Slinton 	    /* NOTREACHED */
574*9657Slinton     }
575*9657Slinton     if (r < sizeof(Word) and isparam(sym)) {
576*9657Slinton 	r = sizeof(Word);
577*9657Slinton     }
578*9657Slinton     return r;
579*9657Slinton }
580*9657Slinton 
581*9657Slinton /*
582*9657Slinton  * Test if a symbol is a parameter.  This is true if there
583*9657Slinton  * is a cycle from s->block to s via chain pointers.
584*9657Slinton  */
585*9657Slinton 
586*9657Slinton public Boolean isparam(s)
587*9657Slinton Symbol s;
588*9657Slinton {
589*9657Slinton     register Symbol t;
590*9657Slinton 
591*9657Slinton     t = s->block;
592*9657Slinton     while (t != nil and t != s) {
593*9657Slinton 	t = t->chain;
594*9657Slinton     }
595*9657Slinton     return (Boolean) (t != nil);
596*9657Slinton }
597*9657Slinton 
598*9657Slinton /*
599*9657Slinton  * Test if a symbol is a var parameter, i.e. has class REF.
600*9657Slinton  */
601*9657Slinton 
602*9657Slinton public Boolean isvarparam(s)
603*9657Slinton Symbol s;
604*9657Slinton {
605*9657Slinton     return (Boolean) (s->class == REF);
606*9657Slinton }
607*9657Slinton 
608*9657Slinton /*
609*9657Slinton  * Test if a symbol is a variable (actually any addressible quantity
610*9657Slinton  * with do).
611*9657Slinton  */
612*9657Slinton 
613*9657Slinton public Boolean isvariable(s)
614*9657Slinton register Symbol s;
615*9657Slinton {
616*9657Slinton     return (Boolean) (s->class == VAR or s->class == FVAR or s->class == REF);
617*9657Slinton }
618*9657Slinton 
619*9657Slinton /*
620*9657Slinton  * Test if a symbol is a block, e.g. function, procedure, or the
621*9657Slinton  * main program.
622*9657Slinton  *
623*9657Slinton  * This function is now expanded inline for efficiency.
624*9657Slinton  *
625*9657Slinton  * public Boolean isblock(s)
626*9657Slinton register Symbol s;
627*9657Slinton {
628*9657Slinton     return (Boolean) (
629*9657Slinton 	s->class == FUNC or s->class == PROC or
630*9657Slinton 	s->class == MODULE or s->class == PROG
631*9657Slinton     );
632*9657Slinton }
633*9657Slinton  *
634*9657Slinton  */
635*9657Slinton 
636*9657Slinton /*
637*9657Slinton  * Test if a symbol is a module.
638*9657Slinton  */
639*9657Slinton 
640*9657Slinton public Boolean ismodule(s)
641*9657Slinton register Symbol s;
642*9657Slinton {
643*9657Slinton     return (Boolean) (s->class == MODULE);
644*9657Slinton }
645*9657Slinton 
646*9657Slinton /*
647*9657Slinton  * Test if a symbol is builtin, that is, a predefined type or
648*9657Slinton  * reserved word.
649*9657Slinton  */
650*9657Slinton 
651*9657Slinton public Boolean isbuiltin(s)
652*9657Slinton register Symbol s;
653*9657Slinton {
654*9657Slinton     return (Boolean) (s->level == 0 and s->class != PROG and s->class != VAR);
655*9657Slinton }
656*9657Slinton 
657*9657Slinton /*
658*9657Slinton  * Test if two types match.
659*9657Slinton  * Equivalent names implies a match in any language.
660*9657Slinton  *
661*9657Slinton  * Special symbols must be handled with care.
662*9657Slinton  */
663*9657Slinton 
664*9657Slinton public Boolean compatible(t1, t2)
665*9657Slinton register Symbol t1, t2;
666*9657Slinton {
667*9657Slinton     Boolean b;
668*9657Slinton 
669*9657Slinton     if (t1 == t2) {
670*9657Slinton 	b = true;
671*9657Slinton     } else if (t1 == nil or t2 == nil) {
672*9657Slinton 	b = false;
673*9657Slinton     } else if (t1 == procsym) {
674*9657Slinton 	b = isblock(t2);
675*9657Slinton     } else if (t2 == procsym) {
676*9657Slinton 	b = isblock(t1);
677*9657Slinton     } else if (t1->language == nil) {
678*9657Slinton 	b = (Boolean) (t2->language == nil or
679*9657Slinton 	    (*language_op(t2->language, L_TYPEMATCH))(t1, t2));
680*9657Slinton     } else {
681*9657Slinton 	b = (Boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2);
682*9657Slinton     }
683*9657Slinton     return b;
684*9657Slinton }
685*9657Slinton 
686*9657Slinton /*
687*9657Slinton  * Check for a type of the given name.
688*9657Slinton  */
689*9657Slinton 
690*9657Slinton public Boolean istypename(type, name)
691*9657Slinton Symbol type;
692*9657Slinton String name;
693*9657Slinton {
694*9657Slinton     Symbol t;
695*9657Slinton     Boolean b;
696*9657Slinton 
697*9657Slinton     t = type;
698*9657Slinton     checkref(t);
699*9657Slinton     b = (Boolean) (
700*9657Slinton 	t->class == TYPE and t->name == identname(name, true)
701*9657Slinton     );
702*9657Slinton     return b;
703*9657Slinton }
704*9657Slinton 
705*9657Slinton /*
706*9657Slinton  * Test if the name of a symbol is uniquely defined or not.
707*9657Slinton  */
708*9657Slinton 
709*9657Slinton public Boolean isambiguous(s)
710*9657Slinton register Symbol s;
711*9657Slinton {
712*9657Slinton     register Symbol t;
713*9657Slinton 
714*9657Slinton     find(t, s->name) where t != s endfind(t);
715*9657Slinton     return (Boolean) (t != nil);
716*9657Slinton }
717*9657Slinton 
718*9657Slinton typedef char *Arglist;
719*9657Slinton 
720*9657Slinton #define nextarg(type)  ((type *) (ap += sizeof(type)))[-1]
721*9657Slinton 
722*9657Slinton private Symbol mkstring();
723*9657Slinton private Symbol namenode();
724*9657Slinton 
725*9657Slinton /*
726*9657Slinton  * Determine the type of a parse tree.
727*9657Slinton  * Also make some symbol-dependent changes to the tree such as
728*9657Slinton  * changing removing RVAL nodes for constant symbols.
729*9657Slinton  */
730*9657Slinton 
731*9657Slinton public assigntypes(p)
732*9657Slinton register Node p;
733*9657Slinton {
734*9657Slinton     register Node p1;
735*9657Slinton     register Symbol s;
736*9657Slinton 
737*9657Slinton     switch (p->op) {
738*9657Slinton 	case O_SYM:
739*9657Slinton 	    p->nodetype = namenode(p);
740*9657Slinton 	    break;
741*9657Slinton 
742*9657Slinton 	case O_LCON:
743*9657Slinton 	    p->nodetype = t_int;
744*9657Slinton 	    break;
745*9657Slinton 
746*9657Slinton 	case O_FCON:
747*9657Slinton 	    p->nodetype = t_real;
748*9657Slinton 	    break;
749*9657Slinton 
750*9657Slinton 	case O_SCON:
751*9657Slinton 	    p->value.scon = strdup(p->value.scon);
752*9657Slinton 	    s = mkstring(p->value.scon);
753*9657Slinton 	    if (s == t_char) {
754*9657Slinton 		p->op = O_LCON;
755*9657Slinton 		p->value.lcon = p->value.scon[0];
756*9657Slinton 	    }
757*9657Slinton 	    p->nodetype = s;
758*9657Slinton 	    break;
759*9657Slinton 
760*9657Slinton 	case O_INDIR:
761*9657Slinton 	    p1 = p->value.arg[0];
762*9657Slinton 	    chkclass(p1, PTR);
763*9657Slinton 	    p->nodetype = rtype(p1->nodetype)->type;
764*9657Slinton 	    break;
765*9657Slinton 
766*9657Slinton 	case O_DOT:
767*9657Slinton 	    p->nodetype = p->value.arg[1]->value.sym;
768*9657Slinton 	    break;
769*9657Slinton 
770*9657Slinton 	case O_RVAL:
771*9657Slinton 	    p1 = p->value.arg[0];
772*9657Slinton 	    p->nodetype = p1->nodetype;
773*9657Slinton 	    if (p1->op == O_SYM) {
774*9657Slinton 		if (p1->nodetype->class == FUNC) {
775*9657Slinton 		    p->op = O_CALL;
776*9657Slinton 		    p->value.arg[1] = nil;
777*9657Slinton 		} else if (p1->value.sym->class == CONST) {
778*9657Slinton 		    if (compatible(p1->value.sym->type, t_real)) {
779*9657Slinton 			p->op = O_FCON;
780*9657Slinton 			p->value.fcon = p1->value.sym->symvalue.fconval;
781*9657Slinton 			p->nodetype = t_real;
782*9657Slinton 			dispose(p1);
783*9657Slinton 		    } else {
784*9657Slinton 			p->op = O_LCON;
785*9657Slinton 			p->value.lcon = p1->value.sym->symvalue.iconval;
786*9657Slinton 			p->nodetype = p1->value.sym->type;
787*9657Slinton 			dispose(p1);
788*9657Slinton 		    }
789*9657Slinton 		} else if (isreg(p1->value.sym)) {
790*9657Slinton 		    p->op = O_SYM;
791*9657Slinton 		    p->value.sym = p1->value.sym;
792*9657Slinton 		    dispose(p1);
793*9657Slinton 		}
794*9657Slinton 	    } else if (p1->op == O_INDIR and p1->value.arg[0]->op == O_SYM) {
795*9657Slinton 		s = p1->value.arg[0]->value.sym;
796*9657Slinton 		if (isreg(s)) {
797*9657Slinton 		    p1->op = O_SYM;
798*9657Slinton 		    dispose(p1->value.arg[0]);
799*9657Slinton 		    p1->value.sym = s;
800*9657Slinton 		    p1->nodetype = s;
801*9657Slinton 		}
802*9657Slinton 	    }
803*9657Slinton 	    break;
804*9657Slinton 
805*9657Slinton 	/*
806*9657Slinton 	 * Perform a cast if the call is of the form "type(expr)".
807*9657Slinton 	 */
808*9657Slinton 	case O_CALL:
809*9657Slinton 	    p1 = p->value.arg[0];
810*9657Slinton 	    if (p1->op == O_SYM and
811*9657Slinton 	      (p1->value.sym->class == TYPE or p1->value.sym->class == TAG)) {
812*9657Slinton 		s = p1->value.sym;
813*9657Slinton 		dispose(p1);
814*9657Slinton 		p1 = p->value.arg[1];
815*9657Slinton 		assert(p1->op == O_COMMA);
816*9657Slinton 		if (p1->value.arg[1] != nil) {
817*9657Slinton 		    error("unexpected comma within type conversion");
818*9657Slinton 		}
819*9657Slinton 		p->op = O_RVAL;
820*9657Slinton 		p->value.arg[0] = p1->value.arg[0];
821*9657Slinton 		p->nodetype = s;
822*9657Slinton 		p->value.arg[0]->nodetype = s;
823*9657Slinton 		dispose(p1);
824*9657Slinton 	    } else {
825*9657Slinton 		p->nodetype = rtype(p1->nodetype)->type;
826*9657Slinton 	    }
827*9657Slinton 	    break;
828*9657Slinton 
829*9657Slinton 	case O_ITOF:
830*9657Slinton 	    p->nodetype = t_real;
831*9657Slinton 	    break;
832*9657Slinton 
833*9657Slinton 	case O_NEG:
834*9657Slinton 	    s = p->value.arg[0]->nodetype;
835*9657Slinton 	    if (not compatible(s, t_int)) {
836*9657Slinton 		if (not compatible(s, t_real)) {
837*9657Slinton 		    beginerrmsg();
838*9657Slinton 		    prtree(stderr, p->value.arg[0]);
839*9657Slinton 		    fprintf(stderr, "is improper type");
840*9657Slinton 		    enderrmsg();
841*9657Slinton 		} else {
842*9657Slinton 		    p->op = O_NEGF;
843*9657Slinton 		}
844*9657Slinton 	    }
845*9657Slinton 	    p->nodetype = s;
846*9657Slinton 	    break;
847*9657Slinton 
848*9657Slinton 	case O_ADD:
849*9657Slinton 	case O_SUB:
850*9657Slinton 	case O_MUL:
851*9657Slinton 	case O_LT:
852*9657Slinton 	case O_LE:
853*9657Slinton 	case O_GT:
854*9657Slinton 	case O_GE:
855*9657Slinton 	case O_EQ:
856*9657Slinton 	case O_NE:
857*9657Slinton 	{
858*9657Slinton 	    Boolean t1real, t2real;
859*9657Slinton 	    Symbol t1, t2;
860*9657Slinton 
861*9657Slinton 	    t1 = rtype(p->value.arg[0]->nodetype);
862*9657Slinton 	    t2 = rtype(p->value.arg[1]->nodetype);
863*9657Slinton 	    t1real = compatible(t1, t_real);
864*9657Slinton 	    t2real = compatible(t2, t_real);
865*9657Slinton 	    if (t1real or t2real) {
866*9657Slinton 		p->op = (Operator) (ord(p->op) + 1);
867*9657Slinton 		if (not t1real) {
868*9657Slinton 		    p->value.arg[0] = build(O_ITOF, p->value.arg[0]);
869*9657Slinton 		} else if (not t2real) {
870*9657Slinton 		    p->value.arg[1] = build(O_ITOF, p->value.arg[1]);
871*9657Slinton 		}
872*9657Slinton 	    } else {
873*9657Slinton 		if (t1real) {
874*9657Slinton 		    convert(&(p->value.arg[0]), t_int, O_NOP);
875*9657Slinton 		}
876*9657Slinton 		if (t2real) {
877*9657Slinton 		    convert(&(p->value.arg[1]), t_int, O_NOP);
878*9657Slinton 		}
879*9657Slinton 	    }
880*9657Slinton 	    if (ord(p->op) >= ord(O_LT)) {
881*9657Slinton 		p->nodetype = t_boolean;
882*9657Slinton 	    } else {
883*9657Slinton 		if (t1real or t2real) {
884*9657Slinton 		    p->nodetype = t_real;
885*9657Slinton 		} else {
886*9657Slinton 		    p->nodetype = t_int;
887*9657Slinton 		}
888*9657Slinton 	    }
889*9657Slinton 	    break;
890*9657Slinton 	}
891*9657Slinton 
892*9657Slinton 	case O_DIVF:
893*9657Slinton 	    convert(&(p->value.arg[0]), t_real, O_ITOF);
894*9657Slinton 	    convert(&(p->value.arg[1]), t_real, O_ITOF);
895*9657Slinton 	    p->nodetype = t_real;
896*9657Slinton 	    break;
897*9657Slinton 
898*9657Slinton 	case O_DIV:
899*9657Slinton 	case O_MOD:
900*9657Slinton 	    convert(&(p->value.arg[0]), t_int, O_NOP);
901*9657Slinton 	    convert(&(p->value.arg[1]), t_int, O_NOP);
902*9657Slinton 	    p->nodetype = t_int;
903*9657Slinton 	    break;
904*9657Slinton 
905*9657Slinton 	case O_AND:
906*9657Slinton 	case O_OR:
907*9657Slinton 	    chkboolean(p->value.arg[0]);
908*9657Slinton 	    chkboolean(p->value.arg[1]);
909*9657Slinton 	    p->nodetype = t_boolean;
910*9657Slinton 	    break;
911*9657Slinton 
912*9657Slinton 	case O_QLINE:
913*9657Slinton 	    p->nodetype = t_int;
914*9657Slinton 	    break;
915*9657Slinton 
916*9657Slinton 	default:
917*9657Slinton 	    p->nodetype = nil;
918*9657Slinton 	    break;
919*9657Slinton     }
920*9657Slinton }
921*9657Slinton 
922*9657Slinton /*
923*9657Slinton  * Create a node for a name.  The symbol for the name has already
924*9657Slinton  * been chosen, either implicitly with "which" or explicitly from
925*9657Slinton  * the dot routine.
926*9657Slinton  */
927*9657Slinton 
928*9657Slinton private Symbol namenode(p)
929*9657Slinton Node p;
930*9657Slinton {
931*9657Slinton     register Symbol r, s;
932*9657Slinton     register Node np;
933*9657Slinton 
934*9657Slinton     s = p->value.sym;
935*9657Slinton     if (s->class == REF) {
936*9657Slinton 	np = new(Node);
937*9657Slinton 	np->op = p->op;
938*9657Slinton 	np->nodetype = s;
939*9657Slinton 	np->value.sym = s;
940*9657Slinton 	p->op = O_INDIR;
941*9657Slinton 	p->value.arg[0] = np;
942*9657Slinton     }
943*9657Slinton /*
944*9657Slinton  * Old way
945*9657Slinton  *
946*9657Slinton     if (s->class == CONST or s->class == VAR or s->class == FVAR) {
947*9657Slinton 	r = s->type;
948*9657Slinton     } else {
949*9657Slinton 	r = s;
950*9657Slinton     }
951*9657Slinton  *
952*9657Slinton  */
953*9657Slinton     return s;
954*9657Slinton }
955*9657Slinton 
956*9657Slinton /*
957*9657Slinton  * Convert a tree to a type via a conversion operator;
958*9657Slinton  * if this isn't possible generate an error.
959*9657Slinton  *
960*9657Slinton  * Note the tree is call by address, hence the #define below.
961*9657Slinton  */
962*9657Slinton 
963*9657Slinton private convert(tp, typeto, op)
964*9657Slinton Node *tp;
965*9657Slinton Symbol typeto;
966*9657Slinton Operator op;
967*9657Slinton {
968*9657Slinton #define tree    (*tp)
969*9657Slinton 
970*9657Slinton     Symbol s;
971*9657Slinton 
972*9657Slinton     s = rtype(tree->nodetype);
973*9657Slinton     typeto = rtype(typeto);
974*9657Slinton     if (compatible(typeto, t_real) and compatible(s, t_int)) {
975*9657Slinton 	tree = build(op, tree);
976*9657Slinton     } else if (not compatible(s, typeto)) {
977*9657Slinton 	beginerrmsg();
978*9657Slinton 	prtree(stderr, s);
979*9657Slinton 	fprintf(stderr, " is improper type");
980*9657Slinton 	enderrmsg();
981*9657Slinton     } else if (op != O_NOP and s != typeto) {
982*9657Slinton 	tree = build(op, tree);
983*9657Slinton     }
984*9657Slinton 
985*9657Slinton #undef tree
986*9657Slinton }
987*9657Slinton 
988*9657Slinton /*
989*9657Slinton  * Construct a node for the dot operator.
990*9657Slinton  *
991*9657Slinton  * If the left operand is not a record, but rather a procedure
992*9657Slinton  * or function, then we interpret the "." as referencing an
993*9657Slinton  * "invisible" variable; i.e. a variable within a dynamically
994*9657Slinton  * active block but not within the static scope of the current procedure.
995*9657Slinton  */
996*9657Slinton 
997*9657Slinton public Node dot(record, fieldname)
998*9657Slinton Node record;
999*9657Slinton Name fieldname;
1000*9657Slinton {
1001*9657Slinton     register Node p;
1002*9657Slinton     register Symbol s, t;
1003*9657Slinton 
1004*9657Slinton     if (isblock(record->nodetype)) {
1005*9657Slinton 	find(s, fieldname) where
1006*9657Slinton 	    s->block == record->nodetype and
1007*9657Slinton 	    s->class != FIELD and s->class != TAG
1008*9657Slinton 	endfind(s);
1009*9657Slinton 	if (s == nil) {
1010*9657Slinton 	    beginerrmsg();
1011*9657Slinton 	    fprintf(stderr, "\"%s\" is not defined in ", ident(fieldname));
1012*9657Slinton 	    printname(stderr, record->nodetype);
1013*9657Slinton 	    enderrmsg();
1014*9657Slinton 	}
1015*9657Slinton 	p = new(Node);
1016*9657Slinton 	p->op = O_SYM;
1017*9657Slinton 	p->value.sym = s;
1018*9657Slinton 	p->nodetype = namenode(p);
1019*9657Slinton     } else {
1020*9657Slinton 	p = record;
1021*9657Slinton 	t = rtype(p->nodetype);
1022*9657Slinton 	if (t->class == PTR) {
1023*9657Slinton 	    s = findfield(fieldname, t->type);
1024*9657Slinton 	} else {
1025*9657Slinton 	    s = findfield(fieldname, t);
1026*9657Slinton 	}
1027*9657Slinton 	if (s == nil) {
1028*9657Slinton 	    beginerrmsg();
1029*9657Slinton 	    fprintf(stderr, "\"%s\" is not a field in ", ident(fieldname));
1030*9657Slinton 	    prtree(stderr, record);
1031*9657Slinton 	    enderrmsg();
1032*9657Slinton 	}
1033*9657Slinton 	if (t->class == PTR and not isreg(record->nodetype)) {
1034*9657Slinton 	    p = build(O_INDIR, record);
1035*9657Slinton 	}
1036*9657Slinton 	p = build(O_DOT, p, build(O_SYM, s));
1037*9657Slinton     }
1038*9657Slinton     return p;
1039*9657Slinton }
1040*9657Slinton 
1041*9657Slinton /*
1042*9657Slinton  * Return a tree corresponding to an array reference and do the
1043*9657Slinton  * error checking.
1044*9657Slinton  */
1045*9657Slinton 
1046*9657Slinton public Node subscript(a, slist)
1047*9657Slinton Node a, slist;
1048*9657Slinton {
1049*9657Slinton     register Symbol t;
1050*9657Slinton     register Node p;
1051*9657Slinton     Symbol etype, atype, eltype;
1052*9657Slinton     Node esub, olda;
1053*9657Slinton 
1054*9657Slinton     olda = a;
1055*9657Slinton     t = rtype(a->nodetype);
1056*9657Slinton     if (t->class != ARRAY) {
1057*9657Slinton 	beginerrmsg();
1058*9657Slinton 	prtree(stderr, a);
1059*9657Slinton 	fprintf(stderr, " is not an array");
1060*9657Slinton 	enderrmsg();
1061*9657Slinton     }
1062*9657Slinton     eltype = t->type;
1063*9657Slinton     p = slist;
1064*9657Slinton     t = t->chain;
1065*9657Slinton     for (; p != nil and t != nil; p = p->value.arg[1], t = t->chain) {
1066*9657Slinton 	esub = p->value.arg[0];
1067*9657Slinton 	etype = rtype(esub->nodetype);
1068*9657Slinton 	atype = rtype(t);
1069*9657Slinton 	if (not compatible(atype, etype)) {
1070*9657Slinton 	    beginerrmsg();
1071*9657Slinton 	    fprintf(stderr, "subscript ");
1072*9657Slinton 	    prtree(stderr, esub);
1073*9657Slinton 	    fprintf(stderr, " is the wrong type");
1074*9657Slinton 	    enderrmsg();
1075*9657Slinton 	}
1076*9657Slinton 	a = build(O_INDEX, a, esub);
1077*9657Slinton 	a->nodetype = eltype;
1078*9657Slinton     }
1079*9657Slinton     if (p != nil or t != nil) {
1080*9657Slinton 	beginerrmsg();
1081*9657Slinton 	if (p != nil) {
1082*9657Slinton 	    fprintf(stderr, "too many subscripts for ");
1083*9657Slinton 	} else {
1084*9657Slinton 	    fprintf(stderr, "not enough subscripts for ");
1085*9657Slinton 	}
1086*9657Slinton 	prtree(stderr, olda);
1087*9657Slinton 	enderrmsg();
1088*9657Slinton     }
1089*9657Slinton     return a;
1090*9657Slinton }
1091*9657Slinton 
1092*9657Slinton /*
1093*9657Slinton  * Evaluate a subscript index.
1094*9657Slinton  */
1095*9657Slinton 
1096*9657Slinton public int evalindex(s, i)
1097*9657Slinton Symbol s;
1098*9657Slinton long i;
1099*9657Slinton {
1100*9657Slinton     long lb, ub;
1101*9657Slinton 
1102*9657Slinton     s = rtype(s)->chain;
1103*9657Slinton     lb = s->symvalue.rangev.lower;
1104*9657Slinton     ub = s->symvalue.rangev.upper;
1105*9657Slinton     if (i < lb or i > ub) {
1106*9657Slinton 	error("subscript out of range");
1107*9657Slinton     }
1108*9657Slinton     return (i - lb);
1109*9657Slinton }
1110*9657Slinton 
1111*9657Slinton /*
1112*9657Slinton  * Check to see if a tree is boolean-valued, if not it's an error.
1113*9657Slinton  */
1114*9657Slinton 
1115*9657Slinton public chkboolean(p)
1116*9657Slinton register Node p;
1117*9657Slinton {
1118*9657Slinton     if (p->nodetype != t_boolean) {
1119*9657Slinton 	beginerrmsg();
1120*9657Slinton 	fprintf(stderr, "found ");
1121*9657Slinton 	prtree(stderr, p);
1122*9657Slinton 	fprintf(stderr, ", expected boolean expression");
1123*9657Slinton 	enderrmsg();
1124*9657Slinton     }
1125*9657Slinton }
1126*9657Slinton 
1127*9657Slinton /*
1128*9657Slinton  * Check to make sure the given tree has a type of the given class.
1129*9657Slinton  */
1130*9657Slinton 
1131*9657Slinton private chkclass(p, class)
1132*9657Slinton Node p;
1133*9657Slinton Symclass class;
1134*9657Slinton {
1135*9657Slinton     struct Symbol tmpsym;
1136*9657Slinton 
1137*9657Slinton     tmpsym.class = class;
1138*9657Slinton     if (rtype(p->nodetype)->class != class) {
1139*9657Slinton 	beginerrmsg();
1140*9657Slinton 	fprintf(stderr, "\"");
1141*9657Slinton 	prtree(stderr, p);
1142*9657Slinton 	fprintf(stderr, "\" is not a %s", classname(&tmpsym));
1143*9657Slinton 	enderrmsg();
1144*9657Slinton     }
1145*9657Slinton }
1146*9657Slinton 
1147*9657Slinton /*
1148*9657Slinton  * Construct a node for the type of a string.  While we're at it,
1149*9657Slinton  * scan the string for '' that collapse to ', and chop off the ends.
1150*9657Slinton  */
1151*9657Slinton 
1152*9657Slinton private Symbol mkstring(str)
1153*9657Slinton String str;
1154*9657Slinton {
1155*9657Slinton     register char *p, *q;
1156*9657Slinton     register Symbol s;
1157*9657Slinton 
1158*9657Slinton     p = str;
1159*9657Slinton     q = str;
1160*9657Slinton     while (*p != '\0') {
1161*9657Slinton 	if (*p == '\\') {
1162*9657Slinton 	    ++p;
1163*9657Slinton 	}
1164*9657Slinton 	*q = *p;
1165*9657Slinton 	++p;
1166*9657Slinton 	++q;
1167*9657Slinton     }
1168*9657Slinton     *q = '\0';
1169*9657Slinton     s = newSymbol(nil, 0, ARRAY, t_char, nil);
1170*9657Slinton     s->language = findlanguage(".s");
1171*9657Slinton     s->chain = newSymbol(nil, 0, RANGE, t_int, nil);
1172*9657Slinton     s->chain->language = s->language;
1173*9657Slinton     s->chain->symvalue.rangev.lower = 1;
1174*9657Slinton     s->chain->symvalue.rangev.upper = p - str + 1;
1175*9657Slinton     return s;
1176*9657Slinton }
1177*9657Slinton 
1178*9657Slinton /*
1179*9657Slinton  * Free up the space allocated for a string type.
1180*9657Slinton  */
1181*9657Slinton 
1182*9657Slinton public unmkstring(s)
1183*9657Slinton Symbol s;
1184*9657Slinton {
1185*9657Slinton     dispose(s->chain);
1186*9657Slinton }
1187*9657Slinton 
1188*9657Slinton /*
1189*9657Slinton  * Figure out the "current" variable or function being referred to,
1190*9657Slinton  * this is either the active one or the most visible from the
1191*9657Slinton  * current scope.
1192*9657Slinton  */
1193*9657Slinton 
1194*9657Slinton public Symbol which(n)
1195*9657Slinton Name n;
1196*9657Slinton {
1197*9657Slinton     register Symbol s, p, t, f;
1198*9657Slinton 
1199*9657Slinton     find(s, n) where s->class != FIELD and s->class != TAG endfind(s);
1200*9657Slinton     if (s == nil) {
1201*9657Slinton 	s = lookup(n);
1202*9657Slinton     }
1203*9657Slinton     if (s == nil) {
1204*9657Slinton 	error("\"%s\" is not defined", ident(n));
1205*9657Slinton     } else if (s == program or isbuiltin(s)) {
1206*9657Slinton 	t = s;
1207*9657Slinton     } else {
1208*9657Slinton     /*
1209*9657Slinton      * Old way
1210*9657Slinton      *
1211*9657Slinton 	if (not isactive(program)) {
1212*9657Slinton 	    f = program;
1213*9657Slinton 	} else {
1214*9657Slinton 	    f = whatblock(pc);
1215*9657Slinton 	    if (f == nil) {
1216*9657Slinton 		panic("no block for addr 0x%x", pc);
1217*9657Slinton 	    }
1218*9657Slinton 	}
1219*9657Slinton      *
1220*9657Slinton      * Now start with curfunc.
1221*9657Slinton      */
1222*9657Slinton 	p = curfunc;
1223*9657Slinton 	do {
1224*9657Slinton 	    find(t, n) where
1225*9657Slinton 		t->block == p and t->class != FIELD and t->class != TAG
1226*9657Slinton 	    endfind(t);
1227*9657Slinton 	    p = p->block;
1228*9657Slinton 	} while (t == nil and p != nil);
1229*9657Slinton 	if (t == nil) {
1230*9657Slinton 	    t = s;
1231*9657Slinton 	}
1232*9657Slinton     }
1233*9657Slinton     return t;
1234*9657Slinton }
1235*9657Slinton 
1236*9657Slinton /*
1237*9657Slinton  * Find the symbol which is has the same name and scope as the
1238*9657Slinton  * given symbol but is of the given field.  Return nil if there is none.
1239*9657Slinton  */
1240*9657Slinton 
1241*9657Slinton public Symbol findfield(fieldname, record)
1242*9657Slinton Name fieldname;
1243*9657Slinton Symbol record;
1244*9657Slinton {
1245*9657Slinton     register Symbol t;
1246*9657Slinton 
1247*9657Slinton     t = rtype(record)->chain;
1248*9657Slinton     while (t != nil and t->name != fieldname) {
1249*9657Slinton 	t = t->chain;
1250*9657Slinton     }
1251*9657Slinton     return t;
1252*9657Slinton }
1253