1*18261Slinton /* Copyright (c) 1982 Regents of the University of California */ 2*18261Slinton 316622Ssam #ifndef lint 4*18261Slinton static char sccsid[] = "@(#)modula-2.c 1.2 (Berkeley) 03/07/85"; /* from 1.4 84/03/27 10:22:04 linton Exp */ 516622Ssam #endif 616622Ssam 716622Ssam /* 816622Ssam * Modula-2 specific symbol routines. 916622Ssam */ 1016622Ssam 11*18261Slinton static char rcsid[] = "$Header: modula-2.c,v 1.6 84/12/26 10:40:33 linton Exp $"; 12*18261Slinton 1316622Ssam #include "defs.h" 1416622Ssam #include "symbols.h" 1516622Ssam #include "modula-2.h" 1616622Ssam #include "languages.h" 1716622Ssam #include "tree.h" 1816622Ssam #include "eval.h" 1916622Ssam #include "mappings.h" 2016622Ssam #include "process.h" 2116622Ssam #include "runtime.h" 2216622Ssam #include "machine.h" 2316622Ssam 2416622Ssam #ifndef public 2516622Ssam #endif 2616622Ssam 2716622Ssam private Language mod2; 2816622Ssam private boolean initialized; 2916622Ssam 30*18261Slinton 31*18261Slinton #define ischar(t) ( \ 32*18261Slinton (t) == t_char->type or \ 33*18261Slinton ((t)->class == RANGE and istypename((t)->type, "char")) \ 34*18261Slinton ) 35*18261Slinton 3616622Ssam /* 3716622Ssam * Initialize Modula-2 information. 3816622Ssam */ 3916622Ssam 4016622Ssam public modula2_init () 4116622Ssam { 4216622Ssam mod2 = language_define("modula-2", ".mod"); 4316622Ssam language_setop(mod2, L_PRINTDECL, modula2_printdecl); 4416622Ssam language_setop(mod2, L_PRINTVAL, modula2_printval); 4516622Ssam language_setop(mod2, L_TYPEMATCH, modula2_typematch); 4616622Ssam language_setop(mod2, L_BUILDAREF, modula2_buildaref); 4716622Ssam language_setop(mod2, L_EVALAREF, modula2_evalaref); 4816622Ssam language_setop(mod2, L_MODINIT, modula2_modinit); 4916622Ssam language_setop(mod2, L_HASMODULES, modula2_hasmodules); 5016622Ssam language_setop(mod2, L_PASSADDR, modula2_passaddr); 5116622Ssam initialized = false; 5216622Ssam } 5316622Ssam 5416622Ssam /* 5516622Ssam * Typematch tests if two types are compatible. The issue 5616622Ssam * is a bit complicated, so several subfunctions are used for 5716622Ssam * various kinds of compatibility. 5816622Ssam */ 5916622Ssam 60*18261Slinton private boolean builtinmatch (t1, t2) 61*18261Slinton register Symbol t1, t2; 62*18261Slinton { 63*18261Slinton boolean b; 64*18261Slinton 65*18261Slinton b = (boolean) ( 66*18261Slinton ( 67*18261Slinton t2 == t_int->type and t1->class == RANGE and 68*18261Slinton ( 69*18261Slinton istypename(t1->type, "integer") or 70*18261Slinton istypename(t1->type, "cardinal") 71*18261Slinton ) 72*18261Slinton ) or ( 73*18261Slinton t2 == t_char->type and 74*18261Slinton t1->class == RANGE and istypename(t1->type, "char") 75*18261Slinton ) or ( 76*18261Slinton t2 == t_real->type and 77*18261Slinton t1->class == RANGE and ( 78*18261Slinton istypename(t1->type, "real") or 79*18261Slinton istypename(t1->type, "longreal") 80*18261Slinton ) 81*18261Slinton ) or ( 82*18261Slinton t2 == t_boolean->type and 83*18261Slinton t1->class == RANGE and istypename(t1->type, "boolean") 84*18261Slinton ) 85*18261Slinton ); 86*18261Slinton return b; 87*18261Slinton } 88*18261Slinton 89*18261Slinton private boolean rangematch (t1, t2) 90*18261Slinton register Symbol t1, t2; 91*18261Slinton { 92*18261Slinton boolean b; 93*18261Slinton register Symbol rt1, rt2; 94*18261Slinton 95*18261Slinton if (t1->class == RANGE and t2->class == RANGE) { 96*18261Slinton b = (boolean) ( 97*18261Slinton t1->symvalue.rangev.lower == t2->symvalue.rangev.lower and 98*18261Slinton t1->symvalue.rangev.upper == t2->symvalue.rangev.upper 99*18261Slinton ); 100*18261Slinton } else { 101*18261Slinton b = false; 102*18261Slinton } 103*18261Slinton return b; 104*18261Slinton } 105*18261Slinton 10616622Ssam private boolean nilMatch (t1, t2) 10716622Ssam register Symbol t1, t2; 10816622Ssam { 10916622Ssam boolean b; 11016622Ssam 11116622Ssam b = (boolean) ( 11216622Ssam (t1 == t_nil and t2->class == PTR) or 11316622Ssam (t1->class == PTR and t2 == t_nil) 11416622Ssam ); 11516622Ssam return b; 11616622Ssam } 11716622Ssam 11816622Ssam private boolean enumMatch (t1, t2) 11916622Ssam register Symbol t1, t2; 12016622Ssam { 12116622Ssam boolean b; 12216622Ssam 12316622Ssam b = (boolean) ( 124*18261Slinton (t1->class == SCAL and t2->class == CONST and t2->type == t1) or 125*18261Slinton (t1->class == CONST and t2->class == SCAL and t1->type == t2) 12616622Ssam ); 12716622Ssam return b; 12816622Ssam } 12916622Ssam 13016622Ssam private boolean openArrayMatch (t1, t2) 13116622Ssam register Symbol t1, t2; 13216622Ssam { 13316622Ssam boolean b; 13416622Ssam 13516622Ssam b = (boolean) ( 13616622Ssam ( 137*18261Slinton t1->class == DYNARRAY and t1->symvalue.ndims == 1 and 13816622Ssam t2->class == ARRAY and 13916622Ssam compatible(rtype(t2->chain)->type, t_int) and 14016622Ssam compatible(t1->type, t2->type) 14116622Ssam ) or ( 142*18261Slinton t2->class == DYNARRAY and t2->symvalue.ndims == 1 and 14316622Ssam t1->class == ARRAY and 14416622Ssam compatible(rtype(t1->chain)->type, t_int) and 14516622Ssam compatible(t1->type, t2->type) 14616622Ssam ) 14716622Ssam ); 14816622Ssam return b; 14916622Ssam } 15016622Ssam 15116622Ssam private boolean isConstString (t) 15216622Ssam register Symbol t; 15316622Ssam { 15416622Ssam boolean b; 15516622Ssam 15616622Ssam b = (boolean) ( 15716622Ssam t->language == primlang and t->class == ARRAY and t->type == t_char 15816622Ssam ); 15916622Ssam return b; 16016622Ssam } 16116622Ssam 16216622Ssam private boolean stringArrayMatch (t1, t2) 16316622Ssam register Symbol t1, t2; 16416622Ssam { 16516622Ssam boolean b; 16616622Ssam 16716622Ssam b = (boolean) ( 16816622Ssam ( 16916622Ssam isConstString(t1) and 17016622Ssam t2->class == ARRAY and compatible(t2->type, t_char->type) 17116622Ssam ) or ( 17216622Ssam isConstString(t2) and 17316622Ssam t1->class == ARRAY and compatible(t1->type, t_char->type) 17416622Ssam ) 17516622Ssam ); 17616622Ssam return b; 17716622Ssam } 17816622Ssam 17916622Ssam public boolean modula2_typematch (type1, type2) 18016622Ssam Symbol type1, type2; 18116622Ssam { 182*18261Slinton boolean b; 18316622Ssam Symbol t1, t2, tmp; 18416622Ssam 18516622Ssam t1 = rtype(type1); 18616622Ssam t2 = rtype(type2); 18716622Ssam if (t1 == t2) { 18816622Ssam b = true; 18916622Ssam } else { 190*18261Slinton if (t1 == t_char->type or t1 == t_int->type or 191*18261Slinton t1 == t_real->type or t1 == t_boolean->type 192*18261Slinton ) { 19316622Ssam tmp = t1; 19416622Ssam t1 = t2; 19516622Ssam t2 = tmp; 19616622Ssam } 19716622Ssam b = (Boolean) ( 198*18261Slinton builtinmatch(t1, t2) or rangematch(t1, t2) or 199*18261Slinton nilMatch(t1, t2) or enumMatch(t1, t2) or 200*18261Slinton openArrayMatch(t1, t2) or stringArrayMatch(t1, t2) 20116622Ssam ); 20216622Ssam } 20316622Ssam return b; 20416622Ssam } 20516622Ssam 20616622Ssam /* 20716622Ssam * Indent n spaces. 20816622Ssam */ 20916622Ssam 21016622Ssam private indent (n) 21116622Ssam int n; 21216622Ssam { 21316622Ssam if (n > 0) { 21416622Ssam printf("%*c", n, ' '); 21516622Ssam } 21616622Ssam } 21716622Ssam 21816622Ssam public modula2_printdecl (s) 21916622Ssam Symbol s; 22016622Ssam { 22116622Ssam register Symbol t; 22216622Ssam Boolean semicolon; 22316622Ssam 22416622Ssam semicolon = true; 22516622Ssam if (s->class == TYPEREF) { 22616622Ssam resolveRef(t); 22716622Ssam } 22816622Ssam switch (s->class) { 22916622Ssam case CONST: 23016622Ssam if (s->type->class == SCAL) { 231*18261Slinton semicolon = false; 232*18261Slinton printf("enumeration constant with value "); 233*18261Slinton eval(s->symvalue.constval); 234*18261Slinton modula2_printval(s); 23516622Ssam } else { 23616622Ssam printf("const %s = ", symname(s)); 237*18261Slinton eval(s->symvalue.constval); 23816622Ssam modula2_printval(s); 23916622Ssam } 24016622Ssam break; 24116622Ssam 24216622Ssam case TYPE: 24316622Ssam printf("type %s = ", symname(s)); 24416622Ssam printtype(s, s->type, 0); 24516622Ssam break; 24616622Ssam 24716622Ssam case TYPEREF: 24816622Ssam printf("type %s", symname(s)); 24916622Ssam break; 25016622Ssam 25116622Ssam case VAR: 25216622Ssam if (isparam(s)) { 25316622Ssam printf("(parameter) %s : ", symname(s)); 25416622Ssam } else { 25516622Ssam printf("var %s : ", symname(s)); 25616622Ssam } 25716622Ssam printtype(s, s->type, 0); 25816622Ssam break; 25916622Ssam 26016622Ssam case REF: 26116622Ssam printf("(var parameter) %s : ", symname(s)); 26216622Ssam printtype(s, s->type, 0); 26316622Ssam break; 26416622Ssam 26516622Ssam case RANGE: 26616622Ssam case ARRAY: 267*18261Slinton case DYNARRAY: 268*18261Slinton case SUBARRAY: 26916622Ssam case RECORD: 27016622Ssam case VARNT: 27116622Ssam case PTR: 27216622Ssam printtype(s, s, 0); 27316622Ssam semicolon = false; 27416622Ssam break; 27516622Ssam 27616622Ssam case FVAR: 27716622Ssam printf("(function variable) %s : ", symname(s)); 27816622Ssam printtype(s, s->type, 0); 27916622Ssam break; 28016622Ssam 28116622Ssam case FIELD: 28216622Ssam printf("(field) %s : ", symname(s)); 28316622Ssam printtype(s, s->type, 0); 28416622Ssam break; 28516622Ssam 28616622Ssam case PROC: 28716622Ssam printf("procedure %s", symname(s)); 28816622Ssam listparams(s); 28916622Ssam break; 29016622Ssam 29116622Ssam case PROG: 29216622Ssam printf("program %s", symname(s)); 29316622Ssam listparams(s); 29416622Ssam break; 29516622Ssam 29616622Ssam case FUNC: 297*18261Slinton printf("procedure %s", symname(s)); 29816622Ssam listparams(s); 29916622Ssam printf(" : "); 30016622Ssam printtype(s, s->type, 0); 30116622Ssam break; 30216622Ssam 30316622Ssam case MODULE: 30416622Ssam printf("module %s", symname(s)); 30516622Ssam break; 30616622Ssam 30716622Ssam default: 308*18261Slinton printf("[%s]", classname(s)); 30916622Ssam break; 31016622Ssam } 31116622Ssam if (semicolon) { 31216622Ssam putchar(';'); 31316622Ssam } 31416622Ssam putchar('\n'); 31516622Ssam } 31616622Ssam 31716622Ssam /* 31816622Ssam * Recursive whiz-bang procedure to print the type portion 31916622Ssam * of a declaration. 32016622Ssam * 32116622Ssam * The symbol associated with the type is passed to allow 32216622Ssam * searching for type names without getting "type blah = blah". 32316622Ssam */ 32416622Ssam 32516622Ssam private printtype (s, t, n) 32616622Ssam Symbol s; 32716622Ssam Symbol t; 32816622Ssam int n; 32916622Ssam { 330*18261Slinton Symbol tmp; 331*18261Slinton int i; 33216622Ssam 33316622Ssam if (t->class == TYPEREF) { 33416622Ssam resolveRef(t); 33516622Ssam } 33616622Ssam switch (t->class) { 33716622Ssam case VAR: 33816622Ssam case CONST: 33916622Ssam case FUNC: 34016622Ssam case PROC: 34116622Ssam panic("printtype: class %s", classname(t)); 34216622Ssam break; 34316622Ssam 34416622Ssam case ARRAY: 34516622Ssam printf("array["); 34616622Ssam tmp = t->chain; 34716622Ssam if (tmp != nil) { 34816622Ssam for (;;) { 34916622Ssam printtype(tmp, tmp, n); 35016622Ssam tmp = tmp->chain; 35116622Ssam if (tmp == nil) { 35216622Ssam break; 35316622Ssam } 35416622Ssam printf(", "); 35516622Ssam } 35616622Ssam } 35716622Ssam printf("] of "); 35816622Ssam printtype(t, t->type, n); 35916622Ssam break; 36016622Ssam 361*18261Slinton case DYNARRAY: 362*18261Slinton printf("dynarray of "); 363*18261Slinton for (i = 1; i < t->symvalue.ndims; i++) { 364*18261Slinton printf("array of "); 365*18261Slinton } 366*18261Slinton printtype(t, t->type, n); 367*18261Slinton break; 368*18261Slinton 369*18261Slinton case SUBARRAY: 370*18261Slinton printf("subarray of "); 371*18261Slinton for (i = 1; i < t->symvalue.ndims; i++) { 372*18261Slinton printf("array of "); 373*18261Slinton } 374*18261Slinton printtype(t, t->type, n); 375*18261Slinton break; 376*18261Slinton 37716622Ssam case RECORD: 37816622Ssam printRecordDecl(t, n); 37916622Ssam break; 38016622Ssam 38116622Ssam case FIELD: 38216622Ssam if (t->chain != nil) { 38316622Ssam printtype(t->chain, t->chain, n); 38416622Ssam } 38516622Ssam printf("\t%s : ", symname(t)); 38616622Ssam printtype(t, t->type, n); 38716622Ssam printf(";\n"); 38816622Ssam break; 38916622Ssam 39016622Ssam case RANGE: 39116622Ssam printRangeDecl(t); 39216622Ssam break; 39316622Ssam 39416622Ssam case PTR: 39516622Ssam printf("pointer to "); 39616622Ssam printtype(t, t->type, n); 39716622Ssam break; 39816622Ssam 39916622Ssam case TYPE: 40016622Ssam if (t->name != nil and ident(t->name)[0] != '\0') { 40116622Ssam printname(stdout, t); 40216622Ssam } else { 40316622Ssam printtype(t, t->type, n); 40416622Ssam } 40516622Ssam break; 40616622Ssam 40716622Ssam case SCAL: 40816622Ssam printEnumDecl(t, n); 40916622Ssam break; 41016622Ssam 41116622Ssam case SET: 41216622Ssam printf("set of "); 41316622Ssam printtype(t, t->type, n); 41416622Ssam break; 41516622Ssam 41616622Ssam case TYPEREF: 41716622Ssam break; 41816622Ssam 419*18261Slinton case FPROC: 420*18261Slinton case FFUNC: 421*18261Slinton printf("procedure"); 422*18261Slinton break; 423*18261Slinton 42416622Ssam default: 425*18261Slinton printf("[%s]", classname(t)); 42616622Ssam break; 42716622Ssam } 42816622Ssam } 42916622Ssam 43016622Ssam /* 43116622Ssam * Print out a record declaration. 43216622Ssam */ 43316622Ssam 43416622Ssam private printRecordDecl (t, n) 43516622Ssam Symbol t; 43616622Ssam int n; 43716622Ssam { 43816622Ssam register Symbol f; 43916622Ssam 44016622Ssam if (t->chain == nil) { 44116622Ssam printf("record end"); 44216622Ssam } else { 44316622Ssam printf("record\n"); 44416622Ssam for (f = t->chain; f != nil; f = f->chain) { 44516622Ssam indent(n+4); 44616622Ssam printf("%s : ", symname(f)); 44716622Ssam printtype(f->type, f->type, n+4); 44816622Ssam printf(";\n"); 44916622Ssam } 45016622Ssam indent(n); 45116622Ssam printf("end"); 45216622Ssam } 45316622Ssam } 45416622Ssam 45516622Ssam /* 45616622Ssam * Print out the declaration of a range type. 45716622Ssam */ 45816622Ssam 45916622Ssam private printRangeDecl (t) 46016622Ssam Symbol t; 46116622Ssam { 46216622Ssam long r0, r1; 46316622Ssam 46416622Ssam r0 = t->symvalue.rangev.lower; 46516622Ssam r1 = t->symvalue.rangev.upper; 466*18261Slinton if (ischar(t)) { 46716622Ssam if (r0 < 0x20 or r0 > 0x7e) { 46816622Ssam printf("%ld..", r0); 46916622Ssam } else { 47016622Ssam printf("'%c'..", (char) r0); 47116622Ssam } 47216622Ssam if (r1 < 0x20 or r1 > 0x7e) { 47316622Ssam printf("\\%lo", r1); 47416622Ssam } else { 47516622Ssam printf("'%c'", (char) r1); 47616622Ssam } 47716622Ssam } else if (r0 > 0 and r1 == 0) { 47816622Ssam printf("%ld byte real", r0); 47916622Ssam } else if (r0 >= 0) { 48016622Ssam printf("%lu..%lu", r0, r1); 48116622Ssam } else { 48216622Ssam printf("%ld..%ld", r0, r1); 48316622Ssam } 48416622Ssam } 48516622Ssam 48616622Ssam /* 48716622Ssam * Print out an enumeration declaration. 48816622Ssam */ 48916622Ssam 49016622Ssam private printEnumDecl (e, n) 49116622Ssam Symbol e; 49216622Ssam int n; 49316622Ssam { 49416622Ssam Symbol t; 49516622Ssam 49616622Ssam printf("("); 49716622Ssam t = e->chain; 49816622Ssam if (t != nil) { 49916622Ssam printf("%s", symname(t)); 50016622Ssam t = t->chain; 50116622Ssam while (t != nil) { 50216622Ssam printf(", %s", symname(t)); 50316622Ssam t = t->chain; 50416622Ssam } 50516622Ssam } 50616622Ssam printf(")"); 50716622Ssam } 50816622Ssam 50916622Ssam /* 51016622Ssam * List the parameters of a procedure or function. 51116622Ssam * No attempt is made to combine like types. 51216622Ssam */ 51316622Ssam 51416622Ssam private listparams (s) 51516622Ssam Symbol s; 51616622Ssam { 51716622Ssam Symbol t; 51816622Ssam 51916622Ssam if (s->chain != nil) { 52016622Ssam putchar('('); 52116622Ssam for (t = s->chain; t != nil; t = t->chain) { 52216622Ssam switch (t->class) { 52316622Ssam case REF: 52416622Ssam printf("var "); 52516622Ssam break; 52616622Ssam 52716622Ssam case FPROC: 52816622Ssam case FFUNC: 52916622Ssam printf("procedure "); 53016622Ssam break; 53116622Ssam 53216622Ssam case VAR: 53316622Ssam break; 53416622Ssam 53516622Ssam default: 53616622Ssam panic("unexpected class %d for parameter", t->class); 53716622Ssam } 53816622Ssam printf("%s", symname(t)); 53916622Ssam if (s->class == PROG) { 54016622Ssam printf(", "); 54116622Ssam } else { 54216622Ssam printf(" : "); 54316622Ssam printtype(t, t->type, 0); 54416622Ssam if (t->chain != nil) { 54516622Ssam printf("; "); 54616622Ssam } 54716622Ssam } 54816622Ssam } 54916622Ssam putchar(')'); 55016622Ssam } 55116622Ssam } 55216622Ssam 55316622Ssam /* 554*18261Slinton * Test if a pointer type should be treated as a null-terminated string. 555*18261Slinton * The type given is the type that is pointed to. 556*18261Slinton */ 557*18261Slinton 558*18261Slinton private boolean isCstring (type) 559*18261Slinton Symbol type; 560*18261Slinton { 561*18261Slinton boolean b; 562*18261Slinton register Symbol a, t; 563*18261Slinton 564*18261Slinton a = rtype(type); 565*18261Slinton if (a->class == ARRAY) { 566*18261Slinton t = rtype(a->chain); 567*18261Slinton b = (boolean) ( 568*18261Slinton t->class == RANGE and istypename(a->type, "char") and 569*18261Slinton (t->symvalue.rangev.upper - t->symvalue.rangev.lower + 1) <= 0 570*18261Slinton ); 571*18261Slinton } else { 572*18261Slinton b = false; 573*18261Slinton } 574*18261Slinton return b; 575*18261Slinton } 576*18261Slinton 577*18261Slinton /* 57816622Ssam * Modula 2 interface to printval. 57916622Ssam */ 58016622Ssam 58116622Ssam public modula2_printval (s) 58216622Ssam Symbol s; 58316622Ssam { 58416622Ssam prval(s, size(s)); 58516622Ssam } 58616622Ssam 58716622Ssam /* 58816622Ssam * Print out the value on the top of the expression stack 58916622Ssam * in the format for the type of the given symbol, assuming 59016622Ssam * the size of the object is n bytes. 59116622Ssam */ 59216622Ssam 59316622Ssam private prval (s, n) 59416622Ssam Symbol s; 59516622Ssam integer n; 59616622Ssam { 59716622Ssam Symbol t; 59816622Ssam Address a; 59916622Ssam integer len; 60016622Ssam double r; 601*18261Slinton integer i; 60216622Ssam 60316622Ssam if (s->class == TYPEREF) { 60416622Ssam resolveRef(s); 60516622Ssam } 60616622Ssam switch (s->class) { 60716622Ssam case CONST: 60816622Ssam case TYPE: 609*18261Slinton case REF: 61016622Ssam case VAR: 61116622Ssam case FVAR: 61216622Ssam case TAG: 61316622Ssam prval(s->type, n); 61416622Ssam break; 61516622Ssam 616*18261Slinton case FIELD: 617*18261Slinton if (isbitfield(s)) { 618*18261Slinton i = 0; 619*18261Slinton popn(size(s), &i); 620*18261Slinton i >>= (s->symvalue.field.offset mod BITSPERBYTE); 621*18261Slinton i &= ((1 << s->symvalue.field.length) - 1); 622*18261Slinton t = rtype(s->type); 623*18261Slinton if (t->class == SCAL) { 624*18261Slinton printEnum(i, t); 625*18261Slinton } else { 626*18261Slinton printRangeVal(i, t); 627*18261Slinton } 628*18261Slinton } else { 629*18261Slinton prval(s->type, n); 630*18261Slinton } 631*18261Slinton break; 632*18261Slinton 63316622Ssam case ARRAY: 63416622Ssam t = rtype(s->type); 635*18261Slinton if (ischar(t)) { 63616622Ssam len = size(s); 63716622Ssam sp -= len; 638*18261Slinton printf("\"%.*s\"", len, sp); 63916622Ssam break; 64016622Ssam } else { 64116622Ssam printarray(s); 64216622Ssam } 64316622Ssam break; 64416622Ssam 645*18261Slinton case DYNARRAY: 646*18261Slinton printDynarray(s); 647*18261Slinton break; 648*18261Slinton 649*18261Slinton case SUBARRAY: 650*18261Slinton printSubarray(s); 651*18261Slinton break; 652*18261Slinton 65316622Ssam case RECORD: 65416622Ssam printrecord(s); 65516622Ssam break; 65616622Ssam 65716622Ssam case VARNT: 658*18261Slinton printf("[variant]"); 65916622Ssam break; 66016622Ssam 66116622Ssam case RANGE: 66216622Ssam printrange(s, n); 66316622Ssam break; 66416622Ssam 665*18261Slinton /* 666*18261Slinton * Unresolved opaque type. 667*18261Slinton * Probably a pointer. 668*18261Slinton */ 669*18261Slinton case TYPEREF: 670*18261Slinton a = pop(Address); 671*18261Slinton printf("@%x", a); 672*18261Slinton break; 673*18261Slinton 67416622Ssam case FILET: 675*18261Slinton a = pop(Address); 676*18261Slinton if (a == 0) { 677*18261Slinton printf("nil"); 678*18261Slinton } else { 679*18261Slinton printf("0x%x", a); 680*18261Slinton } 681*18261Slinton break; 682*18261Slinton 68316622Ssam case PTR: 68416622Ssam a = pop(Address); 68516622Ssam if (a == 0) { 68616622Ssam printf("nil"); 687*18261Slinton } else if (isCstring(s->type)) { 688*18261Slinton printString(a, true); 68916622Ssam } else { 69016622Ssam printf("0x%x", a); 69116622Ssam } 69216622Ssam break; 69316622Ssam 69416622Ssam case SCAL: 695*18261Slinton i = 0; 696*18261Slinton popn(n, &i); 697*18261Slinton printEnum(i, s); 69816622Ssam break; 69916622Ssam 70016622Ssam case FPROC: 70116622Ssam case FFUNC: 70216622Ssam a = pop(long); 70316622Ssam t = whatblock(a); 70416622Ssam if (t == nil) { 705*18261Slinton printf("0x%x", a); 70616622Ssam } else { 707*18261Slinton printname(stdout, t); 70816622Ssam } 70916622Ssam break; 71016622Ssam 71116622Ssam case SET: 71216622Ssam printSet(s); 71316622Ssam break; 71416622Ssam 71516622Ssam default: 71616622Ssam if (ord(s->class) < ord(BADUSE) or ord(s->class) > ord(TYPEREF)) { 71716622Ssam panic("printval: bad class %d", ord(s->class)); 71816622Ssam } 71916622Ssam printf("[%s]", classname(s)); 72016622Ssam break; 72116622Ssam } 72216622Ssam } 72316622Ssam 72416622Ssam /* 725*18261Slinton * Print out a dynamic array. 726*18261Slinton */ 727*18261Slinton 728*18261Slinton private Address printDynSlice(); 729*18261Slinton 730*18261Slinton private printDynarray (t) 731*18261Slinton Symbol t; 732*18261Slinton { 733*18261Slinton Address base; 734*18261Slinton integer n; 735*18261Slinton Stack *savesp, *newsp; 736*18261Slinton Symbol eltype; 737*18261Slinton 738*18261Slinton savesp = sp; 739*18261Slinton sp -= (t->symvalue.ndims * sizeof(Word)); 740*18261Slinton base = pop(Address); 741*18261Slinton newsp = sp; 742*18261Slinton sp = savesp; 743*18261Slinton eltype = rtype(t->type); 744*18261Slinton if (t->symvalue.ndims == 0) { 745*18261Slinton if (ischar(eltype)) { 746*18261Slinton printString(base, true); 747*18261Slinton } else { 748*18261Slinton printf("[dynarray @nocount]"); 749*18261Slinton } 750*18261Slinton } else { 751*18261Slinton n = ((long *) sp)[-(t->symvalue.ndims)]; 752*18261Slinton base = printDynSlice(base, n, t->symvalue.ndims, eltype, size(eltype)); 753*18261Slinton } 754*18261Slinton sp = newsp; 755*18261Slinton } 756*18261Slinton 757*18261Slinton /* 758*18261Slinton * Print out one dimension of a multi-dimension dynamic array. 759*18261Slinton * 760*18261Slinton * Return the address of the element that follows the printed elements. 761*18261Slinton */ 762*18261Slinton 763*18261Slinton private Address printDynSlice (base, count, ndims, eltype, elsize) 764*18261Slinton Address base; 765*18261Slinton integer count, ndims; 766*18261Slinton Symbol eltype; 767*18261Slinton integer elsize; 768*18261Slinton { 769*18261Slinton Address b; 770*18261Slinton integer i, n; 771*18261Slinton char *slice; 772*18261Slinton Stack *savesp; 773*18261Slinton 774*18261Slinton b = base; 775*18261Slinton if (ndims > 1) { 776*18261Slinton n = ((long *) sp)[-ndims + 1]; 777*18261Slinton } 778*18261Slinton if (ndims == 1 and ischar(eltype)) { 779*18261Slinton slice = newarr(char, count); 780*18261Slinton dread(slice, b, count); 781*18261Slinton printf("\"%.*s\"", count, slice); 782*18261Slinton dispose(slice); 783*18261Slinton b += count; 784*18261Slinton } else { 785*18261Slinton printf("("); 786*18261Slinton for (i = 0; i < count; i++) { 787*18261Slinton if (i != 0) { 788*18261Slinton printf(", "); 789*18261Slinton } 790*18261Slinton if (ndims == 1) { 791*18261Slinton slice = newarr(char, elsize); 792*18261Slinton dread(slice, b, elsize); 793*18261Slinton savesp = sp; 794*18261Slinton sp = slice + elsize; 795*18261Slinton printval(eltype); 796*18261Slinton sp = savesp; 797*18261Slinton dispose(slice); 798*18261Slinton b += elsize; 799*18261Slinton } else { 800*18261Slinton b = printDynSlice(b, n, ndims - 1, eltype, elsize); 801*18261Slinton } 802*18261Slinton } 803*18261Slinton printf(")"); 804*18261Slinton } 805*18261Slinton return b; 806*18261Slinton } 807*18261Slinton 808*18261Slinton private printSubarray (t) 809*18261Slinton Symbol t; 810*18261Slinton { 811*18261Slinton printf("[subarray]"); 812*18261Slinton } 813*18261Slinton 814*18261Slinton /* 81516622Ssam * Print out the value of a scalar (non-enumeration) type. 81616622Ssam */ 81716622Ssam 81816622Ssam private printrange (s, n) 81916622Ssam Symbol s; 82016622Ssam integer n; 82116622Ssam { 82216622Ssam double d; 82316622Ssam float f; 82416622Ssam integer i; 82516622Ssam 82616622Ssam if (s->symvalue.rangev.upper == 0 and s->symvalue.rangev.lower > 0) { 82716622Ssam if (n == sizeof(float)) { 82816622Ssam popn(n, &f); 82916622Ssam d = f; 83016622Ssam } else { 83116622Ssam popn(n, &d); 83216622Ssam } 83316622Ssam prtreal(d); 83416622Ssam } else { 83516622Ssam i = 0; 83616622Ssam popn(n, &i); 837*18261Slinton printRangeVal(i, s); 83816622Ssam } 83916622Ssam } 84016622Ssam 84116622Ssam /* 84216622Ssam * Print out a set. 84316622Ssam */ 84416622Ssam 84516622Ssam private printSet (s) 84616622Ssam Symbol s; 84716622Ssam { 84816622Ssam Symbol t; 84916622Ssam integer nbytes; 85016622Ssam 85116622Ssam nbytes = size(s); 85216622Ssam t = rtype(s->type); 85316622Ssam printf("{"); 85416622Ssam sp -= nbytes; 85516622Ssam if (t->class == SCAL) { 85616622Ssam printSetOfEnum(t); 85716622Ssam } else if (t->class == RANGE) { 85816622Ssam printSetOfRange(t); 85916622Ssam } else { 86016622Ssam panic("expected range or enumerated base type for set"); 86116622Ssam } 86216622Ssam printf("}"); 86316622Ssam } 86416622Ssam 86516622Ssam /* 86616622Ssam * Print out a set of an enumeration. 86716622Ssam */ 86816622Ssam 86916622Ssam private printSetOfEnum (t) 87016622Ssam Symbol t; 87116622Ssam { 87216622Ssam register Symbol e; 87316622Ssam register integer i, j, *p; 87416622Ssam boolean first; 87516622Ssam 87616622Ssam p = (int *) sp; 87716622Ssam i = *p; 87816622Ssam j = 0; 87916622Ssam e = t->chain; 88016622Ssam first = true; 88116622Ssam while (e != nil) { 88216622Ssam if ((i&1) == 1) { 88316622Ssam if (first) { 88416622Ssam first = false; 88516622Ssam printf("%s", symname(e)); 88616622Ssam } else { 88716622Ssam printf(", %s", symname(e)); 88816622Ssam } 88916622Ssam } 89016622Ssam i >>= 1; 89116622Ssam ++j; 89216622Ssam if (j >= sizeof(integer)*BITSPERBYTE) { 89316622Ssam j = 0; 89416622Ssam ++p; 89516622Ssam i = *p; 89616622Ssam } 89716622Ssam e = e->chain; 89816622Ssam } 89916622Ssam } 90016622Ssam 90116622Ssam /* 90216622Ssam * Print out a set of a subrange type. 90316622Ssam */ 90416622Ssam 90516622Ssam private printSetOfRange (t) 90616622Ssam Symbol t; 90716622Ssam { 90816622Ssam register integer i, j, *p; 90916622Ssam long v; 91016622Ssam boolean first; 91116622Ssam 91216622Ssam p = (int *) sp; 91316622Ssam i = *p; 91416622Ssam j = 0; 91516622Ssam v = t->symvalue.rangev.lower; 91616622Ssam first = true; 91716622Ssam while (v <= t->symvalue.rangev.upper) { 91816622Ssam if ((i&1) == 1) { 91916622Ssam if (first) { 92016622Ssam first = false; 92116622Ssam printf("%ld", v); 92216622Ssam } else { 92316622Ssam printf(", %ld", v); 92416622Ssam } 92516622Ssam } 92616622Ssam i >>= 1; 92716622Ssam ++j; 92816622Ssam if (j >= sizeof(integer)*BITSPERBYTE) { 92916622Ssam j = 0; 93016622Ssam ++p; 93116622Ssam i = *p; 93216622Ssam } 93316622Ssam ++v; 93416622Ssam } 93516622Ssam } 93616622Ssam 93716622Ssam /* 938*18261Slinton * Construct a node for subscripting a dynamic or subarray. 939*18261Slinton * The list of indices is left for processing in evalaref, 940*18261Slinton * unlike normal subscripting in which the list is expanded 941*18261Slinton * across individual INDEX nodes. 942*18261Slinton */ 943*18261Slinton 944*18261Slinton private Node dynref (a, t, slist) 945*18261Slinton Node a; 946*18261Slinton Symbol t; 947*18261Slinton Node slist; 948*18261Slinton { 949*18261Slinton Node p, r; 950*18261Slinton integer n; 951*18261Slinton 952*18261Slinton p = slist; 953*18261Slinton n = 0; 954*18261Slinton while (p != nil) { 955*18261Slinton if (not compatible(p->value.arg[0]->nodetype, t_int)) { 956*18261Slinton suberror("subscript \"", p->value.arg[0], "\" is the wrong type"); 957*18261Slinton } 958*18261Slinton ++n; 959*18261Slinton p = p->value.arg[1]; 960*18261Slinton } 961*18261Slinton if (n > t->symvalue.ndims and (t->symvalue.ndims != 0 or n != 1)) { 962*18261Slinton suberror("too many subscripts for ", a, nil); 963*18261Slinton } else if (n < t->symvalue.ndims) { 964*18261Slinton suberror("not enough subscripts for ", a, nil); 965*18261Slinton } 966*18261Slinton r = build(O_INDEX, a, slist); 967*18261Slinton r->nodetype = rtype(t->type); 968*18261Slinton return r; 969*18261Slinton } 970*18261Slinton 971*18261Slinton /* 97216622Ssam * Construct a node for subscripting. 97316622Ssam */ 97416622Ssam 97516622Ssam public Node modula2_buildaref (a, slist) 97616622Ssam Node a, slist; 97716622Ssam { 97816622Ssam register Symbol t; 97916622Ssam register Node p; 980*18261Slinton Symbol eltype; 98116622Ssam Node esub, r; 982*18261Slinton integer n; 98316622Ssam 98416622Ssam t = rtype(a->nodetype); 985*18261Slinton if (t->class == DYNARRAY or t->class == SUBARRAY) { 986*18261Slinton r = dynref(a, t, slist); 987*18261Slinton } else if (t->class == ARRAY) { 988*18261Slinton r = a; 989*18261Slinton eltype = rtype(t->type); 99016622Ssam p = slist; 99116622Ssam t = t->chain; 992*18261Slinton while (p != nil and t != nil) { 99316622Ssam esub = p->value.arg[0]; 994*18261Slinton if (not compatible(rtype(t), rtype(esub->nodetype))) { 995*18261Slinton suberror("subscript \"", esub, "\" is the wrong type"); 99616622Ssam } 99716622Ssam r = build(O_INDEX, r, esub); 99816622Ssam r->nodetype = eltype; 999*18261Slinton p = p->value.arg[1]; 1000*18261Slinton t = t->chain; 100116622Ssam } 1002*18261Slinton if (p != nil) { 1003*18261Slinton suberror("too many subscripts for ", a, nil); 1004*18261Slinton } else if (t != nil) { 1005*18261Slinton suberror("not enough subscripts for ", a, nil); 100616622Ssam } 1007*18261Slinton } else { 1008*18261Slinton suberror("\"", a, "\" is not an array"); 100916622Ssam } 101016622Ssam return r; 101116622Ssam } 101216622Ssam 101316622Ssam /* 1014*18261Slinton * Subscript usage error reporting. 1015*18261Slinton */ 1016*18261Slinton 1017*18261Slinton private suberror (s1, e1, s2) 1018*18261Slinton String s1, s2; 1019*18261Slinton Node e1; 1020*18261Slinton { 1021*18261Slinton beginerrmsg(); 1022*18261Slinton if (s1 != nil) { 1023*18261Slinton fprintf(stderr, s1); 1024*18261Slinton } 1025*18261Slinton if (e1 != nil) { 1026*18261Slinton prtree(stderr, e1); 1027*18261Slinton } 1028*18261Slinton if (s2 != nil) { 1029*18261Slinton fprintf(stderr, s2); 1030*18261Slinton } 1031*18261Slinton enderrmsg(); 1032*18261Slinton } 1033*18261Slinton 1034*18261Slinton /* 1035*18261Slinton * Check that a subscript value is in the appropriate range. 1036*18261Slinton */ 1037*18261Slinton 1038*18261Slinton private subchk (value, lower, upper) 1039*18261Slinton long value, lower, upper; 1040*18261Slinton { 1041*18261Slinton if (value < lower or value > upper) { 1042*18261Slinton error("subscript value %d out of range [%d..%d]", value, lower, upper); 1043*18261Slinton } 1044*18261Slinton } 1045*18261Slinton 1046*18261Slinton /* 1047*18261Slinton * Compute the offset for subscripting a dynamic array. 1048*18261Slinton */ 1049*18261Slinton 1050*18261Slinton private getdynoff (ndims, sub) 1051*18261Slinton integer ndims; 1052*18261Slinton long *sub; 1053*18261Slinton { 1054*18261Slinton long k, off, *count; 1055*18261Slinton 1056*18261Slinton count = (long *) sp; 1057*18261Slinton off = 0; 1058*18261Slinton for (k = 0; k < ndims - 1; k++) { 1059*18261Slinton subchk(sub[k], 0, count[k] - 1); 1060*18261Slinton off += (sub[k] * count[k+1]); 1061*18261Slinton } 1062*18261Slinton subchk(sub[ndims - 1], 0, count[ndims - 1] - 1); 1063*18261Slinton return off + sub[ndims - 1]; 1064*18261Slinton } 1065*18261Slinton 1066*18261Slinton /* 1067*18261Slinton * Compute the offset associated with a subarray. 1068*18261Slinton */ 1069*18261Slinton 1070*18261Slinton private getsuboff (ndims, sub) 1071*18261Slinton integer ndims; 1072*18261Slinton long *sub; 1073*18261Slinton { 1074*18261Slinton long k, off; 1075*18261Slinton struct subarrayinfo { 1076*18261Slinton long count; 1077*18261Slinton long mult; 1078*18261Slinton } *info; 1079*18261Slinton 1080*18261Slinton info = (struct subarrayinfo *) sp; 1081*18261Slinton off = 0; 1082*18261Slinton for (k = 0; k < ndims; k++) { 1083*18261Slinton subchk(sub[k], 0, info[k].count - 1); 1084*18261Slinton off += sub[k] * info[k].mult; 1085*18261Slinton } 1086*18261Slinton return off; 1087*18261Slinton } 1088*18261Slinton 1089*18261Slinton /* 109016622Ssam * Evaluate a subscript index. 109116622Ssam */ 109216622Ssam 1093*18261Slinton public modula2_evalaref (s, base, i) 109416622Ssam Symbol s; 1095*18261Slinton Address base; 109616622Ssam long i; 109716622Ssam { 1098*18261Slinton Symbol t; 1099*18261Slinton long lb, ub, off; 1100*18261Slinton long *sub; 1101*18261Slinton Address b; 110216622Ssam 1103*18261Slinton t = rtype(s); 1104*18261Slinton if (t->class == ARRAY) { 1105*18261Slinton findbounds(rtype(t->chain), &lb, &ub); 1106*18261Slinton if (i < lb or i > ub) { 1107*18261Slinton error("subscript %d out of range [%d..%d]", i, lb, ub); 1108*18261Slinton } 1109*18261Slinton push(long, base + (i - lb) * size(t->type)); 1110*18261Slinton } else if (t->class == DYNARRAY and t->symvalue.ndims == 0) { 1111*18261Slinton push(long, base + i * size(t->type)); 1112*18261Slinton } else if (t->class == DYNARRAY or t->class == SUBARRAY) { 1113*18261Slinton push(long, i); 1114*18261Slinton sub = (long *) (sp - (t->symvalue.ndims * sizeof(long))); 1115*18261Slinton rpush(base, size(t)); 1116*18261Slinton sp -= (t->symvalue.ndims * sizeof(long)); 1117*18261Slinton b = pop(Address); 1118*18261Slinton sp += sizeof(Address); 1119*18261Slinton if (t->class == SUBARRAY) { 1120*18261Slinton off = getsuboff(t->symvalue.ndims, sub); 1121*18261Slinton } else { 1122*18261Slinton off = getdynoff(t->symvalue.ndims, sub); 1123*18261Slinton } 1124*18261Slinton sp = (Stack *) sub; 1125*18261Slinton push(long, b + off * size(t->type)); 1126*18261Slinton } else { 1127*18261Slinton error("[internal error: expected array in evalaref]"); 112816622Ssam } 112916622Ssam } 113016622Ssam 113116622Ssam /* 113216622Ssam * Initial Modula-2 type information. 113316622Ssam */ 113416622Ssam 113516622Ssam #define NTYPES 12 113616622Ssam 113716622Ssam private Symbol inittype[NTYPES + 1]; 113816622Ssam 113916622Ssam private addType (n, s, lower, upper) 114016622Ssam integer n; 114116622Ssam String s; 114216622Ssam long lower, upper; 114316622Ssam { 114416622Ssam register Symbol t; 114516622Ssam 114616622Ssam if (n > NTYPES) { 114716622Ssam panic("initial Modula-2 type number too large for '%s'", s); 114816622Ssam } 114916622Ssam t = insert(identname(s, true)); 115016622Ssam t->language = mod2; 115116622Ssam t->class = TYPE; 115216622Ssam t->type = newSymbol(nil, 0, RANGE, t, nil); 115316622Ssam t->type->symvalue.rangev.lower = lower; 115416622Ssam t->type->symvalue.rangev.upper = upper; 115516622Ssam t->type->language = mod2; 115616622Ssam inittype[n] = t; 115716622Ssam } 115816622Ssam 115916622Ssam private initModTypes () 116016622Ssam { 116116622Ssam addType(1, "integer", 0x80000000L, 0x7fffffffL); 116216622Ssam addType(2, "char", 0L, 255L); 116316622Ssam addType(3, "boolean", 0L, 1L); 116416622Ssam addType(4, "unsigned", 0L, 0xffffffffL); 116516622Ssam addType(5, "real", 4L, 0L); 116616622Ssam addType(6, "longreal", 8L, 0L); 116716622Ssam addType(7, "word", 0L, 0xffffffffL); 116816622Ssam addType(8, "byte", 0L, 255L); 116916622Ssam addType(9, "address", 0L, 0xffffffffL); 117016622Ssam addType(10, "file", 0L, 0xffffffffL); 117116622Ssam addType(11, "process", 0L, 0xffffffffL); 117216622Ssam addType(12, "cardinal", 0L, 0x7fffffffL); 117316622Ssam } 117416622Ssam 117516622Ssam /* 117616622Ssam * Initialize typetable. 117716622Ssam */ 117816622Ssam 117916622Ssam public modula2_modinit (typetable) 118016622Ssam Symbol typetable[]; 118116622Ssam { 118216622Ssam register integer i; 118316622Ssam 118416622Ssam if (not initialized) { 118516622Ssam initModTypes(); 1186*18261Slinton initialized = true; 118716622Ssam } 118816622Ssam for (i = 1; i <= NTYPES; i++) { 118916622Ssam typetable[i] = inittype[i]; 119016622Ssam } 119116622Ssam } 119216622Ssam 119316622Ssam public boolean modula2_hasmodules () 119416622Ssam { 119516622Ssam return true; 119616622Ssam } 119716622Ssam 119816622Ssam public boolean modula2_passaddr (param, exprtype) 119916622Ssam Symbol param, exprtype; 120016622Ssam { 120116622Ssam return false; 120216622Ssam } 1203