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