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