xref: /csrg-svn/old/dbx/modula-2.c (revision 33326)
121613Sdist /*
221613Sdist  * Copyright (c) 1983 Regents of the University of California.
321613Sdist  * All rights reserved.  The Berkeley software License Agreement
421613Sdist  * specifies the terms and conditions for redistribution.
521613Sdist  */
618261Slinton 
716622Ssam #ifndef lint
8*33326Sdonn static char sccsid[] = "@(#)modula-2.c	5.2 (Berkeley) 01/12/88";
921613Sdist #endif not lint
1016622Ssam 
1116622Ssam /*
1216622Ssam  * Modula-2 specific symbol routines.
1316622Ssam  */
1416622Ssam 
15*33326Sdonn static char rcsid[] = "$Header: modula-2.c,v 1.2 87/03/26 20:12:54 donn Exp $";
1618261Slinton 
1716622Ssam #include "defs.h"
1816622Ssam #include "symbols.h"
1916622Ssam #include "modula-2.h"
2016622Ssam #include "languages.h"
2116622Ssam #include "tree.h"
2216622Ssam #include "eval.h"
2316622Ssam #include "mappings.h"
2416622Ssam #include "process.h"
2516622Ssam #include "runtime.h"
2616622Ssam #include "machine.h"
2716622Ssam 
2816622Ssam #ifndef public
2916622Ssam #endif
3016622Ssam 
3116622Ssam private Language mod2;
3216622Ssam private boolean initialized;
3316622Ssam 
3418261Slinton 
3518261Slinton #define ischar(t) ( \
3618261Slinton     (t) == t_char->type or \
3718261Slinton     ((t)->class == RANGE and istypename((t)->type, "char")) \
3818261Slinton )
3918261Slinton 
4016622Ssam /*
4116622Ssam  * Initialize Modula-2 information.
4216622Ssam  */
4316622Ssam 
4416622Ssam public modula2_init ()
4516622Ssam {
4616622Ssam     mod2 = language_define("modula-2", ".mod");
4716622Ssam     language_setop(mod2, L_PRINTDECL, modula2_printdecl);
4816622Ssam     language_setop(mod2, L_PRINTVAL, modula2_printval);
4916622Ssam     language_setop(mod2, L_TYPEMATCH, modula2_typematch);
5016622Ssam     language_setop(mod2, L_BUILDAREF, modula2_buildaref);
5116622Ssam     language_setop(mod2, L_EVALAREF, modula2_evalaref);
5216622Ssam     language_setop(mod2, L_MODINIT, modula2_modinit);
5316622Ssam     language_setop(mod2, L_HASMODULES, modula2_hasmodules);
5416622Ssam     language_setop(mod2, L_PASSADDR, modula2_passaddr);
5516622Ssam     initialized = false;
5616622Ssam }
5716622Ssam 
5816622Ssam /*
5916622Ssam  * Typematch tests if two types are compatible.  The issue
6016622Ssam  * is a bit complicated, so several subfunctions are used for
6116622Ssam  * various kinds of compatibility.
6216622Ssam  */
6316622Ssam 
6418261Slinton private boolean builtinmatch (t1, t2)
6518261Slinton register Symbol t1, t2;
6618261Slinton {
6718261Slinton     boolean b;
6818261Slinton 
6918261Slinton     b = (boolean) (
7018261Slinton 	(
7118261Slinton 	    t2 == t_int->type and t1->class == RANGE and
7218261Slinton 	    (
7318261Slinton 		istypename(t1->type, "integer") or
7418261Slinton 		istypename(t1->type, "cardinal")
7518261Slinton 	    )
7618261Slinton 	) or (
7718261Slinton 	    t2 == t_char->type and
7818261Slinton 	    t1->class == RANGE and istypename(t1->type, "char")
7918261Slinton 	) or (
8018261Slinton 	    t2 == t_real->type and
8118261Slinton 	    t1->class == RANGE and (
8218261Slinton 		istypename(t1->type, "real") or
8318261Slinton 		istypename(t1->type, "longreal")
8418261Slinton 	    )
8518261Slinton 	) or (
8618261Slinton 	    t2 == t_boolean->type and
8718261Slinton 	    t1->class == RANGE and istypename(t1->type, "boolean")
8818261Slinton 	)
8918261Slinton     );
9018261Slinton     return b;
9118261Slinton }
9218261Slinton 
9316622Ssam private boolean nilMatch (t1, t2)
9416622Ssam register Symbol t1, t2;
9516622Ssam {
9616622Ssam     boolean b;
9716622Ssam 
9816622Ssam     b = (boolean) (
9916622Ssam 	(t1 == t_nil and t2->class == PTR) or
10016622Ssam 	(t1->class == PTR and t2 == t_nil)
10116622Ssam     );
10216622Ssam     return b;
10316622Ssam }
10416622Ssam 
10516622Ssam private boolean enumMatch (t1, t2)
10616622Ssam register Symbol t1, t2;
10716622Ssam {
10816622Ssam     boolean b;
10916622Ssam 
11016622Ssam     b = (boolean) (
11118261Slinton 	(t1->class == SCAL and t2->class == CONST and t2->type == t1) or
11218261Slinton 	(t1->class == CONST and t2->class == SCAL and t1->type == t2)
11316622Ssam     );
11416622Ssam     return b;
11516622Ssam }
11616622Ssam 
11716622Ssam private boolean openArrayMatch (t1, t2)
11816622Ssam register Symbol t1, t2;
11916622Ssam {
12016622Ssam     boolean b;
12116622Ssam 
12216622Ssam     b = (boolean) (
12316622Ssam 	(
124*33326Sdonn 	    t1->class == OPENARRAY and t1->symvalue.ndims == 1 and
12516622Ssam 	    t2->class == ARRAY and
12616622Ssam 	    compatible(rtype(t2->chain)->type, t_int) and
12716622Ssam 	    compatible(t1->type, t2->type)
12816622Ssam 	) or (
129*33326Sdonn 	    t2->class == OPENARRAY and t2->symvalue.ndims == 1 and
13016622Ssam 	    t1->class == ARRAY and
13116622Ssam 	    compatible(rtype(t1->chain)->type, t_int) and
13216622Ssam 	    compatible(t1->type, t2->type)
13316622Ssam 	)
13416622Ssam     );
13516622Ssam     return b;
13616622Ssam }
13716622Ssam 
13816622Ssam private boolean isConstString (t)
13916622Ssam register Symbol t;
14016622Ssam {
14116622Ssam     boolean b;
14216622Ssam 
14316622Ssam     b = (boolean) (
14416622Ssam 	t->language == primlang and t->class == ARRAY and t->type == t_char
14516622Ssam     );
14616622Ssam     return b;
14716622Ssam }
14816622Ssam 
14916622Ssam private boolean stringArrayMatch (t1, t2)
15016622Ssam register Symbol t1, t2;
15116622Ssam {
15216622Ssam     boolean b;
15316622Ssam 
15416622Ssam     b = (boolean) (
15516622Ssam 	(
15616622Ssam 	    isConstString(t1) and
15716622Ssam 	    t2->class == ARRAY and compatible(t2->type, t_char->type)
15816622Ssam 	) or (
15916622Ssam 	    isConstString(t2) and
16016622Ssam 	    t1->class == ARRAY and compatible(t1->type, t_char->type)
16116622Ssam 	)
16216622Ssam     );
16316622Ssam     return b;
16416622Ssam }
16516622Ssam 
16616622Ssam public boolean modula2_typematch (type1, type2)
16716622Ssam Symbol type1, type2;
16816622Ssam {
16918261Slinton     boolean b;
17016622Ssam     Symbol t1, t2, tmp;
17116622Ssam 
17216622Ssam     t1 = rtype(type1);
17316622Ssam     t2 = rtype(type2);
17416622Ssam     if (t1 == t2) {
17516622Ssam 	b = true;
17616622Ssam     } else {
17718261Slinton 	if (t1 == t_char->type or t1 == t_int->type or
17818261Slinton 	    t1 == t_real->type or t1 == t_boolean->type
17918261Slinton 	) {
18016622Ssam 	    tmp = t1;
18116622Ssam 	    t1 = t2;
18216622Ssam 	    t2 = tmp;
18316622Ssam 	}
18416622Ssam 	b = (Boolean) (
185*33326Sdonn 	    builtinmatch(t1, t2) or
18618261Slinton 	    nilMatch(t1, t2) or enumMatch(t1, t2) or
18718261Slinton 	    openArrayMatch(t1, t2) or stringArrayMatch(t1, t2)
18816622Ssam 	);
18916622Ssam     }
19016622Ssam     return b;
19116622Ssam }
19216622Ssam 
19316622Ssam /*
19416622Ssam  * Indent n spaces.
19516622Ssam  */
19616622Ssam 
19716622Ssam private indent (n)
19816622Ssam int n;
19916622Ssam {
20016622Ssam     if (n > 0) {
20116622Ssam 	printf("%*c", n, ' ');
20216622Ssam     }
20316622Ssam }
20416622Ssam 
20516622Ssam public modula2_printdecl (s)
20616622Ssam Symbol s;
20716622Ssam {
20816622Ssam     register Symbol t;
20916622Ssam     Boolean semicolon;
21016622Ssam 
21116622Ssam     semicolon = true;
21216622Ssam     if (s->class == TYPEREF) {
21316622Ssam 	resolveRef(t);
21416622Ssam     }
21516622Ssam     switch (s->class) {
21616622Ssam 	case CONST:
21716622Ssam 	    if (s->type->class == SCAL) {
21818261Slinton 		semicolon = false;
21918261Slinton 		printf("enumeration constant with value ");
22018261Slinton 		eval(s->symvalue.constval);
22118261Slinton 		modula2_printval(s);
22216622Ssam 	    } else {
22316622Ssam 		printf("const %s = ", symname(s));
22418261Slinton 		eval(s->symvalue.constval);
22516622Ssam 		modula2_printval(s);
22616622Ssam 	    }
22716622Ssam 	    break;
22816622Ssam 
22916622Ssam 	case TYPE:
23016622Ssam 	    printf("type %s = ", symname(s));
23116622Ssam 	    printtype(s, s->type, 0);
23216622Ssam 	    break;
23316622Ssam 
23416622Ssam 	case TYPEREF:
23516622Ssam 	    printf("type %s", symname(s));
23616622Ssam 	    break;
23716622Ssam 
23816622Ssam 	case VAR:
23916622Ssam 	    if (isparam(s)) {
24016622Ssam 		printf("(parameter) %s : ", symname(s));
24116622Ssam 	    } else {
24216622Ssam 		printf("var %s : ", symname(s));
24316622Ssam 	    }
24416622Ssam 	    printtype(s, s->type, 0);
24516622Ssam 	    break;
24616622Ssam 
24716622Ssam 	case REF:
24816622Ssam 	    printf("(var parameter) %s : ", symname(s));
24916622Ssam 	    printtype(s, s->type, 0);
25016622Ssam 	    break;
25116622Ssam 
25216622Ssam 	case RANGE:
25316622Ssam 	case ARRAY:
254*33326Sdonn 	case OPENARRAY:
25518261Slinton 	case DYNARRAY:
25618261Slinton 	case SUBARRAY:
25716622Ssam 	case RECORD:
25816622Ssam 	case VARNT:
25916622Ssam 	case PTR:
26016622Ssam 	    printtype(s, s, 0);
26116622Ssam 	    semicolon = false;
26216622Ssam 	    break;
26316622Ssam 
26416622Ssam 	case FVAR:
26516622Ssam 	    printf("(function variable) %s : ", symname(s));
26616622Ssam 	    printtype(s, s->type, 0);
26716622Ssam 	    break;
26816622Ssam 
26916622Ssam 	case FIELD:
27016622Ssam 	    printf("(field) %s : ", symname(s));
27116622Ssam 	    printtype(s, s->type, 0);
27216622Ssam 	    break;
27316622Ssam 
27416622Ssam 	case PROC:
27516622Ssam 	    printf("procedure %s", symname(s));
27616622Ssam 	    listparams(s);
27716622Ssam 	    break;
27816622Ssam 
27916622Ssam 	case PROG:
28016622Ssam 	    printf("program %s", symname(s));
28116622Ssam 	    listparams(s);
28216622Ssam 	    break;
28316622Ssam 
28416622Ssam 	case FUNC:
28518261Slinton 	    printf("procedure %s", symname(s));
28616622Ssam 	    listparams(s);
28716622Ssam 	    printf(" : ");
28816622Ssam 	    printtype(s, s->type, 0);
28916622Ssam 	    break;
29016622Ssam 
29116622Ssam 	case MODULE:
29216622Ssam 	    printf("module %s", symname(s));
29316622Ssam 	    break;
29416622Ssam 
29516622Ssam 	default:
29618261Slinton 	    printf("[%s]", classname(s));
29716622Ssam 	    break;
29816622Ssam     }
29916622Ssam     if (semicolon) {
30016622Ssam 	putchar(';');
30116622Ssam     }
30216622Ssam     putchar('\n');
30316622Ssam }
30416622Ssam 
30516622Ssam /*
30616622Ssam  * Recursive whiz-bang procedure to print the type portion
30716622Ssam  * of a declaration.
30816622Ssam  *
30916622Ssam  * The symbol associated with the type is passed to allow
31016622Ssam  * searching for type names without getting "type blah = blah".
31116622Ssam  */
31216622Ssam 
31316622Ssam private printtype (s, t, n)
31416622Ssam Symbol s;
31516622Ssam Symbol t;
31616622Ssam int n;
31716622Ssam {
31818261Slinton     Symbol tmp;
31918261Slinton     int i;
32016622Ssam 
32116622Ssam     if (t->class == TYPEREF) {
32216622Ssam 	resolveRef(t);
32316622Ssam     }
32416622Ssam     switch (t->class) {
32516622Ssam 	case VAR:
32616622Ssam 	case CONST:
32716622Ssam 	case FUNC:
32816622Ssam 	case PROC:
32916622Ssam 	    panic("printtype: class %s", classname(t));
33016622Ssam 	    break;
33116622Ssam 
33216622Ssam 	case ARRAY:
33316622Ssam 	    printf("array[");
33416622Ssam 	    tmp = t->chain;
33516622Ssam 	    if (tmp != nil) {
33616622Ssam 		for (;;) {
33716622Ssam 		    printtype(tmp, tmp, n);
33816622Ssam 		    tmp = tmp->chain;
33916622Ssam 		    if (tmp == nil) {
34016622Ssam 			break;
34116622Ssam 		    }
34216622Ssam 		    printf(", ");
34316622Ssam 		}
34416622Ssam 	    }
34516622Ssam 	    printf("] of ");
34616622Ssam 	    printtype(t, t->type, n);
34716622Ssam 	    break;
34816622Ssam 
349*33326Sdonn 	case OPENARRAY:
350*33326Sdonn 	    printf("array of ");
351*33326Sdonn 	    for (i = 1; i < t->symvalue.ndims; i++) {
352*33326Sdonn 		printf("array of ");
353*33326Sdonn 	    }
354*33326Sdonn 	    printtype(t, t->type, n);
355*33326Sdonn 	    break;
356*33326Sdonn 
35718261Slinton 	case DYNARRAY:
35818261Slinton 	    printf("dynarray of ");
35918261Slinton 	    for (i = 1; i < t->symvalue.ndims; i++) {
36018261Slinton 		printf("array of ");
36118261Slinton 	    }
36218261Slinton 	    printtype(t, t->type, n);
36318261Slinton 	    break;
36418261Slinton 
36518261Slinton 	case SUBARRAY:
36618261Slinton 	    printf("subarray of ");
36718261Slinton 	    for (i = 1; i < t->symvalue.ndims; i++) {
36818261Slinton 		printf("array of ");
36918261Slinton 	    }
37018261Slinton 	    printtype(t, t->type, n);
37118261Slinton 	    break;
37218261Slinton 
37316622Ssam 	case RECORD:
37416622Ssam 	    printRecordDecl(t, n);
37516622Ssam 	    break;
37616622Ssam 
37716622Ssam 	case FIELD:
37816622Ssam 	    if (t->chain != nil) {
37916622Ssam 		printtype(t->chain, t->chain, n);
38016622Ssam 	    }
38116622Ssam 	    printf("\t%s : ", symname(t));
38216622Ssam 	    printtype(t, t->type, n);
38316622Ssam 	    printf(";\n");
38416622Ssam 	    break;
38516622Ssam 
38616622Ssam 	case RANGE:
38716622Ssam 	    printRangeDecl(t);
38816622Ssam 	    break;
38916622Ssam 
39016622Ssam 	case PTR:
39116622Ssam 	    printf("pointer to ");
39216622Ssam 	    printtype(t, t->type, n);
39316622Ssam 	    break;
39416622Ssam 
39516622Ssam 	case TYPE:
39616622Ssam 	    if (t->name != nil and ident(t->name)[0] != '\0') {
39716622Ssam 		printname(stdout, t);
39816622Ssam 	    } else {
39916622Ssam 		printtype(t, t->type, n);
40016622Ssam 	    }
40116622Ssam 	    break;
40216622Ssam 
40316622Ssam 	case SCAL:
40416622Ssam 	    printEnumDecl(t, n);
40516622Ssam 	    break;
40616622Ssam 
40716622Ssam 	case SET:
40816622Ssam 	    printf("set of ");
40916622Ssam 	    printtype(t, t->type, n);
41016622Ssam 	    break;
41116622Ssam 
41216622Ssam 	case TYPEREF:
41316622Ssam 	    break;
41416622Ssam 
41518261Slinton 	case FPROC:
41618261Slinton 	case FFUNC:
41718261Slinton 	    printf("procedure");
41818261Slinton 	    break;
41918261Slinton 
42016622Ssam 	default:
42118261Slinton 	    printf("[%s]", classname(t));
42216622Ssam 	    break;
42316622Ssam     }
42416622Ssam }
42516622Ssam 
42616622Ssam /*
42716622Ssam  * Print out a record declaration.
42816622Ssam  */
42916622Ssam 
43016622Ssam private printRecordDecl (t, n)
43116622Ssam Symbol t;
43216622Ssam int n;
43316622Ssam {
43416622Ssam     register Symbol f;
43516622Ssam 
43616622Ssam     if (t->chain == nil) {
43716622Ssam 	printf("record end");
43816622Ssam     } else {
43916622Ssam 	printf("record\n");
44016622Ssam 	for (f = t->chain; f != nil; f = f->chain) {
44116622Ssam 	    indent(n+4);
44216622Ssam 	    printf("%s : ", symname(f));
44316622Ssam 	    printtype(f->type, f->type, n+4);
44416622Ssam 	    printf(";\n");
44516622Ssam 	}
44616622Ssam 	indent(n);
44716622Ssam 	printf("end");
44816622Ssam     }
44916622Ssam }
45016622Ssam 
45116622Ssam /*
45216622Ssam  * Print out the declaration of a range type.
45316622Ssam  */
45416622Ssam 
45516622Ssam private printRangeDecl (t)
45616622Ssam Symbol t;
45716622Ssam {
45816622Ssam     long r0, r1;
45916622Ssam 
46016622Ssam     r0 = t->symvalue.rangev.lower;
46116622Ssam     r1 = t->symvalue.rangev.upper;
46218261Slinton     if (ischar(t)) {
46316622Ssam 	if (r0 < 0x20 or r0 > 0x7e) {
46416622Ssam 	    printf("%ld..", r0);
46516622Ssam 	} else {
46616622Ssam 	    printf("'%c'..", (char) r0);
46716622Ssam 	}
46816622Ssam 	if (r1 < 0x20 or r1 > 0x7e) {
46916622Ssam 	    printf("\\%lo", r1);
47016622Ssam 	} else {
47116622Ssam 	    printf("'%c'", (char) r1);
47216622Ssam 	}
47316622Ssam     } else if (r0 > 0 and r1 == 0) {
47416622Ssam 	printf("%ld byte real", r0);
47516622Ssam     } else if (r0 >= 0) {
47616622Ssam 	printf("%lu..%lu", r0, r1);
47716622Ssam     } else {
47816622Ssam 	printf("%ld..%ld", r0, r1);
47916622Ssam     }
48016622Ssam }
48116622Ssam 
48216622Ssam /*
48316622Ssam  * Print out an enumeration declaration.
48416622Ssam  */
48516622Ssam 
48616622Ssam private printEnumDecl (e, n)
48716622Ssam Symbol e;
48816622Ssam int n;
48916622Ssam {
49016622Ssam     Symbol t;
49116622Ssam 
49216622Ssam     printf("(");
49316622Ssam     t = e->chain;
49416622Ssam     if (t != nil) {
49516622Ssam 	printf("%s", symname(t));
49616622Ssam 	t = t->chain;
49716622Ssam 	while (t != nil) {
49816622Ssam 	    printf(", %s", symname(t));
49916622Ssam 	    t = t->chain;
50016622Ssam 	}
50116622Ssam     }
50216622Ssam     printf(")");
50316622Ssam }
50416622Ssam 
50516622Ssam /*
50616622Ssam  * List the parameters of a procedure or function.
50716622Ssam  * No attempt is made to combine like types.
50816622Ssam  */
50916622Ssam 
51016622Ssam private listparams (s)
51116622Ssam Symbol s;
51216622Ssam {
51316622Ssam     Symbol t;
51416622Ssam 
51516622Ssam     if (s->chain != nil) {
51616622Ssam 	putchar('(');
51716622Ssam 	for (t = s->chain; t != nil; t = t->chain) {
51816622Ssam 	    switch (t->class) {
51916622Ssam 		case REF:
52016622Ssam 		    printf("var ");
52116622Ssam 		    break;
52216622Ssam 
52316622Ssam 		case FPROC:
52416622Ssam 		case FFUNC:
52516622Ssam 		    printf("procedure ");
52616622Ssam 		    break;
52716622Ssam 
52816622Ssam 		case VAR:
52916622Ssam 		    break;
53016622Ssam 
53116622Ssam 		default:
53216622Ssam 		    panic("unexpected class %d for parameter", t->class);
53316622Ssam 	    }
53416622Ssam 	    printf("%s", symname(t));
53516622Ssam 	    if (s->class == PROG) {
53616622Ssam 		printf(", ");
53716622Ssam 	    } else {
53816622Ssam 		printf(" : ");
53916622Ssam 		printtype(t, t->type, 0);
54016622Ssam 		if (t->chain != nil) {
54116622Ssam 		    printf("; ");
54216622Ssam 		}
54316622Ssam 	    }
54416622Ssam 	}
54516622Ssam 	putchar(')');
54616622Ssam     }
54716622Ssam }
54816622Ssam 
54916622Ssam /*
55018261Slinton  * Test if a pointer type should be treated as a null-terminated string.
55118261Slinton  * The type given is the type that is pointed to.
55218261Slinton  */
55318261Slinton 
55418261Slinton private boolean isCstring (type)
55518261Slinton Symbol type;
55618261Slinton {
55718261Slinton     boolean b;
55818261Slinton     register Symbol a, t;
55918261Slinton 
56018261Slinton     a = rtype(type);
56118261Slinton     if (a->class == ARRAY) {
56218261Slinton 	t = rtype(a->chain);
56318261Slinton 	b = (boolean) (
56418261Slinton 	    t->class == RANGE and istypename(a->type, "char") and
56518261Slinton 	    (t->symvalue.rangev.upper - t->symvalue.rangev.lower + 1) <= 0
56618261Slinton 	);
56718261Slinton     } else {
56818261Slinton 	b = false;
56918261Slinton     }
57018261Slinton     return b;
57118261Slinton }
57218261Slinton 
57318261Slinton /*
57416622Ssam  * Modula 2 interface to printval.
57516622Ssam  */
57616622Ssam 
57716622Ssam public modula2_printval (s)
57816622Ssam Symbol s;
57916622Ssam {
58016622Ssam     prval(s, size(s));
58116622Ssam }
58216622Ssam 
58316622Ssam /*
58416622Ssam  * Print out the value on the top of the expression stack
58516622Ssam  * in the format for the type of the given symbol, assuming
58616622Ssam  * the size of the object is n bytes.
58716622Ssam  */
58816622Ssam 
58916622Ssam private prval (s, n)
59016622Ssam Symbol s;
59116622Ssam integer n;
59216622Ssam {
59316622Ssam     Symbol t;
59416622Ssam     Address a;
59516622Ssam     integer len;
59616622Ssam     double r;
59718261Slinton     integer i;
59816622Ssam 
59916622Ssam     if (s->class == TYPEREF) {
60016622Ssam 	resolveRef(s);
60116622Ssam     }
60216622Ssam     switch (s->class) {
60316622Ssam 	case CONST:
60416622Ssam 	case TYPE:
60518261Slinton 	case REF:
60616622Ssam 	case VAR:
60716622Ssam 	case FVAR:
60816622Ssam 	case TAG:
60916622Ssam 	    prval(s->type, n);
61016622Ssam 	    break;
61116622Ssam 
61218261Slinton 	case FIELD:
61318261Slinton 	    if (isbitfield(s)) {
614*33326Sdonn 		i = extractField(s);
61518261Slinton 		t = rtype(s->type);
61618261Slinton 		if (t->class == SCAL) {
61718261Slinton 		    printEnum(i, t);
61818261Slinton 		} else {
61918261Slinton 		    printRangeVal(i, t);
62018261Slinton 		}
62118261Slinton 	    } else {
62218261Slinton 		prval(s->type, n);
62318261Slinton 	    }
62418261Slinton 	    break;
62518261Slinton 
62616622Ssam 	case ARRAY:
62716622Ssam 	    t = rtype(s->type);
62818261Slinton 	    if (ischar(t)) {
62916622Ssam 		len = size(s);
63016622Ssam 		sp -= len;
63118261Slinton 		printf("\"%.*s\"", len, sp);
63216622Ssam 		break;
63316622Ssam 	    } else {
63416622Ssam 		printarray(s);
63516622Ssam 	    }
63616622Ssam 	    break;
63716622Ssam 
638*33326Sdonn 	case OPENARRAY:
63918261Slinton 	case DYNARRAY:
64018261Slinton 	    printDynarray(s);
64118261Slinton 	    break;
64218261Slinton 
64318261Slinton 	case SUBARRAY:
64418261Slinton 	    printSubarray(s);
64518261Slinton 	    break;
64618261Slinton 
64716622Ssam 	case RECORD:
64816622Ssam 	    printrecord(s);
64916622Ssam 	    break;
65016622Ssam 
65116622Ssam 	case VARNT:
65218261Slinton 	    printf("[variant]");
65316622Ssam 	    break;
65416622Ssam 
65516622Ssam 	case RANGE:
65616622Ssam 	    printrange(s, n);
65716622Ssam 	    break;
65816622Ssam 
65918261Slinton 	/*
66018261Slinton 	 * Unresolved opaque type.
66118261Slinton 	 * Probably a pointer.
66218261Slinton 	 */
66318261Slinton 	case TYPEREF:
66418261Slinton 	    a = pop(Address);
66518261Slinton 	    printf("@%x", a);
66618261Slinton 	    break;
66718261Slinton 
66816622Ssam 	case FILET:
66918261Slinton 	    a = pop(Address);
67018261Slinton 	    if (a == 0) {
67118261Slinton 		printf("nil");
67218261Slinton 	    } else {
67318261Slinton 		printf("0x%x", a);
67418261Slinton 	    }
67518261Slinton 	    break;
67618261Slinton 
67716622Ssam 	case PTR:
67816622Ssam 	    a = pop(Address);
67916622Ssam 	    if (a == 0) {
68016622Ssam 		printf("nil");
68118261Slinton 	    } else if (isCstring(s->type)) {
68218261Slinton 		printString(a, true);
68316622Ssam 	    } else {
68416622Ssam 		printf("0x%x", a);
68516622Ssam 	    }
68616622Ssam 	    break;
68716622Ssam 
68816622Ssam 	case SCAL:
68918261Slinton 	    i = 0;
69018261Slinton 	    popn(n, &i);
69118261Slinton 	    printEnum(i, s);
69216622Ssam 	    break;
69316622Ssam 
69416622Ssam 	case FPROC:
69516622Ssam 	case FFUNC:
69616622Ssam 	    a = pop(long);
69716622Ssam 	    t = whatblock(a);
69816622Ssam 	    if (t == nil) {
69918261Slinton 		printf("0x%x", a);
70016622Ssam 	    } else {
70118261Slinton 		printname(stdout, t);
70216622Ssam 	    }
70316622Ssam 	    break;
70416622Ssam 
70516622Ssam 	case SET:
70616622Ssam 	    printSet(s);
70716622Ssam 	    break;
70816622Ssam 
70916622Ssam 	default:
71016622Ssam 	    if (ord(s->class) < ord(BADUSE) or ord(s->class) > ord(TYPEREF)) {
71116622Ssam 		panic("printval: bad class %d", ord(s->class));
71216622Ssam 	    }
71316622Ssam 	    printf("[%s]", classname(s));
71416622Ssam 	    break;
71516622Ssam     }
71616622Ssam }
71716622Ssam 
71816622Ssam /*
71918261Slinton  * Print out a dynamic array.
72018261Slinton  */
72118261Slinton 
72218261Slinton private Address printDynSlice();
72318261Slinton 
72418261Slinton private printDynarray (t)
72518261Slinton Symbol t;
72618261Slinton {
72718261Slinton     Address base;
72818261Slinton     integer n;
72918261Slinton     Stack *savesp, *newsp;
73018261Slinton     Symbol eltype;
73118261Slinton 
73218261Slinton     savesp = sp;
73318261Slinton     sp -= (t->symvalue.ndims * sizeof(Word));
73418261Slinton     base = pop(Address);
73518261Slinton     newsp = sp;
73618261Slinton     sp = savesp;
73718261Slinton     eltype = rtype(t->type);
73818261Slinton     if (t->symvalue.ndims == 0) {
73918261Slinton 	if (ischar(eltype)) {
74018261Slinton 	    printString(base, true);
74118261Slinton 	} else {
74218261Slinton 	    printf("[dynarray @nocount]");
74318261Slinton 	}
74418261Slinton     } else {
74518261Slinton 	n = ((long *) sp)[-(t->symvalue.ndims)];
74618261Slinton 	base = printDynSlice(base, n, t->symvalue.ndims, eltype, size(eltype));
74718261Slinton     }
74818261Slinton     sp = newsp;
74918261Slinton }
75018261Slinton 
75118261Slinton /*
75218261Slinton  * Print out one dimension of a multi-dimension dynamic array.
75318261Slinton  *
75418261Slinton  * Return the address of the element that follows the printed elements.
75518261Slinton  */
75618261Slinton 
75718261Slinton private Address printDynSlice (base, count, ndims, eltype, elsize)
75818261Slinton Address base;
75918261Slinton integer count, ndims;
76018261Slinton Symbol eltype;
76118261Slinton integer elsize;
76218261Slinton {
76318261Slinton     Address b;
76418261Slinton     integer i, n;
76518261Slinton     char *slice;
76618261Slinton     Stack *savesp;
76718261Slinton 
76818261Slinton     b = base;
76918261Slinton     if (ndims > 1) {
77018261Slinton 	n = ((long *) sp)[-ndims + 1];
77118261Slinton     }
77218261Slinton     if (ndims == 1 and ischar(eltype)) {
77318261Slinton 	slice = newarr(char, count);
77418261Slinton 	dread(slice, b, count);
77518261Slinton 	printf("\"%.*s\"", count, slice);
77618261Slinton 	dispose(slice);
77718261Slinton 	b += count;
77818261Slinton     } else {
77918261Slinton 	printf("(");
78018261Slinton 	for (i = 0; i < count; i++) {
78118261Slinton 	    if (i != 0) {
78218261Slinton 		printf(", ");
78318261Slinton 	    }
78418261Slinton 	    if (ndims == 1) {
78518261Slinton 		slice = newarr(char, elsize);
78618261Slinton 		dread(slice, b, elsize);
78718261Slinton 		savesp = sp;
78818261Slinton 		sp = slice + elsize;
78918261Slinton 		printval(eltype);
79018261Slinton 		sp = savesp;
79118261Slinton 		dispose(slice);
79218261Slinton 		b += elsize;
79318261Slinton 	    } else {
79418261Slinton 		b = printDynSlice(b, n, ndims - 1, eltype, elsize);
79518261Slinton 	    }
79618261Slinton 	}
79718261Slinton 	printf(")");
79818261Slinton     }
79918261Slinton     return b;
80018261Slinton }
80118261Slinton 
80218261Slinton private printSubarray (t)
80318261Slinton Symbol t;
80418261Slinton {
80518261Slinton     printf("[subarray]");
80618261Slinton }
80718261Slinton 
80818261Slinton /*
80916622Ssam  * Print out the value of a scalar (non-enumeration) type.
81016622Ssam  */
81116622Ssam 
81216622Ssam private printrange (s, n)
81316622Ssam Symbol s;
81416622Ssam integer n;
81516622Ssam {
81616622Ssam     double d;
81716622Ssam     float f;
81816622Ssam     integer i;
81916622Ssam 
82016622Ssam     if (s->symvalue.rangev.upper == 0 and s->symvalue.rangev.lower > 0) {
82116622Ssam 	if (n == sizeof(float)) {
82216622Ssam 	    popn(n, &f);
82316622Ssam 	    d = f;
82416622Ssam 	} else {
82516622Ssam 	    popn(n, &d);
82616622Ssam 	}
82716622Ssam 	prtreal(d);
82816622Ssam     } else {
82916622Ssam 	i = 0;
83016622Ssam 	popn(n, &i);
83118261Slinton 	printRangeVal(i, s);
83216622Ssam     }
83316622Ssam }
83416622Ssam 
83516622Ssam /*
83616622Ssam  * Print out a set.
83716622Ssam  */
83816622Ssam 
83916622Ssam private printSet (s)
84016622Ssam Symbol s;
84116622Ssam {
84216622Ssam     Symbol t;
84316622Ssam     integer nbytes;
84416622Ssam 
84516622Ssam     nbytes = size(s);
84616622Ssam     t = rtype(s->type);
84716622Ssam     printf("{");
84816622Ssam     sp -= nbytes;
84916622Ssam     if (t->class == SCAL) {
85016622Ssam 	printSetOfEnum(t);
85116622Ssam     } else if (t->class == RANGE) {
85216622Ssam 	printSetOfRange(t);
85316622Ssam     } else {
85416622Ssam 	panic("expected range or enumerated base type for set");
85516622Ssam     }
85616622Ssam     printf("}");
85716622Ssam }
85816622Ssam 
85916622Ssam /*
86016622Ssam  * Print out a set of an enumeration.
86116622Ssam  */
86216622Ssam 
86316622Ssam private printSetOfEnum (t)
86416622Ssam Symbol t;
86516622Ssam {
86616622Ssam     register Symbol e;
86716622Ssam     register integer i, j, *p;
86816622Ssam     boolean first;
86916622Ssam 
87016622Ssam     p = (int *) sp;
87116622Ssam     i = *p;
87216622Ssam     j = 0;
87316622Ssam     e = t->chain;
87416622Ssam     first = true;
87516622Ssam     while (e != nil) {
87616622Ssam 	if ((i&1) == 1) {
87716622Ssam 	    if (first) {
87816622Ssam 		first = false;
87916622Ssam 		printf("%s", symname(e));
88016622Ssam 	    } else {
88116622Ssam 		printf(", %s", symname(e));
88216622Ssam 	    }
88316622Ssam 	}
88416622Ssam 	i >>= 1;
88516622Ssam 	++j;
88616622Ssam 	if (j >= sizeof(integer)*BITSPERBYTE) {
88716622Ssam 	    j = 0;
88816622Ssam 	    ++p;
88916622Ssam 	    i = *p;
89016622Ssam 	}
89116622Ssam 	e = e->chain;
89216622Ssam     }
89316622Ssam }
89416622Ssam 
89516622Ssam /*
89616622Ssam  * Print out a set of a subrange type.
89716622Ssam  */
89816622Ssam 
89916622Ssam private printSetOfRange (t)
90016622Ssam Symbol t;
90116622Ssam {
90216622Ssam     register integer i, j, *p;
90316622Ssam     long v;
90416622Ssam     boolean first;
90516622Ssam 
90616622Ssam     p = (int *) sp;
90716622Ssam     i = *p;
90816622Ssam     j = 0;
90916622Ssam     v = t->symvalue.rangev.lower;
91016622Ssam     first = true;
91116622Ssam     while (v <= t->symvalue.rangev.upper) {
91216622Ssam 	if ((i&1) == 1) {
91316622Ssam 	    if (first) {
91416622Ssam 		first = false;
91516622Ssam 		printf("%ld", v);
91616622Ssam 	    } else {
91716622Ssam 		printf(", %ld", v);
91816622Ssam 	    }
91916622Ssam 	}
92016622Ssam 	i >>= 1;
92116622Ssam 	++j;
92216622Ssam 	if (j >= sizeof(integer)*BITSPERBYTE) {
92316622Ssam 	    j = 0;
92416622Ssam 	    ++p;
92516622Ssam 	    i = *p;
92616622Ssam 	}
92716622Ssam 	++v;
92816622Ssam     }
92916622Ssam }
93016622Ssam 
93116622Ssam /*
93218261Slinton  * Construct a node for subscripting a dynamic or subarray.
93318261Slinton  * The list of indices is left for processing in evalaref,
93418261Slinton  * unlike normal subscripting in which the list is expanded
93518261Slinton  * across individual INDEX nodes.
93618261Slinton  */
93718261Slinton 
93818261Slinton private Node dynref (a, t, slist)
93918261Slinton Node a;
94018261Slinton Symbol t;
94118261Slinton Node slist;
94218261Slinton {
94318261Slinton     Node p, r;
94418261Slinton     integer n;
94518261Slinton 
94618261Slinton     p = slist;
94718261Slinton     n = 0;
94818261Slinton     while (p != nil) {
94918261Slinton 	if (not compatible(p->value.arg[0]->nodetype, t_int)) {
95018261Slinton 	    suberror("subscript \"", p->value.arg[0], "\" is the wrong type");
95118261Slinton 	}
95218261Slinton 	++n;
95318261Slinton 	p = p->value.arg[1];
95418261Slinton     }
95518261Slinton     if (n > t->symvalue.ndims and (t->symvalue.ndims != 0 or n != 1)) {
95618261Slinton 	suberror("too many subscripts for ", a, nil);
95718261Slinton     } else if (n < t->symvalue.ndims) {
95818261Slinton 	suberror("not enough subscripts for ", a, nil);
95918261Slinton     }
96018261Slinton     r = build(O_INDEX, a, slist);
96118261Slinton     r->nodetype = rtype(t->type);
96218261Slinton     return r;
96318261Slinton }
96418261Slinton 
96518261Slinton /*
96616622Ssam  * Construct a node for subscripting.
96716622Ssam  */
96816622Ssam 
96916622Ssam public Node modula2_buildaref (a, slist)
97016622Ssam Node a, slist;
97116622Ssam {
97216622Ssam     register Symbol t;
97316622Ssam     register Node p;
97418261Slinton     Symbol eltype;
97516622Ssam     Node esub, r;
97618261Slinton     integer n;
97716622Ssam 
97816622Ssam     t = rtype(a->nodetype);
979*33326Sdonn     switch (t->class) {
980*33326Sdonn 	case OPENARRAY:
981*33326Sdonn 	case DYNARRAY:
982*33326Sdonn 	case SUBARRAY:
983*33326Sdonn 	    r = dynref(a, t, slist);
984*33326Sdonn 	    break;
985*33326Sdonn 
986*33326Sdonn 	case ARRAY:
987*33326Sdonn 	    r = a;
988*33326Sdonn 	    eltype = rtype(t->type);
989*33326Sdonn 	    p = slist;
990*33326Sdonn 	    t = t->chain;
991*33326Sdonn 	    while (p != nil and t != nil) {
992*33326Sdonn 		esub = p->value.arg[0];
993*33326Sdonn 		if (not compatible(rtype(t), rtype(esub->nodetype))) {
994*33326Sdonn 		    suberror("subscript \"", esub, "\" is the wrong type");
995*33326Sdonn 		}
996*33326Sdonn 		r = build(O_INDEX, r, esub);
997*33326Sdonn 		r->nodetype = eltype;
998*33326Sdonn 		p = p->value.arg[1];
999*33326Sdonn 		t = t->chain;
100016622Ssam 	    }
1001*33326Sdonn 	    if (p != nil) {
1002*33326Sdonn 		suberror("too many subscripts for ", a, nil);
1003*33326Sdonn 	    } else if (t != nil) {
1004*33326Sdonn 		suberror("not enough subscripts for ", a, nil);
1005*33326Sdonn 	    }
1006*33326Sdonn 	    break;
1007*33326Sdonn 
1008*33326Sdonn 	default:
1009*33326Sdonn 	    suberror("\"", a, "\" is not an array");
1010*33326Sdonn 	    break;
101116622Ssam     }
101216622Ssam     return r;
101316622Ssam }
101416622Ssam 
101516622Ssam /*
101618261Slinton  * Subscript usage error reporting.
101718261Slinton  */
101818261Slinton 
101918261Slinton private suberror (s1, e1, s2)
102018261Slinton String s1, s2;
102118261Slinton Node e1;
102218261Slinton {
102318261Slinton     beginerrmsg();
102418261Slinton     if (s1 != nil) {
102518261Slinton 	fprintf(stderr, s1);
102618261Slinton     }
102718261Slinton     if (e1 != nil) {
102818261Slinton 	prtree(stderr, e1);
102918261Slinton     }
103018261Slinton     if (s2 != nil) {
103118261Slinton 	fprintf(stderr, s2);
103218261Slinton     }
103318261Slinton     enderrmsg();
103418261Slinton }
103518261Slinton 
103618261Slinton /*
103718261Slinton  * Check that a subscript value is in the appropriate range.
103818261Slinton  */
103918261Slinton 
104018261Slinton private subchk (value, lower, upper)
104118261Slinton long value, lower, upper;
104218261Slinton {
104318261Slinton     if (value < lower or value > upper) {
104418261Slinton 	error("subscript value %d out of range [%d..%d]", value, lower, upper);
104518261Slinton     }
104618261Slinton }
104718261Slinton 
104818261Slinton /*
104918261Slinton  * Compute the offset for subscripting a dynamic array.
105018261Slinton  */
105118261Slinton 
105218261Slinton private getdynoff (ndims, sub)
105318261Slinton integer ndims;
105418261Slinton long *sub;
105518261Slinton {
105618261Slinton     long k, off, *count;
105718261Slinton 
105818261Slinton     count = (long *) sp;
105918261Slinton     off = 0;
106018261Slinton     for (k = 0; k < ndims - 1; k++) {
106118261Slinton 	subchk(sub[k], 0, count[k] - 1);
106218261Slinton 	off += (sub[k] * count[k+1]);
106318261Slinton     }
106418261Slinton     subchk(sub[ndims - 1], 0, count[ndims - 1] - 1);
106518261Slinton     return off + sub[ndims - 1];
106618261Slinton }
106718261Slinton 
106818261Slinton /*
106918261Slinton  * Compute the offset associated with a subarray.
107018261Slinton  */
107118261Slinton 
107218261Slinton private getsuboff (ndims, sub)
107318261Slinton integer ndims;
107418261Slinton long *sub;
107518261Slinton {
107618261Slinton     long k, off;
107718261Slinton     struct subarrayinfo {
107818261Slinton 	long count;
107918261Slinton 	long mult;
108018261Slinton     } *info;
108118261Slinton 
108218261Slinton     info = (struct subarrayinfo *) sp;
108318261Slinton     off = 0;
108418261Slinton     for (k = 0; k < ndims; k++) {
108518261Slinton 	subchk(sub[k], 0, info[k].count - 1);
108618261Slinton 	off += sub[k] * info[k].mult;
108718261Slinton     }
108818261Slinton     return off;
108918261Slinton }
109018261Slinton 
109118261Slinton /*
109216622Ssam  * Evaluate a subscript index.
109316622Ssam  */
109416622Ssam 
109518261Slinton public modula2_evalaref (s, base, i)
109616622Ssam Symbol s;
109718261Slinton Address base;
109816622Ssam long i;
109916622Ssam {
110018261Slinton     Symbol t;
110118261Slinton     long lb, ub, off;
110218261Slinton     long *sub;
110318261Slinton     Address b;
110416622Ssam 
110518261Slinton     t = rtype(s);
110618261Slinton     if (t->class == ARRAY) {
110718261Slinton 	findbounds(rtype(t->chain), &lb, &ub);
110818261Slinton 	if (i < lb or i > ub) {
110918261Slinton 	    error("subscript %d out of range [%d..%d]", i, lb, ub);
111018261Slinton 	}
111118261Slinton 	push(long, base + (i - lb) * size(t->type));
1112*33326Sdonn     } else if ((t->class == OPENARRAY or t->class == DYNARRAY) and
1113*33326Sdonn 	t->symvalue.ndims == 0
1114*33326Sdonn     ) {
111518261Slinton 	push(long, base + i * size(t->type));
1116*33326Sdonn     } else if (t->class == OPENARRAY or t->class == DYNARRAY or
1117*33326Sdonn 	t->class == SUBARRAY
1118*33326Sdonn     ) {
111918261Slinton 	push(long, i);
112018261Slinton 	sub = (long *) (sp - (t->symvalue.ndims * sizeof(long)));
112118261Slinton 	rpush(base, size(t));
112218261Slinton 	sp -= (t->symvalue.ndims * sizeof(long));
112318261Slinton 	b = pop(Address);
112418261Slinton 	sp += sizeof(Address);
112518261Slinton 	if (t->class == SUBARRAY) {
112618261Slinton 	    off = getsuboff(t->symvalue.ndims, sub);
112718261Slinton 	} else {
112818261Slinton 	    off = getdynoff(t->symvalue.ndims, sub);
112918261Slinton 	}
113018261Slinton 	sp = (Stack *) sub;
113118261Slinton 	push(long, b + off * size(t->type));
113218261Slinton     } else {
113318261Slinton 	error("[internal error: expected array in evalaref]");
113416622Ssam     }
113516622Ssam }
113616622Ssam 
113716622Ssam /*
113816622Ssam  * Initial Modula-2 type information.
113916622Ssam  */
114016622Ssam 
114116622Ssam #define NTYPES 12
114216622Ssam 
114316622Ssam private Symbol inittype[NTYPES + 1];
114416622Ssam 
114516622Ssam private addType (n, s, lower, upper)
114616622Ssam integer n;
114716622Ssam String s;
114816622Ssam long lower, upper;
114916622Ssam {
115016622Ssam     register Symbol t;
115116622Ssam 
115216622Ssam     if (n > NTYPES) {
115316622Ssam 	panic("initial Modula-2 type number too large for '%s'", s);
115416622Ssam     }
115516622Ssam     t = insert(identname(s, true));
115616622Ssam     t->language = mod2;
115716622Ssam     t->class = TYPE;
115816622Ssam     t->type = newSymbol(nil, 0, RANGE, t, nil);
115916622Ssam     t->type->symvalue.rangev.lower = lower;
116016622Ssam     t->type->symvalue.rangev.upper = upper;
116116622Ssam     t->type->language = mod2;
116216622Ssam     inittype[n] = t;
116316622Ssam }
116416622Ssam 
116516622Ssam private initModTypes ()
116616622Ssam {
116716622Ssam     addType(1, "integer", 0x80000000L, 0x7fffffffL);
116816622Ssam     addType(2, "char", 0L, 255L);
116916622Ssam     addType(3, "boolean", 0L, 1L);
117016622Ssam     addType(4, "unsigned", 0L, 0xffffffffL);
117116622Ssam     addType(5, "real", 4L, 0L);
117216622Ssam     addType(6, "longreal", 8L, 0L);
117316622Ssam     addType(7, "word", 0L, 0xffffffffL);
117416622Ssam     addType(8, "byte", 0L, 255L);
117516622Ssam     addType(9, "address", 0L, 0xffffffffL);
117616622Ssam     addType(10, "file", 0L, 0xffffffffL);
117716622Ssam     addType(11, "process", 0L, 0xffffffffL);
117816622Ssam     addType(12, "cardinal", 0L, 0x7fffffffL);
117916622Ssam }
118016622Ssam 
118116622Ssam /*
118216622Ssam  * Initialize typetable.
118316622Ssam  */
118416622Ssam 
118516622Ssam public modula2_modinit (typetable)
118616622Ssam Symbol typetable[];
118716622Ssam {
118816622Ssam     register integer i;
118916622Ssam 
119016622Ssam     if (not initialized) {
119116622Ssam 	initModTypes();
119218261Slinton 	initialized = true;
119316622Ssam     }
119416622Ssam     for (i = 1; i <= NTYPES; i++) {
119516622Ssam 	typetable[i] = inittype[i];
119616622Ssam     }
119716622Ssam }
119816622Ssam 
119916622Ssam public boolean modula2_hasmodules ()
120016622Ssam {
120116622Ssam     return true;
120216622Ssam }
120316622Ssam 
120416622Ssam public boolean modula2_passaddr (param, exprtype)
120516622Ssam Symbol param, exprtype;
120616622Ssam {
120716622Ssam     return false;
120816622Ssam }
1209