|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1983 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #ifndef lint ! 8: static char sccsid[] = "@(#)modula-2.c 5.2 (Berkeley) 1/12/88"; ! 9: #endif not lint ! 10: ! 11: /* ! 12: * Modula-2 specific symbol routines. ! 13: */ ! 14: ! 15: static char rcsid[] = "$Header: modula-2.c,v 1.2 87/03/26 20:12:54 donn Exp $"; ! 16: ! 17: #include "defs.h" ! 18: #include "symbols.h" ! 19: #include "modula-2.h" ! 20: #include "languages.h" ! 21: #include "tree.h" ! 22: #include "eval.h" ! 23: #include "mappings.h" ! 24: #include "process.h" ! 25: #include "runtime.h" ! 26: #include "machine.h" ! 27: ! 28: #ifndef public ! 29: #endif ! 30: ! 31: private Language mod2; ! 32: private boolean initialized; ! 33: ! 34: ! 35: #define ischar(t) ( \ ! 36: (t) == t_char->type or \ ! 37: ((t)->class == RANGE and istypename((t)->type, "char")) \ ! 38: ) ! 39: ! 40: /* ! 41: * Initialize Modula-2 information. ! 42: */ ! 43: ! 44: public modula2_init () ! 45: { ! 46: mod2 = language_define("modula-2", ".mod"); ! 47: language_setop(mod2, L_PRINTDECL, modula2_printdecl); ! 48: language_setop(mod2, L_PRINTVAL, modula2_printval); ! 49: language_setop(mod2, L_TYPEMATCH, modula2_typematch); ! 50: language_setop(mod2, L_BUILDAREF, modula2_buildaref); ! 51: language_setop(mod2, L_EVALAREF, modula2_evalaref); ! 52: language_setop(mod2, L_MODINIT, modula2_modinit); ! 53: language_setop(mod2, L_HASMODULES, modula2_hasmodules); ! 54: language_setop(mod2, L_PASSADDR, modula2_passaddr); ! 55: initialized = false; ! 56: } ! 57: ! 58: /* ! 59: * Typematch tests if two types are compatible. The issue ! 60: * is a bit complicated, so several subfunctions are used for ! 61: * various kinds of compatibility. ! 62: */ ! 63: ! 64: private boolean builtinmatch (t1, t2) ! 65: register Symbol t1, t2; ! 66: { ! 67: boolean b; ! 68: ! 69: b = (boolean) ( ! 70: ( ! 71: t2 == t_int->type and t1->class == RANGE and ! 72: ( ! 73: istypename(t1->type, "integer") or ! 74: istypename(t1->type, "cardinal") ! 75: ) ! 76: ) or ( ! 77: t2 == t_char->type and ! 78: t1->class == RANGE and istypename(t1->type, "char") ! 79: ) or ( ! 80: t2 == t_real->type and ! 81: t1->class == RANGE and ( ! 82: istypename(t1->type, "real") or ! 83: istypename(t1->type, "longreal") ! 84: ) ! 85: ) or ( ! 86: t2 == t_boolean->type and ! 87: t1->class == RANGE and istypename(t1->type, "boolean") ! 88: ) ! 89: ); ! 90: return b; ! 91: } ! 92: ! 93: private boolean nilMatch (t1, t2) ! 94: register Symbol t1, t2; ! 95: { ! 96: boolean b; ! 97: ! 98: b = (boolean) ( ! 99: (t1 == t_nil and t2->class == PTR) or ! 100: (t1->class == PTR and t2 == t_nil) ! 101: ); ! 102: return b; ! 103: } ! 104: ! 105: private boolean enumMatch (t1, t2) ! 106: register Symbol t1, t2; ! 107: { ! 108: boolean b; ! 109: ! 110: b = (boolean) ( ! 111: (t1->class == SCAL and t2->class == CONST and t2->type == t1) or ! 112: (t1->class == CONST and t2->class == SCAL and t1->type == t2) ! 113: ); ! 114: return b; ! 115: } ! 116: ! 117: private boolean openArrayMatch (t1, t2) ! 118: register Symbol t1, t2; ! 119: { ! 120: boolean b; ! 121: ! 122: b = (boolean) ( ! 123: ( ! 124: t1->class == OPENARRAY and t1->symvalue.ndims == 1 and ! 125: t2->class == ARRAY and ! 126: compatible(rtype(t2->chain)->type, t_int) and ! 127: compatible(t1->type, t2->type) ! 128: ) or ( ! 129: t2->class == OPENARRAY and t2->symvalue.ndims == 1 and ! 130: t1->class == ARRAY and ! 131: compatible(rtype(t1->chain)->type, t_int) and ! 132: compatible(t1->type, t2->type) ! 133: ) ! 134: ); ! 135: return b; ! 136: } ! 137: ! 138: private boolean isConstString (t) ! 139: register Symbol t; ! 140: { ! 141: boolean b; ! 142: ! 143: b = (boolean) ( ! 144: t->language == primlang and t->class == ARRAY and t->type == t_char ! 145: ); ! 146: return b; ! 147: } ! 148: ! 149: private boolean stringArrayMatch (t1, t2) ! 150: register Symbol t1, t2; ! 151: { ! 152: boolean b; ! 153: ! 154: b = (boolean) ( ! 155: ( ! 156: isConstString(t1) and ! 157: t2->class == ARRAY and compatible(t2->type, t_char->type) ! 158: ) or ( ! 159: isConstString(t2) and ! 160: t1->class == ARRAY and compatible(t1->type, t_char->type) ! 161: ) ! 162: ); ! 163: return b; ! 164: } ! 165: ! 166: public boolean modula2_typematch (type1, type2) ! 167: Symbol type1, type2; ! 168: { ! 169: boolean b; ! 170: Symbol t1, t2, tmp; ! 171: ! 172: t1 = rtype(type1); ! 173: t2 = rtype(type2); ! 174: if (t1 == t2) { ! 175: b = true; ! 176: } else { ! 177: if (t1 == t_char->type or t1 == t_int->type or ! 178: t1 == t_real->type or t1 == t_boolean->type ! 179: ) { ! 180: tmp = t1; ! 181: t1 = t2; ! 182: t2 = tmp; ! 183: } ! 184: b = (Boolean) ( ! 185: builtinmatch(t1, t2) or ! 186: nilMatch(t1, t2) or enumMatch(t1, t2) or ! 187: openArrayMatch(t1, t2) or stringArrayMatch(t1, t2) ! 188: ); ! 189: } ! 190: return b; ! 191: } ! 192: ! 193: /* ! 194: * Indent n spaces. ! 195: */ ! 196: ! 197: private indent (n) ! 198: int n; ! 199: { ! 200: if (n > 0) { ! 201: printf("%*c", n, ' '); ! 202: } ! 203: } ! 204: ! 205: public modula2_printdecl (s) ! 206: Symbol s; ! 207: { ! 208: register Symbol t; ! 209: Boolean semicolon; ! 210: ! 211: semicolon = true; ! 212: if (s->class == TYPEREF) { ! 213: resolveRef(t); ! 214: } ! 215: switch (s->class) { ! 216: case CONST: ! 217: if (s->type->class == SCAL) { ! 218: semicolon = false; ! 219: printf("enumeration constant with value "); ! 220: eval(s->symvalue.constval); ! 221: modula2_printval(s); ! 222: } else { ! 223: printf("const %s = ", symname(s)); ! 224: eval(s->symvalue.constval); ! 225: modula2_printval(s); ! 226: } ! 227: break; ! 228: ! 229: case TYPE: ! 230: printf("type %s = ", symname(s)); ! 231: printtype(s, s->type, 0); ! 232: break; ! 233: ! 234: case TYPEREF: ! 235: printf("type %s", symname(s)); ! 236: break; ! 237: ! 238: case VAR: ! 239: if (isparam(s)) { ! 240: printf("(parameter) %s : ", symname(s)); ! 241: } else { ! 242: printf("var %s : ", symname(s)); ! 243: } ! 244: printtype(s, s->type, 0); ! 245: break; ! 246: ! 247: case REF: ! 248: printf("(var parameter) %s : ", symname(s)); ! 249: printtype(s, s->type, 0); ! 250: break; ! 251: ! 252: case RANGE: ! 253: case ARRAY: ! 254: case OPENARRAY: ! 255: case DYNARRAY: ! 256: case SUBARRAY: ! 257: case RECORD: ! 258: case VARNT: ! 259: case PTR: ! 260: printtype(s, s, 0); ! 261: semicolon = false; ! 262: break; ! 263: ! 264: case FVAR: ! 265: printf("(function variable) %s : ", symname(s)); ! 266: printtype(s, s->type, 0); ! 267: break; ! 268: ! 269: case FIELD: ! 270: printf("(field) %s : ", symname(s)); ! 271: printtype(s, s->type, 0); ! 272: break; ! 273: ! 274: case PROC: ! 275: printf("procedure %s", symname(s)); ! 276: listparams(s); ! 277: break; ! 278: ! 279: case PROG: ! 280: printf("program %s", symname(s)); ! 281: listparams(s); ! 282: break; ! 283: ! 284: case FUNC: ! 285: printf("procedure %s", symname(s)); ! 286: listparams(s); ! 287: printf(" : "); ! 288: printtype(s, s->type, 0); ! 289: break; ! 290: ! 291: case MODULE: ! 292: printf("module %s", symname(s)); ! 293: break; ! 294: ! 295: default: ! 296: printf("[%s]", classname(s)); ! 297: break; ! 298: } ! 299: if (semicolon) { ! 300: putchar(';'); ! 301: } ! 302: putchar('\n'); ! 303: } ! 304: ! 305: /* ! 306: * Recursive whiz-bang procedure to print the type portion ! 307: * of a declaration. ! 308: * ! 309: * The symbol associated with the type is passed to allow ! 310: * searching for type names without getting "type blah = blah". ! 311: */ ! 312: ! 313: private printtype (s, t, n) ! 314: Symbol s; ! 315: Symbol t; ! 316: int n; ! 317: { ! 318: Symbol tmp; ! 319: int i; ! 320: ! 321: if (t->class == TYPEREF) { ! 322: resolveRef(t); ! 323: } ! 324: switch (t->class) { ! 325: case VAR: ! 326: case CONST: ! 327: case FUNC: ! 328: case PROC: ! 329: panic("printtype: class %s", classname(t)); ! 330: break; ! 331: ! 332: case ARRAY: ! 333: printf("array["); ! 334: tmp = t->chain; ! 335: if (tmp != nil) { ! 336: for (;;) { ! 337: printtype(tmp, tmp, n); ! 338: tmp = tmp->chain; ! 339: if (tmp == nil) { ! 340: break; ! 341: } ! 342: printf(", "); ! 343: } ! 344: } ! 345: printf("] of "); ! 346: printtype(t, t->type, n); ! 347: break; ! 348: ! 349: case OPENARRAY: ! 350: printf("array of "); ! 351: for (i = 1; i < t->symvalue.ndims; i++) { ! 352: printf("array of "); ! 353: } ! 354: printtype(t, t->type, n); ! 355: break; ! 356: ! 357: case DYNARRAY: ! 358: printf("dynarray of "); ! 359: for (i = 1; i < t->symvalue.ndims; i++) { ! 360: printf("array of "); ! 361: } ! 362: printtype(t, t->type, n); ! 363: break; ! 364: ! 365: case SUBARRAY: ! 366: printf("subarray of "); ! 367: for (i = 1; i < t->symvalue.ndims; i++) { ! 368: printf("array of "); ! 369: } ! 370: printtype(t, t->type, n); ! 371: break; ! 372: ! 373: case RECORD: ! 374: printRecordDecl(t, n); ! 375: break; ! 376: ! 377: case FIELD: ! 378: if (t->chain != nil) { ! 379: printtype(t->chain, t->chain, n); ! 380: } ! 381: printf("\t%s : ", symname(t)); ! 382: printtype(t, t->type, n); ! 383: printf(";\n"); ! 384: break; ! 385: ! 386: case RANGE: ! 387: printRangeDecl(t); ! 388: break; ! 389: ! 390: case PTR: ! 391: printf("pointer to "); ! 392: printtype(t, t->type, n); ! 393: break; ! 394: ! 395: case TYPE: ! 396: if (t->name != nil and ident(t->name)[0] != '\0') { ! 397: printname(stdout, t); ! 398: } else { ! 399: printtype(t, t->type, n); ! 400: } ! 401: break; ! 402: ! 403: case SCAL: ! 404: printEnumDecl(t, n); ! 405: break; ! 406: ! 407: case SET: ! 408: printf("set of "); ! 409: printtype(t, t->type, n); ! 410: break; ! 411: ! 412: case TYPEREF: ! 413: break; ! 414: ! 415: case FPROC: ! 416: case FFUNC: ! 417: printf("procedure"); ! 418: break; ! 419: ! 420: default: ! 421: printf("[%s]", classname(t)); ! 422: break; ! 423: } ! 424: } ! 425: ! 426: /* ! 427: * Print out a record declaration. ! 428: */ ! 429: ! 430: private printRecordDecl (t, n) ! 431: Symbol t; ! 432: int n; ! 433: { ! 434: register Symbol f; ! 435: ! 436: if (t->chain == nil) { ! 437: printf("record end"); ! 438: } else { ! 439: printf("record\n"); ! 440: for (f = t->chain; f != nil; f = f->chain) { ! 441: indent(n+4); ! 442: printf("%s : ", symname(f)); ! 443: printtype(f->type, f->type, n+4); ! 444: printf(";\n"); ! 445: } ! 446: indent(n); ! 447: printf("end"); ! 448: } ! 449: } ! 450: ! 451: /* ! 452: * Print out the declaration of a range type. ! 453: */ ! 454: ! 455: private printRangeDecl (t) ! 456: Symbol t; ! 457: { ! 458: long r0, r1; ! 459: ! 460: r0 = t->symvalue.rangev.lower; ! 461: r1 = t->symvalue.rangev.upper; ! 462: if (ischar(t)) { ! 463: if (r0 < 0x20 or r0 > 0x7e) { ! 464: printf("%ld..", r0); ! 465: } else { ! 466: printf("'%c'..", (char) r0); ! 467: } ! 468: if (r1 < 0x20 or r1 > 0x7e) { ! 469: printf("\\%lo", r1); ! 470: } else { ! 471: printf("'%c'", (char) r1); ! 472: } ! 473: } else if (r0 > 0 and r1 == 0) { ! 474: printf("%ld byte real", r0); ! 475: } else if (r0 >= 0) { ! 476: printf("%lu..%lu", r0, r1); ! 477: } else { ! 478: printf("%ld..%ld", r0, r1); ! 479: } ! 480: } ! 481: ! 482: /* ! 483: * Print out an enumeration declaration. ! 484: */ ! 485: ! 486: private printEnumDecl (e, n) ! 487: Symbol e; ! 488: int n; ! 489: { ! 490: Symbol t; ! 491: ! 492: printf("("); ! 493: t = e->chain; ! 494: if (t != nil) { ! 495: printf("%s", symname(t)); ! 496: t = t->chain; ! 497: while (t != nil) { ! 498: printf(", %s", symname(t)); ! 499: t = t->chain; ! 500: } ! 501: } ! 502: printf(")"); ! 503: } ! 504: ! 505: /* ! 506: * List the parameters of a procedure or function. ! 507: * No attempt is made to combine like types. ! 508: */ ! 509: ! 510: private listparams (s) ! 511: Symbol s; ! 512: { ! 513: Symbol t; ! 514: ! 515: if (s->chain != nil) { ! 516: putchar('('); ! 517: for (t = s->chain; t != nil; t = t->chain) { ! 518: switch (t->class) { ! 519: case REF: ! 520: printf("var "); ! 521: break; ! 522: ! 523: case FPROC: ! 524: case FFUNC: ! 525: printf("procedure "); ! 526: break; ! 527: ! 528: case VAR: ! 529: break; ! 530: ! 531: default: ! 532: panic("unexpected class %d for parameter", t->class); ! 533: } ! 534: printf("%s", symname(t)); ! 535: if (s->class == PROG) { ! 536: printf(", "); ! 537: } else { ! 538: printf(" : "); ! 539: printtype(t, t->type, 0); ! 540: if (t->chain != nil) { ! 541: printf("; "); ! 542: } ! 543: } ! 544: } ! 545: putchar(')'); ! 546: } ! 547: } ! 548: ! 549: /* ! 550: * Test if a pointer type should be treated as a null-terminated string. ! 551: * The type given is the type that is pointed to. ! 552: */ ! 553: ! 554: private boolean isCstring (type) ! 555: Symbol type; ! 556: { ! 557: boolean b; ! 558: register Symbol a, t; ! 559: ! 560: a = rtype(type); ! 561: if (a->class == ARRAY) { ! 562: t = rtype(a->chain); ! 563: b = (boolean) ( ! 564: t->class == RANGE and istypename(a->type, "char") and ! 565: (t->symvalue.rangev.upper - t->symvalue.rangev.lower + 1) <= 0 ! 566: ); ! 567: } else { ! 568: b = false; ! 569: } ! 570: return b; ! 571: } ! 572: ! 573: /* ! 574: * Modula 2 interface to printval. ! 575: */ ! 576: ! 577: public modula2_printval (s) ! 578: Symbol s; ! 579: { ! 580: prval(s, size(s)); ! 581: } ! 582: ! 583: /* ! 584: * Print out the value on the top of the expression stack ! 585: * in the format for the type of the given symbol, assuming ! 586: * the size of the object is n bytes. ! 587: */ ! 588: ! 589: private prval (s, n) ! 590: Symbol s; ! 591: integer n; ! 592: { ! 593: Symbol t; ! 594: Address a; ! 595: integer len; ! 596: double r; ! 597: integer i; ! 598: ! 599: if (s->class == TYPEREF) { ! 600: resolveRef(s); ! 601: } ! 602: switch (s->class) { ! 603: case CONST: ! 604: case TYPE: ! 605: case REF: ! 606: case VAR: ! 607: case FVAR: ! 608: case TAG: ! 609: prval(s->type, n); ! 610: break; ! 611: ! 612: case FIELD: ! 613: if (isbitfield(s)) { ! 614: i = extractField(s); ! 615: t = rtype(s->type); ! 616: if (t->class == SCAL) { ! 617: printEnum(i, t); ! 618: } else { ! 619: printRangeVal(i, t); ! 620: } ! 621: } else { ! 622: prval(s->type, n); ! 623: } ! 624: break; ! 625: ! 626: case ARRAY: ! 627: t = rtype(s->type); ! 628: if (ischar(t)) { ! 629: len = size(s); ! 630: sp -= len; ! 631: printf("\"%.*s\"", len, sp); ! 632: break; ! 633: } else { ! 634: printarray(s); ! 635: } ! 636: break; ! 637: ! 638: case OPENARRAY: ! 639: case DYNARRAY: ! 640: printDynarray(s); ! 641: break; ! 642: ! 643: case SUBARRAY: ! 644: printSubarray(s); ! 645: break; ! 646: ! 647: case RECORD: ! 648: printrecord(s); ! 649: break; ! 650: ! 651: case VARNT: ! 652: printf("[variant]"); ! 653: break; ! 654: ! 655: case RANGE: ! 656: printrange(s, n); ! 657: break; ! 658: ! 659: /* ! 660: * Unresolved opaque type. ! 661: * Probably a pointer. ! 662: */ ! 663: case TYPEREF: ! 664: a = pop(Address); ! 665: printf("@%x", a); ! 666: break; ! 667: ! 668: case FILET: ! 669: a = pop(Address); ! 670: if (a == 0) { ! 671: printf("nil"); ! 672: } else { ! 673: printf("0x%x", a); ! 674: } ! 675: break; ! 676: ! 677: case PTR: ! 678: a = pop(Address); ! 679: if (a == 0) { ! 680: printf("nil"); ! 681: } else if (isCstring(s->type)) { ! 682: printString(a, true); ! 683: } else { ! 684: printf("0x%x", a); ! 685: } ! 686: break; ! 687: ! 688: case SCAL: ! 689: i = 0; ! 690: popn(n, &i); ! 691: printEnum(i, s); ! 692: break; ! 693: ! 694: case FPROC: ! 695: case FFUNC: ! 696: a = pop(long); ! 697: t = whatblock(a); ! 698: if (t == nil) { ! 699: printf("0x%x", a); ! 700: } else { ! 701: printname(stdout, t); ! 702: } ! 703: break; ! 704: ! 705: case SET: ! 706: printSet(s); ! 707: break; ! 708: ! 709: default: ! 710: if (ord(s->class) < ord(BADUSE) or ord(s->class) > ord(TYPEREF)) { ! 711: panic("printval: bad class %d", ord(s->class)); ! 712: } ! 713: printf("[%s]", classname(s)); ! 714: break; ! 715: } ! 716: } ! 717: ! 718: /* ! 719: * Print out a dynamic array. ! 720: */ ! 721: ! 722: private Address printDynSlice(); ! 723: ! 724: private printDynarray (t) ! 725: Symbol t; ! 726: { ! 727: Address base; ! 728: integer n; ! 729: Stack *savesp, *newsp; ! 730: Symbol eltype; ! 731: ! 732: savesp = sp; ! 733: sp -= (t->symvalue.ndims * sizeof(Word)); ! 734: base = pop(Address); ! 735: newsp = sp; ! 736: sp = savesp; ! 737: eltype = rtype(t->type); ! 738: if (t->symvalue.ndims == 0) { ! 739: if (ischar(eltype)) { ! 740: printString(base, true); ! 741: } else { ! 742: printf("[dynarray @nocount]"); ! 743: } ! 744: } else { ! 745: n = ((long *) sp)[-(t->symvalue.ndims)]; ! 746: base = printDynSlice(base, n, t->symvalue.ndims, eltype, size(eltype)); ! 747: } ! 748: sp = newsp; ! 749: } ! 750: ! 751: /* ! 752: * Print out one dimension of a multi-dimension dynamic array. ! 753: * ! 754: * Return the address of the element that follows the printed elements. ! 755: */ ! 756: ! 757: private Address printDynSlice (base, count, ndims, eltype, elsize) ! 758: Address base; ! 759: integer count, ndims; ! 760: Symbol eltype; ! 761: integer elsize; ! 762: { ! 763: Address b; ! 764: integer i, n; ! 765: char *slice; ! 766: Stack *savesp; ! 767: ! 768: b = base; ! 769: if (ndims > 1) { ! 770: n = ((long *) sp)[-ndims + 1]; ! 771: } ! 772: if (ndims == 1 and ischar(eltype)) { ! 773: slice = newarr(char, count); ! 774: dread(slice, b, count); ! 775: printf("\"%.*s\"", count, slice); ! 776: dispose(slice); ! 777: b += count; ! 778: } else { ! 779: printf("("); ! 780: for (i = 0; i < count; i++) { ! 781: if (i != 0) { ! 782: printf(", "); ! 783: } ! 784: if (ndims == 1) { ! 785: slice = newarr(char, elsize); ! 786: dread(slice, b, elsize); ! 787: savesp = sp; ! 788: sp = slice + elsize; ! 789: printval(eltype); ! 790: sp = savesp; ! 791: dispose(slice); ! 792: b += elsize; ! 793: } else { ! 794: b = printDynSlice(b, n, ndims - 1, eltype, elsize); ! 795: } ! 796: } ! 797: printf(")"); ! 798: } ! 799: return b; ! 800: } ! 801: ! 802: private printSubarray (t) ! 803: Symbol t; ! 804: { ! 805: printf("[subarray]"); ! 806: } ! 807: ! 808: /* ! 809: * Print out the value of a scalar (non-enumeration) type. ! 810: */ ! 811: ! 812: private printrange (s, n) ! 813: Symbol s; ! 814: integer n; ! 815: { ! 816: double d; ! 817: float f; ! 818: integer i; ! 819: ! 820: if (s->symvalue.rangev.upper == 0 and s->symvalue.rangev.lower > 0) { ! 821: if (n == sizeof(float)) { ! 822: popn(n, &f); ! 823: d = f; ! 824: } else { ! 825: popn(n, &d); ! 826: } ! 827: prtreal(d); ! 828: } else { ! 829: i = 0; ! 830: popn(n, &i); ! 831: printRangeVal(i, s); ! 832: } ! 833: } ! 834: ! 835: /* ! 836: * Print out a set. ! 837: */ ! 838: ! 839: private printSet (s) ! 840: Symbol s; ! 841: { ! 842: Symbol t; ! 843: integer nbytes; ! 844: ! 845: nbytes = size(s); ! 846: t = rtype(s->type); ! 847: printf("{"); ! 848: sp -= nbytes; ! 849: if (t->class == SCAL) { ! 850: printSetOfEnum(t); ! 851: } else if (t->class == RANGE) { ! 852: printSetOfRange(t); ! 853: } else { ! 854: panic("expected range or enumerated base type for set"); ! 855: } ! 856: printf("}"); ! 857: } ! 858: ! 859: /* ! 860: * Print out a set of an enumeration. ! 861: */ ! 862: ! 863: private printSetOfEnum (t) ! 864: Symbol t; ! 865: { ! 866: register Symbol e; ! 867: register integer i, j, *p; ! 868: boolean first; ! 869: ! 870: p = (int *) sp; ! 871: i = *p; ! 872: j = 0; ! 873: e = t->chain; ! 874: first = true; ! 875: while (e != nil) { ! 876: if ((i&1) == 1) { ! 877: if (first) { ! 878: first = false; ! 879: printf("%s", symname(e)); ! 880: } else { ! 881: printf(", %s", symname(e)); ! 882: } ! 883: } ! 884: i >>= 1; ! 885: ++j; ! 886: if (j >= sizeof(integer)*BITSPERBYTE) { ! 887: j = 0; ! 888: ++p; ! 889: i = *p; ! 890: } ! 891: e = e->chain; ! 892: } ! 893: } ! 894: ! 895: /* ! 896: * Print out a set of a subrange type. ! 897: */ ! 898: ! 899: private printSetOfRange (t) ! 900: Symbol t; ! 901: { ! 902: register integer i, j, *p; ! 903: long v; ! 904: boolean first; ! 905: ! 906: p = (int *) sp; ! 907: i = *p; ! 908: j = 0; ! 909: v = t->symvalue.rangev.lower; ! 910: first = true; ! 911: while (v <= t->symvalue.rangev.upper) { ! 912: if ((i&1) == 1) { ! 913: if (first) { ! 914: first = false; ! 915: printf("%ld", v); ! 916: } else { ! 917: printf(", %ld", v); ! 918: } ! 919: } ! 920: i >>= 1; ! 921: ++j; ! 922: if (j >= sizeof(integer)*BITSPERBYTE) { ! 923: j = 0; ! 924: ++p; ! 925: i = *p; ! 926: } ! 927: ++v; ! 928: } ! 929: } ! 930: ! 931: /* ! 932: * Construct a node for subscripting a dynamic or subarray. ! 933: * The list of indices is left for processing in evalaref, ! 934: * unlike normal subscripting in which the list is expanded ! 935: * across individual INDEX nodes. ! 936: */ ! 937: ! 938: private Node dynref (a, t, slist) ! 939: Node a; ! 940: Symbol t; ! 941: Node slist; ! 942: { ! 943: Node p, r; ! 944: integer n; ! 945: ! 946: p = slist; ! 947: n = 0; ! 948: while (p != nil) { ! 949: if (not compatible(p->value.arg[0]->nodetype, t_int)) { ! 950: suberror("subscript \"", p->value.arg[0], "\" is the wrong type"); ! 951: } ! 952: ++n; ! 953: p = p->value.arg[1]; ! 954: } ! 955: if (n > t->symvalue.ndims and (t->symvalue.ndims != 0 or n != 1)) { ! 956: suberror("too many subscripts for ", a, nil); ! 957: } else if (n < t->symvalue.ndims) { ! 958: suberror("not enough subscripts for ", a, nil); ! 959: } ! 960: r = build(O_INDEX, a, slist); ! 961: r->nodetype = rtype(t->type); ! 962: return r; ! 963: } ! 964: ! 965: /* ! 966: * Construct a node for subscripting. ! 967: */ ! 968: ! 969: public Node modula2_buildaref (a, slist) ! 970: Node a, slist; ! 971: { ! 972: register Symbol t; ! 973: register Node p; ! 974: Symbol eltype; ! 975: Node esub, r; ! 976: integer n; ! 977: ! 978: t = rtype(a->nodetype); ! 979: switch (t->class) { ! 980: case OPENARRAY: ! 981: case DYNARRAY: ! 982: case SUBARRAY: ! 983: r = dynref(a, t, slist); ! 984: break; ! 985: ! 986: case ARRAY: ! 987: r = a; ! 988: eltype = rtype(t->type); ! 989: p = slist; ! 990: t = t->chain; ! 991: while (p != nil and t != nil) { ! 992: esub = p->value.arg[0]; ! 993: if (not compatible(rtype(t), rtype(esub->nodetype))) { ! 994: suberror("subscript \"", esub, "\" is the wrong type"); ! 995: } ! 996: r = build(O_INDEX, r, esub); ! 997: r->nodetype = eltype; ! 998: p = p->value.arg[1]; ! 999: t = t->chain; ! 1000: } ! 1001: if (p != nil) { ! 1002: suberror("too many subscripts for ", a, nil); ! 1003: } else if (t != nil) { ! 1004: suberror("not enough subscripts for ", a, nil); ! 1005: } ! 1006: break; ! 1007: ! 1008: default: ! 1009: suberror("\"", a, "\" is not an array"); ! 1010: break; ! 1011: } ! 1012: return r; ! 1013: } ! 1014: ! 1015: /* ! 1016: * Subscript usage error reporting. ! 1017: */ ! 1018: ! 1019: private suberror (s1, e1, s2) ! 1020: String s1, s2; ! 1021: Node e1; ! 1022: { ! 1023: beginerrmsg(); ! 1024: if (s1 != nil) { ! 1025: fprintf(stderr, s1); ! 1026: } ! 1027: if (e1 != nil) { ! 1028: prtree(stderr, e1); ! 1029: } ! 1030: if (s2 != nil) { ! 1031: fprintf(stderr, s2); ! 1032: } ! 1033: enderrmsg(); ! 1034: } ! 1035: ! 1036: /* ! 1037: * Check that a subscript value is in the appropriate range. ! 1038: */ ! 1039: ! 1040: private subchk (value, lower, upper) ! 1041: long value, lower, upper; ! 1042: { ! 1043: if (value < lower or value > upper) { ! 1044: error("subscript value %d out of range [%d..%d]", value, lower, upper); ! 1045: } ! 1046: } ! 1047: ! 1048: /* ! 1049: * Compute the offset for subscripting a dynamic array. ! 1050: */ ! 1051: ! 1052: private getdynoff (ndims, sub) ! 1053: integer ndims; ! 1054: long *sub; ! 1055: { ! 1056: long k, off, *count; ! 1057: ! 1058: count = (long *) sp; ! 1059: off = 0; ! 1060: for (k = 0; k < ndims - 1; k++) { ! 1061: subchk(sub[k], 0, count[k] - 1); ! 1062: off += (sub[k] * count[k+1]); ! 1063: } ! 1064: subchk(sub[ndims - 1], 0, count[ndims - 1] - 1); ! 1065: return off + sub[ndims - 1]; ! 1066: } ! 1067: ! 1068: /* ! 1069: * Compute the offset associated with a subarray. ! 1070: */ ! 1071: ! 1072: private getsuboff (ndims, sub) ! 1073: integer ndims; ! 1074: long *sub; ! 1075: { ! 1076: long k, off; ! 1077: struct subarrayinfo { ! 1078: long count; ! 1079: long mult; ! 1080: } *info; ! 1081: ! 1082: info = (struct subarrayinfo *) sp; ! 1083: off = 0; ! 1084: for (k = 0; k < ndims; k++) { ! 1085: subchk(sub[k], 0, info[k].count - 1); ! 1086: off += sub[k] * info[k].mult; ! 1087: } ! 1088: return off; ! 1089: } ! 1090: ! 1091: /* ! 1092: * Evaluate a subscript index. ! 1093: */ ! 1094: ! 1095: public modula2_evalaref (s, base, i) ! 1096: Symbol s; ! 1097: Address base; ! 1098: long i; ! 1099: { ! 1100: Symbol t; ! 1101: long lb, ub, off; ! 1102: long *sub; ! 1103: Address b; ! 1104: ! 1105: t = rtype(s); ! 1106: if (t->class == ARRAY) { ! 1107: findbounds(rtype(t->chain), &lb, &ub); ! 1108: if (i < lb or i > ub) { ! 1109: error("subscript %d out of range [%d..%d]", i, lb, ub); ! 1110: } ! 1111: push(long, base + (i - lb) * size(t->type)); ! 1112: } else if ((t->class == OPENARRAY or t->class == DYNARRAY) and ! 1113: t->symvalue.ndims == 0 ! 1114: ) { ! 1115: push(long, base + i * size(t->type)); ! 1116: } else if (t->class == OPENARRAY or t->class == DYNARRAY or ! 1117: t->class == SUBARRAY ! 1118: ) { ! 1119: push(long, i); ! 1120: sub = (long *) (sp - (t->symvalue.ndims * sizeof(long))); ! 1121: rpush(base, size(t)); ! 1122: sp -= (t->symvalue.ndims * sizeof(long)); ! 1123: b = pop(Address); ! 1124: sp += sizeof(Address); ! 1125: if (t->class == SUBARRAY) { ! 1126: off = getsuboff(t->symvalue.ndims, sub); ! 1127: } else { ! 1128: off = getdynoff(t->symvalue.ndims, sub); ! 1129: } ! 1130: sp = (Stack *) sub; ! 1131: push(long, b + off * size(t->type)); ! 1132: } else { ! 1133: error("[internal error: expected array in evalaref]"); ! 1134: } ! 1135: } ! 1136: ! 1137: /* ! 1138: * Initial Modula-2 type information. ! 1139: */ ! 1140: ! 1141: #define NTYPES 12 ! 1142: ! 1143: private Symbol inittype[NTYPES + 1]; ! 1144: ! 1145: private addType (n, s, lower, upper) ! 1146: integer n; ! 1147: String s; ! 1148: long lower, upper; ! 1149: { ! 1150: register Symbol t; ! 1151: ! 1152: if (n > NTYPES) { ! 1153: panic("initial Modula-2 type number too large for '%s'", s); ! 1154: } ! 1155: t = insert(identname(s, true)); ! 1156: t->language = mod2; ! 1157: t->class = TYPE; ! 1158: t->type = newSymbol(nil, 0, RANGE, t, nil); ! 1159: t->type->symvalue.rangev.lower = lower; ! 1160: t->type->symvalue.rangev.upper = upper; ! 1161: t->type->language = mod2; ! 1162: inittype[n] = t; ! 1163: } ! 1164: ! 1165: private initModTypes () ! 1166: { ! 1167: addType(1, "integer", 0x80000000L, 0x7fffffffL); ! 1168: addType(2, "char", 0L, 255L); ! 1169: addType(3, "boolean", 0L, 1L); ! 1170: addType(4, "unsigned", 0L, 0xffffffffL); ! 1171: addType(5, "real", 4L, 0L); ! 1172: addType(6, "longreal", 8L, 0L); ! 1173: addType(7, "word", 0L, 0xffffffffL); ! 1174: addType(8, "byte", 0L, 255L); ! 1175: addType(9, "address", 0L, 0xffffffffL); ! 1176: addType(10, "file", 0L, 0xffffffffL); ! 1177: addType(11, "process", 0L, 0xffffffffL); ! 1178: addType(12, "cardinal", 0L, 0x7fffffffL); ! 1179: } ! 1180: ! 1181: /* ! 1182: * Initialize typetable. ! 1183: */ ! 1184: ! 1185: public modula2_modinit (typetable) ! 1186: Symbol typetable[]; ! 1187: { ! 1188: register integer i; ! 1189: ! 1190: if (not initialized) { ! 1191: initModTypes(); ! 1192: initialized = true; ! 1193: } ! 1194: for (i = 1; i <= NTYPES; i++) { ! 1195: typetable[i] = inittype[i]; ! 1196: } ! 1197: } ! 1198: ! 1199: public boolean modula2_hasmodules () ! 1200: { ! 1201: return true; ! 1202: } ! 1203: ! 1204: public boolean modula2_passaddr (param, exprtype) ! 1205: Symbol param, exprtype; ! 1206: { ! 1207: return false; ! 1208: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.