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