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