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