date and time created 82/12/15 04:08:35 by linton
[unix-history] / usr / src / old / dbx / symbols.c
CommitLineData
8a21415b
ML
1/* Copyright (c) 1982 Regents of the University of California */
2
3static char sccsid[] = "@(#)@(#)symbols.c 1.1 %G%";
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;
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
78Symbol t_boolean;
79Symbol t_char;
80Symbol t_int;
81Symbol t_real;
82Symbol t_nil;
83
84Symbol program;
85Symbol 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
120private 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
130typedef struct Sympool {
131 struct Symbol sym[SYMBLOCKSIZE];
132 struct Sympool *prevpool;
133} *Sympool;
134
135private Sympool sympool = nil;
136private Integer nleft = 0;
137private struct Sympool zeropool;
138
139public 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
158public 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
180public Symbol newSymbol(name, blevel, class, type, chain)
181Name name;
182Integer blevel;
183Symclass class;
184Symbol type;
185Symbol 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
202public Symbol insert(name)
203Name 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
220public Symbol lookup(name)
221Name 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
243public dumpvars(f, frame)
244Symbol f;
245Frame 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
269public Symbol maketype(name, lower, upper)
270String name;
271long lower;
272long 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)
288Symbol s;
289{
290 checkref(s);
291 return ident(s->name);
292}
293
294 *
295 * public Address codeloc(f)
296Symbol 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
311public Symbol rtype(type)
312Symbol 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
328public Integer level(s)
329Symbol s;
330{
331 checkref(s);
332 return s->level;
333}
334
335public Symbol container(s)
336Symbol 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
358public Address address(s, frame)
359Symbol s;
360Frame 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
403public defregname(n, r)
404Name n;
405Integer 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
429public findtype(s)
430Symbol 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
469public Integer size(sym)
470Symbol 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
586public Boolean isparam(s)
587Symbol 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
602public Boolean isvarparam(s)
603Symbol 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
613public Boolean isvariable(s)
614register 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)
626register 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
640public Boolean ismodule(s)
641register 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
651public Boolean isbuiltin(s)
652register 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
664public Boolean compatible(t1, t2)
665register 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
690public Boolean istypename(type, name)
691Symbol type;
692String 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
709public Boolean isambiguous(s)
710register 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
718typedef char *Arglist;
719
720#define nextarg(type) ((type *) (ap += sizeof(type)))[-1]
721
722private Symbol mkstring();
723private 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
731public assigntypes(p)
732register 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
928private Symbol namenode(p)
929Node 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
963private convert(tp, typeto, op)
964Node *tp;
965Symbol typeto;
966Operator 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
997public Node dot(record, fieldname)
998Node record;
999Name 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
1046public Node subscript(a, slist)
1047Node 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
1096public int evalindex(s, i)
1097Symbol s;
1098long 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
1115public chkboolean(p)
1116register 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
1131private chkclass(p, class)
1132Node p;
1133Symclass 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
1152private Symbol mkstring(str)
1153String 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
1182public unmkstring(s)
1183Symbol 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
1194public Symbol which(n)
1195Name 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
1241public Symbol findfield(fieldname, record)
1242Name fieldname;
1243Symbol 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}