xref: /csrg-svn/old/dbx/symbols.c (revision 16620)
1 /* Copyright (c) 1982 Regents of the University of California */
2 
3 static char sccsid[] = "@(#)symbols.c 1.10 8/10/83";
4 
5 static char rcsid[] = "$Header: symbols.c,v 1.4 84/03/27 10:24:18 linton Exp $";
6 
7 /*
8  * Symbol management.
9  */
10 
11 #include "defs.h"
12 #include "symbols.h"
13 #include "languages.h"
14 #include "printsym.h"
15 #include "tree.h"
16 #include "operators.h"
17 #include "eval.h"
18 #include "mappings.h"
19 #include "events.h"
20 #include "process.h"
21 #include "runtime.h"
22 #include "machine.h"
23 #include "names.h"
24 
25 #ifndef public
26 typedef struct Symbol *Symbol;
27 
28 #include "machine.h"
29 #include "names.h"
30 #include "languages.h"
31 
32 /*
33  * Symbol classes
34  */
35 
36 typedef enum {
37     BADUSE, CONST, TYPE, VAR, ARRAY, PTRFILE, RECORD, FIELD,
38     PROC, FUNC, FVAR, REF, PTR, FILET, SET, RANGE,
39     LABEL, WITHPTR, SCAL, STR, PROG, IMPROPER, VARNT,
40     FPROC, FFUNC, MODULE, TAG, COMMON, EXTREF, TYPEREF
41 } Symclass;
42 
43 typedef enum { R_CONST, R_TEMP, R_ARG, R_ADJUST } Rangetype;
44 
45 struct Symbol {
46     Name name;
47     Language language;
48     Symclass class : 8;
49     Integer level : 8;
50     Symbol type;
51     Symbol chain;
52     union {
53 	int offset;		/* variable address */
54 	long iconval;		/* integer constant value */
55 	double fconval;		/* floating constant value */
56 	struct {		/* field offset and size (both in bits) */
57 	    int offset;
58 	    int length;
59 	} field;
60 	struct {		/* common offset and chain; used to relocate */
61 	    int offset;         /* vars in global BSS */
62 	    Symbol chain;
63 	} common;
64 	struct {		/* range bounds */
65             Rangetype lowertype : 16;
66             Rangetype uppertype : 16;
67 	    long lower;
68 	    long upper;
69 	} rangev;
70 	struct {
71 	    int offset : 16;	/* offset for of function value */
72 	    Boolean src : 1;	/* true if there is source line info */
73 	    Boolean inline : 1;	/* true if no separate act. rec. */
74 	    Boolean intern : 1; /* internal calling sequence */
75 	    int unused : 13;
76 	    Address beginaddr;	/* address of function code */
77 	} funcv;
78 	struct {		/* variant record info */
79 	    int size;
80 	    Symbol vtorec;
81 	    Symbol vtag;
82 	} varnt;
83 	String typeref;		/* type defined by "<module>:<type>" */
84 	Symbol extref;		/* indirect symbol for external reference */
85     } symvalue;
86     Symbol block;		/* symbol containing this symbol */
87     Symbol next_sym;		/* hash chain */
88 };
89 
90 /*
91  * Basic types.
92  */
93 
94 Symbol t_boolean;
95 Symbol t_char;
96 Symbol t_int;
97 Symbol t_real;
98 Symbol t_nil;
99 Symbol t_open;
100 
101 Symbol program;
102 Symbol curfunc;
103 
104 #define symname(s) ident(s->name)
105 #define codeloc(f) ((f)->symvalue.funcv.beginaddr)
106 #define isblock(s) (Boolean) ( \
107     s->class == FUNC or s->class == PROC or \
108     s->class == MODULE or s->class == PROG \
109 )
110 #define isroutine(s) (Boolean) ( \
111     s->class == FUNC or s->class == PROC \
112 )
113 
114 #define nosource(f) (not (f)->symvalue.funcv.src)
115 #define isinline(f) ((f)->symvalue.funcv.inline)
116 
117 #include "tree.h"
118 
119 /*
120  * Some macros to make finding a symbol with certain attributes.
121  */
122 
123 #define find(s, withname) \
124 { \
125     s = lookup(withname); \
126     while (s != nil and not (s->name == (withname) and
127 
128 #define where /* qualification */
129 
130 #define endfind(s) )) { \
131 	s = s->next_sym; \
132     } \
133 }
134 
135 #endif
136 
137 /*
138  * Symbol table structure currently does not support deletions.
139  */
140 
141 #define HASHTABLESIZE 2003
142 
143 private Symbol hashtab[HASHTABLESIZE];
144 
145 #define hash(name) ((((unsigned) name) >> 2) mod HASHTABLESIZE)
146 
147 /*
148  * Allocate a new symbol.
149  */
150 
151 #define SYMBLOCKSIZE 100
152 
153 typedef struct Sympool {
154     struct Symbol sym[SYMBLOCKSIZE];
155     struct Sympool *prevpool;
156 } *Sympool;
157 
158 private Sympool sympool = nil;
159 private Integer nleft = 0;
160 
161 public Symbol symbol_alloc()
162 {
163     register Sympool newpool;
164 
165     if (nleft <= 0) {
166 	newpool = new(Sympool);
167 	bzero(newpool, sizeof(newpool));
168 	newpool->prevpool = sympool;
169 	sympool = newpool;
170 	nleft = SYMBLOCKSIZE;
171     }
172     --nleft;
173     return &(sympool->sym[nleft]);
174 }
175 
176 
177 public symbol_dump(func)
178 Symbol func;
179 {
180   register Symbol s;
181   register Integer i;
182 
183 	printf(" symbols in %s \n",symname(func));
184 	for(i=0; i< HASHTABLESIZE; i++)
185 	   for(s=hashtab[i]; s != nil; s=s->next_sym)  {
186 		if (s->block == func) psym(s);
187 		}
188 }
189 
190 /*
191  * Free all the symbols currently allocated.
192  */
193 public symbol_free()
194 {
195     Sympool s, t;
196     register Integer i;
197 
198     s = sympool;
199     while (s != nil) {
200 	t = s->prevpool;
201 	dispose(s);
202 	s = t;
203     }
204     for (i = 0; i < HASHTABLESIZE; i++) {
205 	hashtab[i] = nil;
206     }
207     sympool = nil;
208     nleft = 0;
209 }
210 
211 /*
212  * Create a new symbol with the given attributes.
213  */
214 
215 public Symbol newSymbol(name, blevel, class, type, chain)
216 Name name;
217 Integer blevel;
218 Symclass class;
219 Symbol type;
220 Symbol chain;
221 {
222     register Symbol s;
223 
224     s = symbol_alloc();
225     s->name = name;
226     s->level = blevel;
227     s->class = class;
228     s->type = type;
229     s->chain = chain;
230     return s;
231 }
232 
233 /*
234  * Insert a symbol into the hash table.
235  */
236 
237 public Symbol insert(name)
238 Name name;
239 {
240     register Symbol s;
241     register unsigned int h;
242 
243     h = hash(name);
244     s = symbol_alloc();
245     s->name = name;
246     s->next_sym = hashtab[h];
247     hashtab[h] = s;
248     return s;
249 }
250 
251 /*
252  * Symbol lookup.
253  */
254 
255 public Symbol lookup(name)
256 Name name;
257 {
258     register Symbol s;
259     register unsigned int h;
260 
261     h = hash(name);
262     s = hashtab[h];
263     while (s != nil and s->name != name) {
264 	s = s->next_sym;
265     }
266     return s;
267 }
268 
269 /*
270  * Delete a symbol from the symbol table.
271  */
272 
273 public delete (s)
274 Symbol s;
275 {
276     register Symbol t;
277     register unsigned int h;
278 
279     h = hash(s->name);
280     t = hashtab[h];
281     if (t == nil) {
282 	panic("delete of non-symbol '%s'", symname(s));
283     } else if (t == s) {
284 	hashtab[h] = s->next_sym;
285     } else {
286 	while (t->next_sym != s) {
287 	    t = t->next_sym;
288 	    if (t == nil) {
289 		panic("delete of non-symbol '%s'", symname(s));
290 	    }
291 	}
292 	t->next_sym = s->next_sym;
293     }
294 }
295 
296 /*
297  * Dump out all the variables associated with the given
298  * procedure, function, or program at the given recursive level.
299  *
300  * This is quite inefficient.  We traverse the entire symbol table
301  * each time we're called.  The assumption is that this routine
302  * won't be called frequently enough to merit improved performance.
303  */
304 
305 public dumpvars(f, frame)
306 Symbol f;
307 Frame frame;
308 {
309     register Integer i;
310     register Symbol s;
311 
312     for (i = 0; i < HASHTABLESIZE; i++) {
313 	for (s = hashtab[i]; s != nil; s = s->next_sym) {
314 	    if (container(s) == f) {
315 		if (should_print(s)) {
316 		    printv(s, frame);
317 		    putchar('\n');
318 		} else if (s->class == MODULE) {
319 		    dumpvars(s, frame);
320 		}
321 	    }
322 	}
323     }
324 }
325 
326 /*
327  * Create a builtin type.
328  * Builtin types are circular in that btype->type->type = btype.
329  */
330 
331 public Symbol maketype(name, lower, upper)
332 String name;
333 long lower;
334 long upper;
335 {
336     register Symbol s;
337 
338     s = newSymbol(identname(name, true), 0, TYPE, nil, nil);
339     s->language = primlang;
340     s->type = newSymbol(nil, 0, RANGE, s, nil);
341     s->type->language = s->language;
342     s->type->symvalue.rangev.lower = lower;
343     s->type->symvalue.rangev.upper = upper;
344     return s;
345 }
346 
347 /*
348  * These functions are now compiled inline.
349  *
350  * public String symname(s)
351 Symbol s;
352 {
353     checkref(s);
354     return ident(s->name);
355 }
356 
357  *
358  * public Address codeloc(f)
359 Symbol f;
360 {
361     checkref(f);
362     if (not isblock(f)) {
363 	panic("codeloc: \"%s\" is not a block", ident(f->name));
364     }
365     return f->symvalue.funcv.beginaddr;
366 }
367  *
368  */
369 
370 /*
371  * Reduce type to avoid worrying about type names.
372  */
373 
374 public Symbol rtype(type)
375 Symbol type;
376 {
377     register Symbol t;
378 
379     t = type;
380     if (t != nil) {
381 	if (t->class == VAR or t->class == FIELD or t->class == REF ) {
382 	    t = t->type;
383 	}
384 	if (t->class == TYPEREF) {
385 	    resolveRef(t);
386 	}
387 	while (t->class == TYPE or t->class == TAG) {
388 	    t = t->type;
389 	    if (t->class == TYPEREF) {
390 		resolveRef(t);
391 	    }
392 	}
393     }
394     return t;
395 }
396 
397 /*
398  * Find the end of a module name.  Return nil if there is none
399  * in the given string.
400  */
401 
402 private String findModuleMark (s)
403 String s;
404 {
405     register char *p, *r;
406     register boolean done;
407 
408     p = s;
409     done = false;
410     do {
411 	if (*p == ':') {
412 	    done = true;
413 	    r = p;
414 	} else if (*p == '\0') {
415 	    done = true;
416 	    r = nil;
417 	} else {
418 	    ++p;
419 	}
420     } while (not done);
421     return r;
422 }
423 
424 /*
425  * Resolve a type reference by modifying to be the appropriate type.
426  *
427  * If the reference has a name, then it refers to an opaque type and
428  * the actual type is directly accessible.  Otherwise, we must use
429  * the type reference string, which is of the form "module:{module:}name".
430  */
431 
432 public resolveRef (t)
433 Symbol t;
434 {
435     register char *p;
436     char *start;
437     Symbol s, m, outer;
438     Name n;
439 
440     if (t->name != nil) {
441 	s = t;
442     } else {
443 	start = t->symvalue.typeref;
444 	outer = program;
445 	p = findModuleMark(start);
446 	while (p != nil) {
447 	    *p = '\0';
448 	    n = identname(start, true);
449 	    find(m, n) where m->block == outer endfind(m);
450 	    if (m == nil) {
451 		p = nil;
452 		outer = nil;
453 		s = nil;
454 	    } else {
455 		outer = m;
456 		start = p + 1;
457 		p = findModuleMark(start);
458 	    }
459 	}
460 	if (outer != nil) {
461 	    n = identname(start, true);
462 	    find(s, n) where s->block == outer endfind(s);
463 	}
464     }
465     if (s != nil and s->type != nil) {
466 	t->name = s->type->name;
467 	t->class = s->type->class;
468 	t->type = s->type->type;
469 	t->chain = s->type->chain;
470 	t->symvalue = s->type->symvalue;
471 	t->block = s->type->block;
472     }
473 }
474 
475 public Integer level(s)
476 Symbol s;
477 {
478     checkref(s);
479     return s->level;
480 }
481 
482 public Symbol container(s)
483 Symbol s;
484 {
485     checkref(s);
486     return s->block;
487 }
488 
489 /*
490  * Return the object address of the given symbol.
491  *
492  * There are the following possibilities:
493  *
494  *	globals		- just take offset
495  *	locals		- take offset from locals base
496  *	arguments	- take offset from argument base
497  *	register	- offset is register number
498  */
499 
500 #define isglobal(s)		(s->level == 1)
501 #define islocaloff(s)		(s->level >= 2 and s->symvalue.offset < 0)
502 #define isparamoff(s)		(s->level >= 2 and s->symvalue.offset >= 0)
503 #define isreg(s)		(s->level < 0)
504 
505 public Address address(s, frame)
506 Symbol s;
507 Frame frame;
508 {
509     register Frame frp;
510     register Address addr;
511     register Symbol cur;
512 
513     checkref(s);
514     if (not isactive(s->block)) {
515 	error("\"%s\" is not currently defined", symname(s));
516     } else if (isglobal(s)) {
517 	addr = s->symvalue.offset;
518     } else {
519 	frp = frame;
520 	if (frp == nil) {
521 	    cur = s->block;
522 	    while (cur != nil and cur->class == MODULE) {
523 		cur = cur->block;
524 	    }
525 	    if (cur == nil) {
526 		cur = whatblock(pc);
527 	    }
528 	    frp = findframe(cur);
529 	    if (frp == nil) {
530 		panic("unexpected nil frame for \"%s\"", symname(s));
531 	    }
532 	}
533 	if (islocaloff(s)) {
534 	    addr = locals_base(frp) + s->symvalue.offset;
535 	} else if (isparamoff(s)) {
536 	    addr = args_base(frp) + s->symvalue.offset;
537 	} else if (isreg(s)) {
538 	    addr = savereg(s->symvalue.offset, frp);
539 	} else {
540 	    panic("address: bad symbol \"%s\"", symname(s));
541 	}
542     }
543     return addr;
544 }
545 
546 /*
547  * Define a symbol used to access register values.
548  */
549 
550 public defregname(n, r)
551 Name n;
552 Integer r;
553 {
554     register Symbol s, t;
555 
556     s = insert(n);
557     t = newSymbol(nil, 0, PTR, t_int, nil);
558     t->language = primlang;
559     s->language = t->language;
560     s->class = VAR;
561     s->level = -3;
562     s->type = t;
563     s->block = program;
564     s->symvalue.offset = r;
565 }
566 
567 /*
568  * Resolve an "abstract" type reference.
569  *
570  * It is possible in C to define a pointer to a type, but never define
571  * the type in a particular source file.  Here we try to resolve
572  * the type definition.  This is problematic, it is possible to
573  * have multiple, different definitions for the same name type.
574  */
575 
576 public findtype(s)
577 Symbol s;
578 {
579     register Symbol t, u, prev;
580 
581     u = s;
582     prev = nil;
583     while (u != nil and u->class != BADUSE) {
584 	if (u->name != nil) {
585 	    prev = u;
586 	}
587 	u = u->type;
588     }
589     if (prev == nil) {
590 	error("couldn't find link to type reference");
591     }
592     find(t, prev->name) where
593 	t != prev and t->block->class == MODULE and t->class == prev->class and
594 	t->type != nil and t->type->type != nil and
595 	t->type->type->class != BADUSE
596     endfind(t);
597     if (t == nil) {
598 	error("couldn't resolve reference");
599     } else {
600 	prev->type = t->type;
601     }
602 }
603 
604 /*
605  * Find the size in bytes of the given type.
606  *
607  * This is probably the WRONG thing to do.  The size should be kept
608  * as an attribute in the symbol information as is done for structures
609  * and fields.  I haven't gotten around to cleaning this up yet.
610  */
611 
612 #define MAXUCHAR 255
613 #define MAXUSHORT 65535L
614 #define MINCHAR -128
615 #define MAXCHAR 127
616 #define MINSHORT -32768
617 #define MAXSHORT 32767
618 
619 /*
620  * When necessary, compute the upper bound for an open array (Modula-2 style).
621  */
622 
623 public chkOpenArray (sym)
624 Symbol sym;
625 {
626     Symbol t;
627     Address a;
628     integer n;
629 
630     if (sym->class == REF or sym->class == VAR) {
631 	t = rtype(sym->type);
632 	if (t->class == ARRAY and t->chain == t_open) {
633 	    a = address(sym, nil);
634 	    dread(&n, a + sizeof(Word), sizeof(n));
635 	    t->chain->type->symvalue.rangev.upper = n - 1;
636 	}
637     }
638 }
639 
640 public findbounds (u, lower, upper)
641 Symbol u;
642 long *lower, *upper;
643 {
644     Rangetype lbt, ubt;
645     long lb, ub;
646 
647     if (u->class == RANGE) {
648 	lbt = u->symvalue.rangev.lowertype;
649 	ubt = u->symvalue.rangev.uppertype;
650 	lb = u->symvalue.rangev.lower;
651 	ub = u->symvalue.rangev.upper;
652 	if (lbt == R_ARG or lbt == R_TEMP) {
653 	    if (not getbound(u, lb, lbt, lower)) {
654 		error("dynamic bounds not currently available");
655 	    }
656 	} else {
657 	    *lower = lb;
658 	}
659 	if (ubt == R_ARG or ubt == R_TEMP) {
660 	    if (not getbound(u, ub, ubt, upper)) {
661 		error("dynamic bounds not currently available");
662 	    }
663 	} else {
664 	    *upper = ub;
665 	}
666     } else if (u->class == SCAL) {
667 	*lower = 0;
668 	*upper = u->symvalue.iconval - 1;
669     } else {
670 	panic("unexpected array bound type");
671     }
672 }
673 
674 public integer size(sym)
675 Symbol sym;
676 {
677     register Symbol s, t, u;
678     register integer nel, elsize;
679     long lower, upper;
680     integer r, off, len;
681 
682     t = sym;
683     checkref(t);
684     if (t->class == TYPEREF) {
685 	resolveRef(t);
686     }
687     switch (t->class) {
688 	case RANGE:
689 	    lower = t->symvalue.rangev.lower;
690 	    upper = t->symvalue.rangev.upper;
691 	    if (upper == 0 and lower > 0) {
692 		/* real */
693 		r = lower;
694 	    } else if (lower > upper) {
695 		/* unsigned long */
696 		r = sizeof(long);
697 	    } else if (
698   		(lower >= MINCHAR and upper <= MAXCHAR) or
699   		(lower >= 0 and upper <= MAXUCHAR)
700   	      ) {
701 		r = sizeof(char);
702   	    } else if (
703   		(lower >= MINSHORT and upper <= MAXSHORT) or
704   		(lower >= 0 and upper <= MAXUSHORT)
705   	      ) {
706 		r = sizeof(short);
707 	    } else {
708 		r = sizeof(long);
709 	    }
710 	    break;
711 
712 	case ARRAY:
713 	    elsize = size(t->type);
714 	    nel = 1;
715 	    for (t = t->chain; t != nil; t = t->chain) {
716 		u = rtype(t);
717 		findbounds(u, &lower, &upper);
718 		nel *= (upper-lower+1);
719 	    }
720 	    r = nel*elsize;
721 	    break;
722 
723 	case REF:
724 	case VAR:
725 	case FVAR:
726 	    chkOpenArray(t);
727 	    r = size(t->type);
728 	    /*
729 	     *
730 	    if (r < sizeof(Word) and isparam(t)) {
731 		r = sizeof(Word);
732 	    }
733 	    */
734 	    break;
735 
736 	case CONST:
737 	    r = size(t->type);
738 	    break;
739 
740 	case TYPE:
741 	    if (t->type->class == PTR and t->type->type->class == BADUSE) {
742 		findtype(t);
743 	    }
744 	    r = size(t->type);
745 	    break;
746 
747 	case TAG:
748 	    r = size(t->type);
749 	    break;
750 
751 	case FIELD:
752 	    off = t->symvalue.field.offset;
753 	    len = t->symvalue.field.length;
754 	    r = (off + len + 7) div 8 - (off div 8);
755 	    /* r = (t->symvalue.field.length + 7) div 8; */
756 	    break;
757 
758 	case RECORD:
759 	case VARNT:
760 	    r = t->symvalue.offset;
761 	    if (r == 0 and t->chain != nil) {
762 		panic("missing size information for record");
763 	    }
764 	    break;
765 
766 	case PTR:
767 	case FILET:
768 	    r = sizeof(Word);
769 	    break;
770 
771 	case SCAL:
772 	    r = sizeof(Word);
773 	    /*
774 	     *
775 	    if (t->symvalue.iconval > 255) {
776 		r = sizeof(short);
777 	    } else {
778 		r = sizeof(char);
779 	    }
780 	     *
781 	     */
782 	    break;
783 
784 	case FPROC:
785 	case FFUNC:
786 	    r = sizeof(Word);
787 	    break;
788 
789 	case PROC:
790 	case FUNC:
791 	case MODULE:
792 	case PROG:
793 	    r = sizeof(Symbol);
794 	    break;
795 
796 	case SET:
797 	    u = rtype(t->type);
798 	    switch (u->class) {
799 		case RANGE:
800 		    r = u->symvalue.rangev.upper - u->symvalue.rangev.lower + 1;
801 		    break;
802 
803 		case SCAL:
804 		    r = u->symvalue.iconval;
805 		    break;
806 
807 		default:
808 		    error("expected range for set base type");
809 		    break;
810 	    }
811 	    r = (r + BITSPERBYTE - 1) div BITSPERBYTE;
812 	    break;
813 
814 	default:
815 	    if (ord(t->class) > ord(TYPEREF)) {
816 		panic("size: bad class (%d)", ord(t->class));
817 	    } else {
818 		fprintf(stderr, "!! size(%s) ??", classname(t));
819 	    }
820 	    r = 0;
821 	    break;
822     }
823     return r;
824 }
825 
826 /*
827  * Test if a symbol is a parameter.  This is true if there
828  * is a cycle from s->block to s via chain pointers.
829  */
830 
831 public Boolean isparam(s)
832 Symbol s;
833 {
834     register Symbol t;
835 
836     t = s->block;
837     while (t != nil and t != s) {
838 	t = t->chain;
839     }
840     return (Boolean) (t != nil);
841 }
842 
843 /*
844  * Test if a type is an open array parameter type.
845  */
846 
847 public Boolean isopenarray (t)
848 Symbol t;
849 {
850     return (Boolean) (t->class == ARRAY and t->chain == t_open);
851 }
852 
853 /*
854  * Test if a symbol is a var parameter, i.e. has class REF but
855  * is not an open array parameter (those are treated special).
856  */
857 
858 public Boolean isvarparam(s)
859 Symbol s;
860 {
861     return (Boolean) (s->class == REF);
862 }
863 
864 /*
865  * Test if a symbol is a variable (actually any addressible quantity
866  * with do).
867  */
868 
869 public Boolean isvariable(s)
870 register Symbol s;
871 {
872     return (Boolean) (s->class == VAR or s->class == FVAR or s->class == REF);
873 }
874 
875 /*
876  * Test if a symbol is a block, e.g. function, procedure, or the
877  * main program.
878  *
879  * This function is now expanded inline for efficiency.
880  *
881  * public Boolean isblock(s)
882 register Symbol s;
883 {
884     return (Boolean) (
885 	s->class == FUNC or s->class == PROC or
886 	s->class == MODULE or s->class == PROG
887     );
888 }
889  *
890  */
891 
892 /*
893  * Test if a symbol is a module.
894  */
895 
896 public Boolean ismodule(s)
897 register Symbol s;
898 {
899     return (Boolean) (s->class == MODULE);
900 }
901 
902 /*
903  * Test if a symbol is builtin, that is, a predefined type or
904  * reserved word.
905  */
906 
907 public Boolean isbuiltin(s)
908 register Symbol s;
909 {
910     return (Boolean) (s->level == 0 and s->class != PROG and s->class != VAR);
911 }
912 
913 /*
914  * Mark a procedure or function as internal, meaning that it is called
915  * with a different calling sequence.
916  */
917 
918 public markInternal (s)
919 Symbol s;
920 {
921     s->symvalue.funcv.intern = true;
922 }
923 
924 public boolean isinternal (s)
925 Symbol s;
926 {
927     return s->symvalue.funcv.intern;
928 }
929 
930 /*
931  * Test if two types match.
932  * Equivalent names implies a match in any language.
933  *
934  * Special symbols must be handled with care.
935  */
936 
937 public Boolean compatible(t1, t2)
938 register Symbol t1, t2;
939 {
940     Boolean b;
941     Symbol rt1, rt2;
942 
943     if (t1 == t2) {
944 	b = true;
945     } else if (t1 == nil or t2 == nil) {
946 	b = false;
947     } else if (t1 == procsym) {
948 	b = isblock(t2);
949     } else if (t2 == procsym) {
950 	b = isblock(t1);
951     } else if (t1->language == primlang) {
952 	if (t2->language == primlang) {
953 	    rt1 = rtype(t1);
954 	    rt2 = rtype(t2);
955 	    b = (boolean) (
956 		(rt1->type == t_open and rt2->type == t_int) or
957 		(rt2->type == t_open and rt1->type == t_int) or
958 		rt1 == rt2
959 	    );
960 	} else {
961 	    b = (boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2);
962 	}
963     } else if (t2->language == primlang) {
964 	b = (boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2);
965     } else if (t1->language == nil) {
966 	if (t2->language == nil) {
967 	    b = false;
968 	} else {
969 	    b = (boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2);
970 	}
971     } else if (t2->language == nil) {
972 	b = (boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2);
973     } else if (isbuiltin(t1) or isbuiltin(t1->type)) {
974 	b = (boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2);
975     } else {
976 	b = (boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2);
977     }
978     return b;
979 }
980 
981 /*
982  * Check for a type of the given name.
983  */
984 
985 public Boolean istypename(type, name)
986 Symbol type;
987 String name;
988 {
989     Symbol t;
990     Boolean b;
991 
992     t = type;
993     checkref(t);
994     b = (Boolean) (
995 	t->class == TYPE and streq(ident(t->name), name)
996     );
997     return b;
998 }
999 
1000 /*
1001  * Determine if a (value) parameter should actually be passed by address.
1002  */
1003 
1004 public boolean passaddr (p, exprtype)
1005 Symbol p, exprtype;
1006 {
1007     boolean b;
1008     Language def;
1009 
1010     if (p == nil) {
1011 	def = findlanguage(".c");
1012 	b = (boolean) (*language_op(def, L_PASSADDR))(p, exprtype);
1013     } else if (p->language == nil or p->language == primlang) {
1014 	b = false;
1015     } else if (isopenarray(p->type)) {
1016 	b = true;
1017     } else {
1018 	b = (boolean) (*language_op(p->language, L_PASSADDR))(p, exprtype);
1019     }
1020     return b;
1021 }
1022 
1023 /*
1024  * Test if the name of a symbol is uniquely defined or not.
1025  */
1026 
1027 public Boolean isambiguous(s)
1028 register Symbol s;
1029 {
1030     register Symbol t;
1031 
1032     find(t, s->name) where t != s endfind(t);
1033     return (Boolean) (t != nil);
1034 }
1035 
1036 typedef char *Arglist;
1037 
1038 #define nextarg(type)  ((type *) (ap += sizeof(type)))[-1]
1039 
1040 private Symbol mkstring();
1041 private Symbol namenode();
1042 
1043 /*
1044  * Determine the type of a parse tree.
1045  * Also make some symbol-dependent changes to the tree such as
1046  * changing removing RVAL nodes for constant symbols.
1047  */
1048 
1049 public assigntypes(p)
1050 register Node p;
1051 {
1052     register Node p1;
1053     register Symbol s;
1054 
1055     switch (p->op) {
1056 	case O_SYM:
1057 	    p->nodetype = namenode(p);
1058 	    break;
1059 
1060 	case O_LCON:
1061 	    p->nodetype = t_int;
1062 	    break;
1063 
1064 	case O_FCON:
1065 	    p->nodetype = t_real;
1066 	    break;
1067 
1068 	case O_SCON:
1069 	    p->value.scon = strdup(p->value.scon);
1070 	    s = mkstring(p->value.scon);
1071 	    if (s == t_char) {
1072 		p->op = O_LCON;
1073 		p->value.lcon = p->value.scon[0];
1074 	    }
1075 	    p->nodetype = s;
1076 	    break;
1077 
1078 	case O_INDIR:
1079 	    p1 = p->value.arg[0];
1080 	    chkclass(p1, PTR);
1081 	    p->nodetype = rtype(p1->nodetype)->type;
1082 	    break;
1083 
1084 	case O_DOT:
1085 	    p->nodetype = p->value.arg[1]->value.sym;
1086 	    break;
1087 
1088 	case O_RVAL:
1089 	    p1 = p->value.arg[0];
1090 	    p->nodetype = p1->nodetype;
1091 	    if (p1->op == O_SYM) {
1092 		if (p1->nodetype->class == FUNC) {
1093 		    p->op = O_CALL;
1094 		    p->value.arg[1] = nil;
1095 		} else if (p1->value.sym->class == CONST) {
1096 		    if (compatible(p1->value.sym->type, t_real)) {
1097 			p->op = O_FCON;
1098 			p->value.fcon = p1->value.sym->symvalue.fconval;
1099 			p->nodetype = t_real;
1100 			dispose(p1);
1101 		    } else {
1102 			p->op = O_LCON;
1103 			p->value.lcon = p1->value.sym->symvalue.iconval;
1104 			p->nodetype = p1->value.sym->type;
1105 			dispose(p1);
1106 		    }
1107 		} else if (isreg(p1->value.sym)) {
1108 		    p->op = O_SYM;
1109 		    p->value.sym = p1->value.sym;
1110 		    dispose(p1);
1111 		}
1112 	    } else if (p1->op == O_INDIR and p1->value.arg[0]->op == O_SYM) {
1113 		s = p1->value.arg[0]->value.sym;
1114 		if (isreg(s)) {
1115 		    p1->op = O_SYM;
1116 		    dispose(p1->value.arg[0]);
1117 		    p1->value.sym = s;
1118 		    p1->nodetype = s;
1119 		}
1120 	    }
1121 	    break;
1122 
1123 	/*
1124 	 * Perform a cast if the call is of the form "type(expr)".
1125 	 */
1126 	case O_CALL:
1127 	    p1 = p->value.arg[0];
1128 	    p->nodetype = rtype(p1->nodetype)->type;
1129 	    break;
1130 
1131 	case O_TYPERENAME:
1132 	    p->nodetype = p->value.arg[1]->nodetype;
1133 	    break;
1134 
1135 	case O_ITOF:
1136 	    p->nodetype = t_real;
1137 	    break;
1138 
1139 	case O_NEG:
1140 	    s = p->value.arg[0]->nodetype;
1141 	    if (not compatible(s, t_int)) {
1142 		if (not compatible(s, t_real)) {
1143 		    beginerrmsg();
1144 		    fprintf(stderr, "\"");
1145 		    prtree(stderr, p->value.arg[0]);
1146 		    fprintf(stderr, "\" is improper type");
1147 		    enderrmsg();
1148 		} else {
1149 		    p->op = O_NEGF;
1150 		}
1151 	    }
1152 	    p->nodetype = s;
1153 	    break;
1154 
1155 	case O_ADD:
1156 	case O_SUB:
1157 	case O_MUL:
1158 	    binaryop(p, nil);
1159 	    break;
1160 
1161 	case O_LT:
1162 	case O_LE:
1163 	case O_GT:
1164 	case O_GE:
1165 	case O_EQ:
1166 	case O_NE:
1167 	    binaryop(p, t_boolean);
1168 	    break;
1169 
1170 	case O_DIVF:
1171 	    convert(&(p->value.arg[0]), t_real, O_ITOF);
1172 	    convert(&(p->value.arg[1]), t_real, O_ITOF);
1173 	    p->nodetype = t_real;
1174 	    break;
1175 
1176 	case O_DIV:
1177 	case O_MOD:
1178 	    convert(&(p->value.arg[0]), t_int, O_NOP);
1179 	    convert(&(p->value.arg[1]), t_int, O_NOP);
1180 	    p->nodetype = t_int;
1181 	    break;
1182 
1183 	case O_AND:
1184 	case O_OR:
1185 	    chkboolean(p->value.arg[0]);
1186 	    chkboolean(p->value.arg[1]);
1187 	    p->nodetype = t_boolean;
1188 	    break;
1189 
1190 	case O_QLINE:
1191 	    p->nodetype = t_int;
1192 	    break;
1193 
1194 	default:
1195 	    p->nodetype = nil;
1196 	    break;
1197     }
1198 }
1199 
1200 /*
1201  * Process a binary arithmetic or relational operator.
1202  * Convert from integer to real if necessary.
1203  */
1204 
1205 private binaryop (p, t)
1206 Node p;
1207 Symbol t;
1208 {
1209     Node p1, p2;
1210     Boolean t1real, t2real;
1211     Symbol t1, t2;
1212 
1213     p1 = p->value.arg[0];
1214     p2 = p->value.arg[1];
1215     t1 = rtype(p1->nodetype);
1216     t2 = rtype(p2->nodetype);
1217     t1real = compatible(t1, t_real);
1218     t2real = compatible(t2, t_real);
1219     if (t1real or t2real) {
1220 	p->op = (Operator) (ord(p->op) + 1);
1221 	if (not t1real) {
1222 	    p->value.arg[0] = build(O_ITOF, p1);
1223 	} else if (not t2real) {
1224 	    p->value.arg[1] = build(O_ITOF, p2);
1225 	}
1226 	p->nodetype = t_real;
1227     } else {
1228 	if (size(p1->nodetype) > sizeof(integer)) {
1229 	    beginerrmsg();
1230 	    fprintf(stderr, "operation not defined on \"");
1231 	    prtree(stderr, p1);
1232 	    fprintf(stderr, "\"");
1233 	    enderrmsg();
1234 	} else if (size(p2->nodetype) > sizeof(integer)) {
1235 	    beginerrmsg();
1236 	    fprintf(stderr, "operation not defined on \"");
1237 	    prtree(stderr, p2);
1238 	    fprintf(stderr, "\"");
1239 	    enderrmsg();
1240 	}
1241 	p->nodetype = t_int;
1242     }
1243     if (t != nil) {
1244 	p->nodetype = t;
1245     }
1246 }
1247 
1248 /*
1249  * Create a node for a name.  The symbol for the name has already
1250  * been chosen, either implicitly with "which" or explicitly from
1251  * the dot routine.
1252  */
1253 
1254 private Symbol namenode(p)
1255 Node p;
1256 {
1257     register Symbol r, s;
1258     register Node np;
1259 
1260     s = p->value.sym;
1261     if (s->class == REF) {
1262 	np = new(Node);
1263 	np->op = p->op;
1264 	np->nodetype = s;
1265 	np->value.sym = s;
1266 	p->op = O_INDIR;
1267 	p->value.arg[0] = np;
1268     }
1269 /*
1270  * Old way
1271  *
1272     if (s->class == CONST or s->class == VAR or s->class == FVAR) {
1273 	r = s->type;
1274     } else {
1275 	r = s;
1276     }
1277  *
1278  */
1279     return s;
1280 }
1281 
1282 /*
1283  * Convert a tree to a type via a conversion operator;
1284  * if this isn't possible generate an error.
1285  *
1286  * Note the tree is call by address, hence the #define below.
1287  */
1288 
1289 private convert(tp, typeto, op)
1290 Node *tp;
1291 Symbol typeto;
1292 Operator op;
1293 {
1294     Node tree;
1295     Symbol s, t;
1296 
1297     tree = *tp;
1298     s = rtype(tree->nodetype);
1299     t = rtype(typeto);
1300     if (compatible(t, t_real) and compatible(s, t_int)) {
1301 	tree = build(op, tree);
1302     } else if (not compatible(s, t)) {
1303 	beginerrmsg();
1304 	fprintf(stderr, "expected integer or real, found \"");
1305 	prtree(stderr, tree);
1306 	fprintf(stderr, "\"");
1307 	enderrmsg();
1308     } else if (op != O_NOP and s != t) {
1309 	tree = build(op, tree);
1310     }
1311     *tp = tree;
1312 }
1313 
1314 /*
1315  * Construct a node for the dot operator.
1316  *
1317  * If the left operand is not a record, but rather a procedure
1318  * or function, then we interpret the "." as referencing an
1319  * "invisible" variable; i.e. a variable within a dynamically
1320  * active block but not within the static scope of the current procedure.
1321  */
1322 
1323 public Node dot(record, fieldname)
1324 Node record;
1325 Name fieldname;
1326 {
1327     register Node p;
1328     register Symbol s, t;
1329 
1330     if (isblock(record->nodetype)) {
1331 	find(s, fieldname) where
1332 	    s->block == record->nodetype and
1333 	    s->class != FIELD and s->class != TAG
1334 	endfind(s);
1335 	if (s == nil) {
1336 	    beginerrmsg();
1337 	    fprintf(stderr, "\"%s\" is not defined in ", ident(fieldname));
1338 	    printname(stderr, record->nodetype);
1339 	    enderrmsg();
1340 	}
1341 	p = new(Node);
1342 	p->op = O_SYM;
1343 	p->value.sym = s;
1344 	p->nodetype = namenode(p);
1345     } else {
1346 	p = record;
1347 	t = rtype(p->nodetype);
1348 	if (t->class == PTR) {
1349 	    s = findfield(fieldname, t->type);
1350 	} else {
1351 	    s = findfield(fieldname, t);
1352 	}
1353 	if (s == nil) {
1354 	    beginerrmsg();
1355 	    fprintf(stderr, "\"%s\" is not a field in ", ident(fieldname));
1356 	    prtree(stderr, record);
1357 	    enderrmsg();
1358 	}
1359 	if (t->class == PTR and not isreg(record->nodetype)) {
1360 	    p = build(O_INDIR, record);
1361 	}
1362 	p = build(O_DOT, p, build(O_SYM, s));
1363     }
1364     return p;
1365 }
1366 
1367 /*
1368  * Return a tree corresponding to an array reference and do the
1369  * error checking.
1370  */
1371 
1372 public Node subscript(a, slist)
1373 Node a, slist;
1374 {
1375     Symbol t;
1376 
1377     t = rtype(a->nodetype);
1378     if (t->language == nil) {
1379 	error("unknown language");
1380     } else {
1381 	return (Node) (*language_op(t->language, L_BUILDAREF))(a, slist);
1382     }
1383 }
1384 
1385 /*
1386  * Evaluate a subscript index.
1387  */
1388 
1389 public int evalindex(s, i)
1390 Symbol s;
1391 long i;
1392 {
1393     Symbol t;
1394 
1395     t = rtype(s);
1396     if (t->language == nil) {
1397 	error("unknown language");
1398     } else {
1399 	return ((*language_op(t->language, L_EVALAREF)) (s, i));
1400     }
1401 }
1402 
1403 /*
1404  * Check to see if a tree is boolean-valued, if not it's an error.
1405  */
1406 
1407 public chkboolean(p)
1408 register Node p;
1409 {
1410     if (p->nodetype != t_boolean) {
1411 	beginerrmsg();
1412 	fprintf(stderr, "found ");
1413 	prtree(stderr, p);
1414 	fprintf(stderr, ", expected boolean expression");
1415 	enderrmsg();
1416     }
1417 }
1418 
1419 /*
1420  * Check to make sure the given tree has a type of the given class.
1421  */
1422 
1423 private chkclass(p, class)
1424 Node p;
1425 Symclass class;
1426 {
1427     struct Symbol tmpsym;
1428 
1429     tmpsym.class = class;
1430     if (rtype(p->nodetype)->class != class) {
1431 	beginerrmsg();
1432 	fprintf(stderr, "\"");
1433 	prtree(stderr, p);
1434 	fprintf(stderr, "\" is not a %s", classname(&tmpsym));
1435 	enderrmsg();
1436     }
1437 }
1438 
1439 /*
1440  * Construct a node for the type of a string.
1441  */
1442 
1443 private Symbol mkstring(str)
1444 String str;
1445 {
1446     register char *p, *q;
1447     register Symbol s;
1448     integer len;
1449 
1450     p = str;
1451     q = str;
1452     while (*p != '\0') {
1453 	if (*p == '\\') {
1454 	    ++p;
1455 	}
1456 	*q = *p;
1457 	++p;
1458 	++q;
1459     }
1460     *q = '\0';
1461     len = p - str;
1462     if (len == 1) {
1463 	s = t_char;
1464     } else {
1465 	s = newSymbol(nil, 0, ARRAY, t_char, nil);
1466 	s->language = primlang;
1467 	s->chain = newSymbol(nil, 0, RANGE, t_int, nil);
1468 	s->chain->language = s->language;
1469 	s->chain->symvalue.rangev.lower = 1;
1470 	s->chain->symvalue.rangev.upper = len + 1;
1471     }
1472     return s;
1473 }
1474 
1475 /*
1476  * Free up the space allocated for a string type.
1477  */
1478 
1479 public unmkstring(s)
1480 Symbol s;
1481 {
1482     dispose(s->chain);
1483 }
1484 
1485 /*
1486  * Figure out the "current" variable or function being referred to,
1487  * this is either the active one or the most visible from the
1488  * current scope.
1489  */
1490 
1491 public Symbol which(n)
1492 Name n;
1493 {
1494     register Symbol s, p, t, f;
1495 
1496     find(s, n) where s->class != FIELD and s->class != TAG endfind(s);
1497     if (s == nil) {
1498 	s = lookup(n);
1499     }
1500     if (s == nil) {
1501 	error("\"%s\" is not defined", ident(n));
1502     } else if (s == program or isbuiltin(s)) {
1503 	t = s;
1504     } else {
1505     /*
1506      * Old way
1507      *
1508 	if (not isactive(program)) {
1509 	    f = program;
1510 	} else {
1511 	    f = whatblock(pc);
1512 	    if (f == nil) {
1513 		panic("no block for addr 0x%x", pc);
1514 	    }
1515 	}
1516      *
1517      * Now start with curfunc.
1518      */
1519 	p = curfunc;
1520 	do {
1521 	    find(t, n) where
1522 		t->block == p and t->class != FIELD and t->class != TAG
1523 	    endfind(t);
1524 	    p = p->block;
1525 	} while (t == nil and p != nil);
1526 	if (t == nil) {
1527 	    t = s;
1528 	}
1529     }
1530     return t;
1531 }
1532 
1533 /*
1534  * Find the symbol which is has the same name and scope as the
1535  * given symbol but is of the given field.  Return nil if there is none.
1536  */
1537 
1538 public Symbol findfield(fieldname, record)
1539 Name fieldname;
1540 Symbol record;
1541 {
1542     register Symbol t;
1543 
1544     t = rtype(record)->chain;
1545     while (t != nil and t->name != fieldname) {
1546 	t = t->chain;
1547     }
1548     return t;
1549 }
1550 
1551 public Boolean getbound(s,off,type,valp)
1552 Symbol s;
1553 int off;
1554 Rangetype type;
1555 int *valp;
1556 {
1557     Frame frp;
1558     Address addr;
1559     Symbol cur;
1560 
1561     if (not isactive(s->block)) {
1562 	return(false);
1563     }
1564     cur = s->block;
1565     while (cur != nil and cur->class == MODULE) {  /* WHY*/
1566     		cur = cur->block;
1567     }
1568     if(cur == nil) {
1569 		cur = whatblock(pc);
1570     }
1571     frp = findframe(cur);
1572     if (frp == nil) {
1573 	return(false);
1574     }
1575     if(type == R_TEMP) addr = locals_base(frp) + off;
1576     else if (type == R_ARG) addr = args_base(frp) + off;
1577     else return(false);
1578     dread(valp,addr,sizeof(long));
1579     return(true);
1580 }
1581