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