|
|
1.1 ! root 1: /* Copyright (c) 1979 Regents of the University of California */ ! 2: # ! 3: /* ! 4: * pi - Pascal interpreter code translator ! 5: * ! 6: * Charles Haley, Bill Joy UCB ! 7: * Version 1.2 November 1978 ! 8: */ ! 9: ! 10: #include "whoami" ! 11: #include "0.h" ! 12: #include "tree.h" ! 13: #include "opcode.h" ! 14: ! 15: /* ! 16: * The following arrays are used to determine which classes may be ! 17: * read and written to/from text files. ! 18: * They are indexed by the return types from classify. ! 19: */ ! 20: #define rdops(x) rdxxxx[(x)-(TFIRST)] ! 21: #define wrops(x) wrxxxx[(x)-(TFIRST)] ! 22: ! 23: int rdxxxx[] = { ! 24: 0, /* -7 file types */ ! 25: 0, /* -6 record types */ ! 26: 0, /* -5 array types */ ! 27: 0, /* -4 scalar types */ ! 28: 0, /* -3 pointer types */ ! 29: 0, /* -2 set types */ ! 30: 0, /* -1 string types */ ! 31: 0, /* 0 nil - i.e. no type */ ! 32: 0, /* 1 booleans */ ! 33: O_READC, /* 2 character */ ! 34: O_READ4, /* 3 integer */ ! 35: O_READ8 /* 4 real */ ! 36: }; ! 37: ! 38: int wrxxxx[] = { ! 39: 0, /* -7 file types */ ! 40: 0, /* -6 record types */ ! 41: 0, /* -5 array types */ ! 42: 0, /* -4 scalar types */ ! 43: 0, /* -3 pointer types */ ! 44: 0, /* -2 set types */ ! 45: O_WRITG, /* -1 string types */ ! 46: 0, /* 0 nil - i.e. no type */ ! 47: O_WRITB, /* 1 booleans */ ! 48: O_WRITC, /* 2 character */ ! 49: O_WRIT4, /* 3 integer */ ! 50: O_WRIT8, /* 4 real */ ! 51: }; ! 52: ! 53: /* ! 54: * Proc handles procedure calls. ! 55: * Non-builtin procedures are "buck-passed" to func (with a flag ! 56: * indicating that they are actually procedures. ! 57: * builtin procedures are handled here. ! 58: */ ! 59: proc(r) ! 60: int *r; ! 61: { ! 62: register struct nl *p; ! 63: register int *al, op; ! 64: struct nl *filetype, *ap; ! 65: int argc, *argv, c, two, oct, hex, *file; ! 66: int pu; ! 67: int *pua, *pui, *puz; ! 68: int i, j, k; ! 69: ! 70: /* ! 71: * Verify that the name is ! 72: * defined and is that of a ! 73: * procedure. ! 74: */ ! 75: p = lookup(r[2]); ! 76: if (p == NIL) { ! 77: rvlist(r[3]); ! 78: return; ! 79: } ! 80: if (p->class != PROC) { ! 81: error("Can't call %s, its %s not a procedure", p->symbol, classes[p->class]); ! 82: rvlist(r[3]); ! 83: return; ! 84: } ! 85: argv = r[3]; ! 86: ! 87: /* ! 88: * Call handles user defined ! 89: * procedures and functions. ! 90: */ ! 91: if (bn != 0) { ! 92: call(p, argv, PROC, bn); ! 93: return; ! 94: } ! 95: ! 96: /* ! 97: * Call to built-in procedure. ! 98: * Count the arguments. ! 99: */ ! 100: argc = 0; ! 101: for (al = argv; al != NIL; al = al[2]) ! 102: argc++; ! 103: ! 104: /* ! 105: * Switch on the operator ! 106: * associated with the built-in ! 107: * procedure in the namelist ! 108: */ ! 109: op = p->value[0] &~ NSTAND; ! 110: if (opt('s') && (p->value[0] & NSTAND)) { ! 111: standard(); ! 112: error("%s is a nonstandard procedure", p->symbol); ! 113: } ! 114: switch (op) { ! 115: ! 116: case O_NULL: ! 117: if (argc != 0) ! 118: error("null takes no arguments"); ! 119: return; ! 120: ! 121: case O_FLUSH: ! 122: if (argc == 0) { ! 123: put1(O_MESSAGE); ! 124: return; ! 125: } ! 126: if (argc != 1) { ! 127: error("flush takes at most one argument"); ! 128: return; ! 129: } ! 130: ap = rvalue(argv[1], NIL); ! 131: if (ap == NIL) ! 132: return; ! 133: if (ap->class != FILET) { ! 134: error("flush's argument must be a file, not %s", nameof(ap)); ! 135: return; ! 136: } ! 137: put1(op); ! 138: return; ! 139: ! 140: case O_MESSAGE: ! 141: case O_WRIT2: ! 142: case O_WRITLN: ! 143: /* ! 144: * Set up default file "output"'s type ! 145: */ ! 146: file = NIL; ! 147: filetype = nl+T1CHAR; ! 148: /* ! 149: * Determine the file implied ! 150: * for the write and generate ! 151: * code to make it the active file. ! 152: */ ! 153: if (op == O_MESSAGE) { ! 154: /* ! 155: * For message, all that matters ! 156: * is that the filetype is ! 157: * a character file. ! 158: * Thus "output" will suit us fine. ! 159: */ ! 160: put1(O_MESSAGE); ! 161: } else if (argv != NIL && (al = argv[1])[0] != T_WEXP) { ! 162: /* ! 163: * If there is a first argument which has ! 164: * no write widths, then it is potentially ! 165: * a file name. ! 166: */ ! 167: codeoff(); ! 168: ap = rvalue(argv[1], NIL); ! 169: codeon(); ! 170: if (ap == NIL) ! 171: argv = argv[2]; ! 172: if (ap != NIL && ap->class == FILET) { ! 173: /* ! 174: * Got "write(f, ...", make ! 175: * f the active file, and save ! 176: * it and its type for use in ! 177: * processing the rest of the ! 178: * arguments to write. ! 179: */ ! 180: file = argv[1]; ! 181: filetype = ap->type; ! 182: rvalue(argv[1], NIL); ! 183: put1(O_UNIT); ! 184: /* ! 185: * Skip over the first argument ! 186: */ ! 187: argv = argv[2]; ! 188: argc--; ! 189: } else ! 190: /* ! 191: * Set up for writing on ! 192: * standard output. ! 193: */ ! 194: put1(O_UNITOUT); ! 195: } else ! 196: put1(O_UNITOUT); ! 197: /* ! 198: * Loop and process each ! 199: * of the arguments. ! 200: */ ! 201: for (; argv != NIL; argv = argv[2]) { ! 202: al = argv[1]; ! 203: if (al == NIL) ! 204: continue; ! 205: /* ! 206: * Op will be used to ! 207: * accumulate width information, ! 208: * and two records the fact ! 209: * that we saw two write widths ! 210: */ ! 211: op = 0; ! 212: two = 0; ! 213: oct = 0; ! 214: hex = 0; ! 215: if (al[0] == T_WEXP) { ! 216: if (filetype != nl+T1CHAR) { ! 217: error("Write widths allowed only with text files"); ! 218: continue; ! 219: } ! 220: /* ! 221: * Handle width expressions. ! 222: * The basic game here is that width ! 223: * expressions get evaluated and left ! 224: * on the stack and their width's get ! 225: * packed into the high byte of the ! 226: * affected opcode (subop). ! 227: */ ! 228: if (al[3] == OCT) ! 229: oct++; ! 230: else if (al[3] == HEX) ! 231: hex++; ! 232: else if (al[3] != NIL) { ! 233: two++; ! 234: /* ! 235: * Arrange for the write ! 236: * opcode that takes two widths ! 237: */ ! 238: op |= O_WRIT82-O_WRIT8; ! 239: ap = rvalue(al[3], NIL); ! 240: if (ap == NIL) ! 241: continue; ! 242: if (isnta(ap, "i")) { ! 243: error("Second write width must be integer, not %s", nameof(ap)); ! 244: continue; ! 245: } ! 246: op |= even(width(ap)) << 11; ! 247: } ! 248: if (al[2] != NIL) { ! 249: ap = rvalue(al[2], NIL); ! 250: if (ap == NIL) ! 251: continue; ! 252: if (isnta(ap, "i")) { ! 253: error("First write width must be integer, not %s", nameof(ap)); ! 254: continue; ! 255: } ! 256: op |= even(width(ap)) << 8; ! 257: } ! 258: al = al[1]; ! 259: if (al == NIL) ! 260: continue; ! 261: } ! 262: if (filetype != nl+T1CHAR) { ! 263: if (oct || hex) { ! 264: error("Oct/hex allowed only on text files"); ! 265: continue; ! 266: } ! 267: if (op) { ! 268: error("Write widths allowed only on text files"); ! 269: continue; ! 270: } ! 271: /* ! 272: * Generalized write, i.e. ! 273: * to a non-textfile. ! 274: */ ! 275: rvalue(file, NIL); ! 276: put1(O_FNIL); ! 277: /* ! 278: * file^ := ... ! 279: */ ! 280: ap = rvalue(argv[1], NIL); ! 281: if (ap == NIL) ! 282: continue; ! 283: if (incompat(ap, filetype, argv[1])) { ! 284: cerror("Type mismatch in write to non-text file"); ! 285: continue; ! 286: } ! 287: convert(ap, filetype); ! 288: put2(O_AS, width(filetype)); ! 289: /* ! 290: * put(file) ! 291: */ ! 292: put1(O_PUT); ! 293: continue; ! 294: } ! 295: /* ! 296: * Write to a textfile ! 297: * ! 298: * Evaluate the expression ! 299: * to be written. ! 300: */ ! 301: ap = rvalue(al, NIL); ! 302: if (ap == NIL) ! 303: continue; ! 304: c = classify(ap); ! 305: if (two && c != TDOUBLE) { ! 306: if (isnta(ap, "i")) { ! 307: error("Only reals can have two write widths"); ! 308: continue; ! 309: } ! 310: convert(ap, nl+TDOUBLE); ! 311: c = TDOUBLE; ! 312: } ! 313: if (oct || hex) { ! 314: if (opt('s')) { ! 315: standard(); ! 316: error("Oct and hex are non-standard"); ! 317: } ! 318: switch (c) { ! 319: case TREC: ! 320: case TARY: ! 321: case TFILE: ! 322: case TSTR: ! 323: case TSET: ! 324: case TDOUBLE: ! 325: error("Can't write %ss with oct/hex", clnames[c]); ! 326: continue; ! 327: } ! 328: put1(op | (oct ? O_WROCT2 : O_WRHEX2) | (width(ap) >> 2)); ! 329: continue; ! 330: } ! 331: if (wrops(c) == NIL) { ! 332: error("Can't write %ss to a text file", clnames[c]); ! 333: continue; ! 334: } ! 335: if (c == TINT && width(ap) != 4) ! 336: op |= O_WRIT2; ! 337: else ! 338: op |= wrops(c); ! 339: if (c == TSTR) ! 340: put2(op, width(ap)); ! 341: else ! 342: put1(op); ! 343: } ! 344: /* ! 345: * Done with arguments. ! 346: * Handle writeln and ! 347: * insufficent number of args. ! 348: */ ! 349: switch (p->value[0] &~ NSTAND) { ! 350: case O_WRIT2: ! 351: if (argc == 0) ! 352: error("Write requires an argument"); ! 353: break; ! 354: case O_MESSAGE: ! 355: if (argc == 0) ! 356: error("Message requires an argument"); ! 357: case O_WRITLN: ! 358: if (filetype != nl+T1CHAR) ! 359: error("Can't 'writeln' a non text file"); ! 360: put1(O_WRITLN); ! 361: break; ! 362: } ! 363: return; ! 364: ! 365: case O_READ4: ! 366: case O_READLN: ! 367: /* ! 368: * Set up default ! 369: * file "input". ! 370: */ ! 371: file = NIL; ! 372: filetype = nl+T1CHAR; ! 373: /* ! 374: * Determine the file implied ! 375: * for the read and generate ! 376: * code to make it the active file. ! 377: */ ! 378: if (argv != NIL) { ! 379: codeoff(); ! 380: ap = rvalue(argv[1], NIL); ! 381: codeon(); ! 382: if (ap == NIL) ! 383: argv = argv[2]; ! 384: if (ap != NIL && ap->class == FILET) { ! 385: /* ! 386: * Got "read(f, ...", make ! 387: * f the active file, and save ! 388: * it and its type for use in ! 389: * processing the rest of the ! 390: * arguments to read. ! 391: */ ! 392: file = argv[1]; ! 393: filetype = ap->type; ! 394: rvalue(argv[1], NIL); ! 395: put1(O_UNIT); ! 396: argv = argv[2]; ! 397: argc--; ! 398: } else { ! 399: /* ! 400: * Default is read from ! 401: * standard input. ! 402: */ ! 403: put1(O_UNITINP); ! 404: input->nl_flags |= NUSED; ! 405: } ! 406: } else { ! 407: put1(O_UNITINP); ! 408: input->nl_flags |= NUSED; ! 409: } ! 410: /* ! 411: * Loop and process each ! 412: * of the arguments. ! 413: */ ! 414: for (; argv != NIL; argv = argv[2]) { ! 415: /* ! 416: * Get the address of the target ! 417: * on the stack. ! 418: */ ! 419: al = argv[1]; ! 420: if (al == NIL) ! 421: continue; ! 422: if (al[0] != T_VAR) { ! 423: error("Arguments to %s must be variables, not expressions", p->symbol); ! 424: continue; ! 425: } ! 426: ap = lvalue(al, MOD|ASGN|NOUSE); ! 427: if (ap == NIL) ! 428: continue; ! 429: if (filetype != nl+T1CHAR) { ! 430: /* ! 431: * Generalized read, i.e. ! 432: * from a non-textfile. ! 433: */ ! 434: if (incompat(filetype, ap, NIL)) { ! 435: error("Type mismatch in read from non-text file"); ! 436: continue; ! 437: } ! 438: /* ! 439: * var := file ^; ! 440: */ ! 441: if (file != NIL) ! 442: rvalue(file, NIL); ! 443: else /* Magic */ ! 444: put2(O_RV2, input->value[0]); ! 445: put1(O_FNIL); ! 446: put2(O_IND, width(filetype)); ! 447: convert(filetype, ap); ! 448: if (isa(ap, "bsci")) ! 449: rangechk(ap, ap); ! 450: put2(O_AS, width(ap)); ! 451: /* ! 452: * get(file); ! 453: */ ! 454: put1(O_GET); ! 455: continue; ! 456: } ! 457: c = classify(ap); ! 458: op = rdops(c); ! 459: if (op == NIL) { ! 460: error("Can't read %ss from a text file", clnames[c]); ! 461: continue; ! 462: } ! 463: put1(op); ! 464: /* ! 465: * Data read is on the stack. ! 466: * Assign it. ! 467: */ ! 468: if (op != O_READ8) ! 469: rangechk(ap, op == O_READC ? ap : nl+T4INT); ! 470: gen(O_AS2, O_AS2, width(ap), ! 471: op == O_READ8 ? 8 : op == O_READ4 ? 4 : 2); ! 472: } ! 473: /* ! 474: * Done with arguments. ! 475: * Handle readln and ! 476: * insufficient number of args. ! 477: */ ! 478: if (p->value[0] == O_READLN) { ! 479: if (filetype != nl+T1CHAR) ! 480: error("Can't 'readln' a non text file"); ! 481: put1(O_READLN); ! 482: } ! 483: else if (argc == 0) ! 484: error("read requires an argument"); ! 485: return; ! 486: ! 487: case O_GET: ! 488: case O_PUT: ! 489: if (argc != 1) { ! 490: error("%s expects one argument", p->symbol); ! 491: return; ! 492: } ! 493: ap = rvalue(argv[1], NIL); ! 494: if (ap == NIL) ! 495: return; ! 496: if (ap->class != FILET) { ! 497: error("Argument to %s must be a file, not %s", p->symbol, nameof(ap)); ! 498: return; ! 499: } ! 500: put1(O_UNIT); ! 501: put1(op); ! 502: return; ! 503: ! 504: case O_RESET: ! 505: case O_REWRITE: ! 506: if (argc == 0 || argc > 2) { ! 507: error("%s expects one or two arguments", p->symbol); ! 508: return; ! 509: } ! 510: if (opt('s') && argc == 2) { ! 511: standard(); ! 512: error("Two argument forms of reset and rewrite are non-standard"); ! 513: } ! 514: ap = lvalue(argv[1], MOD|NOUSE); ! 515: if (ap == NIL) ! 516: return; ! 517: if (ap->class != FILET) { ! 518: error("First argument to %s must be a file, not %s", p->symbol, nameof(ap)); ! 519: return; ! 520: } ! 521: if (argc == 2) { ! 522: /* ! 523: * Optional second argument ! 524: * is a string name of a ! 525: * UNIX (R) file to be associated. ! 526: */ ! 527: al = argv[2]; ! 528: al = rvalue(al[1], NIL); ! 529: if (al == NIL) ! 530: return; ! 531: if (classify(al) != TSTR) { ! 532: error("Second argument to %s must be a string, not %s", p->symbol, nameof(al)); ! 533: return; ! 534: } ! 535: c = width(al); ! 536: } else ! 537: c = 0; ! 538: if (c > 127) { ! 539: error("File name too long"); ! 540: return; ! 541: } ! 542: put2(op | c << 8, text(ap) ? 0: width(ap->type)); ! 543: return; ! 544: ! 545: case O_NEW: ! 546: case O_DISPOSE: ! 547: if (argc == 0) { ! 548: error("%s expects at least one argument", p->symbol); ! 549: return; ! 550: } ! 551: ap = lvalue(argv[1], MOD|NOUSE); ! 552: if (ap == NIL) ! 553: return; ! 554: if (ap->class != PTR) { ! 555: error("(First) argument to %s must be a pointer, not %s", p->symbol, nameof(ap)); ! 556: return; ! 557: } ! 558: ap = ap->type; ! 559: if (ap == NIL) ! 560: return; ! 561: argv = argv[2]; ! 562: if (argv != NIL) { ! 563: if (ap->class != RECORD) { ! 564: error("Record required when specifying variant tags"); ! 565: return; ! 566: } ! 567: for (; argv != NIL; argv = argv[2]) { ! 568: if (ap->ptr[NL_VARNT] == NIL) { ! 569: error("Too many tag fields"); ! 570: return; ! 571: } ! 572: if (!isconst(argv[1])) { ! 573: error("Second and successive arguments to %s must be constants", p->symbol); ! 574: return; ! 575: } ! 576: gconst(argv[1]); ! 577: if (con.ctype == NIL) ! 578: return; ! 579: if (incompat(con.ctype, (ap->ptr[NL_TAG])->type)) { ! 580: cerror("Specified tag constant type clashed with variant case selector type"); ! 581: return; ! 582: } ! 583: for (ap = ap->ptr[NL_VARNT]; ap != NIL; ap = ap->chain) ! 584: if (ap->range[0] == con.crval) ! 585: break; ! 586: if (ap == NIL) { ! 587: error("No variant case label value equals specified constant value"); ! 588: return; ! 589: } ! 590: ap = ap->ptr[NL_VTOREC]; ! 591: } ! 592: } ! 593: put2(op, width(ap)); ! 594: return; ! 595: ! 596: case O_DATE: ! 597: case O_TIME: ! 598: if (argc != 1) { ! 599: error("%s expects one argument", p->symbol); ! 600: return; ! 601: } ! 602: ap = lvalue(argv[1], MOD|NOUSE); ! 603: if (ap == NIL) ! 604: return; ! 605: if (classify(ap) != TSTR || width(ap) != 10) { ! 606: error("Argument to %s must be a alfa, not %s", p->symbol, nameof(ap)); ! 607: return; ! 608: } ! 609: put1(op); ! 610: return; ! 611: ! 612: case O_HALT: ! 613: if (argc != 0) { ! 614: error("halt takes no arguments"); ! 615: return; ! 616: } ! 617: put1(op); ! 618: noreach = 1; ! 619: return; ! 620: ! 621: case O_ARGV: ! 622: if (argc != 2) { ! 623: error("argv takes two arguments"); ! 624: return; ! 625: } ! 626: ap = rvalue(argv[1], NIL); ! 627: if (ap == NIL) ! 628: return; ! 629: if (isnta(ap, "i")) { ! 630: error("argv's first argument must be an integer, not %s", nameof(ap)); ! 631: return; ! 632: } ! 633: convert(ap, nl+T2INT); ! 634: al = argv[2]; ! 635: ap = lvalue(al[1], MOD|NOUSE); ! 636: if (ap == NIL) ! 637: return; ! 638: if (classify(ap) != TSTR) { ! 639: error("argv's second argument must be a string, not %s", nameof(ap)); ! 640: return; ! 641: } ! 642: put2(op, width(ap)); ! 643: return; ! 644: ! 645: case O_STLIM: ! 646: if (argc != 1) { ! 647: error("stlimit requires one argument"); ! 648: return; ! 649: } ! 650: ap = rvalue(argv[1], NIL); ! 651: if (ap == NIL) ! 652: return; ! 653: if (isnta(ap, "i")) { ! 654: error("stlimit's argument must be an integer, not %s", nameof(ap)); ! 655: return; ! 656: } ! 657: if (width(ap) != 4) ! 658: put1(O_STOI); ! 659: put1(op); ! 660: return; ! 661: ! 662: case O_REMOVE: ! 663: if (argc != 1) { ! 664: error("remove expects one argument"); ! 665: return; ! 666: } ! 667: ap = rvalue(argv[1], NIL); ! 668: if (ap == NIL) ! 669: return; ! 670: if (classify(ap) != TSTR) { ! 671: error("remove's argument must be a string, not %s", nameof(ap)); ! 672: return; ! 673: } ! 674: put2(op, width(ap)); ! 675: return; ! 676: ! 677: case O_LLIMIT: ! 678: if (argc != 2) { ! 679: error("linelimit expects two arguments"); ! 680: return; ! 681: } ! 682: ap = lvalue(argv[1], NOMOD|NOUSE); ! 683: if (ap == NIL) ! 684: return; ! 685: if (!text(ap)) { ! 686: error("linelimit's first argument must be a text file, not %s", nameof(ap)); ! 687: return; ! 688: } ! 689: al = argv[2]; ! 690: ap = rvalue(al[1], NIL); ! 691: if (ap == NIL) ! 692: return; ! 693: if (isnta(ap, "i")) { ! 694: error("linelimit's second argument must be an integer, not %s", nameof(ap)); ! 695: return; ! 696: } ! 697: convert(ap, nl+T4INT); ! 698: put1(op); ! 699: return; ! 700: case O_PAGE: ! 701: if (argc != 1) { ! 702: error("page expects one argument"); ! 703: return; ! 704: } ! 705: ap = rvalue(argv[1], NIL); ! 706: if (ap == NIL) ! 707: return; ! 708: if (!text(ap)) { ! 709: error("Argument to page must be a text file, not %s", nameof(ap)); ! 710: return; ! 711: } ! 712: put1(O_UNIT); ! 713: put1(op); ! 714: return; ! 715: ! 716: case O_PACK: ! 717: if (argc != 3) { ! 718: error("pack expects three arguments"); ! 719: return; ! 720: } ! 721: pu = "pack(a,i,z)"; ! 722: pua = (al = argv)[1]; ! 723: pui = (al = al[2])[1]; ! 724: puz = (al = al[2])[1]; ! 725: goto packunp; ! 726: case O_UNPACK: ! 727: if (argc != 3) { ! 728: error("unpack expects three arguments"); ! 729: return; ! 730: } ! 731: pu = "unpack(z,a,i)"; ! 732: puz = (al = argv)[1]; ! 733: pua = (al = al[2])[1]; ! 734: pui = (al = al[2])[1]; ! 735: packunp: ! 736: ap = rvalue((int *) pui, NLNIL); ! 737: if (ap == NIL) ! 738: return; ! 739: if (width(ap) == 4) ! 740: put1(O_ITOS); ! 741: ap = lvalue(pua, op == O_PACK ? NOMOD : MOD|NOUSE); ! 742: if (ap == NIL) ! 743: return; ! 744: if (ap->class != ARRAY) { ! 745: error("%s requires a to be an unpacked array, not %s", pu, nameof(ap)); ! 746: return; ! 747: } ! 748: al = (struct nl *) lvalue(puz, op == O_UNPACK ? NOMOD : MOD|NOUSE); ! 749: if (al->class != ARRAY) { ! 750: error("%s requires z to be a packed array, not %s", pu, nameof(ap)); ! 751: return; ! 752: } ! 753: if (al->type == NIL || ap->type == NIL) ! 754: return; ! 755: if (al->type != ap->type) { ! 756: error("%s requires a and z to be arrays of the same type", pu, nameof(ap)); ! 757: return; ! 758: } ! 759: k = width(al); ! 760: ap = ap->chain; ! 761: al = al->chain; ! 762: if (ap->chain != NIL || al->chain != NIL) { ! 763: error("%s requires a and z to be single dimension arrays", pu); ! 764: return; ! 765: } ! 766: if (ap == NIL || al == NIL) ! 767: return; ! 768: /* ! 769: * al is the range for z i.e. u..v ! 770: * ap is the range for a i.e. m..n ! 771: * i will be n-m+1 ! 772: * j will be v-u+1 ! 773: */ ! 774: i = ap->range[1] - ap->range[0] + 1; ! 775: j = al->range[1] - al->range[0] + 1; ! 776: if (i < j) { ! 777: error("%s cannot have more elements in a (%d) than in z (%d)", pu, j, i); ! 778: return; ! 779: } ! 780: /* ! 781: * get n-m-(v-u) and m for the interpreter ! 782: */ ! 783: i -= j; ! 784: j = ap->range[0]; ! 785: put(5, op, width(ap), j, i, k); ! 786: return; ! 787: case 0: ! 788: error("%s is an unimplemented 6400 extension", p->symbol); ! 789: return; ! 790: ! 791: default: ! 792: panic("proc case"); ! 793: } ! 794: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.