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