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