121613Sdist /* 2*38105Sbostic * Copyright (c) 1983 The Regents of the University of California. 3*38105Sbostic * All rights reserved. 4*38105Sbostic * 5*38105Sbostic * Redistribution and use in source and binary forms are permitted 6*38105Sbostic * provided that the above copyright notice and this paragraph are 7*38105Sbostic * duplicated in all such forms and that any documentation, 8*38105Sbostic * advertising materials, and other materials related to such 9*38105Sbostic * distribution and use acknowledge that the software was developed 10*38105Sbostic * by the University of California, Berkeley. The name of the 11*38105Sbostic * University may not be used to endorse or promote products derived 12*38105Sbostic * from this software without specific prior written permission. 13*38105Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14*38105Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15*38105Sbostic * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1621613Sdist */ 1718261Slinton 1816622Ssam #ifndef lint 19*38105Sbostic static char sccsid[] = "@(#)modula-2.c 5.3 (Berkeley) 05/23/89"; 20*38105Sbostic #endif /* not lint */ 2116622Ssam 2216622Ssam /* 2316622Ssam * Modula-2 specific symbol routines. 2416622Ssam */ 2516622Ssam 2616622Ssam #include "defs.h" 2716622Ssam #include "symbols.h" 2816622Ssam #include "modula-2.h" 2916622Ssam #include "languages.h" 3016622Ssam #include "tree.h" 3116622Ssam #include "eval.h" 3216622Ssam #include "mappings.h" 3316622Ssam #include "process.h" 3416622Ssam #include "runtime.h" 3516622Ssam #include "machine.h" 3616622Ssam 3716622Ssam #ifndef public 3816622Ssam #endif 3916622Ssam 4016622Ssam private Language mod2; 4116622Ssam private boolean initialized; 4216622Ssam 4318261Slinton 4418261Slinton #define ischar(t) ( \ 4518261Slinton (t) == t_char->type or \ 4618261Slinton ((t)->class == RANGE and istypename((t)->type, "char")) \ 4718261Slinton ) 4818261Slinton 4916622Ssam /* 5016622Ssam * Initialize Modula-2 information. 5116622Ssam */ 5216622Ssam 5316622Ssam public modula2_init () 5416622Ssam { 5516622Ssam mod2 = language_define("modula-2", ".mod"); 5616622Ssam language_setop(mod2, L_PRINTDECL, modula2_printdecl); 5716622Ssam language_setop(mod2, L_PRINTVAL, modula2_printval); 5816622Ssam language_setop(mod2, L_TYPEMATCH, modula2_typematch); 5916622Ssam language_setop(mod2, L_BUILDAREF, modula2_buildaref); 6016622Ssam language_setop(mod2, L_EVALAREF, modula2_evalaref); 6116622Ssam language_setop(mod2, L_MODINIT, modula2_modinit); 6216622Ssam language_setop(mod2, L_HASMODULES, modula2_hasmodules); 6316622Ssam language_setop(mod2, L_PASSADDR, modula2_passaddr); 6416622Ssam initialized = false; 6516622Ssam } 6616622Ssam 6716622Ssam /* 6816622Ssam * Typematch tests if two types are compatible. The issue 6916622Ssam * is a bit complicated, so several subfunctions are used for 7016622Ssam * various kinds of compatibility. 7116622Ssam */ 7216622Ssam 7318261Slinton private boolean builtinmatch (t1, t2) 7418261Slinton register Symbol t1, t2; 7518261Slinton { 7618261Slinton boolean b; 7718261Slinton 7818261Slinton b = (boolean) ( 7918261Slinton ( 8018261Slinton t2 == t_int->type and t1->class == RANGE and 8118261Slinton ( 8218261Slinton istypename(t1->type, "integer") or 8318261Slinton istypename(t1->type, "cardinal") 8418261Slinton ) 8518261Slinton ) or ( 8618261Slinton t2 == t_char->type and 8718261Slinton t1->class == RANGE and istypename(t1->type, "char") 8818261Slinton ) or ( 8918261Slinton t2 == t_real->type and 9018261Slinton t1->class == RANGE and ( 9118261Slinton istypename(t1->type, "real") or 9218261Slinton istypename(t1->type, "longreal") 9318261Slinton ) 9418261Slinton ) or ( 9518261Slinton t2 == t_boolean->type and 9618261Slinton t1->class == RANGE and istypename(t1->type, "boolean") 9718261Slinton ) 9818261Slinton ); 9918261Slinton return b; 10018261Slinton } 10118261Slinton 10216622Ssam private boolean nilMatch (t1, t2) 10316622Ssam register Symbol t1, t2; 10416622Ssam { 10516622Ssam boolean b; 10616622Ssam 10716622Ssam b = (boolean) ( 10816622Ssam (t1 == t_nil and t2->class == PTR) or 10916622Ssam (t1->class == PTR and t2 == t_nil) 11016622Ssam ); 11116622Ssam return b; 11216622Ssam } 11316622Ssam 11416622Ssam private boolean enumMatch (t1, t2) 11516622Ssam register Symbol t1, t2; 11616622Ssam { 11716622Ssam boolean b; 11816622Ssam 11916622Ssam b = (boolean) ( 12018261Slinton (t1->class == SCAL and t2->class == CONST and t2->type == t1) or 12118261Slinton (t1->class == CONST and t2->class == SCAL and t1->type == t2) 12216622Ssam ); 12316622Ssam return b; 12416622Ssam } 12516622Ssam 12616622Ssam private boolean openArrayMatch (t1, t2) 12716622Ssam register Symbol t1, t2; 12816622Ssam { 12916622Ssam boolean b; 13016622Ssam 13116622Ssam b = (boolean) ( 13216622Ssam ( 13333326Sdonn t1->class == OPENARRAY and t1->symvalue.ndims == 1 and 13416622Ssam t2->class == ARRAY and 13516622Ssam compatible(rtype(t2->chain)->type, t_int) and 13616622Ssam compatible(t1->type, t2->type) 13716622Ssam ) or ( 13833326Sdonn t2->class == OPENARRAY and t2->symvalue.ndims == 1 and 13916622Ssam t1->class == ARRAY and 14016622Ssam compatible(rtype(t1->chain)->type, t_int) and 14116622Ssam compatible(t1->type, t2->type) 14216622Ssam ) 14316622Ssam ); 14416622Ssam return b; 14516622Ssam } 14616622Ssam 14716622Ssam private boolean isConstString (t) 14816622Ssam register Symbol t; 14916622Ssam { 15016622Ssam boolean b; 15116622Ssam 15216622Ssam b = (boolean) ( 15316622Ssam t->language == primlang and t->class == ARRAY and t->type == t_char 15416622Ssam ); 15516622Ssam return b; 15616622Ssam } 15716622Ssam 15816622Ssam private boolean stringArrayMatch (t1, t2) 15916622Ssam register Symbol t1, t2; 16016622Ssam { 16116622Ssam boolean b; 16216622Ssam 16316622Ssam b = (boolean) ( 16416622Ssam ( 16516622Ssam isConstString(t1) and 16616622Ssam t2->class == ARRAY and compatible(t2->type, t_char->type) 16716622Ssam ) or ( 16816622Ssam isConstString(t2) and 16916622Ssam t1->class == ARRAY and compatible(t1->type, t_char->type) 17016622Ssam ) 17116622Ssam ); 17216622Ssam return b; 17316622Ssam } 17416622Ssam 17516622Ssam public boolean modula2_typematch (type1, type2) 17616622Ssam Symbol type1, type2; 17716622Ssam { 17818261Slinton boolean b; 17916622Ssam Symbol t1, t2, tmp; 18016622Ssam 18116622Ssam t1 = rtype(type1); 18216622Ssam t2 = rtype(type2); 18316622Ssam if (t1 == t2) { 18416622Ssam b = true; 18516622Ssam } else { 18618261Slinton if (t1 == t_char->type or t1 == t_int->type or 18718261Slinton t1 == t_real->type or t1 == t_boolean->type 18818261Slinton ) { 18916622Ssam tmp = t1; 19016622Ssam t1 = t2; 19116622Ssam t2 = tmp; 19216622Ssam } 19316622Ssam b = (Boolean) ( 19433326Sdonn builtinmatch(t1, t2) or 19518261Slinton nilMatch(t1, t2) or enumMatch(t1, t2) or 19618261Slinton openArrayMatch(t1, t2) or stringArrayMatch(t1, t2) 19716622Ssam ); 19816622Ssam } 19916622Ssam return b; 20016622Ssam } 20116622Ssam 20216622Ssam /* 20316622Ssam * Indent n spaces. 20416622Ssam */ 20516622Ssam 20616622Ssam private indent (n) 20716622Ssam int n; 20816622Ssam { 20916622Ssam if (n > 0) { 21016622Ssam printf("%*c", n, ' '); 21116622Ssam } 21216622Ssam } 21316622Ssam 21416622Ssam public modula2_printdecl (s) 21516622Ssam Symbol s; 21616622Ssam { 21716622Ssam register Symbol t; 21816622Ssam Boolean semicolon; 21916622Ssam 22016622Ssam semicolon = true; 22116622Ssam if (s->class == TYPEREF) { 22216622Ssam resolveRef(t); 22316622Ssam } 22416622Ssam switch (s->class) { 22516622Ssam case CONST: 22616622Ssam if (s->type->class == SCAL) { 22718261Slinton semicolon = false; 22818261Slinton printf("enumeration constant with value "); 22918261Slinton eval(s->symvalue.constval); 23018261Slinton modula2_printval(s); 23116622Ssam } else { 23216622Ssam printf("const %s = ", symname(s)); 23318261Slinton eval(s->symvalue.constval); 23416622Ssam modula2_printval(s); 23516622Ssam } 23616622Ssam break; 23716622Ssam 23816622Ssam case TYPE: 23916622Ssam printf("type %s = ", symname(s)); 24016622Ssam printtype(s, s->type, 0); 24116622Ssam break; 24216622Ssam 24316622Ssam case TYPEREF: 24416622Ssam printf("type %s", symname(s)); 24516622Ssam break; 24616622Ssam 24716622Ssam case VAR: 24816622Ssam if (isparam(s)) { 24916622Ssam printf("(parameter) %s : ", symname(s)); 25016622Ssam } else { 25116622Ssam printf("var %s : ", symname(s)); 25216622Ssam } 25316622Ssam printtype(s, s->type, 0); 25416622Ssam break; 25516622Ssam 25616622Ssam case REF: 25716622Ssam printf("(var parameter) %s : ", symname(s)); 25816622Ssam printtype(s, s->type, 0); 25916622Ssam break; 26016622Ssam 26116622Ssam case RANGE: 26216622Ssam case ARRAY: 26333326Sdonn case OPENARRAY: 26418261Slinton case DYNARRAY: 26518261Slinton case SUBARRAY: 26616622Ssam case RECORD: 26716622Ssam case VARNT: 26816622Ssam case PTR: 26916622Ssam printtype(s, s, 0); 27016622Ssam semicolon = false; 27116622Ssam break; 27216622Ssam 27316622Ssam case FVAR: 27416622Ssam printf("(function variable) %s : ", symname(s)); 27516622Ssam printtype(s, s->type, 0); 27616622Ssam break; 27716622Ssam 27816622Ssam case FIELD: 27916622Ssam printf("(field) %s : ", symname(s)); 28016622Ssam printtype(s, s->type, 0); 28116622Ssam break; 28216622Ssam 28316622Ssam case PROC: 28416622Ssam printf("procedure %s", symname(s)); 28516622Ssam listparams(s); 28616622Ssam break; 28716622Ssam 28816622Ssam case PROG: 28916622Ssam printf("program %s", symname(s)); 29016622Ssam listparams(s); 29116622Ssam break; 29216622Ssam 29316622Ssam case FUNC: 29418261Slinton printf("procedure %s", symname(s)); 29516622Ssam listparams(s); 29616622Ssam printf(" : "); 29716622Ssam printtype(s, s->type, 0); 29816622Ssam break; 29916622Ssam 30016622Ssam case MODULE: 30116622Ssam printf("module %s", symname(s)); 30216622Ssam break; 30316622Ssam 30416622Ssam default: 30518261Slinton printf("[%s]", classname(s)); 30616622Ssam break; 30716622Ssam } 30816622Ssam if (semicolon) { 30916622Ssam putchar(';'); 31016622Ssam } 31116622Ssam putchar('\n'); 31216622Ssam } 31316622Ssam 31416622Ssam /* 31516622Ssam * Recursive whiz-bang procedure to print the type portion 31616622Ssam * of a declaration. 31716622Ssam * 31816622Ssam * The symbol associated with the type is passed to allow 31916622Ssam * searching for type names without getting "type blah = blah". 32016622Ssam */ 32116622Ssam 32216622Ssam private printtype (s, t, n) 32316622Ssam Symbol s; 32416622Ssam Symbol t; 32516622Ssam int n; 32616622Ssam { 32718261Slinton Symbol tmp; 32818261Slinton int i; 32916622Ssam 33016622Ssam if (t->class == TYPEREF) { 33116622Ssam resolveRef(t); 33216622Ssam } 33316622Ssam switch (t->class) { 33416622Ssam case VAR: 33516622Ssam case CONST: 33616622Ssam case FUNC: 33716622Ssam case PROC: 33816622Ssam panic("printtype: class %s", classname(t)); 33916622Ssam break; 34016622Ssam 34116622Ssam case ARRAY: 34216622Ssam printf("array["); 34316622Ssam tmp = t->chain; 34416622Ssam if (tmp != nil) { 34516622Ssam for (;;) { 34616622Ssam printtype(tmp, tmp, n); 34716622Ssam tmp = tmp->chain; 34816622Ssam if (tmp == nil) { 34916622Ssam break; 35016622Ssam } 35116622Ssam printf(", "); 35216622Ssam } 35316622Ssam } 35416622Ssam printf("] of "); 35516622Ssam printtype(t, t->type, n); 35616622Ssam break; 35716622Ssam 35833326Sdonn case OPENARRAY: 35933326Sdonn printf("array of "); 36033326Sdonn for (i = 1; i < t->symvalue.ndims; i++) { 36133326Sdonn printf("array of "); 36233326Sdonn } 36333326Sdonn printtype(t, t->type, n); 36433326Sdonn break; 36533326Sdonn 36618261Slinton case DYNARRAY: 36718261Slinton printf("dynarray of "); 36818261Slinton for (i = 1; i < t->symvalue.ndims; i++) { 36918261Slinton printf("array of "); 37018261Slinton } 37118261Slinton printtype(t, t->type, n); 37218261Slinton break; 37318261Slinton 37418261Slinton case SUBARRAY: 37518261Slinton printf("subarray of "); 37618261Slinton for (i = 1; i < t->symvalue.ndims; i++) { 37718261Slinton printf("array of "); 37818261Slinton } 37918261Slinton printtype(t, t->type, n); 38018261Slinton break; 38118261Slinton 38216622Ssam case RECORD: 38316622Ssam printRecordDecl(t, n); 38416622Ssam break; 38516622Ssam 38616622Ssam case FIELD: 38716622Ssam if (t->chain != nil) { 38816622Ssam printtype(t->chain, t->chain, n); 38916622Ssam } 39016622Ssam printf("\t%s : ", symname(t)); 39116622Ssam printtype(t, t->type, n); 39216622Ssam printf(";\n"); 39316622Ssam break; 39416622Ssam 39516622Ssam case RANGE: 39616622Ssam printRangeDecl(t); 39716622Ssam break; 39816622Ssam 39916622Ssam case PTR: 40016622Ssam printf("pointer to "); 40116622Ssam printtype(t, t->type, n); 40216622Ssam break; 40316622Ssam 40416622Ssam case TYPE: 40516622Ssam if (t->name != nil and ident(t->name)[0] != '\0') { 40616622Ssam printname(stdout, t); 40716622Ssam } else { 40816622Ssam printtype(t, t->type, n); 40916622Ssam } 41016622Ssam break; 41116622Ssam 41216622Ssam case SCAL: 41316622Ssam printEnumDecl(t, n); 41416622Ssam break; 41516622Ssam 41616622Ssam case SET: 41716622Ssam printf("set of "); 41816622Ssam printtype(t, t->type, n); 41916622Ssam break; 42016622Ssam 42116622Ssam case TYPEREF: 42216622Ssam break; 42316622Ssam 42418261Slinton case FPROC: 42518261Slinton case FFUNC: 42618261Slinton printf("procedure"); 42718261Slinton break; 42818261Slinton 42916622Ssam default: 43018261Slinton printf("[%s]", classname(t)); 43116622Ssam break; 43216622Ssam } 43316622Ssam } 43416622Ssam 43516622Ssam /* 43616622Ssam * Print out a record declaration. 43716622Ssam */ 43816622Ssam 43916622Ssam private printRecordDecl (t, n) 44016622Ssam Symbol t; 44116622Ssam int n; 44216622Ssam { 44316622Ssam register Symbol f; 44416622Ssam 44516622Ssam if (t->chain == nil) { 44616622Ssam printf("record end"); 44716622Ssam } else { 44816622Ssam printf("record\n"); 44916622Ssam for (f = t->chain; f != nil; f = f->chain) { 45016622Ssam indent(n+4); 45116622Ssam printf("%s : ", symname(f)); 45216622Ssam printtype(f->type, f->type, n+4); 45316622Ssam printf(";\n"); 45416622Ssam } 45516622Ssam indent(n); 45616622Ssam printf("end"); 45716622Ssam } 45816622Ssam } 45916622Ssam 46016622Ssam /* 46116622Ssam * Print out the declaration of a range type. 46216622Ssam */ 46316622Ssam 46416622Ssam private printRangeDecl (t) 46516622Ssam Symbol t; 46616622Ssam { 46716622Ssam long r0, r1; 46816622Ssam 46916622Ssam r0 = t->symvalue.rangev.lower; 47016622Ssam r1 = t->symvalue.rangev.upper; 47118261Slinton if (ischar(t)) { 47216622Ssam if (r0 < 0x20 or r0 > 0x7e) { 47316622Ssam printf("%ld..", r0); 47416622Ssam } else { 47516622Ssam printf("'%c'..", (char) r0); 47616622Ssam } 47716622Ssam if (r1 < 0x20 or r1 > 0x7e) { 47816622Ssam printf("\\%lo", r1); 47916622Ssam } else { 48016622Ssam printf("'%c'", (char) r1); 48116622Ssam } 48216622Ssam } else if (r0 > 0 and r1 == 0) { 48316622Ssam printf("%ld byte real", r0); 48416622Ssam } else if (r0 >= 0) { 48516622Ssam printf("%lu..%lu", r0, r1); 48616622Ssam } else { 48716622Ssam printf("%ld..%ld", r0, r1); 48816622Ssam } 48916622Ssam } 49016622Ssam 49116622Ssam /* 49216622Ssam * Print out an enumeration declaration. 49316622Ssam */ 49416622Ssam 49516622Ssam private printEnumDecl (e, n) 49616622Ssam Symbol e; 49716622Ssam int n; 49816622Ssam { 49916622Ssam Symbol t; 50016622Ssam 50116622Ssam printf("("); 50216622Ssam t = e->chain; 50316622Ssam if (t != nil) { 50416622Ssam printf("%s", symname(t)); 50516622Ssam t = t->chain; 50616622Ssam while (t != nil) { 50716622Ssam printf(", %s", symname(t)); 50816622Ssam t = t->chain; 50916622Ssam } 51016622Ssam } 51116622Ssam printf(")"); 51216622Ssam } 51316622Ssam 51416622Ssam /* 51516622Ssam * List the parameters of a procedure or function. 51616622Ssam * No attempt is made to combine like types. 51716622Ssam */ 51816622Ssam 51916622Ssam private listparams (s) 52016622Ssam Symbol s; 52116622Ssam { 52216622Ssam Symbol t; 52316622Ssam 52416622Ssam if (s->chain != nil) { 52516622Ssam putchar('('); 52616622Ssam for (t = s->chain; t != nil; t = t->chain) { 52716622Ssam switch (t->class) { 52816622Ssam case REF: 52916622Ssam printf("var "); 53016622Ssam break; 53116622Ssam 53216622Ssam case FPROC: 53316622Ssam case FFUNC: 53416622Ssam printf("procedure "); 53516622Ssam break; 53616622Ssam 53716622Ssam case VAR: 53816622Ssam break; 53916622Ssam 54016622Ssam default: 54116622Ssam panic("unexpected class %d for parameter", t->class); 54216622Ssam } 54316622Ssam printf("%s", symname(t)); 54416622Ssam if (s->class == PROG) { 54516622Ssam printf(", "); 54616622Ssam } else { 54716622Ssam printf(" : "); 54816622Ssam printtype(t, t->type, 0); 54916622Ssam if (t->chain != nil) { 55016622Ssam printf("; "); 55116622Ssam } 55216622Ssam } 55316622Ssam } 55416622Ssam putchar(')'); 55516622Ssam } 55616622Ssam } 55716622Ssam 55816622Ssam /* 55918261Slinton * Test if a pointer type should be treated as a null-terminated string. 56018261Slinton * The type given is the type that is pointed to. 56118261Slinton */ 56218261Slinton 56318261Slinton private boolean isCstring (type) 56418261Slinton Symbol type; 56518261Slinton { 56618261Slinton boolean b; 56718261Slinton register Symbol a, t; 56818261Slinton 56918261Slinton a = rtype(type); 57018261Slinton if (a->class == ARRAY) { 57118261Slinton t = rtype(a->chain); 57218261Slinton b = (boolean) ( 57318261Slinton t->class == RANGE and istypename(a->type, "char") and 57418261Slinton (t->symvalue.rangev.upper - t->symvalue.rangev.lower + 1) <= 0 57518261Slinton ); 57618261Slinton } else { 57718261Slinton b = false; 57818261Slinton } 57918261Slinton return b; 58018261Slinton } 58118261Slinton 58218261Slinton /* 58316622Ssam * Modula 2 interface to printval. 58416622Ssam */ 58516622Ssam 58616622Ssam public modula2_printval (s) 58716622Ssam Symbol s; 58816622Ssam { 58916622Ssam prval(s, size(s)); 59016622Ssam } 59116622Ssam 59216622Ssam /* 59316622Ssam * Print out the value on the top of the expression stack 59416622Ssam * in the format for the type of the given symbol, assuming 59516622Ssam * the size of the object is n bytes. 59616622Ssam */ 59716622Ssam 59816622Ssam private prval (s, n) 59916622Ssam Symbol s; 60016622Ssam integer n; 60116622Ssam { 60216622Ssam Symbol t; 60316622Ssam Address a; 60416622Ssam integer len; 60516622Ssam double r; 60618261Slinton integer i; 60716622Ssam 60816622Ssam if (s->class == TYPEREF) { 60916622Ssam resolveRef(s); 61016622Ssam } 61116622Ssam switch (s->class) { 61216622Ssam case CONST: 61316622Ssam case TYPE: 61418261Slinton case REF: 61516622Ssam case VAR: 61616622Ssam case FVAR: 61716622Ssam case TAG: 61816622Ssam prval(s->type, n); 61916622Ssam break; 62016622Ssam 62118261Slinton case FIELD: 62218261Slinton if (isbitfield(s)) { 62333326Sdonn i = extractField(s); 62418261Slinton t = rtype(s->type); 62518261Slinton if (t->class == SCAL) { 62618261Slinton printEnum(i, t); 62718261Slinton } else { 62818261Slinton printRangeVal(i, t); 62918261Slinton } 63018261Slinton } else { 63118261Slinton prval(s->type, n); 63218261Slinton } 63318261Slinton break; 63418261Slinton 63516622Ssam case ARRAY: 63616622Ssam t = rtype(s->type); 63718261Slinton if (ischar(t)) { 63816622Ssam len = size(s); 63916622Ssam sp -= len; 64018261Slinton printf("\"%.*s\"", len, sp); 64116622Ssam break; 64216622Ssam } else { 64316622Ssam printarray(s); 64416622Ssam } 64516622Ssam break; 64616622Ssam 64733326Sdonn case OPENARRAY: 64818261Slinton case DYNARRAY: 64918261Slinton printDynarray(s); 65018261Slinton break; 65118261Slinton 65218261Slinton case SUBARRAY: 65318261Slinton printSubarray(s); 65418261Slinton break; 65518261Slinton 65616622Ssam case RECORD: 65716622Ssam printrecord(s); 65816622Ssam break; 65916622Ssam 66016622Ssam case VARNT: 66118261Slinton printf("[variant]"); 66216622Ssam break; 66316622Ssam 66416622Ssam case RANGE: 66516622Ssam printrange(s, n); 66616622Ssam break; 66716622Ssam 66818261Slinton /* 66918261Slinton * Unresolved opaque type. 67018261Slinton * Probably a pointer. 67118261Slinton */ 67218261Slinton case TYPEREF: 67318261Slinton a = pop(Address); 67418261Slinton printf("@%x", a); 67518261Slinton break; 67618261Slinton 67716622Ssam case FILET: 67818261Slinton a = pop(Address); 67918261Slinton if (a == 0) { 68018261Slinton printf("nil"); 68118261Slinton } else { 68218261Slinton printf("0x%x", a); 68318261Slinton } 68418261Slinton break; 68518261Slinton 68616622Ssam case PTR: 68716622Ssam a = pop(Address); 68816622Ssam if (a == 0) { 68916622Ssam printf("nil"); 69018261Slinton } else if (isCstring(s->type)) { 69118261Slinton printString(a, true); 69216622Ssam } else { 69316622Ssam printf("0x%x", a); 69416622Ssam } 69516622Ssam break; 69616622Ssam 69716622Ssam case SCAL: 69818261Slinton i = 0; 69918261Slinton popn(n, &i); 70018261Slinton printEnum(i, s); 70116622Ssam break; 70216622Ssam 70316622Ssam case FPROC: 70416622Ssam case FFUNC: 70516622Ssam a = pop(long); 70616622Ssam t = whatblock(a); 70716622Ssam if (t == nil) { 70818261Slinton printf("0x%x", a); 70916622Ssam } else { 71018261Slinton printname(stdout, t); 71116622Ssam } 71216622Ssam break; 71316622Ssam 71416622Ssam case SET: 71516622Ssam printSet(s); 71616622Ssam break; 71716622Ssam 71816622Ssam default: 71916622Ssam if (ord(s->class) < ord(BADUSE) or ord(s->class) > ord(TYPEREF)) { 72016622Ssam panic("printval: bad class %d", ord(s->class)); 72116622Ssam } 72216622Ssam printf("[%s]", classname(s)); 72316622Ssam break; 72416622Ssam } 72516622Ssam } 72616622Ssam 72716622Ssam /* 72818261Slinton * Print out a dynamic array. 72918261Slinton */ 73018261Slinton 73118261Slinton private Address printDynSlice(); 73218261Slinton 73318261Slinton private printDynarray (t) 73418261Slinton Symbol t; 73518261Slinton { 73618261Slinton Address base; 73718261Slinton integer n; 73818261Slinton Stack *savesp, *newsp; 73918261Slinton Symbol eltype; 74018261Slinton 74118261Slinton savesp = sp; 74218261Slinton sp -= (t->symvalue.ndims * sizeof(Word)); 74318261Slinton base = pop(Address); 74418261Slinton newsp = sp; 74518261Slinton sp = savesp; 74618261Slinton eltype = rtype(t->type); 74718261Slinton if (t->symvalue.ndims == 0) { 74818261Slinton if (ischar(eltype)) { 74918261Slinton printString(base, true); 75018261Slinton } else { 75118261Slinton printf("[dynarray @nocount]"); 75218261Slinton } 75318261Slinton } else { 75418261Slinton n = ((long *) sp)[-(t->symvalue.ndims)]; 75518261Slinton base = printDynSlice(base, n, t->symvalue.ndims, eltype, size(eltype)); 75618261Slinton } 75718261Slinton sp = newsp; 75818261Slinton } 75918261Slinton 76018261Slinton /* 76118261Slinton * Print out one dimension of a multi-dimension dynamic array. 76218261Slinton * 76318261Slinton * Return the address of the element that follows the printed elements. 76418261Slinton */ 76518261Slinton 76618261Slinton private Address printDynSlice (base, count, ndims, eltype, elsize) 76718261Slinton Address base; 76818261Slinton integer count, ndims; 76918261Slinton Symbol eltype; 77018261Slinton integer elsize; 77118261Slinton { 77218261Slinton Address b; 77318261Slinton integer i, n; 77418261Slinton char *slice; 77518261Slinton Stack *savesp; 77618261Slinton 77718261Slinton b = base; 77818261Slinton if (ndims > 1) { 77918261Slinton n = ((long *) sp)[-ndims + 1]; 78018261Slinton } 78118261Slinton if (ndims == 1 and ischar(eltype)) { 78218261Slinton slice = newarr(char, count); 78318261Slinton dread(slice, b, count); 78418261Slinton printf("\"%.*s\"", count, slice); 78518261Slinton dispose(slice); 78618261Slinton b += count; 78718261Slinton } else { 78818261Slinton printf("("); 78918261Slinton for (i = 0; i < count; i++) { 79018261Slinton if (i != 0) { 79118261Slinton printf(", "); 79218261Slinton } 79318261Slinton if (ndims == 1) { 79418261Slinton slice = newarr(char, elsize); 79518261Slinton dread(slice, b, elsize); 79618261Slinton savesp = sp; 79718261Slinton sp = slice + elsize; 79818261Slinton printval(eltype); 79918261Slinton sp = savesp; 80018261Slinton dispose(slice); 80118261Slinton b += elsize; 80218261Slinton } else { 80318261Slinton b = printDynSlice(b, n, ndims - 1, eltype, elsize); 80418261Slinton } 80518261Slinton } 80618261Slinton printf(")"); 80718261Slinton } 80818261Slinton return b; 80918261Slinton } 81018261Slinton 81118261Slinton private printSubarray (t) 81218261Slinton Symbol t; 81318261Slinton { 81418261Slinton printf("[subarray]"); 81518261Slinton } 81618261Slinton 81718261Slinton /* 81816622Ssam * Print out the value of a scalar (non-enumeration) type. 81916622Ssam */ 82016622Ssam 82116622Ssam private printrange (s, n) 82216622Ssam Symbol s; 82316622Ssam integer n; 82416622Ssam { 82516622Ssam double d; 82616622Ssam float f; 82716622Ssam integer i; 82816622Ssam 82916622Ssam if (s->symvalue.rangev.upper == 0 and s->symvalue.rangev.lower > 0) { 83016622Ssam if (n == sizeof(float)) { 83116622Ssam popn(n, &f); 83216622Ssam d = f; 83316622Ssam } else { 83416622Ssam popn(n, &d); 83516622Ssam } 83616622Ssam prtreal(d); 83716622Ssam } else { 83816622Ssam i = 0; 83916622Ssam popn(n, &i); 84018261Slinton printRangeVal(i, s); 84116622Ssam } 84216622Ssam } 84316622Ssam 84416622Ssam /* 84516622Ssam * Print out a set. 84616622Ssam */ 84716622Ssam 84816622Ssam private printSet (s) 84916622Ssam Symbol s; 85016622Ssam { 85116622Ssam Symbol t; 85216622Ssam integer nbytes; 85316622Ssam 85416622Ssam nbytes = size(s); 85516622Ssam t = rtype(s->type); 85616622Ssam printf("{"); 85716622Ssam sp -= nbytes; 85816622Ssam if (t->class == SCAL) { 85916622Ssam printSetOfEnum(t); 86016622Ssam } else if (t->class == RANGE) { 86116622Ssam printSetOfRange(t); 86216622Ssam } else { 86316622Ssam panic("expected range or enumerated base type for set"); 86416622Ssam } 86516622Ssam printf("}"); 86616622Ssam } 86716622Ssam 86816622Ssam /* 86916622Ssam * Print out a set of an enumeration. 87016622Ssam */ 87116622Ssam 87216622Ssam private printSetOfEnum (t) 87316622Ssam Symbol t; 87416622Ssam { 87516622Ssam register Symbol e; 87616622Ssam register integer i, j, *p; 87716622Ssam boolean first; 87816622Ssam 87916622Ssam p = (int *) sp; 88016622Ssam i = *p; 88116622Ssam j = 0; 88216622Ssam e = t->chain; 88316622Ssam first = true; 88416622Ssam while (e != nil) { 88516622Ssam if ((i&1) == 1) { 88616622Ssam if (first) { 88716622Ssam first = false; 88816622Ssam printf("%s", symname(e)); 88916622Ssam } else { 89016622Ssam printf(", %s", symname(e)); 89116622Ssam } 89216622Ssam } 89316622Ssam i >>= 1; 89416622Ssam ++j; 89516622Ssam if (j >= sizeof(integer)*BITSPERBYTE) { 89616622Ssam j = 0; 89716622Ssam ++p; 89816622Ssam i = *p; 89916622Ssam } 90016622Ssam e = e->chain; 90116622Ssam } 90216622Ssam } 90316622Ssam 90416622Ssam /* 90516622Ssam * Print out a set of a subrange type. 90616622Ssam */ 90716622Ssam 90816622Ssam private printSetOfRange (t) 90916622Ssam Symbol t; 91016622Ssam { 91116622Ssam register integer i, j, *p; 91216622Ssam long v; 91316622Ssam boolean first; 91416622Ssam 91516622Ssam p = (int *) sp; 91616622Ssam i = *p; 91716622Ssam j = 0; 91816622Ssam v = t->symvalue.rangev.lower; 91916622Ssam first = true; 92016622Ssam while (v <= t->symvalue.rangev.upper) { 92116622Ssam if ((i&1) == 1) { 92216622Ssam if (first) { 92316622Ssam first = false; 92416622Ssam printf("%ld", v); 92516622Ssam } else { 92616622Ssam printf(", %ld", v); 92716622Ssam } 92816622Ssam } 92916622Ssam i >>= 1; 93016622Ssam ++j; 93116622Ssam if (j >= sizeof(integer)*BITSPERBYTE) { 93216622Ssam j = 0; 93316622Ssam ++p; 93416622Ssam i = *p; 93516622Ssam } 93616622Ssam ++v; 93716622Ssam } 93816622Ssam } 93916622Ssam 94016622Ssam /* 94118261Slinton * Construct a node for subscripting a dynamic or subarray. 94218261Slinton * The list of indices is left for processing in evalaref, 94318261Slinton * unlike normal subscripting in which the list is expanded 94418261Slinton * across individual INDEX nodes. 94518261Slinton */ 94618261Slinton 94718261Slinton private Node dynref (a, t, slist) 94818261Slinton Node a; 94918261Slinton Symbol t; 95018261Slinton Node slist; 95118261Slinton { 95218261Slinton Node p, r; 95318261Slinton integer n; 95418261Slinton 95518261Slinton p = slist; 95618261Slinton n = 0; 95718261Slinton while (p != nil) { 95818261Slinton if (not compatible(p->value.arg[0]->nodetype, t_int)) { 95918261Slinton suberror("subscript \"", p->value.arg[0], "\" is the wrong type"); 96018261Slinton } 96118261Slinton ++n; 96218261Slinton p = p->value.arg[1]; 96318261Slinton } 96418261Slinton if (n > t->symvalue.ndims and (t->symvalue.ndims != 0 or n != 1)) { 96518261Slinton suberror("too many subscripts for ", a, nil); 96618261Slinton } else if (n < t->symvalue.ndims) { 96718261Slinton suberror("not enough subscripts for ", a, nil); 96818261Slinton } 96918261Slinton r = build(O_INDEX, a, slist); 97018261Slinton r->nodetype = rtype(t->type); 97118261Slinton return r; 97218261Slinton } 97318261Slinton 97418261Slinton /* 97516622Ssam * Construct a node for subscripting. 97616622Ssam */ 97716622Ssam 97816622Ssam public Node modula2_buildaref (a, slist) 97916622Ssam Node a, slist; 98016622Ssam { 98116622Ssam register Symbol t; 98216622Ssam register Node p; 98318261Slinton Symbol eltype; 98416622Ssam Node esub, r; 98518261Slinton integer n; 98616622Ssam 98716622Ssam t = rtype(a->nodetype); 98833326Sdonn switch (t->class) { 98933326Sdonn case OPENARRAY: 99033326Sdonn case DYNARRAY: 99133326Sdonn case SUBARRAY: 99233326Sdonn r = dynref(a, t, slist); 99333326Sdonn break; 99433326Sdonn 99533326Sdonn case ARRAY: 99633326Sdonn r = a; 99733326Sdonn eltype = rtype(t->type); 99833326Sdonn p = slist; 99933326Sdonn t = t->chain; 100033326Sdonn while (p != nil and t != nil) { 100133326Sdonn esub = p->value.arg[0]; 100233326Sdonn if (not compatible(rtype(t), rtype(esub->nodetype))) { 100333326Sdonn suberror("subscript \"", esub, "\" is the wrong type"); 100433326Sdonn } 100533326Sdonn r = build(O_INDEX, r, esub); 100633326Sdonn r->nodetype = eltype; 100733326Sdonn p = p->value.arg[1]; 100833326Sdonn t = t->chain; 100916622Ssam } 101033326Sdonn if (p != nil) { 101133326Sdonn suberror("too many subscripts for ", a, nil); 101233326Sdonn } else if (t != nil) { 101333326Sdonn suberror("not enough subscripts for ", a, nil); 101433326Sdonn } 101533326Sdonn break; 101633326Sdonn 101733326Sdonn default: 101833326Sdonn suberror("\"", a, "\" is not an array"); 101933326Sdonn break; 102016622Ssam } 102116622Ssam return r; 102216622Ssam } 102316622Ssam 102416622Ssam /* 102518261Slinton * Subscript usage error reporting. 102618261Slinton */ 102718261Slinton 102818261Slinton private suberror (s1, e1, s2) 102918261Slinton String s1, s2; 103018261Slinton Node e1; 103118261Slinton { 103218261Slinton beginerrmsg(); 103318261Slinton if (s1 != nil) { 103418261Slinton fprintf(stderr, s1); 103518261Slinton } 103618261Slinton if (e1 != nil) { 103718261Slinton prtree(stderr, e1); 103818261Slinton } 103918261Slinton if (s2 != nil) { 104018261Slinton fprintf(stderr, s2); 104118261Slinton } 104218261Slinton enderrmsg(); 104318261Slinton } 104418261Slinton 104518261Slinton /* 104618261Slinton * Check that a subscript value is in the appropriate range. 104718261Slinton */ 104818261Slinton 104918261Slinton private subchk (value, lower, upper) 105018261Slinton long value, lower, upper; 105118261Slinton { 105218261Slinton if (value < lower or value > upper) { 105318261Slinton error("subscript value %d out of range [%d..%d]", value, lower, upper); 105418261Slinton } 105518261Slinton } 105618261Slinton 105718261Slinton /* 105818261Slinton * Compute the offset for subscripting a dynamic array. 105918261Slinton */ 106018261Slinton 106118261Slinton private getdynoff (ndims, sub) 106218261Slinton integer ndims; 106318261Slinton long *sub; 106418261Slinton { 106518261Slinton long k, off, *count; 106618261Slinton 106718261Slinton count = (long *) sp; 106818261Slinton off = 0; 106918261Slinton for (k = 0; k < ndims - 1; k++) { 107018261Slinton subchk(sub[k], 0, count[k] - 1); 107118261Slinton off += (sub[k] * count[k+1]); 107218261Slinton } 107318261Slinton subchk(sub[ndims - 1], 0, count[ndims - 1] - 1); 107418261Slinton return off + sub[ndims - 1]; 107518261Slinton } 107618261Slinton 107718261Slinton /* 107818261Slinton * Compute the offset associated with a subarray. 107918261Slinton */ 108018261Slinton 108118261Slinton private getsuboff (ndims, sub) 108218261Slinton integer ndims; 108318261Slinton long *sub; 108418261Slinton { 108518261Slinton long k, off; 108618261Slinton struct subarrayinfo { 108718261Slinton long count; 108818261Slinton long mult; 108918261Slinton } *info; 109018261Slinton 109118261Slinton info = (struct subarrayinfo *) sp; 109218261Slinton off = 0; 109318261Slinton for (k = 0; k < ndims; k++) { 109418261Slinton subchk(sub[k], 0, info[k].count - 1); 109518261Slinton off += sub[k] * info[k].mult; 109618261Slinton } 109718261Slinton return off; 109818261Slinton } 109918261Slinton 110018261Slinton /* 110116622Ssam * Evaluate a subscript index. 110216622Ssam */ 110316622Ssam 110418261Slinton public modula2_evalaref (s, base, i) 110516622Ssam Symbol s; 110618261Slinton Address base; 110716622Ssam long i; 110816622Ssam { 110918261Slinton Symbol t; 111018261Slinton long lb, ub, off; 111118261Slinton long *sub; 111218261Slinton Address b; 111316622Ssam 111418261Slinton t = rtype(s); 111518261Slinton if (t->class == ARRAY) { 111618261Slinton findbounds(rtype(t->chain), &lb, &ub); 111718261Slinton if (i < lb or i > ub) { 111818261Slinton error("subscript %d out of range [%d..%d]", i, lb, ub); 111918261Slinton } 112018261Slinton push(long, base + (i - lb) * size(t->type)); 112133326Sdonn } else if ((t->class == OPENARRAY or t->class == DYNARRAY) and 112233326Sdonn t->symvalue.ndims == 0 112333326Sdonn ) { 112418261Slinton push(long, base + i * size(t->type)); 112533326Sdonn } else if (t->class == OPENARRAY or t->class == DYNARRAY or 112633326Sdonn t->class == SUBARRAY 112733326Sdonn ) { 112818261Slinton push(long, i); 112918261Slinton sub = (long *) (sp - (t->symvalue.ndims * sizeof(long))); 113018261Slinton rpush(base, size(t)); 113118261Slinton sp -= (t->symvalue.ndims * sizeof(long)); 113218261Slinton b = pop(Address); 113318261Slinton sp += sizeof(Address); 113418261Slinton if (t->class == SUBARRAY) { 113518261Slinton off = getsuboff(t->symvalue.ndims, sub); 113618261Slinton } else { 113718261Slinton off = getdynoff(t->symvalue.ndims, sub); 113818261Slinton } 113918261Slinton sp = (Stack *) sub; 114018261Slinton push(long, b + off * size(t->type)); 114118261Slinton } else { 114218261Slinton error("[internal error: expected array in evalaref]"); 114316622Ssam } 114416622Ssam } 114516622Ssam 114616622Ssam /* 114716622Ssam * Initial Modula-2 type information. 114816622Ssam */ 114916622Ssam 115016622Ssam #define NTYPES 12 115116622Ssam 115216622Ssam private Symbol inittype[NTYPES + 1]; 115316622Ssam 115416622Ssam private addType (n, s, lower, upper) 115516622Ssam integer n; 115616622Ssam String s; 115716622Ssam long lower, upper; 115816622Ssam { 115916622Ssam register Symbol t; 116016622Ssam 116116622Ssam if (n > NTYPES) { 116216622Ssam panic("initial Modula-2 type number too large for '%s'", s); 116316622Ssam } 116416622Ssam t = insert(identname(s, true)); 116516622Ssam t->language = mod2; 116616622Ssam t->class = TYPE; 116716622Ssam t->type = newSymbol(nil, 0, RANGE, t, nil); 116816622Ssam t->type->symvalue.rangev.lower = lower; 116916622Ssam t->type->symvalue.rangev.upper = upper; 117016622Ssam t->type->language = mod2; 117116622Ssam inittype[n] = t; 117216622Ssam } 117316622Ssam 117416622Ssam private initModTypes () 117516622Ssam { 117616622Ssam addType(1, "integer", 0x80000000L, 0x7fffffffL); 117716622Ssam addType(2, "char", 0L, 255L); 117816622Ssam addType(3, "boolean", 0L, 1L); 117916622Ssam addType(4, "unsigned", 0L, 0xffffffffL); 118016622Ssam addType(5, "real", 4L, 0L); 118116622Ssam addType(6, "longreal", 8L, 0L); 118216622Ssam addType(7, "word", 0L, 0xffffffffL); 118316622Ssam addType(8, "byte", 0L, 255L); 118416622Ssam addType(9, "address", 0L, 0xffffffffL); 118516622Ssam addType(10, "file", 0L, 0xffffffffL); 118616622Ssam addType(11, "process", 0L, 0xffffffffL); 118716622Ssam addType(12, "cardinal", 0L, 0x7fffffffL); 118816622Ssam } 118916622Ssam 119016622Ssam /* 119116622Ssam * Initialize typetable. 119216622Ssam */ 119316622Ssam 119416622Ssam public modula2_modinit (typetable) 119516622Ssam Symbol typetable[]; 119616622Ssam { 119716622Ssam register integer i; 119816622Ssam 119916622Ssam if (not initialized) { 120016622Ssam initModTypes(); 120118261Slinton initialized = true; 120216622Ssam } 120316622Ssam for (i = 1; i <= NTYPES; i++) { 120416622Ssam typetable[i] = inittype[i]; 120516622Ssam } 120616622Ssam } 120716622Ssam 120816622Ssam public boolean modula2_hasmodules () 120916622Ssam { 121016622Ssam return true; 121116622Ssam } 121216622Ssam 121316622Ssam public boolean modula2_passaddr (param, exprtype) 121416622Ssam Symbol param, exprtype; 121516622Ssam { 121616622Ssam return false; 121716622Ssam } 1218