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