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