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