|
|
1.1 ! root 1: /* Copyright (c) 1979 Regents of the University of California */ ! 2: ! 3: static char sccsid[] = "@(#)pcproc.c 1.21 4/8/83"; ! 4: ! 5: #include "whoami.h" ! 6: #ifdef PC ! 7: /* ! 8: * and to the end of the file ! 9: */ ! 10: #include "0.h" ! 11: #include "tree.h" ! 12: #include "objfmt.h" ! 13: #include "opcode.h" ! 14: #include "pc.h" ! 15: #include "pcops.h" ! 16: #include "tmps.h" ! 17: ! 18: /* ! 19: * The constant EXPOSIZE specifies the number of digits in the exponent ! 20: * of real numbers. ! 21: * ! 22: * The constant REALSPC defines the amount of forced padding preceeding ! 23: * real numbers when they are printed. If REALSPC == 0, then no padding ! 24: * is added, REALSPC == 1 adds one extra blank irregardless of the width ! 25: * specified by the user. ! 26: * ! 27: * N.B. - Values greater than one require program mods. ! 28: */ ! 29: #define EXPOSIZE 2 ! 30: #define REALSPC 0 ! 31: ! 32: /* ! 33: * The following array is used to determine which classes may be read ! 34: * from textfiles. It is indexed by the return value from classify. ! 35: */ ! 36: #define rdops(x) rdxxxx[(x)-(TFIRST)] ! 37: ! 38: int rdxxxx[] = { ! 39: 0, /* -7 file types */ ! 40: 0, /* -6 record types */ ! 41: 0, /* -5 array types */ ! 42: O_READE, /* -4 scalar types */ ! 43: 0, /* -3 pointer types */ ! 44: 0, /* -2 set types */ ! 45: 0, /* -1 string types */ ! 46: 0, /* 0 nil, no type */ ! 47: O_READE, /* 1 boolean */ ! 48: O_READC, /* 2 character */ ! 49: O_READ4, /* 3 integer */ ! 50: O_READ8 /* 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: pcproc(r) ! 60: int *r; ! 61: { ! 62: register struct nl *p; ! 63: register int *alv, *al, op; ! 64: struct nl *filetype, *ap; ! 65: int argc, *argv, typ, fmtspec, strfmt, stkcnt, *file; ! 66: char fmt, format[20], *strptr, *cmd; ! 67: int prec, field, strnglen, fmtlen, fmtstart, pu; ! 68: int *pua, *pui, *puz; ! 69: int i, j, k; ! 70: int itemwidth; ! 71: char *readname; ! 72: struct nl *tempnlp; ! 73: long readtype; ! 74: struct tmps soffset; ! 75: ! 76: #define CONPREC 4 ! 77: #define VARPREC 8 ! 78: #define CONWIDTH 1 ! 79: #define VARWIDTH 2 ! 80: #define SKIP 16 ! 81: ! 82: /* ! 83: * Verify that the name is ! 84: * defined and is that of a ! 85: * procedure. ! 86: */ ! 87: p = lookup(r[2]); ! 88: if (p == NIL) { ! 89: rvlist(r[3]); ! 90: return; ! 91: } ! 92: if (p->class != PROC && p->class != FPROC) { ! 93: error("Can't call %s, its %s not a procedure", p->symbol, classes[p->class]); ! 94: rvlist(r[3]); ! 95: return; ! 96: } ! 97: argv = r[3]; ! 98: ! 99: /* ! 100: * Call handles user defined ! 101: * procedures and functions. ! 102: */ ! 103: if (bn != 0) { ! 104: call(p, argv, PROC, bn); ! 105: return; ! 106: } ! 107: ! 108: /* ! 109: * Call to built-in procedure. ! 110: * Count the arguments. ! 111: */ ! 112: argc = 0; ! 113: for (al = argv; al != NIL; al = al[2]) ! 114: argc++; ! 115: ! 116: /* ! 117: * Switch on the operator ! 118: * associated with the built-in ! 119: * procedure in the namelist ! 120: */ ! 121: op = p->value[0] &~ NSTAND; ! 122: if (opt('s') && (p->value[0] & NSTAND)) { ! 123: standard(); ! 124: error("%s is a nonstandard procedure", p->symbol); ! 125: } ! 126: switch (op) { ! 127: ! 128: case O_ABORT: ! 129: if (argc != 0) ! 130: error("null takes no arguments"); ! 131: return; ! 132: ! 133: case O_FLUSH: ! 134: if (argc == 0) { ! 135: putleaf( P2ICON , 0 , 0 , P2INT , "_PFLUSH" ); ! 136: putop( P2UNARY P2CALL , P2INT ); ! 137: putdot( filename , line ); ! 138: return; ! 139: } ! 140: if (argc != 1) { ! 141: error("flush takes at most one argument"); ! 142: return; ! 143: } ! 144: putleaf( P2ICON , 0 , 0 ! 145: , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 146: , "_FLUSH" ); ! 147: ap = stklval(argv[1], NOFLAGS); ! 148: if (ap == NIL) ! 149: return; ! 150: if (ap->class != FILET) { ! 151: error("flush's argument must be a file, not %s", nameof(ap)); ! 152: return; ! 153: } ! 154: putop( P2CALL , P2INT ); ! 155: putdot( filename , line ); ! 156: return; ! 157: ! 158: case O_MESSAGE: ! 159: case O_WRITEF: ! 160: case O_WRITLN: ! 161: /* ! 162: * Set up default file "output"'s type ! 163: */ ! 164: file = NIL; ! 165: filetype = nl+T1CHAR; ! 166: /* ! 167: * Determine the file implied ! 168: * for the write and generate ! 169: * code to make it the active file. ! 170: */ ! 171: if (op == O_MESSAGE) { ! 172: /* ! 173: * For message, all that matters ! 174: * is that the filetype is ! 175: * a character file. ! 176: * Thus "output" will suit us fine. ! 177: */ ! 178: putleaf( P2ICON , 0 , 0 , P2INT , "_PFLUSH" ); ! 179: putop( P2UNARY P2CALL , P2INT ); ! 180: putdot( filename , line ); ! 181: putRV( 0 , cbn , CURFILEOFFSET , NLOCAL , ! 182: P2PTR|P2STRTY ); ! 183: putLV( "__err" , 0 , 0 , NGLOBAL , P2PTR|P2STRTY ); ! 184: putop( P2ASSIGN , P2PTR|P2STRTY ); ! 185: putdot( filename , line ); ! 186: } else if (argv != NIL && (al = argv[1])[0] != T_WEXP) { ! 187: /* ! 188: * If there is a first argument which has ! 189: * no write widths, then it is potentially ! 190: * a file name. ! 191: */ ! 192: codeoff(); ! 193: ap = stkrval(argv[1], NIL , RREQ ); ! 194: codeon(); ! 195: if (ap == NIL) ! 196: argv = argv[2]; ! 197: if (ap != NIL && ap->class == FILET) { ! 198: /* ! 199: * Got "write(f, ...", make ! 200: * f the active file, and save ! 201: * it and its type for use in ! 202: * processing the rest of the ! 203: * arguments to write. ! 204: */ ! 205: putRV( 0 , cbn , CURFILEOFFSET , NLOCAL , ! 206: P2PTR|P2STRTY ); ! 207: putleaf( P2ICON , 0 , 0 ! 208: , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 209: , "_UNIT" ); ! 210: file = argv[1]; ! 211: filetype = ap->type; ! 212: stklval(argv[1], NOFLAGS); ! 213: putop( P2CALL , P2INT ); ! 214: putop( P2ASSIGN , P2PTR|P2STRTY ); ! 215: putdot( filename , line ); ! 216: /* ! 217: * Skip over the first argument ! 218: */ ! 219: argv = argv[2]; ! 220: argc--; ! 221: } else { ! 222: /* ! 223: * Set up for writing on ! 224: * standard output. ! 225: */ ! 226: putRV( 0, cbn , CURFILEOFFSET , ! 227: NLOCAL , P2PTR|P2STRTY ); ! 228: putLV( "_output" , 0 , 0 , NGLOBAL , ! 229: P2PTR|P2STRTY ); ! 230: putop( P2ASSIGN , P2PTR|P2STRTY ); ! 231: putdot( filename , line ); ! 232: output->nl_flags |= NUSED; ! 233: } ! 234: } else { ! 235: putRV( 0, cbn , CURFILEOFFSET , NLOCAL , ! 236: P2PTR|P2STRTY ); ! 237: putLV( "_output" , 0 , 0 , NGLOBAL , P2PTR|P2STRTY ); ! 238: putop( P2ASSIGN , P2PTR|P2STRTY ); ! 239: putdot( filename , line ); ! 240: output->nl_flags |= NUSED; ! 241: } ! 242: /* ! 243: * Loop and process each ! 244: * of the arguments. ! 245: */ ! 246: for (; argv != NIL; argv = argv[2]) { ! 247: /* ! 248: * fmtspec indicates the type (CONstant or VARiable) ! 249: * and number (none, WIDTH, and/or PRECision) ! 250: * of the fields in the printf format for this ! 251: * output variable. ! 252: * stkcnt is the number of longs pushed on the stack ! 253: * fmt is the format output indicator (D, E, F, O, X, S) ! 254: * fmtstart = 0 for leading blank; = 1 for no blank ! 255: */ ! 256: fmtspec = NIL; ! 257: stkcnt = 0; ! 258: fmt = 'D'; ! 259: fmtstart = 1; ! 260: al = argv[1]; ! 261: if (al == NIL) ! 262: continue; ! 263: if (al[0] == T_WEXP) ! 264: alv = al[1]; ! 265: else ! 266: alv = al; ! 267: if (alv == NIL) ! 268: continue; ! 269: codeoff(); ! 270: ap = stkrval(alv, NIL , RREQ ); ! 271: codeon(); ! 272: if (ap == NIL) ! 273: continue; ! 274: typ = classify(ap); ! 275: if (al[0] == T_WEXP) { ! 276: /* ! 277: * Handle width expressions. ! 278: * The basic game here is that width ! 279: * expressions get evaluated. If they ! 280: * are constant, the value is placed ! 281: * directly in the format string. ! 282: * Otherwise the value is pushed onto ! 283: * the stack and an indirection is ! 284: * put into the format string. ! 285: */ ! 286: if (al[3] == OCT) ! 287: fmt = 'O'; ! 288: else if (al[3] == HEX) ! 289: fmt = 'X'; ! 290: else if (al[3] != NIL) { ! 291: /* ! 292: * Evaluate second format spec ! 293: */ ! 294: if ( constval(al[3]) ! 295: && isa( con.ctype , "i" ) ) { ! 296: fmtspec += CONPREC; ! 297: prec = con.crval; ! 298: } else { ! 299: fmtspec += VARPREC; ! 300: } ! 301: fmt = 'f'; ! 302: switch ( typ ) { ! 303: case TINT: ! 304: if ( opt( 's' ) ) { ! 305: standard(); ! 306: error("Writing %ss with two write widths is non-standard", clnames[typ]); ! 307: } ! 308: /* and fall through */ ! 309: case TDOUBLE: ! 310: break; ! 311: default: ! 312: error("Cannot write %ss with two write widths", clnames[typ]); ! 313: continue; ! 314: } ! 315: } ! 316: /* ! 317: * Evaluate first format spec ! 318: */ ! 319: if (al[2] != NIL) { ! 320: if ( constval(al[2]) ! 321: && isa( con.ctype , "i" ) ) { ! 322: fmtspec += CONWIDTH; ! 323: field = con.crval; ! 324: } else { ! 325: fmtspec += VARWIDTH; ! 326: } ! 327: } ! 328: if ((fmtspec & CONPREC) && prec < 0 || ! 329: (fmtspec & CONWIDTH) && field < 0) { ! 330: error("Negative widths are not allowed"); ! 331: continue; ! 332: } ! 333: if ( opt('s') && ! 334: ((fmtspec & CONPREC) && prec == 0 || ! 335: (fmtspec & CONWIDTH) && field == 0)) { ! 336: standard(); ! 337: error("Zero widths are non-standard"); ! 338: } ! 339: } ! 340: if (filetype != nl+T1CHAR) { ! 341: if (fmt == 'O' || fmt == 'X') { ! 342: error("Oct/hex allowed only on text files"); ! 343: continue; ! 344: } ! 345: if (fmtspec) { ! 346: error("Write widths allowed only on text files"); ! 347: continue; ! 348: } ! 349: /* ! 350: * Generalized write, i.e. ! 351: * to a non-textfile. ! 352: */ ! 353: putleaf( P2ICON , 0 , 0 ! 354: , ADDTYPE( ! 355: ADDTYPE( ! 356: ADDTYPE( p2type( filetype ) ! 357: , P2PTR ) ! 358: , P2FTN ) ! 359: , P2PTR ) ! 360: , "_FNIL" ); ! 361: stklval(file, NOFLAGS); ! 362: putop( P2CALL ! 363: , ADDTYPE( p2type( filetype ) , P2PTR ) ); ! 364: putop( P2UNARY P2MUL , p2type( filetype ) ); ! 365: /* ! 366: * file^ := ... ! 367: */ ! 368: switch ( classify( filetype ) ) { ! 369: case TBOOL: ! 370: case TCHAR: ! 371: case TINT: ! 372: case TSCAL: ! 373: precheck( filetype , "_RANG4" , "_RSNG4" ); ! 374: /* and fall through */ ! 375: case TDOUBLE: ! 376: case TPTR: ! 377: ap = rvalue( argv[1] , filetype , RREQ ); ! 378: break; ! 379: default: ! 380: ap = rvalue( argv[1] , filetype , LREQ ); ! 381: break; ! 382: } ! 383: if (ap == NIL) ! 384: continue; ! 385: if (incompat(ap, filetype, argv[1])) { ! 386: cerror("Type mismatch in write to non-text file"); ! 387: continue; ! 388: } ! 389: switch ( classify( filetype ) ) { ! 390: case TBOOL: ! 391: case TCHAR: ! 392: case TINT: ! 393: case TSCAL: ! 394: postcheck(filetype, ap); ! 395: sconv(p2type(ap), p2type(filetype)); ! 396: /* and fall through */ ! 397: case TDOUBLE: ! 398: case TPTR: ! 399: putop( P2ASSIGN , p2type( filetype ) ); ! 400: putdot( filename , line ); ! 401: break; ! 402: default: ! 403: putstrop(P2STASG, ! 404: ADDTYPE(p2type(filetype), ! 405: P2PTR), ! 406: lwidth(filetype), ! 407: align(filetype)); ! 408: putdot( filename , line ); ! 409: break; ! 410: } ! 411: /* ! 412: * put(file) ! 413: */ ! 414: putleaf( P2ICON , 0 , 0 ! 415: , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 416: , "_PUT" ); ! 417: putRV( 0 , cbn , CURFILEOFFSET , NLOCAL , ! 418: P2PTR|P2STRTY ); ! 419: putop( P2CALL , P2INT ); ! 420: putdot( filename , line ); ! 421: continue; ! 422: } ! 423: /* ! 424: * Write to a textfile ! 425: * ! 426: * Evaluate the expression ! 427: * to be written. ! 428: */ ! 429: if (fmt == 'O' || fmt == 'X') { ! 430: if (opt('s')) { ! 431: standard(); ! 432: error("Oct and hex are non-standard"); ! 433: } ! 434: if (typ == TSTR || typ == TDOUBLE) { ! 435: error("Can't write %ss with oct/hex", clnames[typ]); ! 436: continue; ! 437: } ! 438: if (typ == TCHAR || typ == TBOOL) ! 439: typ = TINT; ! 440: } ! 441: /* ! 442: * If there is no format specified by the programmer, ! 443: * implement the default. ! 444: */ ! 445: switch (typ) { ! 446: case TPTR: ! 447: warning(); ! 448: if (opt('s')) { ! 449: standard(); ! 450: } ! 451: error("Writing %ss to text files is non-standard", ! 452: clnames[typ]); ! 453: /* and fall through */ ! 454: case TINT: ! 455: if (fmt == 'f') { ! 456: typ = TDOUBLE; ! 457: goto tdouble; ! 458: } ! 459: if (fmtspec == NIL) { ! 460: if (fmt == 'D') ! 461: field = 10; ! 462: else if (fmt == 'X') ! 463: field = 8; ! 464: else if (fmt == 'O') ! 465: field = 11; ! 466: else ! 467: panic("fmt1"); ! 468: fmtspec = CONWIDTH; ! 469: } ! 470: break; ! 471: case TCHAR: ! 472: tchar: ! 473: fmt = 'c'; ! 474: break; ! 475: case TSCAL: ! 476: warning(); ! 477: if (opt('s')) { ! 478: standard(); ! 479: } ! 480: error("Writing %ss to text files is non-standard", ! 481: clnames[typ]); ! 482: case TBOOL: ! 483: fmt = 's'; ! 484: break; ! 485: case TDOUBLE: ! 486: tdouble: ! 487: switch (fmtspec) { ! 488: case NIL: ! 489: field = 14 + (5 + EXPOSIZE); ! 490: prec = field - (5 + EXPOSIZE); ! 491: fmt = 'e'; ! 492: fmtspec = CONWIDTH + CONPREC; ! 493: break; ! 494: case CONWIDTH: ! 495: field -= REALSPC; ! 496: if (field < 1) ! 497: field = 1; ! 498: prec = field - (5 + EXPOSIZE); ! 499: if (prec < 1) ! 500: prec = 1; ! 501: fmtspec += CONPREC; ! 502: fmt = 'e'; ! 503: break; ! 504: case VARWIDTH: ! 505: fmtspec += VARPREC; ! 506: fmt = 'e'; ! 507: break; ! 508: case CONWIDTH + CONPREC: ! 509: case CONWIDTH + VARPREC: ! 510: field -= REALSPC; ! 511: if (field < 1) ! 512: field = 1; ! 513: } ! 514: format[0] = ' '; ! 515: fmtstart = 1 - REALSPC; ! 516: break; ! 517: case TSTR: ! 518: constval( alv ); ! 519: switch ( classify( con.ctype ) ) { ! 520: case TCHAR: ! 521: typ = TCHAR; ! 522: goto tchar; ! 523: case TSTR: ! 524: strptr = con.cpval; ! 525: for (strnglen = 0; *strptr++; strnglen++) /* void */; ! 526: strptr = con.cpval; ! 527: break; ! 528: default: ! 529: strnglen = width(ap); ! 530: break; ! 531: } ! 532: fmt = 's'; ! 533: strfmt = fmtspec; ! 534: if (fmtspec == NIL) { ! 535: fmtspec = SKIP; ! 536: break; ! 537: } ! 538: if (fmtspec & CONWIDTH) { ! 539: if (field <= strnglen) ! 540: fmtspec = SKIP; ! 541: else ! 542: field -= strnglen; ! 543: } ! 544: break; ! 545: default: ! 546: error("Can't write %ss to a text file", clnames[typ]); ! 547: continue; ! 548: } ! 549: /* ! 550: * Generate the format string ! 551: */ ! 552: switch (fmtspec) { ! 553: default: ! 554: panic("fmt2"); ! 555: case NIL: ! 556: if (fmt == 'c') { ! 557: if ( opt( 't' ) ) { ! 558: putleaf( P2ICON , 0 , 0 ! 559: , ADDTYPE( P2FTN|P2INT , P2PTR ) ! 560: , "_WRITEC" ); ! 561: putRV( 0 , cbn , CURFILEOFFSET , ! 562: NLOCAL , P2PTR|P2STRTY ); ! 563: stkrval( alv , NIL , RREQ ); ! 564: putop( P2LISTOP , P2INT ); ! 565: } else { ! 566: putleaf( P2ICON , 0 , 0 ! 567: , ADDTYPE( P2FTN|P2INT , P2PTR ) ! 568: , "_fputc" ); ! 569: stkrval( alv , NIL , RREQ ); ! 570: } ! 571: putleaf( P2ICON , 0 , 0 ! 572: , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 573: , "_ACTFILE" ); ! 574: putRV( 0, cbn , CURFILEOFFSET , ! 575: NLOCAL , P2PTR|P2STRTY ); ! 576: putop( P2CALL , P2INT ); ! 577: putop( P2LISTOP , P2INT ); ! 578: putop( P2CALL , P2INT ); ! 579: putdot( filename , line ); ! 580: } else { ! 581: sprintf(&format[1], "%%%c", fmt); ! 582: goto fmtgen; ! 583: } ! 584: case SKIP: ! 585: break; ! 586: case CONWIDTH: ! 587: sprintf(&format[1], "%%%1D%c", field, fmt); ! 588: goto fmtgen; ! 589: case VARWIDTH: ! 590: sprintf(&format[1], "%%*%c", fmt); ! 591: goto fmtgen; ! 592: case CONWIDTH + CONPREC: ! 593: sprintf(&format[1], "%%%1D.%1D%c", field, prec, fmt); ! 594: goto fmtgen; ! 595: case CONWIDTH + VARPREC: ! 596: sprintf(&format[1], "%%%1D.*%c", field, fmt); ! 597: goto fmtgen; ! 598: case VARWIDTH + CONPREC: ! 599: sprintf(&format[1], "%%*.%1D%c", prec, fmt); ! 600: goto fmtgen; ! 601: case VARWIDTH + VARPREC: ! 602: sprintf(&format[1], "%%*.*%c", fmt); ! 603: fmtgen: ! 604: if ( opt( 't' ) ) { ! 605: putleaf( P2ICON , 0 , 0 ! 606: , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 607: , "_WRITEF" ); ! 608: putRV( 0 , cbn , CURFILEOFFSET , ! 609: NLOCAL , P2PTR|P2STRTY ); ! 610: putleaf( P2ICON , 0 , 0 ! 611: , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 612: , "_ACTFILE" ); ! 613: putRV( 0 , cbn , CURFILEOFFSET , ! 614: NLOCAL , P2PTR|P2STRTY ); ! 615: putop( P2CALL , P2INT ); ! 616: putop( P2LISTOP , P2INT ); ! 617: } else { ! 618: putleaf( P2ICON , 0 , 0 ! 619: , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 620: , "_fprintf" ); ! 621: putleaf( P2ICON , 0 , 0 ! 622: , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 623: , "_ACTFILE" ); ! 624: putRV( 0 , cbn , CURFILEOFFSET , ! 625: NLOCAL , P2PTR|P2STRTY ); ! 626: putop( P2CALL , P2INT ); ! 627: } ! 628: putCONG( &format[ fmtstart ] ! 629: , strlen( &format[ fmtstart ] ) ! 630: , LREQ ); ! 631: putop( P2LISTOP , P2INT ); ! 632: if ( fmtspec & VARWIDTH ) { ! 633: /* ! 634: * either ! 635: * ,(temp=width,MAX(temp,...)), ! 636: * or ! 637: * , MAX( width , ... ) , ! 638: */ ! 639: if ( ( typ == TDOUBLE && al[3] == NIL ) ! 640: || typ == TSTR ) { ! 641: soffset = sizes[cbn].curtmps; ! 642: tempnlp = tmpalloc(sizeof(long), ! 643: nl+T4INT, REGOK); ! 644: putRV( 0 , cbn , ! 645: tempnlp -> value[ NL_OFFS ] , ! 646: tempnlp -> extra_flags , P2INT ); ! 647: ap = stkrval( al[2] , NIL , RREQ ); ! 648: putop( P2ASSIGN , P2INT ); ! 649: putleaf( P2ICON , 0 , 0 ! 650: , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 651: , "_MAX" ); ! 652: putRV( 0 , cbn , ! 653: tempnlp -> value[ NL_OFFS ] , ! 654: tempnlp -> extra_flags , P2INT ); ! 655: } else { ! 656: if (opt('t') ! 657: || typ == TSTR || typ == TDOUBLE) { ! 658: putleaf( P2ICON , 0 , 0 ! 659: ,ADDTYPE( P2FTN | P2INT, P2PTR ) ! 660: ,"_MAX" ); ! 661: } ! 662: ap = stkrval( al[2] , NIL , RREQ ); ! 663: } ! 664: if (ap == NIL) ! 665: continue; ! 666: if (isnta(ap,"i")) { ! 667: error("First write width must be integer, not %s", nameof(ap)); ! 668: continue; ! 669: } ! 670: switch ( typ ) { ! 671: case TDOUBLE: ! 672: putleaf( P2ICON , REALSPC , 0 , P2INT , 0 ); ! 673: putop( P2LISTOP , P2INT ); ! 674: putleaf( P2ICON , 1 , 0 , P2INT , 0 ); ! 675: putop( P2LISTOP , P2INT ); ! 676: putop( P2CALL , P2INT ); ! 677: if ( al[3] == NIL ) { ! 678: /* ! 679: * finish up the comma op ! 680: */ ! 681: putop( P2COMOP , P2INT ); ! 682: fmtspec &= ~VARPREC; ! 683: putop( P2LISTOP , P2INT ); ! 684: putleaf( P2ICON , 0 , 0 ! 685: , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 686: , "_MAX" ); ! 687: putRV( 0 , cbn , ! 688: tempnlp -> value[ NL_OFFS ] , ! 689: tempnlp -> extra_flags , ! 690: P2INT ); ! 691: tmpfree(&soffset); ! 692: putleaf( P2ICON , ! 693: 5 + EXPOSIZE + REALSPC , ! 694: 0 , P2INT , 0 ); ! 695: putop( P2LISTOP , P2INT ); ! 696: putleaf( P2ICON , 1 , 0 , P2INT , 0 ); ! 697: putop( P2LISTOP , P2INT ); ! 698: putop( P2CALL , P2INT ); ! 699: } ! 700: putop( P2LISTOP , P2INT ); ! 701: break; ! 702: case TSTR: ! 703: putleaf( P2ICON , strnglen , 0 , P2INT , 0 ); ! 704: putop( P2LISTOP , P2INT ); ! 705: putleaf( P2ICON , 0 , 0 , P2INT , 0 ); ! 706: putop( P2LISTOP , P2INT ); ! 707: putop( P2CALL , P2INT ); ! 708: putop( P2COMOP , P2INT ); ! 709: putop( P2LISTOP , P2INT ); ! 710: break; ! 711: default: ! 712: if (opt('t')) { ! 713: putleaf( P2ICON , 0 , 0 , P2INT , 0 ); ! 714: putop( P2LISTOP , P2INT ); ! 715: putleaf( P2ICON , 0 , 0 , P2INT , 0 ); ! 716: putop( P2LISTOP , P2INT ); ! 717: putop( P2CALL , P2INT ); ! 718: } ! 719: putop( P2LISTOP , P2INT ); ! 720: break; ! 721: } ! 722: } ! 723: /* ! 724: * If there is a variable precision, ! 725: * evaluate it ! 726: */ ! 727: if (fmtspec & VARPREC) { ! 728: if (opt('t')) { ! 729: putleaf( P2ICON , 0 , 0 ! 730: , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 731: , "_MAX" ); ! 732: } ! 733: ap = stkrval( al[3] , NIL , RREQ ); ! 734: if (ap == NIL) ! 735: continue; ! 736: if (isnta(ap,"i")) { ! 737: error("Second write width must be integer, not %s", nameof(ap)); ! 738: continue; ! 739: } ! 740: if (opt('t')) { ! 741: putleaf( P2ICON , 0 , 0 , P2INT , 0 ); ! 742: putop( P2LISTOP , P2INT ); ! 743: putleaf( P2ICON , 0 , 0 , P2INT , 0 ); ! 744: putop( P2LISTOP , P2INT ); ! 745: putop( P2CALL , P2INT ); ! 746: } ! 747: putop( P2LISTOP , P2INT ); ! 748: } ! 749: /* ! 750: * evaluate the thing we want printed. ! 751: */ ! 752: switch ( typ ) { ! 753: case TPTR: ! 754: case TCHAR: ! 755: case TINT: ! 756: stkrval( alv , NIL , RREQ ); ! 757: putop( P2LISTOP , P2INT ); ! 758: break; ! 759: case TDOUBLE: ! 760: ap = stkrval( alv , NIL , RREQ ); ! 761: if (isnta(ap, "d")) { ! 762: sconv(p2type(ap), P2DOUBLE); ! 763: } ! 764: putop( P2LISTOP , P2INT ); ! 765: break; ! 766: case TSCAL: ! 767: case TBOOL: ! 768: putleaf( P2ICON , 0 , 0 ! 769: , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 770: , "_NAM" ); ! 771: ap = stkrval( alv , NIL , RREQ ); ! 772: sprintf( format , PREFIXFORMAT , LABELPREFIX ! 773: , listnames( ap ) ); ! 774: putleaf( P2ICON , 0 , 0 , P2PTR | P2CHAR ! 775: , format ); ! 776: putop( P2LISTOP , P2INT ); ! 777: putop( P2CALL , P2INT ); ! 778: putop( P2LISTOP , P2INT ); ! 779: break; ! 780: case TSTR: ! 781: putCONG( "" , 0 , LREQ ); ! 782: putop( P2LISTOP , P2INT ); ! 783: break; ! 784: default: ! 785: panic("fmt3"); ! 786: break; ! 787: } ! 788: putop( P2CALL , P2INT ); ! 789: putdot( filename , line ); ! 790: } ! 791: /* ! 792: * Write the string after its blank padding ! 793: */ ! 794: if (typ == TSTR ) { ! 795: if ( opt( 't' ) ) { ! 796: putleaf( P2ICON , 0 , 0 ! 797: , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 798: , "_WRITES" ); ! 799: putRV( 0 , cbn , CURFILEOFFSET , ! 800: NLOCAL , P2PTR|P2STRTY ); ! 801: ap = stkrval(alv, NIL , RREQ ); ! 802: putop( P2LISTOP , P2INT ); ! 803: } else { ! 804: putleaf( P2ICON , 0 , 0 ! 805: , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 806: , "_fwrite" ); ! 807: ap = stkrval(alv, NIL , RREQ ); ! 808: } ! 809: if (strfmt & VARWIDTH) { ! 810: /* ! 811: * min, inline expanded as ! 812: * temp < len ? temp : len ! 813: */ ! 814: putRV( 0 , cbn , ! 815: tempnlp -> value[ NL_OFFS ] , ! 816: tempnlp -> extra_flags , P2INT ); ! 817: putleaf( P2ICON , strnglen , 0 , P2INT , 0 ); ! 818: putop( P2LT , P2INT ); ! 819: putRV( 0 , cbn , ! 820: tempnlp -> value[ NL_OFFS ] , ! 821: tempnlp -> extra_flags , P2INT ); ! 822: putleaf( P2ICON , strnglen , 0 , P2INT , 0 ); ! 823: putop( P2COLON , P2INT ); ! 824: putop( P2QUEST , P2INT ); ! 825: tmpfree(&soffset); ! 826: } else { ! 827: if ( ( fmtspec & SKIP ) ! 828: && ( strfmt & CONWIDTH ) ) { ! 829: strnglen = field; ! 830: } ! 831: putleaf( P2ICON , strnglen , 0 , P2INT , 0 ); ! 832: } ! 833: putop( P2LISTOP , P2INT ); ! 834: putleaf( P2ICON , 1 , 0 , P2INT , 0 ); ! 835: putop( P2LISTOP , P2INT ); ! 836: putleaf( P2ICON , 0 , 0 ! 837: , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 838: , "_ACTFILE" ); ! 839: putRV( 0, cbn , CURFILEOFFSET , NLOCAL , ! 840: P2PTR|P2STRTY ); ! 841: putop( P2CALL , P2INT ); ! 842: putop( P2LISTOP , P2INT ); ! 843: putop( P2CALL , P2INT ); ! 844: putdot( filename , line ); ! 845: } ! 846: } ! 847: /* ! 848: * Done with arguments. ! 849: * Handle writeln and ! 850: * insufficent number of args. ! 851: */ ! 852: switch (p->value[0] &~ NSTAND) { ! 853: case O_WRITEF: ! 854: if (argc == 0) ! 855: error("Write requires an argument"); ! 856: break; ! 857: case O_MESSAGE: ! 858: if (argc == 0) ! 859: error("Message requires an argument"); ! 860: case O_WRITLN: ! 861: if (filetype != nl+T1CHAR) ! 862: error("Can't 'writeln' a non text file"); ! 863: if ( opt( 't' ) ) { ! 864: putleaf( P2ICON , 0 , 0 ! 865: , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 866: , "_WRITLN" ); ! 867: putRV( 0 , cbn , CURFILEOFFSET , ! 868: NLOCAL , P2PTR|P2STRTY ); ! 869: } else { ! 870: putleaf( P2ICON , 0 , 0 ! 871: , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 872: , "_fputc" ); ! 873: putleaf( P2ICON , '\n' , 0 , P2CHAR , 0 ); ! 874: putleaf( P2ICON , 0 , 0 ! 875: , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 876: , "_ACTFILE" ); ! 877: putRV( 0 , cbn , CURFILEOFFSET , ! 878: NLOCAL , P2PTR|P2STRTY ); ! 879: putop( P2CALL , P2INT ); ! 880: putop( P2LISTOP , P2INT ); ! 881: } ! 882: putop( P2CALL , P2INT ); ! 883: putdot( filename , line ); ! 884: break; ! 885: } ! 886: return; ! 887: ! 888: case O_READ4: ! 889: case O_READLN: ! 890: /* ! 891: * Set up default ! 892: * file "input". ! 893: */ ! 894: file = NIL; ! 895: filetype = nl+T1CHAR; ! 896: /* ! 897: * Determine the file implied ! 898: * for the read and generate ! 899: * code to make it the active file. ! 900: */ ! 901: if (argv != NIL) { ! 902: codeoff(); ! 903: ap = stkrval(argv[1], NIL , RREQ ); ! 904: codeon(); ! 905: if (ap == NIL) ! 906: argv = argv[2]; ! 907: if (ap != NIL && ap->class == FILET) { ! 908: /* ! 909: * Got "read(f, ...", make ! 910: * f the active file, and save ! 911: * it and its type for use in ! 912: * processing the rest of the ! 913: * arguments to read. ! 914: */ ! 915: file = argv[1]; ! 916: filetype = ap->type; ! 917: putRV( 0, cbn , CURFILEOFFSET , NLOCAL , ! 918: P2PTR|P2STRTY ); ! 919: putleaf( P2ICON , 0 , 0 ! 920: , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 921: , "_UNIT" ); ! 922: stklval(argv[1], NOFLAGS); ! 923: putop( P2CALL , P2INT ); ! 924: putop( P2ASSIGN , P2PTR|P2STRTY ); ! 925: putdot( filename , line ); ! 926: argv = argv[2]; ! 927: argc--; ! 928: } else { ! 929: /* ! 930: * Default is read from ! 931: * standard input. ! 932: */ ! 933: putRV( 0, cbn , CURFILEOFFSET , NLOCAL , ! 934: P2PTR|P2STRTY ); ! 935: putLV( "_input" , 0 , 0 , NGLOBAL , ! 936: P2PTR|P2STRTY ); ! 937: putop( P2ASSIGN , P2PTR|P2STRTY ); ! 938: putdot( filename , line ); ! 939: input->nl_flags |= NUSED; ! 940: } ! 941: } else { ! 942: putRV( 0, cbn , CURFILEOFFSET , NLOCAL , ! 943: P2PTR|P2STRTY ); ! 944: putLV( "_input" , 0 , 0 , NGLOBAL , P2PTR|P2STRTY ); ! 945: putop( P2ASSIGN , P2PTR|P2STRTY ); ! 946: putdot( filename , line ); ! 947: input->nl_flags |= NUSED; ! 948: } ! 949: /* ! 950: * Loop and process each ! 951: * of the arguments. ! 952: */ ! 953: for (; argv != NIL; argv = argv[2]) { ! 954: /* ! 955: * Get the address of the target ! 956: * on the stack. ! 957: */ ! 958: al = argv[1]; ! 959: if (al == NIL) ! 960: continue; ! 961: if (al[0] != T_VAR) { ! 962: error("Arguments to %s must be variables, not expressions", p->symbol); ! 963: continue; ! 964: } ! 965: codeoff(); ! 966: ap = stklval(al, MOD|ASGN|NOUSE); ! 967: codeon(); ! 968: if (ap == NIL) ! 969: continue; ! 970: if (filetype != nl+T1CHAR) { ! 971: /* ! 972: * Generalized read, i.e. ! 973: * from a non-textfile. ! 974: */ ! 975: if (incompat(filetype, ap, argv[1] )) { ! 976: error("Type mismatch in read from non-text file"); ! 977: continue; ! 978: } ! 979: /* ! 980: * var := file ^; ! 981: */ ! 982: ap = lvalue( al , MOD | ASGN | NOUSE , RREQ ); ! 983: if ( isa( ap , "bsci" ) ) { ! 984: precheck( ap , "_RANG4" , "_RSNG4" ); ! 985: } ! 986: putleaf( P2ICON , 0 , 0 ! 987: , ADDTYPE( ! 988: ADDTYPE( ! 989: ADDTYPE( ! 990: p2type( filetype ) , P2PTR ) ! 991: , P2FTN ) ! 992: , P2PTR ) ! 993: , "_FNIL" ); ! 994: if (file != NIL) ! 995: stklval(file, NOFLAGS); ! 996: else /* Magic */ ! 997: putRV( "_input" , 0 , 0 , NGLOBAL , ! 998: P2PTR | P2STRTY ); ! 999: putop(P2CALL, ADDTYPE(p2type(filetype), P2PTR)); ! 1000: switch ( classify( filetype ) ) { ! 1001: case TBOOL: ! 1002: case TCHAR: ! 1003: case TINT: ! 1004: case TSCAL: ! 1005: case TDOUBLE: ! 1006: case TPTR: ! 1007: putop( P2UNARY P2MUL ! 1008: , p2type( filetype ) ); ! 1009: } ! 1010: switch ( classify( filetype ) ) { ! 1011: case TBOOL: ! 1012: case TCHAR: ! 1013: case TINT: ! 1014: case TSCAL: ! 1015: postcheck(ap, filetype); ! 1016: sconv(p2type(filetype), p2type(ap)); ! 1017: /* and fall through */ ! 1018: case TDOUBLE: ! 1019: case TPTR: ! 1020: putop( P2ASSIGN , p2type( ap ) ); ! 1021: putdot( filename , line ); ! 1022: break; ! 1023: default: ! 1024: putstrop(P2STASG, ! 1025: ADDTYPE(p2type(ap), P2PTR), ! 1026: lwidth(ap), ! 1027: align(ap)); ! 1028: putdot( filename , line ); ! 1029: break; ! 1030: } ! 1031: /* ! 1032: * get(file); ! 1033: */ ! 1034: putleaf( P2ICON , 0 , 0 ! 1035: , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 1036: , "_GET" ); ! 1037: putRV( 0 , cbn , CURFILEOFFSET , NLOCAL , ! 1038: P2PTR|P2STRTY ); ! 1039: putop( P2CALL , P2INT ); ! 1040: putdot( filename , line ); ! 1041: continue; ! 1042: } ! 1043: /* ! 1044: * if you get to here, you are reading from ! 1045: * a text file. only possiblities are: ! 1046: * character, integer, real, or scalar. ! 1047: * read( f , foo , ... ) is done as ! 1048: * foo := read( f ) with rangechecking ! 1049: * if appropriate. ! 1050: */ ! 1051: typ = classify(ap); ! 1052: op = rdops(typ); ! 1053: if (op == NIL) { ! 1054: error("Can't read %ss from a text file", clnames[typ]); ! 1055: continue; ! 1056: } ! 1057: /* ! 1058: * left hand side of foo := read( f ) ! 1059: */ ! 1060: ap = lvalue( al , MOD|ASGN|NOUSE , RREQ ); ! 1061: if ( isa( ap , "bsci" ) ) { ! 1062: precheck( ap , "_RANG4" , "_RSNG4" ); ! 1063: } ! 1064: switch ( op ) { ! 1065: case O_READC: ! 1066: readname = "_READC"; ! 1067: readtype = P2INT; ! 1068: break; ! 1069: case O_READ4: ! 1070: readname = "_READ4"; ! 1071: readtype = P2INT; ! 1072: break; ! 1073: case O_READ8: ! 1074: readname = "_READ8"; ! 1075: readtype = P2DOUBLE; ! 1076: break; ! 1077: case O_READE: ! 1078: readname = "_READE"; ! 1079: readtype = P2INT; ! 1080: break; ! 1081: } ! 1082: putleaf( P2ICON , 0 , 0 ! 1083: , ADDTYPE( P2FTN | readtype , P2PTR ) ! 1084: , readname ); ! 1085: putRV( 0 , cbn , CURFILEOFFSET , NLOCAL , ! 1086: P2PTR|P2STRTY ); ! 1087: if ( op == O_READE ) { ! 1088: sprintf( format , PREFIXFORMAT , LABELPREFIX ! 1089: , listnames( ap ) ); ! 1090: putleaf( P2ICON , 0 , 0 , P2PTR | P2CHAR ! 1091: , format ); ! 1092: putop( P2LISTOP , P2INT ); ! 1093: warning(); ! 1094: if (opt('s')) { ! 1095: standard(); ! 1096: } ! 1097: error("Reading scalars from text files is non-standard"); ! 1098: } ! 1099: putop( P2CALL , readtype ); ! 1100: if ( isa( ap , "bcsi" ) ) { ! 1101: postcheck(ap, readtype==P2INT?nl+T4INT:nl+TDOUBLE); ! 1102: } ! 1103: sconv(readtype, p2type(ap)); ! 1104: putop( P2ASSIGN , p2type( ap ) ); ! 1105: putdot( filename , line ); ! 1106: } ! 1107: /* ! 1108: * Done with arguments. ! 1109: * Handle readln and ! 1110: * insufficient number of args. ! 1111: */ ! 1112: if (p->value[0] == O_READLN) { ! 1113: if (filetype != nl+T1CHAR) ! 1114: error("Can't 'readln' a non text file"); ! 1115: putleaf( P2ICON , 0 , 0 ! 1116: , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 1117: , "_READLN" ); ! 1118: putRV( 0 , cbn , CURFILEOFFSET , NLOCAL , ! 1119: P2PTR|P2STRTY ); ! 1120: putop( P2CALL , P2INT ); ! 1121: putdot( filename , line ); ! 1122: } else if (argc == 0) ! 1123: error("read requires an argument"); ! 1124: return; ! 1125: ! 1126: case O_GET: ! 1127: case O_PUT: ! 1128: if (argc != 1) { ! 1129: error("%s expects one argument", p->symbol); ! 1130: return; ! 1131: } ! 1132: putRV( 0 , cbn , CURFILEOFFSET , NLOCAL , P2PTR|P2STRTY ); ! 1133: putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 1134: , "_UNIT" ); ! 1135: ap = stklval(argv[1], NOFLAGS); ! 1136: if (ap == NIL) ! 1137: return; ! 1138: if (ap->class != FILET) { ! 1139: error("Argument to %s must be a file, not %s", p->symbol, nameof(ap)); ! 1140: return; ! 1141: } ! 1142: putop( P2CALL , P2INT ); ! 1143: putop( P2ASSIGN , P2PTR|P2STRTY ); ! 1144: putdot( filename , line ); ! 1145: putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 1146: , op == O_GET ? "_GET" : "_PUT" ); ! 1147: putRV( 0 , cbn , CURFILEOFFSET , NLOCAL , P2PTR|P2STRTY ); ! 1148: putop( P2CALL , P2INT ); ! 1149: putdot( filename , line ); ! 1150: return; ! 1151: ! 1152: case O_RESET: ! 1153: case O_REWRITE: ! 1154: if (argc == 0 || argc > 2) { ! 1155: error("%s expects one or two arguments", p->symbol); ! 1156: return; ! 1157: } ! 1158: if (opt('s') && argc == 2) { ! 1159: standard(); ! 1160: error("Two argument forms of reset and rewrite are non-standard"); ! 1161: } ! 1162: putleaf( P2ICON , 0 , 0 , P2INT ! 1163: , op == O_RESET ? "_RESET" : "_REWRITE" ); ! 1164: ap = stklval(argv[1], MOD|NOUSE); ! 1165: if (ap == NIL) ! 1166: return; ! 1167: if (ap->class != FILET) { ! 1168: error("First argument to %s must be a file, not %s", p->symbol, nameof(ap)); ! 1169: return; ! 1170: } ! 1171: if (argc == 2) { ! 1172: /* ! 1173: * Optional second argument ! 1174: * is a string name of a ! 1175: * UNIX (R) file to be associated. ! 1176: */ ! 1177: al = argv[2]; ! 1178: al = stkrval(al[1], NOFLAGS , RREQ ); ! 1179: if (al == NIL) ! 1180: return; ! 1181: if (classify(al) != TSTR) { ! 1182: error("Second argument to %s must be a string, not %s", p->symbol, nameof(al)); ! 1183: return; ! 1184: } ! 1185: strnglen = width(al); ! 1186: } else { ! 1187: putleaf( P2ICON , 0 , 0 , P2INT , 0 ); ! 1188: strnglen = 0; ! 1189: } ! 1190: putop( P2LISTOP , P2INT ); ! 1191: putleaf( P2ICON , strnglen , 0 , P2INT , 0 ); ! 1192: putop( P2LISTOP , P2INT ); ! 1193: putleaf( P2ICON , text(ap) ? 0: width(ap->type) , 0 , P2INT , 0 ); ! 1194: putop( P2LISTOP , P2INT ); ! 1195: putop( P2CALL , P2INT ); ! 1196: putdot( filename , line ); ! 1197: return; ! 1198: ! 1199: case O_NEW: ! 1200: case O_DISPOSE: ! 1201: if (argc == 0) { ! 1202: error("%s expects at least one argument", p->symbol); ! 1203: return; ! 1204: } ! 1205: alv = argv[1]; ! 1206: codeoff(); ! 1207: ap = stklval(alv, op == O_NEW ? ( MOD | NOUSE ) : MOD ); ! 1208: codeon(); ! 1209: if (ap == NIL) ! 1210: return; ! 1211: if (ap->class != PTR) { ! 1212: error("(First) argument to %s must be a pointer, not %s", p->symbol, nameof(ap)); ! 1213: return; ! 1214: } ! 1215: ap = ap->type; ! 1216: if (ap == NIL) ! 1217: return; ! 1218: if (op == O_NEW) ! 1219: cmd = "_NEW"; ! 1220: else /* op == O_DISPOSE */ ! 1221: if ((ap->nl_flags & NFILES) != 0) ! 1222: cmd = "_DFDISPOSE"; ! 1223: else ! 1224: cmd = "_DISPOSE"; ! 1225: putleaf( P2ICON, 0, 0, ADDTYPE( P2FTN | P2INT , P2PTR ), cmd); ! 1226: stklval(alv, op == O_NEW ? ( MOD | NOUSE ) : MOD ); ! 1227: argv = argv[2]; ! 1228: if (argv != NIL) { ! 1229: if (ap->class != RECORD) { ! 1230: error("Record required when specifying variant tags"); ! 1231: return; ! 1232: } ! 1233: for (; argv != NIL; argv = argv[2]) { ! 1234: if (ap->ptr[NL_VARNT] == NIL) { ! 1235: error("Too many tag fields"); ! 1236: return; ! 1237: } ! 1238: if (!isconst(argv[1])) { ! 1239: error("Second and successive arguments to %s must be constants", p->symbol); ! 1240: return; ! 1241: } ! 1242: gconst(argv[1]); ! 1243: if (con.ctype == NIL) ! 1244: return; ! 1245: if (incompat(con.ctype, (ap->ptr[NL_TAG])->type , NIL )) { ! 1246: cerror("Specified tag constant type clashed with variant case selector type"); ! 1247: return; ! 1248: } ! 1249: for (ap = ap->ptr[NL_VARNT]; ap != NIL; ap = ap->chain) ! 1250: if (ap->range[0] == con.crval) ! 1251: break; ! 1252: if (ap == NIL) { ! 1253: error("No variant case label value equals specified constant value"); ! 1254: return; ! 1255: } ! 1256: ap = ap->ptr[NL_VTOREC]; ! 1257: } ! 1258: } ! 1259: putleaf( P2ICON , width( ap ) , 0 , P2INT , 0 ); ! 1260: putop( P2LISTOP , P2INT ); ! 1261: putop( P2CALL , P2INT ); ! 1262: putdot( filename , line ); ! 1263: if (opt('t') && op == O_NEW) { ! 1264: putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 1265: , "_blkclr" ); ! 1266: stkrval(alv, NIL , RREQ ); ! 1267: putleaf( P2ICON , width( ap ) , 0 , P2INT , 0 ); ! 1268: putop( P2LISTOP , P2INT ); ! 1269: putop( P2CALL , P2INT ); ! 1270: putdot( filename , line ); ! 1271: } ! 1272: return; ! 1273: ! 1274: case O_DATE: ! 1275: case O_TIME: ! 1276: if (argc != 1) { ! 1277: error("%s expects one argument", p->symbol); ! 1278: return; ! 1279: } ! 1280: putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 1281: , op == O_DATE ? "_DATE" : "_TIME" ); ! 1282: ap = stklval(argv[1], MOD|NOUSE); ! 1283: if (ap == NIL) ! 1284: return; ! 1285: if (classify(ap) != TSTR || width(ap) != 10) { ! 1286: error("Argument to %s must be a alfa, not %s", p->symbol, nameof(ap)); ! 1287: return; ! 1288: } ! 1289: putop( P2CALL , P2INT ); ! 1290: putdot( filename , line ); ! 1291: return; ! 1292: ! 1293: case O_HALT: ! 1294: if (argc != 0) { ! 1295: error("halt takes no arguments"); ! 1296: return; ! 1297: } ! 1298: putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 1299: , "_HALT" ); ! 1300: ! 1301: putop( P2UNARY P2CALL , P2INT ); ! 1302: putdot( filename , line ); ! 1303: noreach = 1; ! 1304: return; ! 1305: ! 1306: case O_ARGV: ! 1307: if (argc != 2) { ! 1308: error("argv takes two arguments"); ! 1309: return; ! 1310: } ! 1311: putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 1312: , "_ARGV" ); ! 1313: ap = stkrval(argv[1], NIL , RREQ ); ! 1314: if (ap == NIL) ! 1315: return; ! 1316: if (isnta(ap, "i")) { ! 1317: error("argv's first argument must be an integer, not %s", nameof(ap)); ! 1318: return; ! 1319: } ! 1320: al = argv[2]; ! 1321: ap = stklval(al[1], MOD|NOUSE); ! 1322: if (ap == NIL) ! 1323: return; ! 1324: if (classify(ap) != TSTR) { ! 1325: error("argv's second argument must be a string, not %s", nameof(ap)); ! 1326: return; ! 1327: } ! 1328: putop( P2LISTOP , P2INT ); ! 1329: putleaf( P2ICON , width( ap ) , 0 , P2INT , 0 ); ! 1330: putop( P2LISTOP , P2INT ); ! 1331: putop( P2CALL , P2INT ); ! 1332: putdot( filename , line ); ! 1333: return; ! 1334: ! 1335: case O_STLIM: ! 1336: if (argc != 1) { ! 1337: error("stlimit requires one argument"); ! 1338: return; ! 1339: } ! 1340: putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 1341: , "_STLIM" ); ! 1342: ap = stkrval(argv[1], NIL , RREQ ); ! 1343: if (ap == NIL) ! 1344: return; ! 1345: if (isnta(ap, "i")) { ! 1346: error("stlimit's argument must be an integer, not %s", nameof(ap)); ! 1347: return; ! 1348: } ! 1349: putop( P2CALL , P2INT ); ! 1350: putdot( filename , line ); ! 1351: return; ! 1352: ! 1353: case O_REMOVE: ! 1354: if (argc != 1) { ! 1355: error("remove expects one argument"); ! 1356: return; ! 1357: } ! 1358: putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 1359: , "_REMOVE" ); ! 1360: ap = stkrval(argv[1], NOFLAGS , RREQ ); ! 1361: if (ap == NIL) ! 1362: return; ! 1363: if (classify(ap) != TSTR) { ! 1364: error("remove's argument must be a string, not %s", nameof(ap)); ! 1365: return; ! 1366: } ! 1367: putleaf( P2ICON , width( ap ) , 0 , P2INT , 0 ); ! 1368: putop( P2LISTOP , P2INT ); ! 1369: putop( P2CALL , P2INT ); ! 1370: putdot( filename , line ); ! 1371: return; ! 1372: ! 1373: case O_LLIMIT: ! 1374: if (argc != 2) { ! 1375: error("linelimit expects two arguments"); ! 1376: return; ! 1377: } ! 1378: putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 1379: , "_LLIMIT" ); ! 1380: ap = stklval(argv[1], NOFLAGS|NOUSE); ! 1381: if (ap == NIL) ! 1382: return; ! 1383: if (!text(ap)) { ! 1384: error("linelimit's first argument must be a text file, not %s", nameof(ap)); ! 1385: return; ! 1386: } ! 1387: al = argv[2]; ! 1388: ap = stkrval(al[1], NIL , RREQ ); ! 1389: if (ap == NIL) ! 1390: return; ! 1391: if (isnta(ap, "i")) { ! 1392: error("linelimit's second argument must be an integer, not %s", nameof(ap)); ! 1393: return; ! 1394: } ! 1395: putop( P2LISTOP , P2INT ); ! 1396: putop( P2CALL , P2INT ); ! 1397: putdot( filename , line ); ! 1398: return; ! 1399: case O_PAGE: ! 1400: if (argc != 1) { ! 1401: error("page expects one argument"); ! 1402: return; ! 1403: } ! 1404: putRV( 0 , cbn , CURFILEOFFSET , NLOCAL , P2PTR|P2STRTY ); ! 1405: putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 1406: , "_UNIT" ); ! 1407: ap = stklval(argv[1], NOFLAGS); ! 1408: if (ap == NIL) ! 1409: return; ! 1410: if (!text(ap)) { ! 1411: error("Argument to page must be a text file, not %s", nameof(ap)); ! 1412: return; ! 1413: } ! 1414: putop( P2CALL , P2INT ); ! 1415: putop( P2ASSIGN , P2PTR|P2STRTY ); ! 1416: putdot( filename , line ); ! 1417: if ( opt( 't' ) ) { ! 1418: putleaf( P2ICON , 0 , 0 ! 1419: , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 1420: , "_PAGE" ); ! 1421: putRV( 0 , cbn , CURFILEOFFSET , NLOCAL , P2PTR|P2STRTY ); ! 1422: } else { ! 1423: putleaf( P2ICON , 0 , 0 ! 1424: , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 1425: , "_fputc" ); ! 1426: putleaf( P2ICON , '\f' , 0 , P2CHAR , 0 ); ! 1427: putleaf( P2ICON , 0 , 0 ! 1428: , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 1429: , "_ACTFILE" ); ! 1430: putRV( 0 , cbn , CURFILEOFFSET , NLOCAL , P2PTR|P2STRTY ); ! 1431: putop( P2CALL , P2INT ); ! 1432: putop( P2LISTOP , P2INT ); ! 1433: } ! 1434: putop( P2CALL , P2INT ); ! 1435: putdot( filename , line ); ! 1436: return; ! 1437: ! 1438: case O_ASRT: ! 1439: if (!opt('t')) ! 1440: return; ! 1441: if (argc == 0 || argc > 2) { ! 1442: error("Assert expects one or two arguments"); ! 1443: return; ! 1444: } ! 1445: if (argc == 2) ! 1446: cmd = "_ASRTS"; ! 1447: else ! 1448: cmd = "_ASRT"; ! 1449: putleaf( P2ICON , 0 , 0 ! 1450: , ADDTYPE( P2FTN | P2INT , P2PTR ) , cmd ); ! 1451: ap = stkrval(argv[1], NIL , RREQ ); ! 1452: if (ap == NIL) ! 1453: return; ! 1454: if (isnta(ap, "b")) ! 1455: error("Assert expression must be Boolean, not %ss", nameof(ap)); ! 1456: if (argc == 2) { ! 1457: /* ! 1458: * Optional second argument is a string specifying ! 1459: * why the assertion failed. ! 1460: */ ! 1461: al = argv[2]; ! 1462: al = stkrval(al[1], NIL , RREQ ); ! 1463: if (al == NIL) ! 1464: return; ! 1465: if (classify(al) != TSTR) { ! 1466: error("Second argument to assert must be a string, not %s", nameof(al)); ! 1467: return; ! 1468: } ! 1469: putop( P2LISTOP , P2INT ); ! 1470: } ! 1471: putop( P2CALL , P2INT ); ! 1472: putdot( filename , line ); ! 1473: return; ! 1474: ! 1475: case O_PACK: ! 1476: if (argc != 3) { ! 1477: error("pack expects three arguments"); ! 1478: return; ! 1479: } ! 1480: putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 1481: , "_PACK" ); ! 1482: pu = "pack(a,i,z)"; ! 1483: pua = (al = argv)[1]; ! 1484: pui = (al = al[2])[1]; ! 1485: puz = (al = al[2])[1]; ! 1486: goto packunp; ! 1487: case O_UNPACK: ! 1488: if (argc != 3) { ! 1489: error("unpack expects three arguments"); ! 1490: return; ! 1491: } ! 1492: putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 1493: , "_UNPACK" ); ! 1494: pu = "unpack(z,a,i)"; ! 1495: puz = (al = argv)[1]; ! 1496: pua = (al = al[2])[1]; ! 1497: pui = (al = al[2])[1]; ! 1498: packunp: ! 1499: ap = stkrval((int *) pui, NLNIL , RREQ ); ! 1500: if (ap == NIL) ! 1501: return; ! 1502: ap = stklval(pua, op == O_PACK ? NOFLAGS : MOD|NOUSE); ! 1503: if (ap == NIL) ! 1504: return; ! 1505: if (ap->class != ARRAY) { ! 1506: error("%s requires a to be an unpacked array, not %s", pu, nameof(ap)); ! 1507: return; ! 1508: } ! 1509: putop( P2LISTOP , P2INT ); ! 1510: al = (struct nl *) stklval(puz, op == O_UNPACK ? NOFLAGS : MOD|NOUSE); ! 1511: if (al->class != ARRAY) { ! 1512: error("%s requires z to be a packed array, not %s", pu, nameof(ap)); ! 1513: return; ! 1514: } ! 1515: if (al->type == NIL || ap->type == NIL) ! 1516: return; ! 1517: if (al->type != ap->type) { ! 1518: error("%s requires a and z to be arrays of the same type", pu, nameof(ap)); ! 1519: return; ! 1520: } ! 1521: putop( P2LISTOP , P2INT ); ! 1522: k = width(al); ! 1523: itemwidth = width(ap->type); ! 1524: ap = ap->chain; ! 1525: al = al->chain; ! 1526: if (ap->chain != NIL || al->chain != NIL) { ! 1527: error("%s requires a and z to be single dimension arrays", pu); ! 1528: return; ! 1529: } ! 1530: if (ap == NIL || al == NIL) ! 1531: return; ! 1532: /* ! 1533: * al is the range for z i.e. u..v ! 1534: * ap is the range for a i.e. m..n ! 1535: * i will be n-m+1 ! 1536: * j will be v-u+1 ! 1537: */ ! 1538: i = ap->range[1] - ap->range[0] + 1; ! 1539: j = al->range[1] - al->range[0] + 1; ! 1540: if (i < j) { ! 1541: error("%s cannot have more elements in a (%d) than in z (%d)", pu, j, i); ! 1542: return; ! 1543: } ! 1544: /* ! 1545: * get n-m-(v-u) and m for the interpreter ! 1546: */ ! 1547: i -= j; ! 1548: j = ap->range[0]; ! 1549: putleaf( P2ICON , itemwidth , 0 , P2INT , 0 ); ! 1550: putop( P2LISTOP , P2INT ); ! 1551: putleaf( P2ICON , j , 0 , P2INT , 0 ); ! 1552: putop( P2LISTOP , P2INT ); ! 1553: putleaf( P2ICON , i , 0 , P2INT , 0 ); ! 1554: putop( P2LISTOP , P2INT ); ! 1555: putleaf( P2ICON , k , 0 , P2INT , 0 ); ! 1556: putop( P2LISTOP , P2INT ); ! 1557: putop( P2CALL , P2INT ); ! 1558: putdot( filename , line ); ! 1559: return; ! 1560: case 0: ! 1561: error("%s is an unimplemented extension", p->symbol); ! 1562: return; ! 1563: ! 1564: default: ! 1565: panic("proc case"); ! 1566: } ! 1567: } ! 1568: #endif PC
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.