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 = "@(#)io.c 5.3 (Berkeley) 3/9/86"; 9: #endif 10: 11: /* 12: * io.c 13: * 14: * Routines to generate code for I/O statements. 15: * Some corrections and improvements due to David Wasley, U. C. Berkeley 16: * 17: * University of Utah CS Dept modification history: 18: * 19: * $Header: io.c,v 5.3 86/03/04 17:45:33 donn Exp $ 20: * $Log: io.c,v $ 21: * Revision 5.3 86/03/04 17:45:33 donn 22: * Change the order of length and offset code in startrw() -- always emit 23: * the memoffset first, since it may define a temporary which is used in 24: * the length expression. 25: * 26: * Revision 5.2 85/12/19 17:22:35 donn 27: * Don't permit more than one 'positional iocontrol' parameter unless we 28: * are doing a READ or a WRITE. 29: * 30: * Revision 5.1 85/08/10 03:47:42 donn 31: * 4.3 alpha 32: * 33: * Revision 2.4 85/02/23 21:09:02 donn 34: * Jerry Berkman's compiled format fixes move setfmt into a separate file. 35: * 36: * Revision 2.3 85/01/10 22:33:41 donn 37: * Added some strategic cpexpr()s to prevent memory management bugs. 38: * 39: * Revision 2.2 84/08/04 21:15:47 donn 40: * Removed code that creates extra statement labels, per Jerry Berkman's 41: * fixes to make ASSIGNs work right. 42: * 43: * Revision 2.1 84/07/19 12:03:33 donn 44: * Changed comment headers for UofU. 45: * 46: * Revision 1.2 84/02/26 06:35:57 donn 47: * Added Berkeley changes necessary for shortening offsets to data. 48: * 49: */ 50: 51: /* TEMPORARY */ 52: #define TYIOINT TYLONG 53: #define SZIOINT SZLONG 54: 55: #include "defs.h" 56: #include "io.h" 57: 58: 59: LOCAL char ioroutine[XL+1]; 60: 61: LOCAL int ioendlab; 62: LOCAL int ioerrlab; 63: LOCAL int endbit; 64: LOCAL int errbit; 65: LOCAL int jumplab; 66: LOCAL int skiplab; 67: LOCAL int ioformatted; 68: LOCAL int statstruct = NO; 69: LOCAL ftnint blklen; 70: 71: LOCAL offsetlist *mkiodata(); 72: 73: 74: #define UNFORMATTED 0 75: #define FORMATTED 1 76: #define LISTDIRECTED 2 77: #define NAMEDIRECTED 3 78: 79: #define V(z) ioc[z].iocval 80: 81: #define IOALL 07777 82: 83: LOCAL struct Ioclist 84: { 85: char *iocname; 86: int iotype; 87: expptr iocval; 88: } ioc[ ] = 89: { 90: { "", 0 }, 91: { "unit", IOALL }, 92: { "fmt", M(IOREAD) | M(IOWRITE) }, 93: { "err", IOALL }, 94: { "end", M(IOREAD) }, 95: { "iostat", IOALL }, 96: { "rec", M(IOREAD) | M(IOWRITE) }, 97: { "recl", M(IOOPEN) | M(IOINQUIRE) }, 98: { "file", M(IOOPEN) | M(IOINQUIRE) }, 99: { "status", M(IOOPEN) | M(IOCLOSE) }, 100: { "access", M(IOOPEN) | M(IOINQUIRE) }, 101: { "form", M(IOOPEN) | M(IOINQUIRE) }, 102: { "blank", M(IOOPEN) | M(IOINQUIRE) }, 103: { "exist", M(IOINQUIRE) }, 104: { "opened", M(IOINQUIRE) }, 105: { "number", M(IOINQUIRE) }, 106: { "named", M(IOINQUIRE) }, 107: { "name", M(IOINQUIRE) }, 108: { "sequential", M(IOINQUIRE) }, 109: { "direct", M(IOINQUIRE) }, 110: { "formatted", M(IOINQUIRE) }, 111: { "unformatted", M(IOINQUIRE) }, 112: { "nextrec", M(IOINQUIRE) } 113: } ; 114: 115: #define NIOS (sizeof(ioc)/sizeof(struct Ioclist) - 1) 116: #define MAXIO SZFLAG + 10*SZIOINT + 15*SZADDR 117: 118: #define IOSUNIT 1 119: #define IOSFMT 2 120: #define IOSERR 3 121: #define IOSEND 4 122: #define IOSIOSTAT 5 123: #define IOSREC 6 124: #define IOSRECL 7 125: #define IOSFILE 8 126: #define IOSSTATUS 9 127: #define IOSACCESS 10 128: #define IOSFORM 11 129: #define IOSBLANK 12 130: #define IOSEXISTS 13 131: #define IOSOPENED 14 132: #define IOSNUMBER 15 133: #define IOSNAMED 16 134: #define IOSNAME 17 135: #define IOSSEQUENTIAL 18 136: #define IOSDIRECT 19 137: #define IOSFORMATTED 20 138: #define IOSUNFORMATTED 21 139: #define IOSNEXTREC 22 140: 141: #define IOSTP V(IOSIOSTAT) 142: 143: 144: /* offsets in generated structures */ 145: 146: #define SZFLAG SZIOINT 147: 148: /* offsets for external READ and WRITE statements */ 149: 150: #define XERR 0 151: #define XUNIT SZFLAG 152: #define XEND SZFLAG + SZIOINT 153: #define XFMT 2*SZFLAG + SZIOINT 154: #define XREC 2*SZFLAG + SZIOINT + SZADDR 155: #define XRLEN 2*SZFLAG + 2*SZADDR 156: #define XRNUM 2*SZFLAG + 2*SZADDR + SZIOINT 157: 158: /* offsets for internal READ and WRITE statements */ 159: 160: #define XIERR 0 161: #define XIUNIT SZFLAG 162: #define XIEND SZFLAG + SZADDR 163: #define XIFMT 2*SZFLAG + SZADDR 164: #define XIRLEN 2*SZFLAG + 2*SZADDR 165: #define XIRNUM 2*SZFLAG + 2*SZADDR + SZIOINT 166: #define XIREC 2*SZFLAG + 2*SZADDR + 2*SZIOINT 167: 168: /* offsets for OPEN statements */ 169: 170: #define XFNAME SZFLAG + SZIOINT 171: #define XFNAMELEN SZFLAG + SZIOINT + SZADDR 172: #define XSTATUS SZFLAG + 2*SZIOINT + SZADDR 173: #define XACCESS SZFLAG + 2*SZIOINT + 2*SZADDR 174: #define XFORMATTED SZFLAG + 2*SZIOINT + 3*SZADDR 175: #define XRECLEN SZFLAG + 2*SZIOINT + 4*SZADDR 176: #define XBLANK SZFLAG + 3*SZIOINT + 4*SZADDR 177: 178: /* offset for CLOSE statement */ 179: 180: #define XCLSTATUS SZFLAG + SZIOINT 181: 182: /* offsets for INQUIRE statement */ 183: 184: #define XFILE SZFLAG + SZIOINT 185: #define XFILELEN SZFLAG + SZIOINT + SZADDR 186: #define XEXISTS SZFLAG + 2*SZIOINT + SZADDR 187: #define XOPEN SZFLAG + 2*SZIOINT + 2*SZADDR 188: #define XNUMBER SZFLAG + 2*SZIOINT + 3*SZADDR 189: #define XNAMED SZFLAG + 2*SZIOINT + 4*SZADDR 190: #define XNAME SZFLAG + 2*SZIOINT + 5*SZADDR 191: #define XNAMELEN SZFLAG + 2*SZIOINT + 6*SZADDR 192: #define XQACCESS SZFLAG + 3*SZIOINT + 6*SZADDR 193: #define XQACCLEN SZFLAG + 3*SZIOINT + 7*SZADDR 194: #define XSEQ SZFLAG + 4*SZIOINT + 7*SZADDR 195: #define XSEQLEN SZFLAG + 4*SZIOINT + 8*SZADDR 196: #define XDIRECT SZFLAG + 5*SZIOINT + 8*SZADDR 197: #define XDIRLEN SZFLAG + 5*SZIOINT + 9*SZADDR 198: #define XFORM SZFLAG + 6*SZIOINT + 9*SZADDR 199: #define XFORMLEN SZFLAG + 6*SZIOINT + 10*SZADDR 200: #define XFMTED SZFLAG + 7*SZIOINT + 10*SZADDR 201: #define XFMTEDLEN SZFLAG + 7*SZIOINT + 11*SZADDR 202: #define XUNFMT SZFLAG + 8*SZIOINT + 11*SZADDR 203: #define XUNFMTLEN SZFLAG + 8*SZIOINT + 12*SZADDR 204: #define XQRECL SZFLAG + 9*SZIOINT + 12*SZADDR 205: #define XNEXTREC SZFLAG + 9*SZIOINT + 13*SZADDR 206: #define XQBLANK SZFLAG + 9*SZIOINT + 14*SZADDR 207: #define XQBLANKLEN SZFLAG + 9*SZIOINT + 15*SZADDR 208: 209: fmtstmt(lp) 210: register struct Labelblock *lp; 211: { 212: if(lp == NULL) 213: { 214: execerr("unlabeled format statement" , CNULL); 215: return(-1); 216: } 217: if(lp->labtype == LABUNKNOWN) 218: lp->labtype = LABFORMAT; 219: else if(lp->labtype != LABFORMAT) 220: { 221: execerr("bad format number", CNULL); 222: return(-1); 223: } 224: return(lp->labelno); 225: } 226: 227: 228: 229: startioctl() 230: { 231: register int i; 232: 233: inioctl = YES; 234: nioctl = 0; 235: ioformatted = UNFORMATTED; 236: for(i = 1 ; i<=NIOS ; ++i) 237: V(i) = NULL; 238: } 239: 240: 241: 242: endioctl() 243: { 244: int i; 245: expptr p; 246: 247: inioctl = NO; 248: 249: /* set up for error recovery */ 250: 251: ioerrlab = ioendlab = skiplab = jumplab = 0; 252: 253: if(p = V(IOSEND)) 254: if(ISICON(p)) 255: ioendlab = execlab(p->constblock.const.ci) ->labelno; 256: else 257: err("bad end= clause"); 258: 259: if(p = V(IOSERR)) 260: if(ISICON(p)) 261: ioerrlab = execlab(p->constblock.const.ci) ->labelno; 262: else 263: err("bad err= clause"); 264: 265: if(IOSTP) 266: if(IOSTP->tag!=TADDR || ! ISINT(IOSTP->addrblock.vtype) ) 267: { 268: err("iostat must be an integer variable"); 269: frexpr(IOSTP); 270: IOSTP = NULL; 271: } 272: 273: if(iostmt == IOREAD) 274: { 275: if(IOSTP) 276: { 277: if(ioerrlab && ioendlab && ioerrlab==ioendlab) 278: jumplab = ioerrlab; 279: else 280: skiplab = jumplab = newlabel(); 281: } 282: else { 283: if(ioerrlab && ioendlab && ioerrlab!=ioendlab) 284: { 285: IOSTP = (expptr) mktemp(TYINT, PNULL); 286: skiplab = jumplab = newlabel(); 287: } 288: else 289: jumplab = (ioerrlab ? ioerrlab : ioendlab); 290: } 291: } 292: else if(iostmt == IOWRITE) 293: { 294: if(IOSTP && !ioerrlab) 295: skiplab = jumplab = newlabel(); 296: else 297: jumplab = ioerrlab; 298: } 299: else 300: jumplab = ioerrlab; 301: 302: endbit = IOSTP!=NULL || ioendlab!=0; /* for use in startrw() */ 303: errbit = IOSTP!=NULL || ioerrlab!=0; 304: if(iostmt!=IOREAD && iostmt!=IOWRITE) 305: { 306: if(ioblkp == NULL) 307: ioblkp = autovar( (MAXIO+SZIOINT-1)/SZIOINT , TYIOINT, PNULL); 308: ioset(TYIOINT, XERR, ICON(errbit)); 309: } 310: 311: switch(iostmt) 312: { 313: case IOOPEN: 314: dofopen(); break; 315: 316: case IOCLOSE: 317: dofclose(); break; 318: 319: case IOINQUIRE: 320: dofinquire(); break; 321: 322: case IOBACKSPACE: 323: dofmove("f_back"); break; 324: 325: case IOREWIND: 326: dofmove("f_rew"); break; 327: 328: case IOENDFILE: 329: dofmove("f_end"); break; 330: 331: case IOREAD: 332: case IOWRITE: 333: startrw(); break; 334: 335: default: 336: fatali("impossible iostmt %d", iostmt); 337: } 338: for(i = 1 ; i<=NIOS ; ++i) 339: if(i!=IOSIOSTAT && V(i)!=NULL) 340: frexpr(V(i)); 341: } 342: 343: 344: 345: iocname() 346: { 347: register int i; 348: int found, mask; 349: 350: found = 0; 351: mask = M(iostmt); 352: for(i = 1 ; i <= NIOS ; ++i) 353: if(toklen==strlen(ioc[i].iocname) && eqn(toklen, token, ioc[i].iocname)) 354: if(ioc[i].iotype & mask) 355: return(i); 356: else found = i; 357: if(found) 358: errstr("invalid control %s for statement", ioc[found].iocname); 359: else 360: errstr("unknown iocontrol %s", varstr(toklen, token) ); 361: return(IOSBAD); 362: } 363: 364: 365: ioclause(n, p) 366: register int n; 367: register expptr p; 368: { 369: struct Ioclist *iocp; 370: 371: ++nioctl; 372: if(n == IOSBAD) 373: return; 374: if(n == IOSPOSITIONAL) 375: { 376: if(nioctl > IOSFMT || 377: nioctl > IOSUNIT && !(iostmt == IOREAD || iostmt == IOWRITE)) 378: { 379: err("illegal positional iocontrol"); 380: return; 381: } 382: n = nioctl; 383: } 384: 385: if(p == NULL) 386: { 387: if(n == IOSUNIT) 388: p = (expptr) (iostmt==IOREAD ? IOSTDIN : IOSTDOUT); 389: else if(n != IOSFMT) 390: { 391: err("illegal * iocontrol"); 392: return; 393: } 394: } 395: if(n == IOSFMT) 396: ioformatted = (p==NULL ? LISTDIRECTED : FORMATTED); 397: 398: iocp = & ioc[n]; 399: if(iocp->iocval == NULL) 400: { 401: p = (expptr) cpexpr(p); 402: if(n!=IOSFMT && ( n!=IOSUNIT || (p!=NULL && p->headblock.vtype!=TYCHAR) ) ) 403: p = fixtype(p); 404: if(p!=NULL && ISCONST(p) && p->constblock.vtype==TYCHAR) 405: p = (expptr) putconst(p); 406: iocp->iocval = p; 407: } 408: else 409: errstr("iocontrol %s repeated", iocp->iocname); 410: } 411: 412: /* io list item */ 413: 414: doio(list) 415: chainp list; 416: { 417: expptr call0(); 418: 419: if(ioformatted == NAMEDIRECTED) 420: { 421: if(list) 422: err("no I/O list allowed in NAMELIST read/write"); 423: } 424: else 425: { 426: doiolist(list); 427: ioroutine[0] = 'e'; 428: putiocall( call0(TYINT, ioroutine) ); 429: } 430: } 431: 432: 433: 434: 435: 436: LOCAL doiolist(p0) 437: chainp p0; 438: { 439: chainp p; 440: register tagptr q; 441: register expptr qe; 442: register Namep qn; 443: Addrp tp, mkscalar(); 444: int range; 445: expptr expr; 446: 447: for (p = p0 ; p ; p = p->nextp) 448: { 449: q = p->datap; 450: if(q->tag == TIMPLDO) 451: { 452: exdo(range=newlabel(), q->impldoblock.impdospec); 453: doiolist(q->impldoblock.datalist); 454: enddo(range); 455: free( (charptr) q); 456: } 457: else { 458: if(q->tag==TPRIM && q->primblock.argsp==NULL 459: && q->primblock.namep->vdim!=NULL) 460: { 461: vardcl(qn = q->primblock.namep); 462: if(qn->vdim->nelt) 463: putio( fixtype(cpexpr(qn->vdim->nelt)), 464: mkscalar(qn) ); 465: else 466: err("attempt to i/o array of unknown size"); 467: } 468: else if(q->tag==TPRIM && q->primblock.argsp==NULL && 469: (qe = (expptr) memversion(q->primblock.namep)) ) 470: putio(ICON(1),qe); 471: else if( (qe = fixtype(cpexpr(q)))->tag==TADDR) 472: putio(ICON(1), qe); 473: else if(qe->headblock.vtype != TYERROR) 474: { 475: if(iostmt == IOWRITE) 476: { 477: ftnint lencat(); 478: expptr qvl; 479: qvl = NULL; 480: if( ISCHAR(qe) ) 481: { 482: qvl = (expptr) 483: cpexpr(qe->headblock.vleng); 484: tp = mktemp(qe->headblock.vtype, 485: ICON(lencat(qe))); 486: } 487: else 488: tp = mktemp(qe->headblock.vtype, 489: qe->headblock.vleng); 490: if (optimflag) 491: { 492: expr = mkexpr(OPASSIGN,cpexpr(tp),qe); 493: optbuff (SKEQ,expr,0,0); 494: } 495: else 496: puteq (cpexpr(tp),qe); 497: if(qvl) /* put right length on block */ 498: { 499: frexpr(tp->vleng); 500: tp->vleng = qvl; 501: } 502: putio(ICON(1), tp); 503: } 504: else 505: err("non-left side in READ list"); 506: } 507: frexpr(q); 508: } 509: } 510: frchain( &p0 ); 511: } 512: 513: 514: 515: 516: 517: LOCAL putio(nelt, addr) 518: expptr nelt; 519: register expptr addr; 520: { 521: int type; 522: register expptr q; 523: 524: type = addr->headblock.vtype; 525: if(ioformatted!=LISTDIRECTED && ISCOMPLEX(type) ) 526: { 527: nelt = mkexpr(OPSTAR, ICON(2), nelt); 528: type -= (TYCOMPLEX-TYREAL); 529: } 530: 531: /* pass a length with every item. for noncharacter data, fake one */ 532: if(type != TYCHAR) 533: { 534: addr->headblock.vtype = TYCHAR; 535: addr->headblock.vleng = ICON( typesize[type] ); 536: } 537: 538: nelt = fixtype( mkconv(TYLENG,nelt) ); 539: if(ioformatted == LISTDIRECTED) 540: q = call3(TYINT, "do_lio", mkconv(TYLONG, ICON(type)), nelt, addr); 541: else 542: q = call2(TYINT, (ioformatted==FORMATTED ? "do_fio" : "do_uio"), 543: nelt, addr); 544: putiocall(q); 545: } 546: 547: 548: 549: 550: endio() 551: { 552: if(skiplab) 553: { 554: if (optimflag) 555: optbuff (SKLABEL, 0, skiplab, 0); 556: else 557: putlabel (skiplab); 558: if(ioendlab) 559: { 560: expptr test; 561: test = mkexpr(OPGE, cpexpr(IOSTP), ICON(0)); 562: if (optimflag) 563: optbuff (SKIOIFN,test,ioendlab,0); 564: else 565: putif (test,ioendlab); 566: } 567: if(ioerrlab) 568: { 569: expptr test; 570: test = mkexpr 571: ( ((iostmt==IOREAD||iostmt==IOWRITE) ? OPLE : OPEQ), 572: cpexpr(IOSTP), ICON(0)); 573: if (optimflag) 574: optbuff (SKIOIFN,test,ioerrlab,0); 575: else 576: putif (test,ioerrlab); 577: } 578: } 579: if(IOSTP) 580: frexpr(IOSTP); 581: } 582: 583: 584: 585: LOCAL putiocall(q) 586: register expptr q; 587: { 588: if(IOSTP) 589: { 590: q->headblock.vtype = TYINT; 591: q = fixexpr( mkexpr(OPASSIGN, cpexpr(IOSTP), q)); 592: } 593: 594: if(jumplab) 595: if (optimflag) 596: optbuff (SKIOIFN,mkexpr(OPEQ,q,ICON(0)),jumplab,0); 597: else 598: putif (mkexpr(OPEQ,q,ICON(0)),jumplab); 599: else 600: if (optimflag) 601: optbuff (SKEQ, q, 0, 0); 602: else 603: putexpr(q); 604: } 605: 606: startrw() 607: { 608: register expptr p; 609: register Namep np; 610: register Addrp unitp, fmtp, recp, tioblkp; 611: register expptr nump; 612: register ioblock *t; 613: Addrp mkscalar(); 614: expptr mkaddcon(); 615: int k; 616: flag intfile, sequential, ok, varfmt; 617: 618: /* First look at all the parameters and determine what is to be done */ 619: 620: ok = YES; 621: statstruct = YES; 622: 623: intfile = NO; 624: if(p = V(IOSUNIT)) 625: { 626: if( ISINT(p->headblock.vtype) ) 627: unitp = (Addrp) cpexpr(p); 628: else if(p->headblock.vtype == TYCHAR) 629: { 630: intfile = YES; 631: if(p->tag==TPRIM && p->primblock.argsp==NULL && 632: (np = p->primblock.namep)->vdim!=NULL) 633: { 634: vardcl(np); 635: if(np->vdim->nelt) 636: { 637: nump = (expptr) cpexpr(np->vdim->nelt); 638: if( ! ISCONST(nump) ) 639: statstruct = NO; 640: } 641: else 642: { 643: err("attempt to use internal unit array of unknown size"); 644: ok = NO; 645: nump = ICON(1); 646: } 647: unitp = mkscalar(np); 648: } 649: else { 650: nump = ICON(1); 651: unitp = (Addrp) fixtype(cpexpr(p)); 652: } 653: if(! isstatic(unitp) ) 654: statstruct = NO; 655: } 656: else 657: { 658: err("bad unit specifier type"); 659: ok = NO; 660: } 661: } 662: else 663: { 664: err("bad unit specifier"); 665: ok = NO; 666: } 667: 668: sequential = YES; 669: if(p = V(IOSREC)) 670: if( ISINT(p->headblock.vtype) ) 671: { 672: recp = (Addrp) cpexpr(p); 673: sequential = NO; 674: } 675: else { 676: err("bad REC= clause"); 677: ok = NO; 678: } 679: else 680: recp = NULL; 681: 682: 683: varfmt = YES; 684: fmtp = NULL; 685: if(p = V(IOSFMT)) 686: { 687: if(p->tag==TPRIM && p->primblock.argsp==NULL) 688: { 689: np = p->primblock.namep; 690: if(np->vclass == CLNAMELIST) 691: { 692: ioformatted = NAMEDIRECTED; 693: fmtp = (Addrp) fixtype(cpexpr(p)); 694: goto endfmt; 695: } 696: vardcl(np); 697: if(np->vdim) 698: { 699: if( ! ONEOF(np->vstg, MSKSTATIC) ) 700: statstruct = NO; 701: fmtp = mkscalar(np); 702: goto endfmt; 703: } 704: if( ISINT(np->vtype) ) /* ASSIGNed label */ 705: { 706: statstruct = NO; 707: varfmt = NO; 708: fmtp = (Addrp) fixtype(cpexpr(p)); 709: goto endfmt; 710: } 711: } 712: p = V(IOSFMT) = fixtype(p); 713: if(p->headblock.vtype == TYCHAR) 714: { 715: if (p->tag == TCONST) p = (expptr) putconst(p); 716: if( ! isstatic(p) ) 717: statstruct = NO; 718: fmtp = (Addrp) cpexpr(p); 719: } 720: else if( ISICON(p) ) 721: { 722: if( (k = fmtstmt( mklabel(p->constblock.const.ci) )) > 0 ) 723: { 724: fmtp = (Addrp) mkaddcon(k); 725: varfmt = NO; 726: } 727: else 728: ioformatted = UNFORMATTED; 729: } 730: else { 731: err("bad format descriptor"); 732: ioformatted = UNFORMATTED; 733: ok = NO; 734: } 735: } 736: else 737: fmtp = NULL; 738: 739: endfmt: 740: if(intfile && ioformatted==UNFORMATTED) 741: { 742: err("unformatted internal I/O not allowed"); 743: ok = NO; 744: } 745: if(!sequential && ioformatted==LISTDIRECTED) 746: { 747: err("direct list-directed I/O not allowed"); 748: ok = NO; 749: } 750: if(!sequential && ioformatted==NAMEDIRECTED) 751: { 752: err("direct namelist I/O not allowed"); 753: ok = NO; 754: } 755: 756: if( ! ok ) 757: return; 758: 759: if (optimflag && ISCONST (fmtp)) 760: fmtp = putconst ( (expptr) fmtp); 761: 762: /* 763: Now put out the I/O structure, statically if all the clauses 764: are constants, dynamically otherwise 765: */ 766: 767: if(statstruct) 768: { 769: tioblkp = ioblkp; 770: ioblkp = ALLOC(Addrblock); 771: ioblkp->tag = TADDR; 772: ioblkp->vtype = TYIOINT; 773: ioblkp->vclass = CLVAR; 774: ioblkp->vstg = STGINIT; 775: ioblkp->memno = ++lastvarno; 776: ioblkp->memoffset = ICON(0); 777: blklen = (intfile ? XIREC+SZIOINT : 778: (sequential ? XFMT+SZADDR : XRNUM+SZIOINT) ); 779: t = ALLOC(IoBlock); 780: t->blkno = ioblkp->memno; 781: t->len = blklen; 782: t->next = iodata; 783: iodata = t; 784: } 785: else if(ioblkp == NULL) 786: ioblkp = autovar( (MAXIO+SZIOINT-1)/SZIOINT , TYIOINT, PNULL); 787: 788: ioset(TYIOINT, XERR, ICON(errbit)); 789: if(iostmt == IOREAD) 790: ioset(TYIOINT, (intfile ? XIEND : XEND), ICON(endbit) ); 791: 792: if(intfile) 793: { 794: ioset(TYIOINT, XIRNUM, nump); 795: ioseta(XIUNIT, cpexpr(unitp)); 796: ioset(TYIOINT, XIRLEN, cpexpr(unitp->vleng) ); 797: frexpr(unitp); 798: } 799: else 800: ioset(TYIOINT, XUNIT, (expptr) unitp); 801: 802: if(recp) 803: ioset(TYIOINT, (intfile ? XIREC : XREC) , (expptr) recp); 804: 805: if(varfmt) 806: ioseta( intfile ? XIFMT : XFMT , fmtp); 807: else 808: ioset(TYADDR, intfile ? XIFMT : XFMT, (expptr) fmtp); 809: 810: ioroutine[0] = 's'; 811: ioroutine[1] = '_'; 812: ioroutine[2] = (iostmt==IOREAD ? 'r' : 'w'); 813: ioroutine[3] = (sequential ? 's' : 'd'); 814: ioroutine[4] = "ufln" [ioformatted]; 815: ioroutine[5] = (intfile ? 'i' : 'e'); 816: ioroutine[6] = '\0'; 817: 818: putiocall( call1(TYINT, ioroutine, cpexpr(ioblkp) )); 819: 820: if(statstruct) 821: { 822: frexpr(ioblkp); 823: ioblkp = tioblkp; 824: statstruct = NO; 825: } 826: } 827: 828: 829: 830: LOCAL dofopen() 831: { 832: register expptr p; 833: 834: if( (p = V(IOSUNIT)) && ISINT(p->headblock.vtype) ) 835: ioset(TYIOINT, XUNIT, cpexpr(p) ); 836: else 837: err("bad unit in open"); 838: if( (p = V(IOSFILE)) ) 839: if(p->headblock.vtype == TYCHAR) 840: ioset(TYIOINT, XFNAMELEN, cpexpr(p->headblock.vleng) ); 841: else 842: err("bad file in open"); 843: 844: iosetc(XFNAME, p); 845: 846: if(p = V(IOSRECL)) 847: if( ISINT(p->headblock.vtype) ) 848: ioset(TYIOINT, XRECLEN, cpexpr(p) ); 849: else 850: err("bad recl"); 851: else 852: ioset(TYIOINT, XRECLEN, ICON(0) ); 853: 854: iosetc(XSTATUS, V(IOSSTATUS)); 855: iosetc(XACCESS, V(IOSACCESS)); 856: iosetc(XFORMATTED, V(IOSFORM)); 857: iosetc(XBLANK, V(IOSBLANK)); 858: 859: putiocall( call1(TYINT, "f_open", cpexpr(ioblkp) )); 860: } 861: 862: 863: LOCAL dofclose() 864: { 865: register expptr p; 866: 867: if( (p = V(IOSUNIT)) && ISINT(p->headblock.vtype) ) 868: { 869: ioset(TYIOINT, XUNIT, cpexpr(p) ); 870: iosetc(XCLSTATUS, V(IOSSTATUS)); 871: putiocall( call1(TYINT, "f_clos", cpexpr(ioblkp)) ); 872: } 873: else 874: err("bad unit in close statement"); 875: } 876: 877: 878: LOCAL dofinquire() 879: { 880: register expptr p; 881: if(p = V(IOSUNIT)) 882: { 883: if( V(IOSFILE) ) 884: err("inquire by unit or by file, not both"); 885: ioset(TYIOINT, XUNIT, cpexpr(p) ); 886: } 887: else if( ! V(IOSFILE) ) 888: err("must inquire by unit or by file"); 889: iosetlc(IOSFILE, XFILE, XFILELEN); 890: iosetip(IOSEXISTS, XEXISTS); 891: iosetip(IOSOPENED, XOPEN); 892: iosetip(IOSNUMBER, XNUMBER); 893: iosetip(IOSNAMED, XNAMED); 894: iosetlc(IOSNAME, XNAME, XNAMELEN); 895: iosetlc(IOSACCESS, XQACCESS, XQACCLEN); 896: iosetlc(IOSSEQUENTIAL, XSEQ, XSEQLEN); 897: iosetlc(IOSDIRECT, XDIRECT, XDIRLEN); 898: iosetlc(IOSFORM, XFORM, XFORMLEN); 899: iosetlc(IOSFORMATTED, XFMTED, XFMTEDLEN); 900: iosetlc(IOSUNFORMATTED, XUNFMT, XUNFMTLEN); 901: iosetip(IOSRECL, XQRECL); 902: iosetip(IOSNEXTREC, XNEXTREC); 903: iosetlc(IOSBLANK, XQBLANK, XQBLANKLEN); 904: 905: putiocall( call1(TYINT, "f_inqu", cpexpr(ioblkp) )); 906: } 907: 908: 909: 910: LOCAL dofmove(subname) 911: char *subname; 912: { 913: register expptr p; 914: 915: if( (p = V(IOSUNIT)) && ISINT(p->headblock.vtype) ) 916: { 917: ioset(TYIOINT, XUNIT, cpexpr(p) ); 918: putiocall( call1(TYINT, subname, cpexpr(ioblkp) )); 919: } 920: else 921: err("bad unit in I/O motion statement"); 922: } 923: 924: 925: 926: LOCAL 927: ioset(type, offset, p) 928: int type; 929: int offset; 930: register expptr p; 931: { 932: static char *badoffset = "badoffset in ioset"; 933: 934: register Addrp q; 935: register offsetlist *op; 936: 937: q = (Addrp) cpexpr(ioblkp); 938: q->vtype = type; 939: q->memoffset = fixtype( mkexpr(OPPLUS, q->memoffset, ICON(offset)) ); 940: 941: if (statstruct && ISCONST(p)) 942: { 943: if (!ISICON(q->memoffset)) 944: fatal(badoffset); 945: 946: op = mkiodata(q->memno, q->memoffset->constblock.const.ci, blklen); 947: if (op->tag != 0) 948: fatal(badoffset); 949: 950: if (type == TYADDR) 951: { 952: op->tag = NDLABEL; 953: op->val.label = p->constblock.const.ci; 954: } 955: else 956: { 957: op->tag = NDDATA; 958: op->val.cp = (Constp) convconst(type, 0, p); 959: } 960: 961: frexpr((tagptr) p); 962: frexpr((tagptr) q); 963: } 964: else 965: if (optimflag) 966: optbuff (SKEQ, mkexpr(OPASSIGN,q,p), 0,0); 967: else 968: puteq (q,p); 969: 970: return; 971: } 972: 973: 974: 975: 976: LOCAL iosetc(offset, p) 977: int offset; 978: register expptr p; 979: { 980: if(p == NULL) 981: ioset(TYADDR, offset, ICON(0) ); 982: else if(p->headblock.vtype == TYCHAR) 983: ioset(TYADDR, offset, addrof(cpexpr(p) )); 984: else 985: err("non-character control clause"); 986: } 987: 988: 989: 990: LOCAL ioseta(offset, p) 991: int offset; 992: register Addrp p; 993: { 994: static char *badoffset = "bad offset in ioseta"; 995: 996: int blkno; 997: register offsetlist *op; 998: 999: if(statstruct) 1000: { 1001: blkno = ioblkp->memno; 1002: op = mkiodata(blkno, offset, blklen); 1003: if (op->tag != 0) 1004: fatal(badoffset); 1005: 1006: if (p == NULL) 1007: op->tag = NDNULL; 1008: else if (p->tag == TADDR) 1009: { 1010: op->tag = NDADDR; 1011: op->val.addr.stg = p->vstg; 1012: op->val.addr.memno = p->memno; 1013: op->val.addr.offset = p->memoffset->constblock.const.ci; 1014: } 1015: else 1016: badtag("ioseta", p->tag); 1017: } 1018: else 1019: ioset(TYADDR, offset, p ? addrof(p) : ICON(0) ); 1020: 1021: return; 1022: } 1023: 1024: 1025: 1026: 1027: LOCAL iosetip(i, offset) 1028: int i, offset; 1029: { 1030: register expptr p; 1031: 1032: if(p = V(i)) 1033: if(p->tag==TADDR && 1034: ONEOF(p->addrblock.vtype, M(TYLONG)|M(TYLOGICAL)) ) 1035: ioset(TYADDR, offset, addrof(cpexpr(p)) ); 1036: else 1037: errstr("impossible inquire parameter %s", ioc[i].iocname); 1038: else 1039: ioset(TYADDR, offset, ICON(0) ); 1040: } 1041: 1042: 1043: 1044: LOCAL iosetlc(i, offp, offl) 1045: int i, offp, offl; 1046: { 1047: register expptr p; 1048: if( (p = V(i)) && p->headblock.vtype==TYCHAR) 1049: ioset(TYIOINT, offl, cpexpr(p->headblock.vleng) ); 1050: iosetc(offp, p); 1051: } 1052: 1053: 1054: LOCAL offsetlist * 1055: mkiodata(blkno, offset, len) 1056: int blkno; 1057: ftnint offset; 1058: ftnint len; 1059: { 1060: register offsetlist *p, *q; 1061: register ioblock *t; 1062: register int found; 1063: 1064: found = NO; 1065: t = iodata; 1066: 1067: while (found == NO && t != NULL) 1068: { 1069: if (t->blkno == blkno) 1070: found = YES; 1071: else 1072: t = t->next; 1073: } 1074: 1075: if (found == NO) 1076: { 1077: t = ALLOC(IoBlock); 1078: t->blkno = blkno; 1079: t->next = iodata; 1080: iodata = t; 1081: } 1082: 1083: if (len > t->len) 1084: t->len = len; 1085: 1086: p = t->olist; 1087: 1088: if (p == NULL) 1089: { 1090: p = ALLOC(OffsetList); 1091: p->next = NULL; 1092: p->offset = offset; 1093: t->olist = p; 1094: return (p); 1095: } 1096: 1097: for (;;) 1098: { 1099: if (p->offset == offset) 1100: return (p); 1101: else if (p->next != NULL && 1102: p->next->offset <= offset) 1103: p = p->next; 1104: else 1105: { 1106: q = ALLOC(OffsetList); 1107: q->next = p->next; 1108: p->next = q; 1109: q->offset = offset; 1110: return (q); 1111: } 1112: } 1113: } 1114: 1115: 1116: outiodata() 1117: { 1118: static char *varfmt = "v.%d:\n"; 1119: 1120: register ioblock *p; 1121: register ioblock *t; 1122: 1123: if (iodata == NULL) return; 1124: 1125: p = iodata; 1126: 1127: while (p != NULL) 1128: { 1129: pralign(ALIDOUBLE); 1130: fprintf(initfile, varfmt, p->blkno); 1131: outolist(p->olist, p->len); 1132: 1133: t = p; 1134: p = t->next; 1135: free((char *) t); 1136: } 1137: 1138: iodata = NULL; 1139: return; 1140: } 1141: 1142: 1143: 1144: LOCAL 1145: outolist(op, len) 1146: register offsetlist *op; 1147: register int len; 1148: { 1149: static char *overlap = "overlapping i/o fields in outolist"; 1150: static char *toolong = "offset too large in outolist"; 1151: 1152: register offsetlist *t; 1153: register ftnint clen; 1154: register Constp cp; 1155: register int type; 1156: 1157: clen = 0; 1158: 1159: while (op != NULL) 1160: { 1161: if (clen > op->offset) 1162: fatal(overlap); 1163: 1164: if (clen < op->offset) 1165: { 1166: prspace(op->offset - clen); 1167: clen = op->offset; 1168: } 1169: 1170: switch (op->tag) 1171: { 1172: default: 1173: badtag("outolist", op->tag); 1174: 1175: case NDDATA: 1176: cp = op->val.cp; 1177: type = cp->vtype; 1178: if (type != TYIOINT) 1179: badtype("outolist", type); 1180: prconi(initfile, type, cp->const.ci); 1181: clen += typesize[type]; 1182: frexpr((tagptr) cp); 1183: break; 1184: 1185: case NDLABEL: 1186: prcona(initfile, op->val.label); 1187: clen += typesize[TYADDR]; 1188: break; 1189: 1190: case NDADDR: 1191: praddr(initfile, op->val.addr.stg, op->val.addr.memno, 1192: op->val.addr.offset); 1193: clen += typesize[TYADDR]; 1194: break; 1195: 1196: case NDNULL: 1197: praddr(initfile, STGNULL, 0, (ftnint) 0); 1198: clen += typesize[TYADDR]; 1199: break; 1200: } 1201: 1202: t = op; 1203: op = t->next; 1204: free((char *) t); 1205: } 1206: 1207: if (clen > len) 1208: fatal(toolong); 1209: 1210: if (clen < len) 1211: prspace(len - clen); 1212: 1213: return; 1214: }