xref: /csrg-svn/old/dbx/symbols.c (revision 12609)
1 /* Copyright (c) 1982 Regents of the University of California */
2 
3 static char sccsid[] = "@(#)symbols.c 1.9 05/20/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 		if (t->symvalue.rangev.lowertype == R_ARG or
530 		  t->symvalue.rangev.lowertype == R_TEMP)  {
531 		    if (not getbound(t, t->symvalue.rangev.lower,
532 		      t->symvalue.rangev.lowertype, &lower)) {
533 			error("dynamic bounds not currently available");
534 		    }
535 		} else {
536 		    lower = t->symvalue.rangev.lower;
537 		}
538 		if (t->symvalue.rangev.uppertype == R_ARG or
539 		  t->symvalue.rangev.uppertype == R_TEMP) {
540 		    if (not getbound(t, t->symvalue.rangev.upper,
541 		      t->symvalue.rangev.uppertype, &upper)) {
542 			error("dynamic bounds nor currently available");
543 		    }
544 		} else {
545 		    upper = t->symvalue.rangev.upper;
546 		}
547 		nel *= (upper-lower+1);
548 	    }
549 	    r = nel*elsize;
550 	    break;
551 
552 	case REF:
553 	case VAR:
554 	case FVAR:
555 	    r = size(t->type);
556 	    /*
557 	     *
558 	    if (r < sizeof(Word) and isparam(t)) {
559 		r = sizeof(Word);
560 	    }
561 	    */
562 	    break;
563 
564 	case CONST:
565 	    r = size(t->type);
566 	    break;
567 
568 	case TYPE:
569 	    if (t->type->class == PTR and t->type->type->class == BADUSE) {
570 		findtype(t);
571 	    }
572 	    r = size(t->type);
573 	    break;
574 
575 	case TAG:
576 	    r = size(t->type);
577 	    break;
578 
579 	case FIELD:
580 	    r = (t->symvalue.field.length + 7) div 8;
581 	    break;
582 
583 	case RECORD:
584 	case VARNT:
585 	    r = t->symvalue.offset;
586 	    if (r == 0 and t->chain != nil) {
587 		panic("missing size information for record");
588 	    }
589 	    break;
590 
591 	case PTR:
592 	case FILET:
593 	    r = sizeof(Word);
594 	    break;
595 
596 	case SCAL:
597 	    r = sizeof(Word);
598 	    /*
599 	     *
600 	    if (t->symvalue.iconval > 255) {
601 		r = sizeof(short);
602 	    } else {
603 		r = sizeof(char);
604 	    }
605 	     *
606 	     */
607 	    break;
608 
609 	case FPROC:
610 	case FFUNC:
611 	    r = sizeof(Word);
612 	    break;
613 
614 	case PROC:
615 	case FUNC:
616 	case MODULE:
617 	case PROG:
618 	    r = sizeof(Symbol);
619 	    break;
620 
621 	default:
622 	    if (ord(t->class) > ord(TYPEREF)) {
623 		panic("size: bad class (%d)", ord(t->class));
624 	    } else {
625 		error("improper operation on a %s", classname(t));
626 	    }
627 	    /* NOTREACHED */
628     }
629     return r;
630 }
631 
632 /*
633  * Test if a symbol is a parameter.  This is true if there
634  * is a cycle from s->block to s via chain pointers.
635  */
636 
637 public Boolean isparam(s)
638 Symbol s;
639 {
640     register Symbol t;
641 
642     t = s->block;
643     while (t != nil and t != s) {
644 	t = t->chain;
645     }
646     return (Boolean) (t != nil);
647 }
648 
649 /*
650  * Test if a symbol is a var parameter, i.e. has class REF.
651  */
652 
653 public Boolean isvarparam(s)
654 Symbol s;
655 {
656     return (Boolean) (s->class == REF);
657 }
658 
659 /*
660  * Test if a symbol is a variable (actually any addressible quantity
661  * with do).
662  */
663 
664 public Boolean isvariable(s)
665 register Symbol s;
666 {
667     return (Boolean) (s->class == VAR or s->class == FVAR or s->class == REF);
668 }
669 
670 /*
671  * Test if a symbol is a block, e.g. function, procedure, or the
672  * main program.
673  *
674  * This function is now expanded inline for efficiency.
675  *
676  * public Boolean isblock(s)
677 register Symbol s;
678 {
679     return (Boolean) (
680 	s->class == FUNC or s->class == PROC or
681 	s->class == MODULE or s->class == PROG
682     );
683 }
684  *
685  */
686 
687 /*
688  * Test if a symbol is a module.
689  */
690 
691 public Boolean ismodule(s)
692 register Symbol s;
693 {
694     return (Boolean) (s->class == MODULE);
695 }
696 
697 /*
698  * Test if a symbol is builtin, that is, a predefined type or
699  * reserved word.
700  */
701 
702 public Boolean isbuiltin(s)
703 register Symbol s;
704 {
705     return (Boolean) (s->level == 0 and s->class != PROG and s->class != VAR);
706 }
707 
708 /*
709  * Test if two types match.
710  * Equivalent names implies a match in any language.
711  *
712  * Special symbols must be handled with care.
713  */
714 
715 public Boolean compatible(t1, t2)
716 register Symbol t1, t2;
717 {
718     Boolean b;
719 
720     if (t1 == t2) {
721 	b = true;
722     } else if (t1 == nil or t2 == nil) {
723 	b = false;
724     } else if (t1 == procsym) {
725 	b = isblock(t2);
726     } else if (t2 == procsym) {
727 	b = isblock(t1);
728     } else if (t1->language == nil) {
729 	b = (Boolean) (t2->language == nil or
730 	    (*language_op(t2->language, L_TYPEMATCH))(t1, t2));
731     } else if (t2->language == nil) {
732 	b = (Boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2);
733     } else if ( isbuiltin(t1) or isbuiltin(t1->type) ) {
734 	b = (Boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2);
735     } else {
736 	b = (Boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2);
737     }
738     return b;
739 }
740 
741 /*
742  * Check for a type of the given name.
743  */
744 
745 public Boolean istypename(type, name)
746 Symbol type;
747 String name;
748 {
749     Symbol t;
750     Boolean b;
751 
752     t = type;
753     checkref(t);
754     b = (Boolean) (
755 	t->class == TYPE and t->name == identname(name, true)
756     );
757     return b;
758 }
759 
760 /*
761  * Test if the name of a symbol is uniquely defined or not.
762  */
763 
764 public Boolean isambiguous(s)
765 register Symbol s;
766 {
767     register Symbol t;
768 
769     find(t, s->name) where t != s endfind(t);
770     return (Boolean) (t != nil);
771 }
772 
773 typedef char *Arglist;
774 
775 #define nextarg(type)  ((type *) (ap += sizeof(type)))[-1]
776 
777 private Symbol mkstring();
778 private Symbol namenode();
779 
780 /*
781  * Determine the type of a parse tree.
782  * Also make some symbol-dependent changes to the tree such as
783  * changing removing RVAL nodes for constant symbols.
784  */
785 
786 public assigntypes(p)
787 register Node p;
788 {
789     register Node p1;
790     register Symbol s;
791 
792     switch (p->op) {
793 	case O_SYM:
794 	    p->nodetype = namenode(p);
795 	    break;
796 
797 	case O_LCON:
798 	    p->nodetype = t_int;
799 	    break;
800 
801 	case O_FCON:
802 	    p->nodetype = t_real;
803 	    break;
804 
805 	case O_SCON:
806 	    p->value.scon = strdup(p->value.scon);
807 	    s = mkstring(p->value.scon);
808 	    if (s == t_char) {
809 		p->op = O_LCON;
810 		p->value.lcon = p->value.scon[0];
811 	    }
812 	    p->nodetype = s;
813 	    break;
814 
815 	case O_INDIR:
816 	    p1 = p->value.arg[0];
817 	    chkclass(p1, PTR);
818 	    p->nodetype = rtype(p1->nodetype)->type;
819 	    break;
820 
821 	case O_DOT:
822 	    p->nodetype = p->value.arg[1]->value.sym;
823 	    break;
824 
825 	case O_RVAL:
826 	    p1 = p->value.arg[0];
827 	    p->nodetype = p1->nodetype;
828 	    if (p1->op == O_SYM) {
829 		if (p1->nodetype->class == FUNC) {
830 		    p->op = O_CALL;
831 		    p->value.arg[1] = nil;
832 		} else if (p1->value.sym->class == CONST) {
833 		    if (compatible(p1->value.sym->type, t_real)) {
834 			p->op = O_FCON;
835 			p->value.fcon = p1->value.sym->symvalue.fconval;
836 			p->nodetype = t_real;
837 			dispose(p1);
838 		    } else {
839 			p->op = O_LCON;
840 			p->value.lcon = p1->value.sym->symvalue.iconval;
841 			p->nodetype = p1->value.sym->type;
842 			dispose(p1);
843 		    }
844 		} else if (isreg(p1->value.sym)) {
845 		    p->op = O_SYM;
846 		    p->value.sym = p1->value.sym;
847 		    dispose(p1);
848 		}
849 	    } else if (p1->op == O_INDIR and p1->value.arg[0]->op == O_SYM) {
850 		s = p1->value.arg[0]->value.sym;
851 		if (isreg(s)) {
852 		    p1->op = O_SYM;
853 		    dispose(p1->value.arg[0]);
854 		    p1->value.sym = s;
855 		    p1->nodetype = s;
856 		}
857 	    }
858 	    break;
859 
860 	/*
861 	 * Perform a cast if the call is of the form "type(expr)".
862 	 */
863 	case O_CALL:
864 	    p1 = p->value.arg[0];
865 	    p->nodetype = rtype(p1->nodetype)->type;
866 	    break;
867 
868 	case O_TYPERENAME:
869 	    p->nodetype = p->value.arg[1]->nodetype;
870 	    break;
871 
872 	case O_ITOF:
873 	    p->nodetype = t_real;
874 	    break;
875 
876 	case O_NEG:
877 	    s = p->value.arg[0]->nodetype;
878 	    if (not compatible(s, t_int)) {
879 		if (not compatible(s, t_real)) {
880 		    beginerrmsg();
881 		    prtree(stderr, p->value.arg[0]);
882 		    fprintf(stderr, "is improper type");
883 		    enderrmsg();
884 		} else {
885 		    p->op = O_NEGF;
886 		}
887 	    }
888 	    p->nodetype = s;
889 	    break;
890 
891 	case O_ADD:
892 	case O_SUB:
893 	case O_MUL:
894 	case O_LT:
895 	case O_LE:
896 	case O_GT:
897 	case O_GE:
898 	case O_EQ:
899 	case O_NE:
900 	{
901 	    Boolean t1real, t2real;
902 	    Symbol t1, t2;
903 
904 	    t1 = rtype(p->value.arg[0]->nodetype);
905 	    t2 = rtype(p->value.arg[1]->nodetype);
906 	    t1real = compatible(t1, t_real);
907 	    t2real = compatible(t2, t_real);
908 	    if (t1real or t2real) {
909 		p->op = (Operator) (ord(p->op) + 1);
910 		if (not t1real) {
911 		    p->value.arg[0] = build(O_ITOF, p->value.arg[0]);
912 		} else if (not t2real) {
913 		    p->value.arg[1] = build(O_ITOF, p->value.arg[1]);
914 		}
915 	    } else {
916 		if (t1real) {
917 		    convert(&(p->value.arg[0]), t_int, O_NOP);
918 		}
919 		if (t2real) {
920 		    convert(&(p->value.arg[1]), t_int, O_NOP);
921 		}
922 	    }
923 	    if (ord(p->op) >= ord(O_LT)) {
924 		p->nodetype = t_boolean;
925 	    } else {
926 		if (t1real or t2real) {
927 		    p->nodetype = t_real;
928 		} else {
929 		    p->nodetype = t_int;
930 		}
931 	    }
932 	    break;
933 	}
934 
935 	case O_DIVF:
936 	    convert(&(p->value.arg[0]), t_real, O_ITOF);
937 	    convert(&(p->value.arg[1]), t_real, O_ITOF);
938 	    p->nodetype = t_real;
939 	    break;
940 
941 	case O_DIV:
942 	case O_MOD:
943 	    convert(&(p->value.arg[0]), t_int, O_NOP);
944 	    convert(&(p->value.arg[1]), t_int, O_NOP);
945 	    p->nodetype = t_int;
946 	    break;
947 
948 	case O_AND:
949 	case O_OR:
950 	    chkboolean(p->value.arg[0]);
951 	    chkboolean(p->value.arg[1]);
952 	    p->nodetype = t_boolean;
953 	    break;
954 
955 	case O_QLINE:
956 	    p->nodetype = t_int;
957 	    break;
958 
959 	default:
960 	    p->nodetype = nil;
961 	    break;
962     }
963 }
964 
965 /*
966  * Create a node for a name.  The symbol for the name has already
967  * been chosen, either implicitly with "which" or explicitly from
968  * the dot routine.
969  */
970 
971 private Symbol namenode(p)
972 Node p;
973 {
974     register Symbol r, s;
975     register Node np;
976 
977     s = p->value.sym;
978     if (s->class == REF) {
979 	np = new(Node);
980 	np->op = p->op;
981 	np->nodetype = s;
982 	np->value.sym = s;
983 	p->op = O_INDIR;
984 	p->value.arg[0] = np;
985     }
986 /*
987  * Old way
988  *
989     if (s->class == CONST or s->class == VAR or s->class == FVAR) {
990 	r = s->type;
991     } else {
992 	r = s;
993     }
994  *
995  */
996     return s;
997 }
998 
999 /*
1000  * Convert a tree to a type via a conversion operator;
1001  * if this isn't possible generate an error.
1002  *
1003  * Note the tree is call by address, hence the #define below.
1004  */
1005 
1006 private convert(tp, typeto, op)
1007 Node *tp;
1008 Symbol typeto;
1009 Operator op;
1010 {
1011 #define tree    (*tp)
1012 
1013     Symbol s;
1014 
1015     s = rtype(tree->nodetype);
1016     typeto = rtype(typeto);
1017     if (compatible(typeto, t_real) and compatible(s, t_int)) {
1018 	tree = build(op, tree);
1019     } else if (not compatible(s, typeto)) {
1020 	beginerrmsg();
1021 	prtree(stderr, s);
1022 	fprintf(stderr, " is improper type");
1023 	enderrmsg();
1024     } else if (op != O_NOP and s != typeto) {
1025 	tree = build(op, tree);
1026     }
1027 
1028 #undef tree
1029 }
1030 
1031 /*
1032  * Construct a node for the dot operator.
1033  *
1034  * If the left operand is not a record, but rather a procedure
1035  * or function, then we interpret the "." as referencing an
1036  * "invisible" variable; i.e. a variable within a dynamically
1037  * active block but not within the static scope of the current procedure.
1038  */
1039 
1040 public Node dot(record, fieldname)
1041 Node record;
1042 Name fieldname;
1043 {
1044     register Node p;
1045     register Symbol s, t;
1046 
1047     if (isblock(record->nodetype)) {
1048 	find(s, fieldname) where
1049 	    s->block == record->nodetype and
1050 	    s->class != FIELD and s->class != TAG
1051 	endfind(s);
1052 	if (s == nil) {
1053 	    beginerrmsg();
1054 	    fprintf(stderr, "\"%s\" is not defined in ", ident(fieldname));
1055 	    printname(stderr, record->nodetype);
1056 	    enderrmsg();
1057 	}
1058 	p = new(Node);
1059 	p->op = O_SYM;
1060 	p->value.sym = s;
1061 	p->nodetype = namenode(p);
1062     } else {
1063 	p = record;
1064 	t = rtype(p->nodetype);
1065 	if (t->class == PTR) {
1066 	    s = findfield(fieldname, t->type);
1067 	} else {
1068 	    s = findfield(fieldname, t);
1069 	}
1070 	if (s == nil) {
1071 	    beginerrmsg();
1072 	    fprintf(stderr, "\"%s\" is not a field in ", ident(fieldname));
1073 	    prtree(stderr, record);
1074 	    enderrmsg();
1075 	}
1076 	if (t->class == PTR and not isreg(record->nodetype)) {
1077 	    p = build(O_INDIR, record);
1078 	}
1079 	p = build(O_DOT, p, build(O_SYM, s));
1080     }
1081     return p;
1082 }
1083 
1084 /*
1085  * Return a tree corresponding to an array reference and do the
1086  * error checking.
1087  */
1088 
1089 public Node subscript(a, slist)
1090 Node a, slist;
1091 {
1092 Symbol t;
1093 
1094    t = rtype(a->nodetype);
1095    if(t->language == nil) {
1096 	error("unknown language");
1097    }
1098    else {
1099         return ( (Node)
1100         (*language_op(t->language, L_BUILDAREF)) (a,slist)
1101                );
1102    }
1103 }
1104 
1105 /*
1106  * Evaluate a subscript index.
1107  */
1108 
1109 public int evalindex(s, i)
1110 Symbol s;
1111 long i;
1112 {
1113 Symbol t;
1114 
1115    t = rtype(s);
1116    if(t->language == nil) {
1117 	error("unknown language");
1118    }
1119    else {
1120         return (
1121              (*language_op(t->language, L_EVALAREF)) (s,i)
1122                );
1123    }
1124 }
1125 
1126 /*
1127  * Check to see if a tree is boolean-valued, if not it's an error.
1128  */
1129 
1130 public chkboolean(p)
1131 register Node p;
1132 {
1133     if (p->nodetype != t_boolean) {
1134 	beginerrmsg();
1135 	fprintf(stderr, "found ");
1136 	prtree(stderr, p);
1137 	fprintf(stderr, ", expected boolean expression");
1138 	enderrmsg();
1139     }
1140 }
1141 
1142 /*
1143  * Check to make sure the given tree has a type of the given class.
1144  */
1145 
1146 private chkclass(p, class)
1147 Node p;
1148 Symclass class;
1149 {
1150     struct Symbol tmpsym;
1151 
1152     tmpsym.class = class;
1153     if (rtype(p->nodetype)->class != class) {
1154 	beginerrmsg();
1155 	fprintf(stderr, "\"");
1156 	prtree(stderr, p);
1157 	fprintf(stderr, "\" is not a %s", classname(&tmpsym));
1158 	enderrmsg();
1159     }
1160 }
1161 
1162 /*
1163  * Construct a node for the type of a string.  While we're at it,
1164  * scan the string for '' that collapse to ', and chop off the ends.
1165  */
1166 
1167 private Symbol mkstring(str)
1168 String str;
1169 {
1170     register char *p, *q;
1171     register Symbol s;
1172 
1173     p = str;
1174     q = str;
1175     while (*p != '\0') {
1176 	if (*p == '\\') {
1177 	    ++p;
1178 	}
1179 	*q = *p;
1180 	++p;
1181 	++q;
1182     }
1183     *q = '\0';
1184     s = newSymbol(nil, 0, ARRAY, t_char, nil);
1185     s->language = findlanguage(".s");
1186     s->chain = newSymbol(nil, 0, RANGE, t_int, nil);
1187     s->chain->language = s->language;
1188     s->chain->symvalue.rangev.lower = 1;
1189     s->chain->symvalue.rangev.upper = p - str + 1;
1190     return s;
1191 }
1192 
1193 /*
1194  * Free up the space allocated for a string type.
1195  */
1196 
1197 public unmkstring(s)
1198 Symbol s;
1199 {
1200     dispose(s->chain);
1201 }
1202 
1203 /*
1204  * Figure out the "current" variable or function being referred to,
1205  * this is either the active one or the most visible from the
1206  * current scope.
1207  */
1208 
1209 public Symbol which(n)
1210 Name n;
1211 {
1212     register Symbol s, p, t, f;
1213 
1214     find(s, n) where s->class != FIELD and s->class != TAG endfind(s);
1215     if (s == nil) {
1216 	s = lookup(n);
1217     }
1218     if (s == nil) {
1219 	error("\"%s\" is not defined", ident(n));
1220     } else if (s == program or isbuiltin(s)) {
1221 	t = s;
1222     } else {
1223     /*
1224      * Old way
1225      *
1226 	if (not isactive(program)) {
1227 	    f = program;
1228 	} else {
1229 	    f = whatblock(pc);
1230 	    if (f == nil) {
1231 		panic("no block for addr 0x%x", pc);
1232 	    }
1233 	}
1234      *
1235      * Now start with curfunc.
1236      */
1237 	p = curfunc;
1238 	do {
1239 	    find(t, n) where
1240 		t->block == p and t->class != FIELD and t->class != TAG
1241 	    endfind(t);
1242 	    p = p->block;
1243 	} while (t == nil and p != nil);
1244 	if (t == nil) {
1245 	    t = s;
1246 	}
1247     }
1248     return t;
1249 }
1250 
1251 /*
1252  * Find the symbol which is has the same name and scope as the
1253  * given symbol but is of the given field.  Return nil if there is none.
1254  */
1255 
1256 public Symbol findfield(fieldname, record)
1257 Name fieldname;
1258 Symbol record;
1259 {
1260     register Symbol t;
1261 
1262     t = rtype(record)->chain;
1263     while (t != nil and t->name != fieldname) {
1264 	t = t->chain;
1265     }
1266     return t;
1267 }
1268 
1269 public Boolean getbound(s,off,type,valp)
1270 Symbol s;
1271 int off;
1272 Rangetype type;
1273 int *valp;
1274 {
1275     Frame frp;
1276     Address addr;
1277     Symbol cur;
1278 
1279     if (not isactive(s->block)) {
1280 	return(false);
1281     }
1282     cur = s->block;
1283     while (cur != nil and cur->class == MODULE) {  /* WHY*/
1284     		cur = cur->block;
1285     }
1286     if(cur == nil) {
1287 		cur = whatblock(pc);
1288     }
1289     frp = findframe(cur);
1290     if (frp == nil) {
1291 	return(false);
1292     }
1293     if(type == R_TEMP) addr = locals_base(frp) + off;
1294     else if (type == R_ARG) addr = args_base(frp) + off;
1295     else return(false);
1296     dread(valp,addr,sizeof(long));
1297     return(true);
1298 }
1299