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