changes for new printer daemon.
[unix-history] / usr / src / old / dbx / symbols.c
CommitLineData
8a21415b
ML
1/* Copyright (c) 1982 Regents of the University of California */
2
99552332 3static char sccsid[] = "@(#)symbols.c 1.6 %G%";
8a21415b
ML
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
24typedef struct Symbol *Symbol;
25
26#include "machine.h"
27#include "names.h"
28#include "languages.h"
29
30/*
31 * Symbol classes
32 */
33
34typedef 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
41struct 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;
5455a470
ML
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 */
8a21415b
ML
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
79Symbol t_boolean;
80Symbol t_char;
81Symbol t_int;
82Symbol t_real;
83Symbol t_nil;
84
85Symbol program;
86Symbol 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
5455a470
ML
95#define nosource(f) (not (f)->symvalue.funcv.src)
96
8a21415b
ML
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
123private Symbol hashtab[HASHTABLESIZE];
124
125#define hash(name) ((((unsigned) name) >> 2) mod HASHTABLESIZE)
126
127/*
128 * Allocate a new symbol.
129 */
130
74dabb40 131#define SYMBLOCKSIZE 100
8a21415b
ML
132
133typedef struct Sympool {
134 struct Symbol sym[SYMBLOCKSIZE];
135 struct Sympool *prevpool;
136} *Sympool;
137
138private Sympool sympool = nil;
139private Integer nleft = 0;
8a21415b
ML
140
141public Symbol symbol_alloc()
142{
143 register Sympool newpool;
144
145 if (nleft <= 0) {
146 newpool = new(Sympool);
74dabb40 147 bzero(newpool, sizeof(newpool));
8a21415b
ML
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
160public 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
182public Symbol newSymbol(name, blevel, class, type, chain)
183Name name;
184Integer blevel;
185Symclass class;
186Symbol type;
187Symbol 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
204public Symbol insert(name)
205Name 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
222public Symbol lookup(name)
223Name 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
245public dumpvars(f, frame)
246Symbol f;
247Frame 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
271public Symbol maketype(name, lower, upper)
272String name;
273long lower;
274long 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)
290Symbol s;
291{
292 checkref(s);
293 return ident(s->name);
294}
295
296 *
297 * public Address codeloc(f)
298Symbol 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
313public Symbol rtype(type)
314Symbol 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
330public Integer level(s)
331Symbol s;
332{
333 checkref(s);
334 return s->level;
335}
336
337public Symbol container(s)
338Symbol 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
360public Address address(s, frame)
361Symbol s;
362Frame 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
405public defregname(n, r)
406Name n;
407Integer 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
431public findtype(s)
432Symbol 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
99552332 468#define MAXUCHAR 255
8a21415b
ML
469#define MINSHORT -32768
470#define MAXSHORT 32767
99552332 471#define MAXUSHORT 65535L
8a21415b
ML
472
473public Integer size(sym)
474Symbol sym;
475{
476 register Symbol s, t;
477 register int nel, elsize;
478 long lower, upper;
479 int r;
480
481 t = sym;
482 checkref(t);
483 switch (t->class) {
484 case RANGE:
485 lower = t->symvalue.rangev.lower;
486 upper = t->symvalue.rangev.upper;
487 if (upper == 0 and lower > 0) { /* real */
488 r = lower;
99552332
ML
489 } else if (
490 (lower >= MINCHAR and upper <= MAXCHAR) or
491 (lower >= 0 and upper <= MAXUCHAR)
492 ) {
8a21415b 493 r = sizeof(char);
99552332
ML
494 } else if (
495 (lower >= MINSHORT and upper <= MAXSHORT) or
496 (lower >= 0 and upper <= MAXUSHORT)
497 ) {
8a21415b
ML
498 r = sizeof(short);
499 } else {
500 r = sizeof(long);
501 }
502 break;
503
504 case ARRAY:
505 elsize = size(t->type);
506 nel = 1;
507 for (t = t->chain; t != nil; t = t->chain) {
508 s = rtype(t);
509 lower = s->symvalue.rangev.lower;
510 upper = s->symvalue.rangev.upper;
511 nel *= (upper-lower+1);
512 }
513 r = nel*elsize;
514 break;
515
516 case VAR:
517 case FVAR:
518 r = size(t->type);
99552332 519 if (r < sizeof(Word) and isparam(t)) {
8a21415b
ML
520 r = sizeof(Word);
521 }
522 break;
523
524 case CONST:
525 r = size(t->type);
526 break;
527
528 case TYPE:
529 if (t->type->class == PTR and t->type->type->class == BADUSE) {
530 findtype(t);
531 }
532 r = size(t->type);
533 break;
534
535 case TAG:
536 r = size(t->type);
537 break;
538
539 case FIELD:
540 r = (t->symvalue.field.length + 7) div 8;
541 break;
542
543 case RECORD:
544 case VARNT:
545 r = t->symvalue.offset;
546 if (r == 0 and t->chain != nil) {
547 panic("missing size information for record");
548 }
549 break;
550
551 case PTR:
552 case REF:
553 case FILET:
554 r = sizeof(Word);
555 break;
556
557 case SCAL:
558 if (t->symvalue.iconval > 255) {
559 r = sizeof(short);
560 } else {
561 r = sizeof(char);
562 }
563 break;
564
565 case FPROC:
566 case FFUNC:
567 r = sizeof(Word);
568 break;
569
570 case PROC:
571 case FUNC:
572 case MODULE:
573 case PROG:
574 r = sizeof(Symbol);
575 break;
576
577 default:
578 if (ord(t->class) > ord(TYPEREF)) {
579 panic("size: bad class (%d)", ord(t->class));
580 } else {
581 error("improper operation on a %s", classname(t));
582 }
583 /* NOTREACHED */
584 }
585 if (r < sizeof(Word) and isparam(sym)) {
586 r = sizeof(Word);
587 }
588 return r;
589}
590
591/*
592 * Test if a symbol is a parameter. This is true if there
593 * is a cycle from s->block to s via chain pointers.
594 */
595
596public Boolean isparam(s)
597Symbol s;
598{
599 register Symbol t;
600
601 t = s->block;
602 while (t != nil and t != s) {
603 t = t->chain;
604 }
605 return (Boolean) (t != nil);
606}
607
608/*
609 * Test if a symbol is a var parameter, i.e. has class REF.
610 */
611
612public Boolean isvarparam(s)
613Symbol s;
614{
615 return (Boolean) (s->class == REF);
616}
617
618/*
619 * Test if a symbol is a variable (actually any addressible quantity
620 * with do).
621 */
622
623public Boolean isvariable(s)
624register Symbol s;
625{
626 return (Boolean) (s->class == VAR or s->class == FVAR or s->class == REF);
627}
628
629/*
630 * Test if a symbol is a block, e.g. function, procedure, or the
631 * main program.
632 *
633 * This function is now expanded inline for efficiency.
634 *
635 * public Boolean isblock(s)
636register Symbol s;
637{
638 return (Boolean) (
639 s->class == FUNC or s->class == PROC or
640 s->class == MODULE or s->class == PROG
641 );
642}
643 *
644 */
645
646/*
647 * Test if a symbol is a module.
648 */
649
650public Boolean ismodule(s)
651register Symbol s;
652{
653 return (Boolean) (s->class == MODULE);
654}
655
656/*
657 * Test if a symbol is builtin, that is, a predefined type or
658 * reserved word.
659 */
660
661public Boolean isbuiltin(s)
662register Symbol s;
663{
664 return (Boolean) (s->level == 0 and s->class != PROG and s->class != VAR);
665}
666
667/*
668 * Test if two types match.
669 * Equivalent names implies a match in any language.
670 *
671 * Special symbols must be handled with care.
672 */
673
674public Boolean compatible(t1, t2)
675register Symbol t1, t2;
676{
677 Boolean b;
678
679 if (t1 == t2) {
680 b = true;
681 } else if (t1 == nil or t2 == nil) {
682 b = false;
683 } else if (t1 == procsym) {
684 b = isblock(t2);
685 } else if (t2 == procsym) {
686 b = isblock(t1);
687 } else if (t1->language == nil) {
688 b = (Boolean) (t2->language == nil or
689 (*language_op(t2->language, L_TYPEMATCH))(t1, t2));
690 } else {
691 b = (Boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2);
692 }
693 return b;
694}
695
696/*
697 * Check for a type of the given name.
698 */
699
700public Boolean istypename(type, name)
701Symbol type;
702String name;
703{
704 Symbol t;
705 Boolean b;
706
707 t = type;
708 checkref(t);
709 b = (Boolean) (
710 t->class == TYPE and t->name == identname(name, true)
711 );
712 return b;
713}
714
715/*
716 * Test if the name of a symbol is uniquely defined or not.
717 */
718
719public Boolean isambiguous(s)
720register Symbol s;
721{
722 register Symbol t;
723
724 find(t, s->name) where t != s endfind(t);
725 return (Boolean) (t != nil);
726}
727
728typedef char *Arglist;
729
730#define nextarg(type) ((type *) (ap += sizeof(type)))[-1]
731
732private Symbol mkstring();
733private Symbol namenode();
734
735/*
736 * Determine the type of a parse tree.
737 * Also make some symbol-dependent changes to the tree such as
738 * changing removing RVAL nodes for constant symbols.
739 */
740
741public assigntypes(p)
742register Node p;
743{
744 register Node p1;
745 register Symbol s;
746
747 switch (p->op) {
748 case O_SYM:
749 p->nodetype = namenode(p);
750 break;
751
752 case O_LCON:
753 p->nodetype = t_int;
754 break;
755
756 case O_FCON:
757 p->nodetype = t_real;
758 break;
759
760 case O_SCON:
761 p->value.scon = strdup(p->value.scon);
762 s = mkstring(p->value.scon);
763 if (s == t_char) {
764 p->op = O_LCON;
765 p->value.lcon = p->value.scon[0];
766 }
767 p->nodetype = s;
768 break;
769
770 case O_INDIR:
771 p1 = p->value.arg[0];
772 chkclass(p1, PTR);
773 p->nodetype = rtype(p1->nodetype)->type;
774 break;
775
776 case O_DOT:
777 p->nodetype = p->value.arg[1]->value.sym;
778 break;
779
780 case O_RVAL:
781 p1 = p->value.arg[0];
782 p->nodetype = p1->nodetype;
783 if (p1->op == O_SYM) {
784 if (p1->nodetype->class == FUNC) {
785 p->op = O_CALL;
786 p->value.arg[1] = nil;
787 } else if (p1->value.sym->class == CONST) {
788 if (compatible(p1->value.sym->type, t_real)) {
789 p->op = O_FCON;
790 p->value.fcon = p1->value.sym->symvalue.fconval;
791 p->nodetype = t_real;
792 dispose(p1);
793 } else {
794 p->op = O_LCON;
795 p->value.lcon = p1->value.sym->symvalue.iconval;
796 p->nodetype = p1->value.sym->type;
797 dispose(p1);
798 }
799 } else if (isreg(p1->value.sym)) {
800 p->op = O_SYM;
801 p->value.sym = p1->value.sym;
802 dispose(p1);
803 }
804 } else if (p1->op == O_INDIR and p1->value.arg[0]->op == O_SYM) {
805 s = p1->value.arg[0]->value.sym;
806 if (isreg(s)) {
807 p1->op = O_SYM;
808 dispose(p1->value.arg[0]);
809 p1->value.sym = s;
810 p1->nodetype = s;
811 }
812 }
813 break;
814
815 /*
816 * Perform a cast if the call is of the form "type(expr)".
817 */
818 case O_CALL:
819 p1 = p->value.arg[0];
74dabb40
ML
820 p->nodetype = rtype(p1->nodetype)->type;
821 break;
822
823 case O_TYPERENAME:
824 p->nodetype = p->value.arg[1]->nodetype;
8a21415b
ML
825 break;
826
827 case O_ITOF:
828 p->nodetype = t_real;
829 break;
830
831 case O_NEG:
832 s = p->value.arg[0]->nodetype;
833 if (not compatible(s, t_int)) {
834 if (not compatible(s, t_real)) {
835 beginerrmsg();
836 prtree(stderr, p->value.arg[0]);
837 fprintf(stderr, "is improper type");
838 enderrmsg();
839 } else {
840 p->op = O_NEGF;
841 }
842 }
843 p->nodetype = s;
844 break;
845
846 case O_ADD:
847 case O_SUB:
848 case O_MUL:
849 case O_LT:
850 case O_LE:
851 case O_GT:
852 case O_GE:
853 case O_EQ:
854 case O_NE:
855 {
856 Boolean t1real, t2real;
857 Symbol t1, t2;
858
859 t1 = rtype(p->value.arg[0]->nodetype);
860 t2 = rtype(p->value.arg[1]->nodetype);
861 t1real = compatible(t1, t_real);
862 t2real = compatible(t2, t_real);
863 if (t1real or t2real) {
864 p->op = (Operator) (ord(p->op) + 1);
865 if (not t1real) {
866 p->value.arg[0] = build(O_ITOF, p->value.arg[0]);
867 } else if (not t2real) {
868 p->value.arg[1] = build(O_ITOF, p->value.arg[1]);
869 }
870 } else {
871 if (t1real) {
872 convert(&(p->value.arg[0]), t_int, O_NOP);
873 }
874 if (t2real) {
875 convert(&(p->value.arg[1]), t_int, O_NOP);
876 }
877 }
878 if (ord(p->op) >= ord(O_LT)) {
879 p->nodetype = t_boolean;
880 } else {
881 if (t1real or t2real) {
882 p->nodetype = t_real;
883 } else {
884 p->nodetype = t_int;
885 }
886 }
887 break;
888 }
889
890 case O_DIVF:
891 convert(&(p->value.arg[0]), t_real, O_ITOF);
892 convert(&(p->value.arg[1]), t_real, O_ITOF);
893 p->nodetype = t_real;
894 break;
895
896 case O_DIV:
897 case O_MOD:
898 convert(&(p->value.arg[0]), t_int, O_NOP);
899 convert(&(p->value.arg[1]), t_int, O_NOP);
900 p->nodetype = t_int;
901 break;
902
903 case O_AND:
904 case O_OR:
905 chkboolean(p->value.arg[0]);
906 chkboolean(p->value.arg[1]);
907 p->nodetype = t_boolean;
908 break;
909
910 case O_QLINE:
911 p->nodetype = t_int;
912 break;
913
914 default:
915 p->nodetype = nil;
916 break;
917 }
918}
919
920/*
921 * Create a node for a name. The symbol for the name has already
922 * been chosen, either implicitly with "which" or explicitly from
923 * the dot routine.
924 */
925
926private Symbol namenode(p)
927Node p;
928{
929 register Symbol r, s;
930 register Node np;
931
932 s = p->value.sym;
933 if (s->class == REF) {
934 np = new(Node);
935 np->op = p->op;
936 np->nodetype = s;
937 np->value.sym = s;
938 p->op = O_INDIR;
939 p->value.arg[0] = np;
940 }
941/*
942 * Old way
943 *
944 if (s->class == CONST or s->class == VAR or s->class == FVAR) {
945 r = s->type;
946 } else {
947 r = s;
948 }
949 *
950 */
951 return s;
952}
953
954/*
955 * Convert a tree to a type via a conversion operator;
956 * if this isn't possible generate an error.
957 *
958 * Note the tree is call by address, hence the #define below.
959 */
960
961private convert(tp, typeto, op)
962Node *tp;
963Symbol typeto;
964Operator op;
965{
966#define tree (*tp)
967
968 Symbol s;
969
970 s = rtype(tree->nodetype);
971 typeto = rtype(typeto);
972 if (compatible(typeto, t_real) and compatible(s, t_int)) {
973 tree = build(op, tree);
974 } else if (not compatible(s, typeto)) {
975 beginerrmsg();
976 prtree(stderr, s);
977 fprintf(stderr, " is improper type");
978 enderrmsg();
979 } else if (op != O_NOP and s != typeto) {
980 tree = build(op, tree);
981 }
982
983#undef tree
984}
985
986/*
987 * Construct a node for the dot operator.
988 *
989 * If the left operand is not a record, but rather a procedure
990 * or function, then we interpret the "." as referencing an
991 * "invisible" variable; i.e. a variable within a dynamically
992 * active block but not within the static scope of the current procedure.
993 */
994
995public Node dot(record, fieldname)
996Node record;
997Name fieldname;
998{
999 register Node p;
1000 register Symbol s, t;
1001
1002 if (isblock(record->nodetype)) {
1003 find(s, fieldname) where
1004 s->block == record->nodetype and
1005 s->class != FIELD and s->class != TAG
1006 endfind(s);
1007 if (s == nil) {
1008 beginerrmsg();
1009 fprintf(stderr, "\"%s\" is not defined in ", ident(fieldname));
1010 printname(stderr, record->nodetype);
1011 enderrmsg();
1012 }
1013 p = new(Node);
1014 p->op = O_SYM;
1015 p->value.sym = s;
1016 p->nodetype = namenode(p);
1017 } else {
1018 p = record;
1019 t = rtype(p->nodetype);
1020 if (t->class == PTR) {
1021 s = findfield(fieldname, t->type);
1022 } else {
1023 s = findfield(fieldname, t);
1024 }
1025 if (s == nil) {
1026 beginerrmsg();
1027 fprintf(stderr, "\"%s\" is not a field in ", ident(fieldname));
1028 prtree(stderr, record);
1029 enderrmsg();
1030 }
1031 if (t->class == PTR and not isreg(record->nodetype)) {
1032 p = build(O_INDIR, record);
1033 }
1034 p = build(O_DOT, p, build(O_SYM, s));
1035 }
1036 return p;
1037}
1038
1039/*
1040 * Return a tree corresponding to an array reference and do the
1041 * error checking.
1042 */
1043
1044public Node subscript(a, slist)
1045Node a, slist;
1046{
1047 register Symbol t;
1048 register Node p;
1049 Symbol etype, atype, eltype;
483c4884 1050 Node esub, r;
8a21415b 1051
483c4884 1052 r = a;
8a21415b 1053 t = rtype(a->nodetype);
483c4884
ML
1054 eltype = t->type;
1055 if (t->class == PTR) {
1056 p = slist->value.arg[0];
1057 if (not compatible(p->nodetype, t_int)) {
1058 beginerrmsg();
1059 fprintf(stderr, "bad type for subscript of ");
1060 prtree(stderr, a);
1061 enderrmsg();
1062 }
1063 r = build(O_MUL, p, build(O_LCON, (long) size(eltype)));
1064 r = build(O_ADD, build(O_RVAL, a), r);
1065 r->nodetype = eltype;
1066 } else if (t->class != ARRAY) {
8a21415b
ML
1067 beginerrmsg();
1068 prtree(stderr, a);
1069 fprintf(stderr, " is not an array");
1070 enderrmsg();
483c4884
ML
1071 } else {
1072 p = slist;
1073 t = t->chain;
1074 for (; p != nil and t != nil; p = p->value.arg[1], t = t->chain) {
1075 esub = p->value.arg[0];
1076 etype = rtype(esub->nodetype);
1077 atype = rtype(t);
1078 if (not compatible(atype, etype)) {
1079 beginerrmsg();
1080 fprintf(stderr, "subscript ");
1081 prtree(stderr, esub);
1082 fprintf(stderr, " is the wrong type");
1083 enderrmsg();
1084 }
1085 r = build(O_INDEX, r, esub);
1086 r->nodetype = eltype;
1087 }
1088 if (p != nil or t != nil) {
8a21415b 1089 beginerrmsg();
483c4884
ML
1090 if (p != nil) {
1091 fprintf(stderr, "too many subscripts for ");
1092 } else {
1093 fprintf(stderr, "not enough subscripts for ");
1094 }
1095 prtree(stderr, a);
8a21415b
ML
1096 enderrmsg();
1097 }
8a21415b 1098 }
483c4884 1099 return r;
8a21415b
ML
1100}
1101
1102/*
1103 * Evaluate a subscript index.
1104 */
1105
1106public int evalindex(s, i)
1107Symbol s;
1108long i;
1109{
1110 long lb, ub;
1111
1112 s = rtype(s)->chain;
1113 lb = s->symvalue.rangev.lower;
1114 ub = s->symvalue.rangev.upper;
1115 if (i < lb or i > ub) {
1116 error("subscript out of range");
1117 }
1118 return (i - lb);
1119}
1120
1121/*
1122 * Check to see if a tree is boolean-valued, if not it's an error.
1123 */
1124
1125public chkboolean(p)
1126register Node p;
1127{
1128 if (p->nodetype != t_boolean) {
1129 beginerrmsg();
1130 fprintf(stderr, "found ");
1131 prtree(stderr, p);
1132 fprintf(stderr, ", expected boolean expression");
1133 enderrmsg();
1134 }
1135}
1136
1137/*
1138 * Check to make sure the given tree has a type of the given class.
1139 */
1140
1141private chkclass(p, class)
1142Node p;
1143Symclass class;
1144{
1145 struct Symbol tmpsym;
1146
1147 tmpsym.class = class;
1148 if (rtype(p->nodetype)->class != class) {
1149 beginerrmsg();
1150 fprintf(stderr, "\"");
1151 prtree(stderr, p);
1152 fprintf(stderr, "\" is not a %s", classname(&tmpsym));
1153 enderrmsg();
1154 }
1155}
1156
1157/*
1158 * Construct a node for the type of a string. While we're at it,
1159 * scan the string for '' that collapse to ', and chop off the ends.
1160 */
1161
1162private Symbol mkstring(str)
1163String str;
1164{
1165 register char *p, *q;
1166 register Symbol s;
1167
1168 p = str;
1169 q = str;
1170 while (*p != '\0') {
1171 if (*p == '\\') {
1172 ++p;
1173 }
1174 *q = *p;
1175 ++p;
1176 ++q;
1177 }
1178 *q = '\0';
1179 s = newSymbol(nil, 0, ARRAY, t_char, nil);
1180 s->language = findlanguage(".s");
1181 s->chain = newSymbol(nil, 0, RANGE, t_int, nil);
1182 s->chain->language = s->language;
1183 s->chain->symvalue.rangev.lower = 1;
1184 s->chain->symvalue.rangev.upper = p - str + 1;
1185 return s;
1186}
1187
1188/*
1189 * Free up the space allocated for a string type.
1190 */
1191
1192public unmkstring(s)
1193Symbol s;
1194{
1195 dispose(s->chain);
1196}
1197
1198/*
1199 * Figure out the "current" variable or function being referred to,
1200 * this is either the active one or the most visible from the
1201 * current scope.
1202 */
1203
1204public Symbol which(n)
1205Name n;
1206{
1207 register Symbol s, p, t, f;
1208
1209 find(s, n) where s->class != FIELD and s->class != TAG endfind(s);
1210 if (s == nil) {
1211 s = lookup(n);
1212 }
1213 if (s == nil) {
1214 error("\"%s\" is not defined", ident(n));
1215 } else if (s == program or isbuiltin(s)) {
1216 t = s;
1217 } else {
1218 /*
1219 * Old way
1220 *
1221 if (not isactive(program)) {
1222 f = program;
1223 } else {
1224 f = whatblock(pc);
1225 if (f == nil) {
1226 panic("no block for addr 0x%x", pc);
1227 }
1228 }
1229 *
1230 * Now start with curfunc.
1231 */
1232 p = curfunc;
1233 do {
1234 find(t, n) where
1235 t->block == p and t->class != FIELD and t->class != TAG
1236 endfind(t);
1237 p = p->block;
1238 } while (t == nil and p != nil);
1239 if (t == nil) {
1240 t = s;
1241 }
1242 }
1243 return t;
1244}
1245
1246/*
1247 * Find the symbol which is has the same name and scope as the
1248 * given symbol but is of the given field. Return nil if there is none.
1249 */
1250
1251public Symbol findfield(fieldname, record)
1252Name fieldname;
1253Symbol record;
1254{
1255 register Symbol t;
1256
1257 t = rtype(record)->chain;
1258 while (t != nil and t->name != fieldname) {
1259 t = t->chain;
1260 }
1261 return t;
1262}