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