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