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