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