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