|
|
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 = "@(#)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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.