date and time created 84/06/23 10:59:16 by sam
[unix-history] / usr / src / old / dbx / modula-2.c
CommitLineData
a629ae97
SL
1#ifndef lint
2static char sccsid[] = "@(#)modula-2.c 1.1 (Berkeley) %G%"; /* from 1.4 84/03/27 10:22:04 linton Exp */
3#endif
4
5/*
6 * Modula-2 specific symbol routines.
7 */
8
9#include "defs.h"
10#include "symbols.h"
11#include "modula-2.h"
12#include "languages.h"
13#include "tree.h"
14#include "eval.h"
15#include "mappings.h"
16#include "process.h"
17#include "runtime.h"
18#include "machine.h"
19
20#ifndef public
21#endif
22
23private Language mod2;
24private boolean initialized;
25
26/*
27 * Initialize Modula-2 information.
28 */
29
30public modula2_init ()
31{
32 mod2 = language_define("modula-2", ".mod");
33 language_setop(mod2, L_PRINTDECL, modula2_printdecl);
34 language_setop(mod2, L_PRINTVAL, modula2_printval);
35 language_setop(mod2, L_TYPEMATCH, modula2_typematch);
36 language_setop(mod2, L_BUILDAREF, modula2_buildaref);
37 language_setop(mod2, L_EVALAREF, modula2_evalaref);
38 language_setop(mod2, L_MODINIT, modula2_modinit);
39 language_setop(mod2, L_HASMODULES, modula2_hasmodules);
40 language_setop(mod2, L_PASSADDR, modula2_passaddr);
41 initialized = false;
42}
43
44/*
45 * Typematch tests if two types are compatible. The issue
46 * is a bit complicated, so several subfunctions are used for
47 * various kinds of compatibility.
48 */
49
50private boolean nilMatch (t1, t2)
51register Symbol t1, t2;
52{
53 boolean b;
54
55 b = (boolean) (
56 (t1 == t_nil and t2->class == PTR) or
57 (t1->class == PTR and t2 == t_nil)
58 );
59 return b;
60}
61
62private boolean enumMatch (t1, t2)
63register Symbol t1, t2;
64{
65 boolean b;
66
67 b = (boolean) (
68 t1->type == t2->type and (
69 (t1->class == t2->class) or
70 (t1->class == SCAL and t2->class == CONST) or
71 (t1->class == CONST and t2->class == SCAL)
72 )
73 );
74 return b;
75}
76
77private boolean openArrayMatch (t1, t2)
78register Symbol t1, t2;
79{
80 boolean b;
81
82 b = (boolean) (
83 (
84 t1->class == ARRAY and t1->chain == t_open and
85 t2->class == ARRAY and
86 compatible(rtype(t2->chain)->type, t_int) and
87 compatible(t1->type, t2->type)
88 ) or (
89 t2->class == ARRAY and t2->chain == t_open and
90 t1->class == ARRAY and
91 compatible(rtype(t1->chain)->type, t_int) and
92 compatible(t1->type, t2->type)
93 )
94 );
95 return b;
96}
97
98private boolean isConstString (t)
99register Symbol t;
100{
101 boolean b;
102
103 b = (boolean) (
104 t->language == primlang and t->class == ARRAY and t->type == t_char
105 );
106 return b;
107}
108
109private boolean stringArrayMatch (t1, t2)
110register Symbol t1, t2;
111{
112 boolean b;
113
114 b = (boolean) (
115 (
116 isConstString(t1) and
117 t2->class == ARRAY and compatible(t2->type, t_char->type)
118 ) or (
119 isConstString(t2) and
120 t1->class == ARRAY and compatible(t1->type, t_char->type)
121 )
122 );
123 return b;
124}
125
126public boolean modula2_typematch (type1, type2)
127Symbol type1, type2;
128{
129 Boolean b;
130 Symbol t1, t2, tmp;
131
132 t1 = rtype(type1);
133 t2 = rtype(type2);
134 if (t1 == t2) {
135 b = true;
136 } else {
137 if (t1 == t_char->type or t1 == t_int->type or t1 == t_real->type) {
138 tmp = t1;
139 t1 = t2;
140 t2 = tmp;
141 }
142 b = (Boolean) (
143 (
144 t2 == t_int->type and
145 t1->class == RANGE and (
146 istypename(t1->type, "integer") or
147 istypename(t1->type, "cardinal")
148 )
149 ) or (
150 t2 == t_char->type and
151 t1->class == RANGE and istypename(t1->type, "char")
152 ) or (
153 t2 == t_real->type and
154 t1->class == RANGE and (
155 istypename(t1->type, "real") or
156 istypename(t1->type, "longreal")
157 )
158 ) or (
159 nilMatch(t1, t2)
160 ) or (
161 enumMatch(t1, t2)
162 ) or (
163 openArrayMatch(t1, t2)
164 ) or (
165 stringArrayMatch(t1, t2)
166 )
167 );
168 }
169 return b;
170}
171
172/*
173 * Indent n spaces.
174 */
175
176private indent (n)
177int n;
178{
179 if (n > 0) {
180 printf("%*c", n, ' ');
181 }
182}
183
184public modula2_printdecl (s)
185Symbol s;
186{
187 register Symbol t;
188 Boolean semicolon;
189
190 semicolon = true;
191 if (s->class == TYPEREF) {
192 resolveRef(t);
193 }
194 switch (s->class) {
195 case CONST:
196 if (s->type->class == SCAL) {
197 printf("(enumeration constant, ord %ld)",
198 s->symvalue.iconval);
199 } else {
200 printf("const %s = ", symname(s));
201 modula2_printval(s);
202 }
203 break;
204
205 case TYPE:
206 printf("type %s = ", symname(s));
207 printtype(s, s->type, 0);
208 break;
209
210 case TYPEREF:
211 printf("type %s", symname(s));
212 break;
213
214 case VAR:
215 if (isparam(s)) {
216 printf("(parameter) %s : ", symname(s));
217 } else {
218 printf("var %s : ", symname(s));
219 }
220 printtype(s, s->type, 0);
221 break;
222
223 case REF:
224 printf("(var parameter) %s : ", symname(s));
225 printtype(s, s->type, 0);
226 break;
227
228 case RANGE:
229 case ARRAY:
230 case RECORD:
231 case VARNT:
232 case PTR:
233 printtype(s, s, 0);
234 semicolon = false;
235 break;
236
237 case FVAR:
238 printf("(function variable) %s : ", symname(s));
239 printtype(s, s->type, 0);
240 break;
241
242 case FIELD:
243 printf("(field) %s : ", symname(s));
244 printtype(s, s->type, 0);
245 break;
246
247 case PROC:
248 printf("procedure %s", symname(s));
249 listparams(s);
250 break;
251
252 case PROG:
253 printf("program %s", symname(s));
254 listparams(s);
255 break;
256
257 case FUNC:
258 printf("function %s", symname(s));
259 listparams(s);
260 printf(" : ");
261 printtype(s, s->type, 0);
262 break;
263
264 case MODULE:
265 printf("module %s", symname(s));
266 break;
267
268 default:
269 printf("%s : (class %s)", symname(s), classname(s));
270 break;
271 }
272 if (semicolon) {
273 putchar(';');
274 }
275 putchar('\n');
276}
277
278/*
279 * Recursive whiz-bang procedure to print the type portion
280 * of a declaration.
281 *
282 * The symbol associated with the type is passed to allow
283 * searching for type names without getting "type blah = blah".
284 */
285
286private printtype (s, t, n)
287Symbol s;
288Symbol t;
289int n;
290{
291 register Symbol tmp;
292
293 if (t->class == TYPEREF) {
294 resolveRef(t);
295 }
296 switch (t->class) {
297 case VAR:
298 case CONST:
299 case FUNC:
300 case PROC:
301 panic("printtype: class %s", classname(t));
302 break;
303
304 case ARRAY:
305 printf("array[");
306 tmp = t->chain;
307 if (tmp != nil) {
308 for (;;) {
309 printtype(tmp, tmp, n);
310 tmp = tmp->chain;
311 if (tmp == nil) {
312 break;
313 }
314 printf(", ");
315 }
316 }
317 printf("] of ");
318 printtype(t, t->type, n);
319 break;
320
321 case RECORD:
322 printRecordDecl(t, n);
323 break;
324
325 case FIELD:
326 if (t->chain != nil) {
327 printtype(t->chain, t->chain, n);
328 }
329 printf("\t%s : ", symname(t));
330 printtype(t, t->type, n);
331 printf(";\n");
332 break;
333
334 case RANGE:
335 printRangeDecl(t);
336 break;
337
338 case PTR:
339 printf("pointer to ");
340 printtype(t, t->type, n);
341 break;
342
343 case TYPE:
344 if (t->name != nil and ident(t->name)[0] != '\0') {
345 printname(stdout, t);
346 } else {
347 printtype(t, t->type, n);
348 }
349 break;
350
351 case SCAL:
352 printEnumDecl(t, n);
353 break;
354
355 case SET:
356 printf("set of ");
357 printtype(t, t->type, n);
358 break;
359
360 case TYPEREF:
361 break;
362
363 default:
364 printf("(class %d)", t->class);
365 break;
366 }
367}
368
369/*
370 * Print out a record declaration.
371 */
372
373private printRecordDecl (t, n)
374Symbol t;
375int n;
376{
377 register Symbol f;
378
379 if (t->chain == nil) {
380 printf("record end");
381 } else {
382 printf("record\n");
383 for (f = t->chain; f != nil; f = f->chain) {
384 indent(n+4);
385 printf("%s : ", symname(f));
386 printtype(f->type, f->type, n+4);
387 printf(";\n");
388 }
389 indent(n);
390 printf("end");
391 }
392}
393
394/*
395 * Print out the declaration of a range type.
396 */
397
398private printRangeDecl (t)
399Symbol t;
400{
401 long r0, r1;
402
403 r0 = t->symvalue.rangev.lower;
404 r1 = t->symvalue.rangev.upper;
405 if (t == t_char or istypename(t, "char")) {
406 if (r0 < 0x20 or r0 > 0x7e) {
407 printf("%ld..", r0);
408 } else {
409 printf("'%c'..", (char) r0);
410 }
411 if (r1 < 0x20 or r1 > 0x7e) {
412 printf("\\%lo", r1);
413 } else {
414 printf("'%c'", (char) r1);
415 }
416 } else if (r0 > 0 and r1 == 0) {
417 printf("%ld byte real", r0);
418 } else if (r0 >= 0) {
419 printf("%lu..%lu", r0, r1);
420 } else {
421 printf("%ld..%ld", r0, r1);
422 }
423}
424
425/*
426 * Print out an enumeration declaration.
427 */
428
429private printEnumDecl (e, n)
430Symbol e;
431int n;
432{
433 Symbol t;
434
435 printf("(");
436 t = e->chain;
437 if (t != nil) {
438 printf("%s", symname(t));
439 t = t->chain;
440 while (t != nil) {
441 printf(", %s", symname(t));
442 t = t->chain;
443 }
444 }
445 printf(")");
446}
447
448/*
449 * List the parameters of a procedure or function.
450 * No attempt is made to combine like types.
451 */
452
453private listparams (s)
454Symbol s;
455{
456 Symbol t;
457
458 if (s->chain != nil) {
459 putchar('(');
460 for (t = s->chain; t != nil; t = t->chain) {
461 switch (t->class) {
462 case REF:
463 printf("var ");
464 break;
465
466 case FPROC:
467 case FFUNC:
468 printf("procedure ");
469 break;
470
471 case VAR:
472 break;
473
474 default:
475 panic("unexpected class %d for parameter", t->class);
476 }
477 printf("%s", symname(t));
478 if (s->class == PROG) {
479 printf(", ");
480 } else {
481 printf(" : ");
482 printtype(t, t->type, 0);
483 if (t->chain != nil) {
484 printf("; ");
485 }
486 }
487 }
488 putchar(')');
489 }
490}
491
492/*
493 * Modula 2 interface to printval.
494 */
495
496public modula2_printval (s)
497Symbol s;
498{
499 prval(s, size(s));
500}
501
502/*
503 * Print out the value on the top of the expression stack
504 * in the format for the type of the given symbol, assuming
505 * the size of the object is n bytes.
506 */
507
508private prval (s, n)
509Symbol s;
510integer n;
511{
512 Symbol t;
513 Address a;
514 integer len;
515 double r;
516 integer scalar;
517 boolean found;
518
519 if (s->class == TYPEREF) {
520 resolveRef(s);
521 }
522 switch (s->class) {
523 case CONST:
524 case TYPE:
525 case VAR:
526 case REF:
527 case FVAR:
528 case TAG:
529 case FIELD:
530 prval(s->type, n);
531 break;
532
533 case ARRAY:
534 t = rtype(s->type);
535 if (t->class == RANGE and istypename(t->type, "char")) {
536 len = size(s);
537 sp -= len;
538 printf("'%.*s'", len, sp);
539 break;
540 } else {
541 printarray(s);
542 }
543 break;
544
545 case RECORD:
546 printrecord(s);
547 break;
548
549 case VARNT:
550 printf("can't print out variant records");
551 break;
552
553 case RANGE:
554 printrange(s, n);
555 break;
556
557 case FILET:
558 case PTR:
559 a = pop(Address);
560 if (a == 0) {
561 printf("nil");
562 } else {
563 printf("0x%x", a);
564 }
565 break;
566
567 case SCAL:
568 popn(n, &scalar);
569 found = false;
570 for (t = s->chain; t != nil; t = t->chain) {
571 if (t->symvalue.iconval == scalar) {
572 printf("%s", symname(t));
573 found = true;
574 break;
575 }
576 }
577 if (not found) {
578 printf("(scalar = %d)", scalar);
579 }
580 break;
581
582 case FPROC:
583 case FFUNC:
584 a = pop(long);
585 t = whatblock(a);
586 if (t == nil) {
587 printf("(proc 0x%x)", a);
588 } else {
589 printf("%s", symname(t));
590 }
591 break;
592
593 case SET:
594 printSet(s);
595 break;
596
597 default:
598 if (ord(s->class) < ord(BADUSE) or ord(s->class) > ord(TYPEREF)) {
599 panic("printval: bad class %d", ord(s->class));
600 }
601 printf("[%s]", classname(s));
602 break;
603 }
604}
605
606/*
607 * Print out the value of a scalar (non-enumeration) type.
608 */
609
610private printrange (s, n)
611Symbol s;
612integer n;
613{
614 double d;
615 float f;
616 integer i;
617
618 if (s->symvalue.rangev.upper == 0 and s->symvalue.rangev.lower > 0) {
619 if (n == sizeof(float)) {
620 popn(n, &f);
621 d = f;
622 } else {
623 popn(n, &d);
624 }
625 prtreal(d);
626 } else {
627 i = 0;
628 popn(n, &i);
629 if (s == t_boolean) {
630 printf(((Boolean) i) == true ? "true" : "false");
631 } else if (s == t_char or istypename(s->type, "char")) {
632 printf("'%c'", i);
633 } else if (s->symvalue.rangev.lower >= 0) {
634 printf("%lu", i);
635 } else {
636 printf("%ld", i);
637 }
638 }
639}
640
641/*
642 * Print out a set.
643 */
644
645private printSet (s)
646Symbol s;
647{
648 Symbol t;
649 integer nbytes;
650
651 nbytes = size(s);
652 t = rtype(s->type);
653 printf("{");
654 sp -= nbytes;
655 if (t->class == SCAL) {
656 printSetOfEnum(t);
657 } else if (t->class == RANGE) {
658 printSetOfRange(t);
659 } else {
660 panic("expected range or enumerated base type for set");
661 }
662 printf("}");
663}
664
665/*
666 * Print out a set of an enumeration.
667 */
668
669private printSetOfEnum (t)
670Symbol t;
671{
672 register Symbol e;
673 register integer i, j, *p;
674 boolean first;
675
676 p = (int *) sp;
677 i = *p;
678 j = 0;
679 e = t->chain;
680 first = true;
681 while (e != nil) {
682 if ((i&1) == 1) {
683 if (first) {
684 first = false;
685 printf("%s", symname(e));
686 } else {
687 printf(", %s", symname(e));
688 }
689 }
690 i >>= 1;
691 ++j;
692 if (j >= sizeof(integer)*BITSPERBYTE) {
693 j = 0;
694 ++p;
695 i = *p;
696 }
697 e = e->chain;
698 }
699}
700
701/*
702 * Print out a set of a subrange type.
703 */
704
705private printSetOfRange (t)
706Symbol t;
707{
708 register integer i, j, *p;
709 long v;
710 boolean first;
711
712 p = (int *) sp;
713 i = *p;
714 j = 0;
715 v = t->symvalue.rangev.lower;
716 first = true;
717 while (v <= t->symvalue.rangev.upper) {
718 if ((i&1) == 1) {
719 if (first) {
720 first = false;
721 printf("%ld", v);
722 } else {
723 printf(", %ld", v);
724 }
725 }
726 i >>= 1;
727 ++j;
728 if (j >= sizeof(integer)*BITSPERBYTE) {
729 j = 0;
730 ++p;
731 i = *p;
732 }
733 ++v;
734 }
735}
736
737/*
738 * Construct a node for subscripting.
739 */
740
741public Node modula2_buildaref (a, slist)
742Node a, slist;
743{
744 register Symbol t;
745 register Node p;
746 Symbol etype, atype, eltype;
747 Node esub, r;
748
749 r = a;
750 t = rtype(a->nodetype);
751 eltype = t->type;
752 if (t->class != ARRAY) {
753 beginerrmsg();
754 prtree(stderr, a);
755 fprintf(stderr, " is not an array");
756 enderrmsg();
757 } else {
758 p = slist;
759 t = t->chain;
760 for (; p != nil and t != nil; p = p->value.arg[1], t = t->chain) {
761 esub = p->value.arg[0];
762 etype = rtype(esub->nodetype);
763 atype = rtype(t);
764 if (not compatible(atype, etype)) {
765 beginerrmsg();
766 fprintf(stderr, "subscript ");
767 prtree(stderr, esub);
768 fprintf(stderr, " is the wrong type");
769 enderrmsg();
770 }
771 r = build(O_INDEX, r, esub);
772 r->nodetype = eltype;
773 }
774 if (p != nil or t != nil) {
775 beginerrmsg();
776 if (p != nil) {
777 fprintf(stderr, "too many subscripts for ");
778 } else {
779 fprintf(stderr, "not enough subscripts for ");
780 }
781 prtree(stderr, a);
782 enderrmsg();
783 }
784 }
785 return r;
786}
787
788/*
789 * Evaluate a subscript index.
790 */
791
792public int modula2_evalaref (s, i)
793Symbol s;
794long i;
795{
796 long lb, ub;
797
798 chkOpenArray(s);
799 s = rtype(rtype(s)->chain);
800 findbounds(s, &lb, &ub);
801 if (i < lb or i > ub) {
802 error("subscript %d out of range [%d..%d]", i, lb, ub);
803 }
804 return (i - lb);
805}
806
807/*
808 * Initial Modula-2 type information.
809 */
810
811#define NTYPES 12
812
813private Symbol inittype[NTYPES + 1];
814
815private addType (n, s, lower, upper)
816integer n;
817String s;
818long lower, upper;
819{
820 register Symbol t;
821
822 if (n > NTYPES) {
823 panic("initial Modula-2 type number too large for '%s'", s);
824 }
825 t = insert(identname(s, true));
826 t->language = mod2;
827 t->class = TYPE;
828 t->type = newSymbol(nil, 0, RANGE, t, nil);
829 t->type->symvalue.rangev.lower = lower;
830 t->type->symvalue.rangev.upper = upper;
831 t->type->language = mod2;
832 inittype[n] = t;
833}
834
835private initModTypes ()
836{
837 addType(1, "integer", 0x80000000L, 0x7fffffffL);
838 addType(2, "char", 0L, 255L);
839 addType(3, "boolean", 0L, 1L);
840 addType(4, "unsigned", 0L, 0xffffffffL);
841 addType(5, "real", 4L, 0L);
842 addType(6, "longreal", 8L, 0L);
843 addType(7, "word", 0L, 0xffffffffL);
844 addType(8, "byte", 0L, 255L);
845 addType(9, "address", 0L, 0xffffffffL);
846 addType(10, "file", 0L, 0xffffffffL);
847 addType(11, "process", 0L, 0xffffffffL);
848 addType(12, "cardinal", 0L, 0x7fffffffL);
849}
850
851/*
852 * Initialize typetable.
853 */
854
855public modula2_modinit (typetable)
856Symbol typetable[];
857{
858 register integer i;
859
860 if (not initialized) {
861 initModTypes();
862 }
863 for (i = 1; i <= NTYPES; i++) {
864 typetable[i] = inittype[i];
865 }
866}
867
868public boolean modula2_hasmodules ()
869{
870 return true;
871}
872
873public boolean modula2_passaddr (param, exprtype)
874Symbol param, exprtype;
875{
876 return false;
877}