|
|
1.1 root 1: /*
2: * Copyright (c) 1983 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted
6: * provided that: (1) source distributions retain this entire copyright
7: * notice and comment, and (2) distributions including binaries display
8: * the following acknowledgement: ``This product includes software
9: * developed by the University of California, Berkeley and its contributors''
10: * in the documentation or other materials provided with the distribution
11: * and in all advertising materials mentioning features or use of this
12: * software. Neither the name of the University nor the names of its
13: * contributors may be used to endorse or promote products derived
14: * from this software without specific prior written permission.
15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18: */
19:
20: #ifndef lint
21: static char sccsid[] = "@(#)modula-2.c 5.4 (Berkeley) 6/1/90";
22: #endif /* not lint */
23:
24: /*
25: * Modula-2 specific symbol routines.
26: */
27:
28: #include "defs.h"
29: #include "symbols.h"
30: #include "modula-2.h"
31: #include "languages.h"
32: #include "tree.h"
33: #include "eval.h"
34: #include "mappings.h"
35: #include "process.h"
36: #include "runtime.h"
37: #include "machine.h"
38:
39: #ifndef public
40: #endif
41:
42: private Language mod2;
43: private boolean initialized;
44:
45:
46: #define ischar(t) ( \
47: (t) == t_char->type or \
48: ((t)->class == RANGE and istypename((t)->type, "char")) \
49: )
50:
51: /*
52: * Initialize Modula-2 information.
53: */
54:
55: public modula2_init ()
56: {
57: mod2 = language_define("modula-2", ".mod");
58: language_setop(mod2, L_PRINTDECL, modula2_printdecl);
59: language_setop(mod2, L_PRINTVAL, modula2_printval);
60: language_setop(mod2, L_TYPEMATCH, modula2_typematch);
61: language_setop(mod2, L_BUILDAREF, modula2_buildaref);
62: language_setop(mod2, L_EVALAREF, modula2_evalaref);
63: language_setop(mod2, L_MODINIT, modula2_modinit);
64: language_setop(mod2, L_HASMODULES, modula2_hasmodules);
65: language_setop(mod2, L_PASSADDR, modula2_passaddr);
66: initialized = false;
67: }
68:
69: /*
70: * Typematch tests if two types are compatible. The issue
71: * is a bit complicated, so several subfunctions are used for
72: * various kinds of compatibility.
73: */
74:
75: private boolean builtinmatch (t1, t2)
76: register Symbol t1, t2;
77: {
78: boolean b;
79:
80: b = (boolean) (
81: (
82: t2 == t_int->type and t1->class == RANGE and
83: (
84: istypename(t1->type, "integer") or
85: istypename(t1->type, "cardinal")
86: )
87: ) or (
88: t2 == t_char->type and
89: t1->class == RANGE and istypename(t1->type, "char")
90: ) or (
91: t2 == t_real->type and
92: t1->class == RANGE and (
93: istypename(t1->type, "real") or
94: istypename(t1->type, "longreal")
95: )
96: ) or (
97: t2 == t_boolean->type and
98: t1->class == RANGE and istypename(t1->type, "boolean")
99: )
100: );
101: return b;
102: }
103:
104: private boolean nilMatch (t1, t2)
105: register Symbol t1, t2;
106: {
107: boolean b;
108:
109: b = (boolean) (
110: (t1 == t_nil and t2->class == PTR) or
111: (t1->class == PTR and t2 == t_nil)
112: );
113: return b;
114: }
115:
116: private boolean enumMatch (t1, t2)
117: register Symbol t1, t2;
118: {
119: boolean b;
120:
121: b = (boolean) (
122: (t1->class == SCAL and t2->class == CONST and t2->type == t1) or
123: (t1->class == CONST and t2->class == SCAL and t1->type == t2)
124: );
125: return b;
126: }
127:
128: private boolean openArrayMatch (t1, t2)
129: register Symbol t1, t2;
130: {
131: boolean b;
132:
133: b = (boolean) (
134: (
135: t1->class == OPENARRAY and t1->symvalue.ndims == 1 and
136: t2->class == ARRAY and
137: compatible(rtype(t2->chain)->type, t_int) and
138: compatible(t1->type, t2->type)
139: ) or (
140: t2->class == OPENARRAY and t2->symvalue.ndims == 1 and
141: t1->class == ARRAY and
142: compatible(rtype(t1->chain)->type, t_int) and
143: compatible(t1->type, t2->type)
144: )
145: );
146: return b;
147: }
148:
149: private boolean isConstString (t)
150: register Symbol t;
151: {
152: boolean b;
153:
154: b = (boolean) (
155: t->language == primlang and t->class == ARRAY and t->type == t_char
156: );
157: return b;
158: }
159:
160: private boolean stringArrayMatch (t1, t2)
161: register Symbol t1, t2;
162: {
163: boolean b;
164:
165: b = (boolean) (
166: (
167: isConstString(t1) and
168: t2->class == ARRAY and compatible(t2->type, t_char->type)
169: ) or (
170: isConstString(t2) and
171: t1->class == ARRAY and compatible(t1->type, t_char->type)
172: )
173: );
174: return b;
175: }
176:
177: public boolean modula2_typematch (type1, type2)
178: Symbol type1, type2;
179: {
180: boolean b;
181: Symbol t1, t2, tmp;
182:
183: t1 = rtype(type1);
184: t2 = rtype(type2);
185: if (t1 == t2) {
186: b = true;
187: } else {
188: if (t1 == t_char->type or t1 == t_int->type or
189: t1 == t_real->type or t1 == t_boolean->type
190: ) {
191: tmp = t1;
192: t1 = t2;
193: t2 = tmp;
194: }
195: b = (Boolean) (
196: builtinmatch(t1, t2) or
197: nilMatch(t1, t2) or enumMatch(t1, t2) or
198: openArrayMatch(t1, t2) or stringArrayMatch(t1, t2)
199: );
200: }
201: return b;
202: }
203:
204: /*
205: * Indent n spaces.
206: */
207:
208: private indent (n)
209: int n;
210: {
211: if (n > 0) {
212: printf("%*c", n, ' ');
213: }
214: }
215:
216: public modula2_printdecl (s)
217: Symbol s;
218: {
219: register Symbol t;
220: Boolean semicolon;
221:
222: semicolon = true;
223: if (s->class == TYPEREF) {
224: resolveRef(t);
225: }
226: switch (s->class) {
227: case CONST:
228: if (s->type->class == SCAL) {
229: semicolon = false;
230: printf("enumeration constant with value ");
231: eval(s->symvalue.constval);
232: modula2_printval(s);
233: } else {
234: printf("const %s = ", symname(s));
235: eval(s->symvalue.constval);
236: modula2_printval(s);
237: }
238: break;
239:
240: case TYPE:
241: printf("type %s = ", symname(s));
242: printtype(s, s->type, 0);
243: break;
244:
245: case TYPEREF:
246: printf("type %s", symname(s));
247: break;
248:
249: case VAR:
250: if (isparam(s)) {
251: printf("(parameter) %s : ", symname(s));
252: } else {
253: printf("var %s : ", symname(s));
254: }
255: printtype(s, s->type, 0);
256: break;
257:
258: case REF:
259: printf("(var parameter) %s : ", symname(s));
260: printtype(s, s->type, 0);
261: break;
262:
263: case RANGE:
264: case ARRAY:
265: case OPENARRAY:
266: case DYNARRAY:
267: case SUBARRAY:
268: case RECORD:
269: case VARNT:
270: case PTR:
271: printtype(s, s, 0);
272: semicolon = false;
273: break;
274:
275: case FVAR:
276: printf("(function variable) %s : ", symname(s));
277: printtype(s, s->type, 0);
278: break;
279:
280: case FIELD:
281: printf("(field) %s : ", symname(s));
282: printtype(s, s->type, 0);
283: break;
284:
285: case PROC:
286: printf("procedure %s", symname(s));
287: listparams(s);
288: break;
289:
290: case PROG:
291: printf("program %s", symname(s));
292: listparams(s);
293: break;
294:
295: case FUNC:
296: printf("procedure %s", symname(s));
297: listparams(s);
298: printf(" : ");
299: printtype(s, s->type, 0);
300: break;
301:
302: case MODULE:
303: printf("module %s", symname(s));
304: break;
305:
306: default:
307: printf("[%s]", classname(s));
308: break;
309: }
310: if (semicolon) {
311: putchar(';');
312: }
313: putchar('\n');
314: }
315:
316: /*
317: * Recursive whiz-bang procedure to print the type portion
318: * of a declaration.
319: *
320: * The symbol associated with the type is passed to allow
321: * searching for type names without getting "type blah = blah".
322: */
323:
324: private printtype (s, t, n)
325: Symbol s;
326: Symbol t;
327: int n;
328: {
329: Symbol tmp;
330: int i;
331:
332: if (t->class == TYPEREF) {
333: resolveRef(t);
334: }
335: switch (t->class) {
336: case VAR:
337: case CONST:
338: case FUNC:
339: case PROC:
340: panic("printtype: class %s", classname(t));
341: break;
342:
343: case ARRAY:
344: printf("array[");
345: tmp = t->chain;
346: if (tmp != nil) {
347: for (;;) {
348: printtype(tmp, tmp, n);
349: tmp = tmp->chain;
350: if (tmp == nil) {
351: break;
352: }
353: printf(", ");
354: }
355: }
356: printf("] of ");
357: printtype(t, t->type, n);
358: break;
359:
360: case OPENARRAY:
361: printf("array of ");
362: for (i = 1; i < t->symvalue.ndims; i++) {
363: printf("array of ");
364: }
365: printtype(t, t->type, n);
366: break;
367:
368: case DYNARRAY:
369: printf("dynarray of ");
370: for (i = 1; i < t->symvalue.ndims; i++) {
371: printf("array of ");
372: }
373: printtype(t, t->type, n);
374: break;
375:
376: case SUBARRAY:
377: printf("subarray of ");
378: for (i = 1; i < t->symvalue.ndims; i++) {
379: printf("array of ");
380: }
381: printtype(t, t->type, n);
382: break;
383:
384: case RECORD:
385: printRecordDecl(t, n);
386: break;
387:
388: case FIELD:
389: if (t->chain != nil) {
390: printtype(t->chain, t->chain, n);
391: }
392: printf("\t%s : ", symname(t));
393: printtype(t, t->type, n);
394: printf(";\n");
395: break;
396:
397: case RANGE:
398: printRangeDecl(t);
399: break;
400:
401: case PTR:
402: printf("pointer to ");
403: printtype(t, t->type, n);
404: break;
405:
406: case TYPE:
407: if (t->name != nil and ident(t->name)[0] != '\0') {
408: printname(stdout, t);
409: } else {
410: printtype(t, t->type, n);
411: }
412: break;
413:
414: case SCAL:
415: printEnumDecl(t, n);
416: break;
417:
418: case SET:
419: printf("set of ");
420: printtype(t, t->type, n);
421: break;
422:
423: case TYPEREF:
424: break;
425:
426: case FPROC:
427: case FFUNC:
428: printf("procedure");
429: break;
430:
431: default:
432: printf("[%s]", classname(t));
433: break;
434: }
435: }
436:
437: /*
438: * Print out a record declaration.
439: */
440:
441: private printRecordDecl (t, n)
442: Symbol t;
443: int n;
444: {
445: register Symbol f;
446:
447: if (t->chain == nil) {
448: printf("record end");
449: } else {
450: printf("record\n");
451: for (f = t->chain; f != nil; f = f->chain) {
452: indent(n+4);
453: printf("%s : ", symname(f));
454: printtype(f->type, f->type, n+4);
455: printf(";\n");
456: }
457: indent(n);
458: printf("end");
459: }
460: }
461:
462: /*
463: * Print out the declaration of a range type.
464: */
465:
466: private printRangeDecl (t)
467: Symbol t;
468: {
469: long r0, r1;
470:
471: r0 = t->symvalue.rangev.lower;
472: r1 = t->symvalue.rangev.upper;
473: if (ischar(t)) {
474: if (r0 < 0x20 or r0 > 0x7e) {
475: printf("%ld..", r0);
476: } else {
477: printf("'%c'..", (char) r0);
478: }
479: if (r1 < 0x20 or r1 > 0x7e) {
480: printf("\\%lo", r1);
481: } else {
482: printf("'%c'", (char) r1);
483: }
484: } else if (r0 > 0 and r1 == 0) {
485: printf("%ld byte real", r0);
486: } else if (r0 >= 0) {
487: printf("%lu..%lu", r0, r1);
488: } else {
489: printf("%ld..%ld", r0, r1);
490: }
491: }
492:
493: /*
494: * Print out an enumeration declaration.
495: */
496:
497: private printEnumDecl (e, n)
498: Symbol e;
499: int n;
500: {
501: Symbol t;
502:
503: printf("(");
504: t = e->chain;
505: if (t != nil) {
506: printf("%s", symname(t));
507: t = t->chain;
508: while (t != nil) {
509: printf(", %s", symname(t));
510: t = t->chain;
511: }
512: }
513: printf(")");
514: }
515:
516: /*
517: * List the parameters of a procedure or function.
518: * No attempt is made to combine like types.
519: */
520:
521: private listparams (s)
522: Symbol s;
523: {
524: Symbol t;
525:
526: if (s->chain != nil) {
527: putchar('(');
528: for (t = s->chain; t != nil; t = t->chain) {
529: switch (t->class) {
530: case REF:
531: printf("var ");
532: break;
533:
534: case FPROC:
535: case FFUNC:
536: printf("procedure ");
537: break;
538:
539: case VAR:
540: break;
541:
542: default:
543: panic("unexpected class %d for parameter", t->class);
544: }
545: printf("%s", symname(t));
546: if (s->class == PROG) {
547: printf(", ");
548: } else {
549: printf(" : ");
550: printtype(t, t->type, 0);
551: if (t->chain != nil) {
552: printf("; ");
553: }
554: }
555: }
556: putchar(')');
557: }
558: }
559:
560: /*
561: * Test if a pointer type should be treated as a null-terminated string.
562: * The type given is the type that is pointed to.
563: */
564:
565: private boolean isCstring (type)
566: Symbol type;
567: {
568: boolean b;
569: register Symbol a, t;
570:
571: a = rtype(type);
572: if (a->class == ARRAY) {
573: t = rtype(a->chain);
574: b = (boolean) (
575: t->class == RANGE and istypename(a->type, "char") and
576: (t->symvalue.rangev.upper - t->symvalue.rangev.lower + 1) <= 0
577: );
578: } else {
579: b = false;
580: }
581: return b;
582: }
583:
584: /*
585: * Modula 2 interface to printval.
586: */
587:
588: public modula2_printval (s)
589: Symbol s;
590: {
591: prval(s, size(s));
592: }
593:
594: /*
595: * Print out the value on the top of the expression stack
596: * in the format for the type of the given symbol, assuming
597: * the size of the object is n bytes.
598: */
599:
600: private prval (s, n)
601: Symbol s;
602: integer n;
603: {
604: Symbol t;
605: Address a;
606: integer len;
607: double r;
608: integer i;
609:
610: if (s->class == TYPEREF) {
611: resolveRef(s);
612: }
613: switch (s->class) {
614: case CONST:
615: case TYPE:
616: case REF:
617: case VAR:
618: case FVAR:
619: case TAG:
620: prval(s->type, n);
621: break;
622:
623: case FIELD:
624: if (isbitfield(s)) {
625: i = extractField(s);
626: t = rtype(s->type);
627: if (t->class == SCAL) {
628: printEnum(i, t);
629: } else {
630: printRangeVal(i, t);
631: }
632: } else {
633: prval(s->type, n);
634: }
635: break;
636:
637: case ARRAY:
638: t = rtype(s->type);
639: if (ischar(t)) {
640: len = size(s);
641: sp -= len;
642: printf("\"%.*s\"", len, sp);
643: break;
644: } else {
645: printarray(s);
646: }
647: break;
648:
649: case OPENARRAY:
650: case DYNARRAY:
651: printDynarray(s);
652: break;
653:
654: case SUBARRAY:
655: printSubarray(s);
656: break;
657:
658: case RECORD:
659: printrecord(s);
660: break;
661:
662: case VARNT:
663: printf("[variant]");
664: break;
665:
666: case RANGE:
667: printrange(s, n);
668: break;
669:
670: /*
671: * Unresolved opaque type.
672: * Probably a pointer.
673: */
674: case TYPEREF:
675: a = pop(Address);
676: printf("@%x", a);
677: break;
678:
679: case FILET:
680: a = pop(Address);
681: if (a == 0) {
682: printf("nil");
683: } else {
684: printf("0x%x", a);
685: }
686: break;
687:
688: case PTR:
689: a = pop(Address);
690: if (a == 0) {
691: printf("nil");
692: } else if (isCstring(s->type)) {
693: printString(a, true);
694: } else {
695: printf("0x%x", a);
696: }
697: break;
698:
699: case SCAL:
700: i = 0;
701: popn(n, &i);
702: printEnum(i, s);
703: break;
704:
705: case FPROC:
706: case FFUNC:
707: a = pop(long);
708: t = whatblock(a);
709: if (t == nil) {
710: printf("0x%x", a);
711: } else {
712: printname(stdout, t);
713: }
714: break;
715:
716: case SET:
717: printSet(s);
718: break;
719:
720: default:
721: if (ord(s->class) < ord(BADUSE) or ord(s->class) > ord(TYPEREF)) {
722: panic("printval: bad class %d", ord(s->class));
723: }
724: printf("[%s]", classname(s));
725: break;
726: }
727: }
728:
729: /*
730: * Print out a dynamic array.
731: */
732:
733: private Address printDynSlice();
734:
735: private printDynarray (t)
736: Symbol t;
737: {
738: Address base;
739: integer n;
740: Stack *savesp, *newsp;
741: Symbol eltype;
742:
743: savesp = sp;
744: sp -= (t->symvalue.ndims * sizeof(Word));
745: base = pop(Address);
746: newsp = sp;
747: sp = savesp;
748: eltype = rtype(t->type);
749: if (t->symvalue.ndims == 0) {
750: if (ischar(eltype)) {
751: printString(base, true);
752: } else {
753: printf("[dynarray @nocount]");
754: }
755: } else {
756: n = ((long *) sp)[-(t->symvalue.ndims)];
757: base = printDynSlice(base, n, t->symvalue.ndims, eltype, size(eltype));
758: }
759: sp = newsp;
760: }
761:
762: /*
763: * Print out one dimension of a multi-dimension dynamic array.
764: *
765: * Return the address of the element that follows the printed elements.
766: */
767:
768: private Address printDynSlice (base, count, ndims, eltype, elsize)
769: Address base;
770: integer count, ndims;
771: Symbol eltype;
772: integer elsize;
773: {
774: Address b;
775: integer i, n;
776: char *slice;
777: Stack *savesp;
778:
779: b = base;
780: if (ndims > 1) {
781: n = ((long *) sp)[-ndims + 1];
782: }
783: if (ndims == 1 and ischar(eltype)) {
784: slice = newarr(char, count);
785: dread(slice, b, count);
786: printf("\"%.*s\"", count, slice);
787: dispose(slice);
788: b += count;
789: } else {
790: printf("(");
791: for (i = 0; i < count; i++) {
792: if (i != 0) {
793: printf(", ");
794: }
795: if (ndims == 1) {
796: slice = newarr(char, elsize);
797: dread(slice, b, elsize);
798: savesp = sp;
799: sp = slice + elsize;
800: printval(eltype);
801: sp = savesp;
802: dispose(slice);
803: b += elsize;
804: } else {
805: b = printDynSlice(b, n, ndims - 1, eltype, elsize);
806: }
807: }
808: printf(")");
809: }
810: return b;
811: }
812:
813: private printSubarray (t)
814: Symbol t;
815: {
816: printf("[subarray]");
817: }
818:
819: /*
820: * Print out the value of a scalar (non-enumeration) type.
821: */
822:
823: private printrange (s, n)
824: Symbol s;
825: integer n;
826: {
827: double d;
828: float f;
829: integer i;
830:
831: if (s->symvalue.rangev.upper == 0 and s->symvalue.rangev.lower > 0) {
832: if (n == sizeof(float)) {
833: popn(n, &f);
834: d = f;
835: } else {
836: popn(n, &d);
837: }
838: prtreal(d);
839: } else {
840: i = 0;
841: popn(n, &i);
842: printRangeVal(i, s);
843: }
844: }
845:
846: /*
847: * Print out a set.
848: */
849:
850: private printSet (s)
851: Symbol s;
852: {
853: Symbol t;
854: integer nbytes;
855:
856: nbytes = size(s);
857: t = rtype(s->type);
858: printf("{");
859: sp -= nbytes;
860: if (t->class == SCAL) {
861: printSetOfEnum(t);
862: } else if (t->class == RANGE) {
863: printSetOfRange(t);
864: } else {
865: panic("expected range or enumerated base type for set");
866: }
867: printf("}");
868: }
869:
870: /*
871: * Print out a set of an enumeration.
872: */
873:
874: private printSetOfEnum (t)
875: Symbol t;
876: {
877: register Symbol e;
878: register integer i, j, *p;
879: boolean first;
880:
881: p = (int *) sp;
882: i = *p;
883: j = 0;
884: e = t->chain;
885: first = true;
886: while (e != nil) {
887: if ((i&1) == 1) {
888: if (first) {
889: first = false;
890: printf("%s", symname(e));
891: } else {
892: printf(", %s", symname(e));
893: }
894: }
895: i >>= 1;
896: ++j;
897: if (j >= sizeof(integer)*BITSPERBYTE) {
898: j = 0;
899: ++p;
900: i = *p;
901: }
902: e = e->chain;
903: }
904: }
905:
906: /*
907: * Print out a set of a subrange type.
908: */
909:
910: private printSetOfRange (t)
911: Symbol t;
912: {
913: register integer i, j, *p;
914: long v;
915: boolean first;
916:
917: p = (int *) sp;
918: i = *p;
919: j = 0;
920: v = t->symvalue.rangev.lower;
921: first = true;
922: while (v <= t->symvalue.rangev.upper) {
923: if ((i&1) == 1) {
924: if (first) {
925: first = false;
926: printf("%ld", v);
927: } else {
928: printf(", %ld", v);
929: }
930: }
931: i >>= 1;
932: ++j;
933: if (j >= sizeof(integer)*BITSPERBYTE) {
934: j = 0;
935: ++p;
936: i = *p;
937: }
938: ++v;
939: }
940: }
941:
942: /*
943: * Construct a node for subscripting a dynamic or subarray.
944: * The list of indices is left for processing in evalaref,
945: * unlike normal subscripting in which the list is expanded
946: * across individual INDEX nodes.
947: */
948:
949: private Node dynref (a, t, slist)
950: Node a;
951: Symbol t;
952: Node slist;
953: {
954: Node p, r;
955: integer n;
956:
957: p = slist;
958: n = 0;
959: while (p != nil) {
960: if (not compatible(p->value.arg[0]->nodetype, t_int)) {
961: suberror("subscript \"", p->value.arg[0], "\" is the wrong type");
962: }
963: ++n;
964: p = p->value.arg[1];
965: }
966: if (n > t->symvalue.ndims and (t->symvalue.ndims != 0 or n != 1)) {
967: suberror("too many subscripts for ", a, nil);
968: } else if (n < t->symvalue.ndims) {
969: suberror("not enough subscripts for ", a, nil);
970: }
971: r = build(O_INDEX, a, slist);
972: r->nodetype = rtype(t->type);
973: return r;
974: }
975:
976: /*
977: * Construct a node for subscripting.
978: */
979:
980: public Node modula2_buildaref (a, slist)
981: Node a, slist;
982: {
983: register Symbol t;
984: register Node p;
985: Symbol eltype;
986: Node esub, r;
987: integer n;
988:
989: t = rtype(a->nodetype);
990: switch (t->class) {
991: case OPENARRAY:
992: case DYNARRAY:
993: case SUBARRAY:
994: r = dynref(a, t, slist);
995: break;
996:
997: case ARRAY:
998: r = a;
999: eltype = rtype(t->type);
1000: p = slist;
1001: t = t->chain;
1002: while (p != nil and t != nil) {
1003: esub = p->value.arg[0];
1004: if (not compatible(rtype(t), rtype(esub->nodetype))) {
1005: suberror("subscript \"", esub, "\" is the wrong type");
1006: }
1007: r = build(O_INDEX, r, esub);
1008: r->nodetype = eltype;
1009: p = p->value.arg[1];
1010: t = t->chain;
1011: }
1012: if (p != nil) {
1013: suberror("too many subscripts for ", a, nil);
1014: } else if (t != nil) {
1015: suberror("not enough subscripts for ", a, nil);
1016: }
1017: break;
1018:
1019: default:
1020: suberror("\"", a, "\" is not an array");
1021: break;
1022: }
1023: return r;
1024: }
1025:
1026: /*
1027: * Subscript usage error reporting.
1028: */
1029:
1030: private suberror (s1, e1, s2)
1031: String s1, s2;
1032: Node e1;
1033: {
1034: beginerrmsg();
1035: if (s1 != nil) {
1036: fprintf(stderr, s1);
1037: }
1038: if (e1 != nil) {
1039: prtree(stderr, e1);
1040: }
1041: if (s2 != nil) {
1042: fprintf(stderr, s2);
1043: }
1044: enderrmsg();
1045: }
1046:
1047: /*
1048: * Check that a subscript value is in the appropriate range.
1049: */
1050:
1051: private subchk (value, lower, upper)
1052: long value, lower, upper;
1053: {
1054: if (value < lower or value > upper) {
1055: error("subscript value %d out of range [%d..%d]", value, lower, upper);
1056: }
1057: }
1058:
1059: /*
1060: * Compute the offset for subscripting a dynamic array.
1061: */
1062:
1063: private getdynoff (ndims, sub)
1064: integer ndims;
1065: long *sub;
1066: {
1067: long k, off, *count;
1068:
1069: count = (long *) sp;
1070: off = 0;
1071: for (k = 0; k < ndims - 1; k++) {
1072: subchk(sub[k], 0, count[k] - 1);
1073: off += (sub[k] * count[k+1]);
1074: }
1075: subchk(sub[ndims - 1], 0, count[ndims - 1] - 1);
1076: return off + sub[ndims - 1];
1077: }
1078:
1079: /*
1080: * Compute the offset associated with a subarray.
1081: */
1082:
1083: private getsuboff (ndims, sub)
1084: integer ndims;
1085: long *sub;
1086: {
1087: long k, off;
1088: struct subarrayinfo {
1089: long count;
1090: long mult;
1091: } *info;
1092:
1093: info = (struct subarrayinfo *) sp;
1094: off = 0;
1095: for (k = 0; k < ndims; k++) {
1096: subchk(sub[k], 0, info[k].count - 1);
1097: off += sub[k] * info[k].mult;
1098: }
1099: return off;
1100: }
1101:
1102: /*
1103: * Evaluate a subscript index.
1104: */
1105:
1106: public modula2_evalaref (s, base, i)
1107: Symbol s;
1108: Address base;
1109: long i;
1110: {
1111: Symbol t;
1112: long lb, ub, off;
1113: long *sub;
1114: Address b;
1115:
1116: t = rtype(s);
1117: if (t->class == ARRAY) {
1118: findbounds(rtype(t->chain), &lb, &ub);
1119: if (i < lb or i > ub) {
1120: error("subscript %d out of range [%d..%d]", i, lb, ub);
1121: }
1122: push(long, base + (i - lb) * size(t->type));
1123: } else if ((t->class == OPENARRAY or t->class == DYNARRAY) and
1124: t->symvalue.ndims == 0
1125: ) {
1126: push(long, base + i * size(t->type));
1127: } else if (t->class == OPENARRAY or t->class == DYNARRAY or
1128: t->class == SUBARRAY
1129: ) {
1130: push(long, i);
1131: sub = (long *) (sp - (t->symvalue.ndims * sizeof(long)));
1132: rpush(base, size(t));
1133: sp -= (t->symvalue.ndims * sizeof(long));
1134: b = pop(Address);
1135: sp += sizeof(Address);
1136: if (t->class == SUBARRAY) {
1137: off = getsuboff(t->symvalue.ndims, sub);
1138: } else {
1139: off = getdynoff(t->symvalue.ndims, sub);
1140: }
1141: sp = (Stack *) sub;
1142: push(long, b + off * size(t->type));
1143: } else {
1144: error("[internal error: expected array in evalaref]");
1145: }
1146: }
1147:
1148: /*
1149: * Initial Modula-2 type information.
1150: */
1151:
1152: #define NTYPES 12
1153:
1154: private Symbol inittype[NTYPES + 1];
1155:
1156: private addType (n, s, lower, upper)
1157: integer n;
1158: String s;
1159: long lower, upper;
1160: {
1161: register Symbol t;
1162:
1163: if (n > NTYPES) {
1164: panic("initial Modula-2 type number too large for '%s'", s);
1165: }
1166: t = insert(identname(s, true));
1167: t->language = mod2;
1168: t->class = TYPE;
1169: t->type = newSymbol(nil, 0, RANGE, t, nil);
1170: t->type->symvalue.rangev.lower = lower;
1171: t->type->symvalue.rangev.upper = upper;
1172: t->type->language = mod2;
1173: inittype[n] = t;
1174: }
1175:
1176: private initModTypes ()
1177: {
1178: addType(1, "integer", 0x80000000L, 0x7fffffffL);
1179: addType(2, "char", 0L, 255L);
1180: addType(3, "boolean", 0L, 1L);
1181: addType(4, "unsigned", 0L, 0xffffffffL);
1182: addType(5, "real", 4L, 0L);
1183: addType(6, "longreal", 8L, 0L);
1184: addType(7, "word", 0L, 0xffffffffL);
1185: addType(8, "byte", 0L, 255L);
1186: addType(9, "address", 0L, 0xffffffffL);
1187: addType(10, "file", 0L, 0xffffffffL);
1188: addType(11, "process", 0L, 0xffffffffL);
1189: addType(12, "cardinal", 0L, 0x7fffffffL);
1190: }
1191:
1192: /*
1193: * Initialize typetable.
1194: */
1195:
1196: public modula2_modinit (typetable)
1197: Symbol typetable[];
1198: {
1199: register integer i;
1200:
1201: if (not initialized) {
1202: initModTypes();
1203: initialized = true;
1204: }
1205: for (i = 1; i <= NTYPES; i++) {
1206: typetable[i] = inittype[i];
1207: }
1208: }
1209:
1210: public boolean modula2_hasmodules ()
1211: {
1212: return true;
1213: }
1214:
1215: public boolean modula2_passaddr (param, exprtype)
1216: Symbol param, exprtype;
1217: {
1218: return false;
1219: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.