|
|
1.1 root 1: /****************************************************************
2: Copyright 1990, 1991, 1993 by AT&T Bell Laboratories and Bellcore.
3:
4: Permission to use, copy, modify, and distribute this software
5: and its documentation for any purpose and without fee is hereby
6: granted, provided that the above copyright notice appear in all
7: copies and that both that the copyright notice and this
8: permission notice and warranty disclaimer appear in supporting
9: documentation, and that the names of AT&T Bell Laboratories or
10: Bellcore or any of their entities not be used in advertising or
11: publicity pertaining to distribution of the software without
12: specific, written prior permission.
13:
14: AT&T and Bellcore disclaim all warranties with regard to this
15: software, including all implied warranties of merchantability
16: and fitness. In no event shall AT&T or Bellcore be liable for
17: any special, indirect or consequential damages or any damages
18: whatsoever resulting from loss of use, data or profits, whether
19: in an action of contract, negligence or other tortious action,
20: arising out of or in connection with the use or performance of
21: this software.
22: ****************************************************************/
23:
24: /* Routines to generate code for I/O statements.
25: Some corrections and improvements due to David Wasley, U. C. Berkeley
26: */
27:
28: /* TEMPORARY */
29: #define TYIOINT TYLONG
30: #define SZIOINT SZLONG
31:
32: #include "defs.h"
33: #include "names.h"
34: #include "iob.h"
35:
36: extern int inqmask;
37:
38: LOCAL void dofclose(), dofinquire(), dofinquire(), dofmove(), dofopen(),
39: doiolist(), ioset(), ioseta(), iosetc(), iosetip(), iosetlc(),
40: putio(), putiocall();
41:
42: iob_data *iob_list;
43: Addrp io_structs[9];
44:
45: LOCAL char ioroutine[12];
46:
47: LOCAL long ioendlab;
48: LOCAL long ioerrlab;
49: LOCAL int endbit;
50: LOCAL int errbit;
51: LOCAL long jumplab;
52: LOCAL long skiplab;
53: LOCAL int ioformatted;
54: LOCAL int statstruct = NO;
55: LOCAL struct Labelblock *skiplabel;
56: Addrp ioblkp;
57:
58: #define UNFORMATTED 0
59: #define FORMATTED 1
60: #define LISTDIRECTED 2
61: #define NAMEDIRECTED 3
62:
63: #define V(z) ioc[z].iocval
64:
65: #define IOALL 07777
66:
67: LOCAL struct Ioclist
68: {
69: char *iocname;
70: int iotype;
71: expptr iocval;
72: }
73: ioc[ ] =
74: {
75: { "", 0 },
76: { "unit", IOALL },
77: { "fmt", M(IOREAD) | M(IOWRITE) },
78: { "err", IOALL },
79: { "end", M(IOREAD) },
80: { "iostat", IOALL },
81: { "rec", M(IOREAD) | M(IOWRITE) },
82: { "recl", M(IOOPEN) | M(IOINQUIRE) },
83: { "file", M(IOOPEN) | M(IOINQUIRE) },
84: { "status", M(IOOPEN) | M(IOCLOSE) },
85: { "access", M(IOOPEN) | M(IOINQUIRE) },
86: { "form", M(IOOPEN) | M(IOINQUIRE) },
87: { "blank", M(IOOPEN) | M(IOINQUIRE) },
88: { "exist", M(IOINQUIRE) },
89: { "opened", M(IOINQUIRE) },
90: { "number", M(IOINQUIRE) },
91: { "named", M(IOINQUIRE) },
92: { "name", M(IOINQUIRE) },
93: { "sequential", M(IOINQUIRE) },
94: { "direct", M(IOINQUIRE) },
95: { "formatted", M(IOINQUIRE) },
96: { "unformatted", M(IOINQUIRE) },
97: { "nextrec", M(IOINQUIRE) },
98: { "nml", M(IOREAD) | M(IOWRITE) }
99: };
100:
101: #define NIOS (sizeof(ioc)/sizeof(struct Ioclist) - 1)
102:
103: /* #define IOSUNIT 1 */
104: /* #define IOSFMT 2 */
105: #define IOSERR 3
106: #define IOSEND 4
107: #define IOSIOSTAT 5
108: #define IOSREC 6
109: #define IOSRECL 7
110: #define IOSFILE 8
111: #define IOSSTATUS 9
112: #define IOSACCESS 10
113: #define IOSFORM 11
114: #define IOSBLANK 12
115: #define IOSEXISTS 13
116: #define IOSOPENED 14
117: #define IOSNUMBER 15
118: #define IOSNAMED 16
119: #define IOSNAME 17
120: #define IOSSEQUENTIAL 18
121: #define IOSDIRECT 19
122: #define IOSFORMATTED 20
123: #define IOSUNFORMATTED 21
124: #define IOSNEXTREC 22
125: #define IOSNML 23
126:
127: #define IOSTP V(IOSIOSTAT)
128:
129:
130: /* offsets in generated structures */
131:
132: #define SZFLAG SZIOINT
133:
134: /* offsets for external READ and WRITE statements */
135:
136: #define XERR 0
137: #define XUNIT SZFLAG
138: #define XEND SZFLAG + SZIOINT
139: #define XFMT 2*SZFLAG + SZIOINT
140: #define XREC 2*SZFLAG + SZIOINT + SZADDR
141:
142: /* offsets for internal READ and WRITE statements */
143:
144: #define XIUNIT SZFLAG
145: #define XIEND SZFLAG + SZADDR
146: #define XIFMT 2*SZFLAG + SZADDR
147: #define XIRLEN 2*SZFLAG + 2*SZADDR
148: #define XIRNUM 2*SZFLAG + 2*SZADDR + SZIOINT
149: #define XIREC 2*SZFLAG + 2*SZADDR + 2*SZIOINT
150:
151: /* offsets for OPEN statements */
152:
153: #define XFNAME SZFLAG + SZIOINT
154: #define XFNAMELEN SZFLAG + SZIOINT + SZADDR
155: #define XSTATUS SZFLAG + 2*SZIOINT + SZADDR
156: #define XACCESS SZFLAG + 2*SZIOINT + 2*SZADDR
157: #define XFORMATTED SZFLAG + 2*SZIOINT + 3*SZADDR
158: #define XRECLEN SZFLAG + 2*SZIOINT + 4*SZADDR
159: #define XBLANK SZFLAG + 3*SZIOINT + 4*SZADDR
160:
161: /* offset for CLOSE statement */
162:
163: #define XCLSTATUS SZFLAG + SZIOINT
164:
165: /* offsets for INQUIRE statement */
166:
167: #define XFILE SZFLAG + SZIOINT
168: #define XFILELEN SZFLAG + SZIOINT + SZADDR
169: #define XEXISTS SZFLAG + 2*SZIOINT + SZADDR
170: #define XOPEN SZFLAG + 2*SZIOINT + 2*SZADDR
171: #define XNUMBER SZFLAG + 2*SZIOINT + 3*SZADDR
172: #define XNAMED SZFLAG + 2*SZIOINT + 4*SZADDR
173: #define XNAME SZFLAG + 2*SZIOINT + 5*SZADDR
174: #define XNAMELEN SZFLAG + 2*SZIOINT + 6*SZADDR
175: #define XQACCESS SZFLAG + 3*SZIOINT + 6*SZADDR
176: #define XQACCLEN SZFLAG + 3*SZIOINT + 7*SZADDR
177: #define XSEQ SZFLAG + 4*SZIOINT + 7*SZADDR
178: #define XSEQLEN SZFLAG + 4*SZIOINT + 8*SZADDR
179: #define XDIRECT SZFLAG + 5*SZIOINT + 8*SZADDR
180: #define XDIRLEN SZFLAG + 5*SZIOINT + 9*SZADDR
181: #define XFORM SZFLAG + 6*SZIOINT + 9*SZADDR
182: #define XFORMLEN SZFLAG + 6*SZIOINT + 10*SZADDR
183: #define XFMTED SZFLAG + 7*SZIOINT + 10*SZADDR
184: #define XFMTEDLEN SZFLAG + 7*SZIOINT + 11*SZADDR
185: #define XUNFMT SZFLAG + 8*SZIOINT + 11*SZADDR
186: #define XUNFMTLEN SZFLAG + 8*SZIOINT + 12*SZADDR
187: #define XQRECL SZFLAG + 9*SZIOINT + 12*SZADDR
188: #define XNEXTREC SZFLAG + 9*SZIOINT + 13*SZADDR
189: #define XQBLANK SZFLAG + 9*SZIOINT + 14*SZADDR
190: #define XQBLANKLEN SZFLAG + 9*SZIOINT + 15*SZADDR
191:
192: LOCAL char *cilist_names[] = {
193: "cilist",
194: "cierr",
195: "ciunit",
196: "ciend",
197: "cifmt",
198: "cirec"
199: };
200: LOCAL char *icilist_names[] = {
201: "icilist",
202: "icierr",
203: "iciunit",
204: "iciend",
205: "icifmt",
206: "icirlen",
207: "icirnum"
208: };
209: LOCAL char *olist_names[] = {
210: "olist",
211: "oerr",
212: "ounit",
213: "ofnm",
214: "ofnmlen",
215: "osta",
216: "oacc",
217: "ofm",
218: "orl",
219: "oblnk"
220: };
221: LOCAL char *cllist_names[] = {
222: "cllist",
223: "cerr",
224: "cunit",
225: "csta"
226: };
227: LOCAL char *alist_names[] = {
228: "alist",
229: "aerr",
230: "aunit"
231: };
232: LOCAL char *inlist_names[] = {
233: "inlist",
234: "inerr",
235: "inunit",
236: "infile",
237: "infilen",
238: "inex",
239: "inopen",
240: "innum",
241: "innamed",
242: "inname",
243: "innamlen",
244: "inacc",
245: "inacclen",
246: "inseq",
247: "inseqlen",
248: "indir",
249: "indirlen",
250: "infmt",
251: "infmtlen",
252: "inform",
253: "informlen",
254: "inunf",
255: "inunflen",
256: "inrecl",
257: "innrec",
258: "inblank",
259: "inblanklen"
260: };
261:
262: LOCAL char **io_fields;
263:
264: #define zork(n,t) n, sizeof(n)/sizeof(char *) - 1, t
265:
266: LOCAL io_setup io_stuff[] = {
267: zork(cilist_names, TYCILIST), /* external read/write */
268: zork(inlist_names, TYINLIST), /* inquire */
269: zork(olist_names, TYOLIST), /* open */
270: zork(cllist_names, TYCLLIST), /* close */
271: zork(alist_names, TYALIST), /* rewind */
272: zork(alist_names, TYALIST), /* backspace */
273: zork(alist_names, TYALIST), /* endfile */
274: zork(icilist_names,TYICILIST), /* internal read */
275: zork(icilist_names,TYICILIST) /* internal write */
276: };
277:
278: #undef zork
279:
280:
281: fmtstmt(lp)
282: register struct Labelblock *lp;
283: {
284: if(lp == NULL)
285: {
286: execerr("unlabeled format statement" , CNULL);
287: return(-1);
288: }
289: if(lp->labtype == LABUNKNOWN)
290: {
291: lp->labtype = LABFORMAT;
292: lp->labelno = newlabel();
293: }
294: else if(lp->labtype != LABFORMAT)
295: {
296: execerr("bad format number", CNULL);
297: return(-1);
298: }
299: return(lp->labelno);
300: }
301:
302:
303: setfmt(lp)
304: struct Labelblock *lp;
305: {
306: int n;
307: char *s0, *lexline();
308: register char *s, *se, *t;
309: register k;
310:
311: s0 = s = lexline(&n);
312: se = t = s + n;
313:
314: /* warn of trivial errors, e.g. " 11 CONTINUE" (one too few spaces) */
315: /* following FORMAT... */
316:
317: if (n <= 0)
318: warn("No (...) after FORMAT");
319: else if (*s != '(')
320: warni("%c rather than ( after FORMAT", *s);
321: else if (se[-1] != ')') {
322: *se = 0;
323: while(--t > s && *t != ')') ;
324: if (t <= s)
325: warn("No ) at end of FORMAT statement");
326: else if (se - t > 30)
327: warn1("Extraneous text at end of FORMAT: ...%s", se-12);
328: else
329: warn1("Extraneous text at end of FORMAT: %s", t+1);
330: t = se;
331: }
332:
333: /* fix MYQUOTES (\002's) and \\'s */
334:
335: while(s < se)
336: switch(*s++) {
337: case 2:
338: t += 3; break;
339: case '"':
340: case '\\':
341: t++; break;
342: }
343: s = s0;
344: if (lp) {
345: lp->fmtstring = t = mem((int)(t - s + 1), 0);
346: while(s < se)
347: switch(k = *s++) {
348: case 2:
349: t[0] = '\\';
350: t[1] = '0';
351: t[2] = '0';
352: t[3] = '2';
353: t += 4;
354: break;
355: case '"':
356: case '\\':
357: *t++ = '\\';
358: /* no break */
359: default:
360: *t++ = k;
361: }
362: *t = 0;
363: }
364: flline();
365: }
366:
367:
368:
369: startioctl()
370: {
371: register int i;
372:
373: inioctl = YES;
374: nioctl = 0;
375: ioformatted = UNFORMATTED;
376: for(i = 1 ; i<=NIOS ; ++i)
377: V(i) = NULL;
378: }
379:
380: static long
381: newiolabel() {
382: long rv;
383: rv = ++lastiolabno;
384: skiplabel = mklabel(rv);
385: skiplabel->labdefined = 1;
386: return rv;
387: }
388:
389:
390: endioctl()
391: {
392: int i;
393: expptr p;
394: struct io_setup *ios;
395:
396: inioctl = NO;
397:
398: /* set up for error recovery */
399:
400: ioerrlab = ioendlab = skiplab = jumplab = 0;
401:
402: if(p = V(IOSEND))
403: if(ISICON(p))
404: execlab(ioendlab = p->constblock.Const.ci);
405: else
406: err("bad end= clause");
407:
408: if(p = V(IOSERR))
409: if(ISICON(p))
410: execlab(ioerrlab = p->constblock.Const.ci);
411: else
412: err("bad err= clause");
413:
414: if(IOSTP)
415: if(IOSTP->tag!=TADDR || ! ISINT(IOSTP->addrblock.vtype) )
416: {
417: err("iostat must be an integer variable");
418: frexpr(IOSTP);
419: IOSTP = NULL;
420: }
421:
422: if(iostmt == IOREAD)
423: {
424: if(IOSTP)
425: {
426: if(ioerrlab && ioendlab && ioerrlab==ioendlab)
427: jumplab = ioerrlab;
428: else
429: skiplab = jumplab = newiolabel();
430: }
431: else {
432: if(ioerrlab && ioendlab && ioerrlab!=ioendlab)
433: {
434: IOSTP = (expptr) mktmp(TYINT, ENULL);
435: skiplab = jumplab = newiolabel();
436: }
437: else
438: jumplab = (ioerrlab ? ioerrlab : ioendlab);
439: }
440: }
441: else if(iostmt == IOWRITE)
442: {
443: if(IOSTP && !ioerrlab)
444: skiplab = jumplab = newiolabel();
445: else
446: jumplab = ioerrlab;
447: }
448: else
449: jumplab = ioerrlab;
450:
451: endbit = IOSTP!=NULL || ioendlab!=0; /* for use in startrw() */
452: errbit = IOSTP!=NULL || ioerrlab!=0;
453: if (jumplab && !IOSTP)
454: IOSTP = (expptr) mktmp(TYINT, ENULL);
455:
456: if(iostmt!=IOREAD && iostmt!=IOWRITE)
457: {
458: ios = io_stuff + iostmt;
459: io_fields = ios->fields;
460: ioblkp = io_structs[iostmt];
461: if(ioblkp == NULL)
462: io_structs[iostmt] = ioblkp =
463: autovar(1, ios->type, ENULL, "");
464: ioset(TYIOINT, XERR, ICON(errbit));
465: }
466:
467: switch(iostmt)
468: {
469: case IOOPEN:
470: dofopen();
471: break;
472:
473: case IOCLOSE:
474: dofclose();
475: break;
476:
477: case IOINQUIRE:
478: dofinquire();
479: break;
480:
481: case IOBACKSPACE:
482: dofmove("f_back");
483: break;
484:
485: case IOREWIND:
486: dofmove("f_rew");
487: break;
488:
489: case IOENDFILE:
490: dofmove("f_end");
491: break;
492:
493: case IOREAD:
494: case IOWRITE:
495: startrw();
496: break;
497:
498: default:
499: fatali("impossible iostmt %d", iostmt);
500: }
501: for(i = 1 ; i<=NIOS ; ++i)
502: if(i!=IOSIOSTAT && V(i)!=NULL)
503: frexpr(V(i));
504: }
505:
506:
507:
508: iocname()
509: {
510: register int i;
511: int found, mask;
512:
513: found = 0;
514: mask = M(iostmt);
515: for(i = 1 ; i <= NIOS ; ++i)
516: if(!strcmp(ioc[i].iocname, token))
517: if(ioc[i].iotype & mask)
518: return(i);
519: else {
520: found = i;
521: break;
522: }
523: if(found) {
524: if (iostmt == IOOPEN && !strcmp(ioc[i].iocname, "name")) {
525: NOEXT("open with \"name=\" treated as \"file=\"");
526: for(i = 1; strcmp(ioc[i].iocname, "file"); i++);
527: return i;
528: }
529: errstr("invalid control %s for statement", ioc[found].iocname);
530: }
531: else
532: errstr("unknown iocontrol %s", token);
533: return(IOSBAD);
534: }
535:
536:
537: ioclause(n, p)
538: register int n;
539: register expptr p;
540: {
541: struct Ioclist *iocp;
542:
543: ++nioctl;
544: if(n == IOSBAD)
545: return;
546: if(n == IOSPOSITIONAL)
547: {
548: n = nioctl;
549: if (n == IOSFMT) {
550: if (iostmt == IOOPEN) {
551: n = IOSFILE;
552: NOEXT("file= specifier omitted from open");
553: }
554: else if (iostmt < IOREAD)
555: goto illegal;
556: }
557: else if(n > IOSFMT)
558: {
559: illegal:
560: err("illegal positional iocontrol");
561: return;
562: }
563: }
564: else if (n == IOSNML)
565: n = IOSFMT;
566:
567: if(p == NULL)
568: {
569: if(n == IOSUNIT)
570: p = (expptr) (iostmt==IOREAD ? IOSTDIN : IOSTDOUT);
571: else if(n != IOSFMT)
572: {
573: err("illegal * iocontrol");
574: return;
575: }
576: }
577: if(n == IOSFMT)
578: ioformatted = (p==NULL ? LISTDIRECTED : FORMATTED);
579:
580: iocp = & ioc[n];
581: if(iocp->iocval == NULL)
582: {
583: if(n!=IOSFMT && ( n!=IOSUNIT || (p && p->headblock.vtype!=TYCHAR) ) )
584: p = fixtype(p);
585: else if (p && p->tag == TPRIM
586: && p->primblock.namep->vclass == CLUNKNOWN) {
587: /* kludge made necessary by attempt to infer types
588: * for untyped external parameters: given an error
589: * in calling sequences, an integer argument might
590: * tentatively be assumed TYCHAR; this would otherwise
591: * be corrected too late in startrw after startrw
592: * had decided this to be an internal file.
593: */
594: vardcl(p->primblock.namep);
595: p->primblock.vtype = p->primblock.namep->vtype;
596: }
597: iocp->iocval = p;
598: }
599: else
600: errstr("iocontrol %s repeated", iocp->iocname);
601: }
602:
603: /* io list item */
604:
605: doio(list)
606: chainp list;
607: {
608: expptr call0();
609:
610: if(ioformatted == NAMEDIRECTED)
611: {
612: if(list)
613: err("no I/O list allowed in NAMELIST read/write");
614: }
615: else
616: {
617: doiolist(list);
618: ioroutine[0] = 'e';
619: if (skiplab || ioroutine[4] == 'l')
620: jumplab = 0;
621: putiocall( call0(TYINT, ioroutine) );
622: }
623: }
624:
625:
626:
627:
628:
629: LOCAL void
630: doiolist(p0)
631: chainp p0;
632: {
633: chainp p;
634: register tagptr q;
635: register expptr qe;
636: register Namep qn;
637: Addrp tp, mkscalar();
638: int range;
639: extern char *ohalign;
640:
641: for (p = p0 ; p ; p = p->nextp)
642: {
643: q = (tagptr)p->datap;
644: if(q->tag == TIMPLDO)
645: {
646: exdo(range=newlabel(), (Namep)0,
647: q->impldoblock.impdospec);
648: doiolist(q->impldoblock.datalist);
649: enddo(range);
650: free( (charptr) q);
651: }
652: else {
653: if(q->tag==TPRIM && q->primblock.argsp==NULL
654: && q->primblock.namep->vdim!=NULL)
655: {
656: vardcl(qn = q->primblock.namep);
657: if(qn->vdim->nelt) {
658: putio( fixtype(cpexpr(qn->vdim->nelt)),
659: (expptr)mkscalar(qn) );
660: qn->vlastdim = 0;
661: }
662: else
663: err("attempt to i/o array of unknown size");
664: }
665: else if(q->tag==TPRIM && q->primblock.argsp==NULL &&
666: (qe = (expptr) memversion(q->primblock.namep)) )
667: putio(ICON(1),qe);
668: else if (ISCONST(q) && q->constblock.vtype == TYCHAR) {
669: halign = 0;
670: putio(ICON(1), qe = fixtype(cpexpr(q)));
671: halign = ohalign;
672: }
673: else if(((qe = fixtype(cpexpr(q)))->tag==TADDR &&
674: (qe->addrblock.uname_tag != UNAM_CONST ||
675: !ISCOMPLEX(qe -> addrblock.vtype))) ||
676: (qe -> tag == TCONST && !ISCOMPLEX(qe ->
677: headblock.vtype))) {
678: if (qe -> tag == TCONST)
679: qe = (expptr) putconst((Constp)qe);
680: putio(ICON(1), qe);
681: }
682: else if(qe->headblock.vtype != TYERROR)
683: {
684: if(iostmt == IOWRITE)
685: {
686: ftnint lencat();
687: expptr qvl;
688: qvl = NULL;
689: if( ISCHAR(qe) )
690: {
691: qvl = (expptr)
692: cpexpr(qe->headblock.vleng);
693: tp = mktmp(qe->headblock.vtype,
694: ICON(lencat(qe)));
695: }
696: else
697: tp = mktmp(qe->headblock.vtype,
698: qe->headblock.vleng);
699: puteq( cpexpr((expptr)tp), qe);
700: if(qvl) /* put right length on block */
701: {
702: frexpr(tp->vleng);
703: tp->vleng = qvl;
704: }
705: putio(ICON(1), (expptr)tp);
706: }
707: else
708: err("non-left side in READ list");
709: }
710: frexpr(q);
711: }
712: }
713: frchain( &p0 );
714: }
715:
716: int iocalladdr = TYADDR; /* for fixing TYADDR in saveargtypes */
717: int typeconv[TYERROR+1] = {
718: #ifdef TYQUAD
719: 0, 1, 11, 2, 3, 14, 4, 5, 6, 7, 12, 13, 8, 9, 10, 15
720: #else
721: 0, 1, 11, 2, 3, 4, 5, 6, 7, 12, 13, 8, 9, 10, 14
722: #endif
723: };
724:
725: LOCAL void
726: putio(nelt, addr)
727: expptr nelt;
728: register expptr addr;
729: {
730: int type;
731: register expptr q;
732: register Addrp c = 0;
733:
734: type = addr->headblock.vtype;
735: if(ioformatted!=LISTDIRECTED && ISCOMPLEX(type) )
736: {
737: nelt = mkexpr(OPSTAR, ICON(2), nelt);
738: type -= (TYCOMPLEX-TYREAL);
739: }
740:
741: /* pass a length with every item. for noncharacter data, fake one */
742: if(type != TYCHAR)
743: {
744:
745: if( ISCONST(addr) )
746: addr = (expptr) putconst((Constp)addr);
747: c = ALLOC(Addrblock);
748: c->tag = TADDR;
749: c->vtype = TYLENG;
750: c->vstg = STGAUTO;
751: c->ntempelt = 1;
752: c->isarray = 1;
753: c->memoffset = ICON(0);
754: c->uname_tag = UNAM_IDENT;
755: c->charleng = 1;
756: sprintf(c->user.ident, "(ftnlen)sizeof(%s)", typename[type]);
757: addr = mkexpr(OPCHARCAST, addr, ENULL);
758: }
759:
760: nelt = fixtype( mkconv(tyioint,nelt) );
761: if(ioformatted == LISTDIRECTED) {
762: expptr mc = mkconv(tyioint, ICON(typeconv[type]));
763: q = c ? call4(TYINT, "do_lio", mc, nelt, addr, (expptr)c)
764: : call3(TYINT, "do_lio", mc, nelt, addr);
765: }
766: else {
767: char *s = ioformatted==FORMATTED ? "do_fio" : "do_uio";
768: q = c ? call3(TYINT, s, nelt, addr, (expptr)c)
769: : call2(TYINT, s, nelt, addr);
770: }
771: iocalladdr = TYCHAR;
772: putiocall(q);
773: iocalladdr = TYADDR;
774: }
775:
776:
777:
778:
779: endio()
780: {
781: extern void p1_label();
782:
783: if(skiplab)
784: {
785: if (ioformatted != NAMEDIRECTED)
786: p1_label((long)(skiplabel - labeltab));
787: if(ioendlab) {
788: exif( mkexpr(OPLT, cpexpr(IOSTP), ICON(0)));
789: exgoto(execlab(ioendlab));
790: exendif();
791: }
792: if(ioerrlab) {
793: exif( mkexpr(iostmt==IOREAD||iostmt==IOWRITE
794: ? OPGT : OPNE,
795: cpexpr(IOSTP), ICON(0)));
796: exgoto(execlab(ioerrlab));
797: exendif();
798: }
799: }
800:
801: if(IOSTP)
802: frexpr(IOSTP);
803: }
804:
805:
806:
807: LOCAL void
808: putiocall(q)
809: register expptr q;
810: {
811: int tyintsave;
812:
813: tyintsave = tyint;
814: tyint = tyioint; /* for -I2 and -i2 */
815:
816: if(IOSTP)
817: {
818: q->headblock.vtype = TYINT;
819: q = fixexpr((Exprp)mkexpr(OPASSIGN, cpexpr(IOSTP), q));
820: }
821: putexpr(q);
822: if(jumplab) {
823: exif(mkexpr(OPNE, cpexpr(IOSTP), ICON(0)));
824: exgoto(execlab(jumplab));
825: exendif();
826: }
827: tyint = tyintsave;
828: }
829:
830: void
831: fmtname(np, q)
832: Namep np;
833: register Addrp q;
834: {
835: register int k;
836: register char *s, *t;
837: extern chainp assigned_fmts;
838:
839: if (!np->vfmt_asg) {
840: np->vfmt_asg = 1;
841: assigned_fmts = mkchain((char *)np, assigned_fmts);
842: }
843: k = strlen(s = np->fvarname);
844: if (k < IDENT_LEN - 4) {
845: q->uname_tag = UNAM_IDENT;
846: t = q->user.ident;
847: }
848: else {
849: q->uname_tag = UNAM_CHARP;
850: q->user.Charp = t = mem(k + 5,0);
851: }
852: sprintf(t, "%s_fmt", s);
853: }
854:
855: LOCAL Addrp asg_addr(p)
856: union Expression *p;
857: {
858: register Addrp q;
859:
860: if (p->tag != TPRIM)
861: badtag("asg_addr", p->tag);
862: q = ALLOC(Addrblock);
863: q->tag = TADDR;
864: q->vtype = TYCHAR;
865: q->vstg = STGAUTO;
866: q->ntempelt = 1;
867: q->isarray = 0;
868: q->memoffset = ICON(0);
869: fmtname(p->primblock.namep, q);
870: return q;
871: }
872:
873: startrw()
874: {
875: register expptr p;
876: register Namep np;
877: register Addrp unitp, fmtp, recp;
878: register expptr nump;
879: Addrp mkscalar();
880: expptr mkaddcon();
881: int iostmt1;
882: flag intfile, sequential, ok, varfmt;
883: struct io_setup *ios;
884:
885: /* First look at all the parameters and determine what is to be done */
886:
887: ok = YES;
888: statstruct = YES;
889:
890: intfile = NO;
891: if(p = V(IOSUNIT))
892: {
893: if( ISINT(p->headblock.vtype) ) {
894: int_unit:
895: unitp = (Addrp) cpexpr(p);
896: }
897: else if(p->headblock.vtype == TYCHAR)
898: {
899: if (nioctl == 1 && iostmt == IOREAD) {
900: /* kludge to recognize READ(format expr) */
901: V(IOSFMT) = p;
902: V(IOSUNIT) = p = (expptr) IOSTDIN;
903: ioformatted = FORMATTED;
904: goto int_unit;
905: }
906: intfile = YES;
907: if(p->tag==TPRIM && p->primblock.argsp==NULL &&
908: (np = p->primblock.namep)->vdim!=NULL)
909: {
910: vardcl(np);
911: if(nump = np->vdim->nelt)
912: {
913: nump = fixtype(cpexpr(nump));
914: if( ! ISCONST(nump) ) {
915: statstruct = NO;
916: np->vlastdim = 0;
917: }
918: }
919: else
920: {
921: err("attempt to use internal unit array of unknown size");
922: ok = NO;
923: nump = ICON(1);
924: }
925: unitp = mkscalar(np);
926: }
927: else {
928: nump = ICON(1);
929: unitp = (Addrp /*pjw */) fixtype(cpexpr(p));
930: }
931: if(! isstatic((expptr)unitp) )
932: statstruct = NO;
933: }
934: else {
935: err("unit specifier not of type integer or character");
936: ok = NO;
937: }
938: }
939: else
940: {
941: err("bad unit specifier");
942: ok = NO;
943: }
944:
945: sequential = YES;
946: if(p = V(IOSREC))
947: if( ISINT(p->headblock.vtype) )
948: {
949: recp = (Addrp) cpexpr(p);
950: sequential = NO;
951: }
952: else {
953: err("bad REC= clause");
954: ok = NO;
955: }
956: else
957: recp = NULL;
958:
959:
960: varfmt = YES;
961: fmtp = NULL;
962: if(p = V(IOSFMT))
963: {
964: if(p->tag==TPRIM && p->primblock.argsp==NULL)
965: {
966: np = p->primblock.namep;
967: if(np->vclass == CLNAMELIST)
968: {
969: ioformatted = NAMEDIRECTED;
970: fmtp = (Addrp) fixtype(p);
971: V(IOSFMT) = (expptr)fmtp;
972: if (skiplab)
973: jumplab = 0;
974: goto endfmt;
975: }
976: vardcl(np);
977: if(np->vdim)
978: {
979: if( ! ONEOF(np->vstg, MSKSTATIC) )
980: statstruct = NO;
981: fmtp = mkscalar(np);
982: goto endfmt;
983: }
984: if( ISINT(np->vtype) ) /* ASSIGNed label */
985: {
986: statstruct = NO;
987: varfmt = YES;
988: fmtp = asg_addr(p);
989: goto endfmt;
990: }
991: }
992: p = V(IOSFMT) = fixtype(p);
993: if(p->headblock.vtype == TYCHAR
994: /* Since we allow write(6,n) */
995: /* we may as well allow write(6,n(2)) */
996: || p->tag == TADDR && ISINT(p->addrblock.vtype))
997: {
998: if( ! isstatic(p) )
999: statstruct = NO;
1000: fmtp = (Addrp) cpexpr(p);
1001: }
1002: else if( ISICON(p) )
1003: {
1004: struct Labelblock *lp;
1005: lp = mklabel(p->constblock.Const.ci);
1006: if (fmtstmt(lp) > 0)
1007: {
1008: fmtp = (Addrp)mkaddcon(lp->stateno);
1009: /* lp->stateno for names fmt_nnn */
1010: lp->fmtlabused = 1;
1011: varfmt = NO;
1012: }
1013: else
1014: ioformatted = UNFORMATTED;
1015: }
1016: else {
1017: err("bad format descriptor");
1018: ioformatted = UNFORMATTED;
1019: ok = NO;
1020: }
1021: }
1022: else
1023: fmtp = NULL;
1024:
1025: endfmt:
1026: if(intfile) {
1027: if (ioformatted==UNFORMATTED) {
1028: err("unformatted internal I/O not allowed");
1029: ok = NO;
1030: }
1031: if (recp) {
1032: err("direct internal I/O not allowed");
1033: ok = NO;
1034: }
1035: }
1036: if(!sequential && ioformatted==LISTDIRECTED)
1037: {
1038: err("direct list-directed I/O not allowed");
1039: ok = NO;
1040: }
1041: if(!sequential && ioformatted==NAMEDIRECTED)
1042: {
1043: err("direct namelist I/O not allowed");
1044: ok = NO;
1045: }
1046:
1047: if( ! ok ) {
1048: statstruct = NO;
1049: return;
1050: }
1051:
1052: /*
1053: Now put out the I/O structure, statically if all the clauses
1054: are constants, dynamically otherwise
1055: */
1056:
1057: if (intfile) {
1058: ios = io_stuff + iostmt;
1059: iostmt1 = IOREAD;
1060: }
1061: else {
1062: ios = io_stuff;
1063: iostmt1 = 0;
1064: }
1065: io_fields = ios->fields;
1066: if(statstruct)
1067: {
1068: ioblkp = ALLOC(Addrblock);
1069: ioblkp->tag = TADDR;
1070: ioblkp->vtype = ios->type;
1071: ioblkp->vclass = CLVAR;
1072: ioblkp->vstg = STGINIT;
1073: ioblkp->memno = ++lastvarno;
1074: ioblkp->memoffset = ICON(0);
1075: ioblkp -> uname_tag = UNAM_IDENT;
1076: new_iob_data(ios,
1077: temp_name("io_", lastvarno, ioblkp->user.ident)); }
1078: else if(!(ioblkp = io_structs[iostmt1]))
1079: io_structs[iostmt1] = ioblkp =
1080: autovar(1, ios->type, ENULL, "");
1081:
1082: ioset(TYIOINT, XERR, ICON(errbit));
1083: if(iostmt == IOREAD)
1084: ioset(TYIOINT, (intfile ? XIEND : XEND), ICON(endbit) );
1085:
1086: if(intfile)
1087: {
1088: ioset(TYIOINT, XIRNUM, nump);
1089: ioset(TYIOINT, XIRLEN, cpexpr(unitp->vleng) );
1090: ioseta(XIUNIT, unitp);
1091: }
1092: else
1093: ioset(TYIOINT, XUNIT, (expptr) unitp);
1094:
1095: if(recp)
1096: ioset(TYIOINT, /* intfile ? XIREC : */ XREC, (expptr) recp);
1097:
1098: if(varfmt)
1099: ioseta( intfile ? XIFMT : XFMT , fmtp);
1100: else
1101: ioset(TYADDR, intfile ? XIFMT : XFMT, (expptr) fmtp);
1102:
1103: ioroutine[0] = 's';
1104: ioroutine[1] = '_';
1105: ioroutine[2] = iostmt==IOREAD ? 'r' : 'w';
1106: ioroutine[3] = "ds"[sequential];
1107: ioroutine[4] = "ufln"[ioformatted];
1108: ioroutine[5] = "ei"[intfile];
1109: ioroutine[6] = '\0';
1110:
1111: putiocall( call1(TYINT, ioroutine, cpexpr((expptr)ioblkp) ));
1112:
1113: if(statstruct)
1114: {
1115: frexpr((expptr)ioblkp);
1116: statstruct = NO;
1117: ioblkp = 0; /* unnecessary */
1118: }
1119: }
1120:
1121:
1122:
1123: LOCAL void
1124: dofopen()
1125: {
1126: register expptr p;
1127:
1128: if( (p = V(IOSUNIT)) && ISINT(p->headblock.vtype) )
1129: ioset(TYIOINT, XUNIT, cpexpr(p) );
1130: else
1131: err("bad unit in open");
1132: if( (p = V(IOSFILE)) )
1133: if(p->headblock.vtype == TYCHAR)
1134: ioset(TYIOINT, XFNAMELEN, cpexpr(p->headblock.vleng) );
1135: else
1136: err("bad file in open");
1137:
1138: iosetc(XFNAME, p);
1139:
1140: if(p = V(IOSRECL))
1141: if( ISINT(p->headblock.vtype) )
1142: ioset(TYIOINT, XRECLEN, cpexpr(p) );
1143: else
1144: err("bad recl");
1145: else
1146: ioset(TYIOINT, XRECLEN, ICON(0) );
1147:
1148: iosetc(XSTATUS, V(IOSSTATUS));
1149: iosetc(XACCESS, V(IOSACCESS));
1150: iosetc(XFORMATTED, V(IOSFORM));
1151: iosetc(XBLANK, V(IOSBLANK));
1152:
1153: putiocall( call1(TYINT, "f_open", cpexpr((expptr)ioblkp) ));
1154: }
1155:
1156:
1157: LOCAL void
1158: dofclose()
1159: {
1160: register expptr p;
1161:
1162: if( (p = V(IOSUNIT)) && ISINT(p->headblock.vtype) )
1163: {
1164: ioset(TYIOINT, XUNIT, cpexpr(p) );
1165: iosetc(XCLSTATUS, V(IOSSTATUS));
1166: putiocall( call1(TYINT, "f_clos", cpexpr((expptr)ioblkp)) );
1167: }
1168: else
1169: err("bad unit in close statement");
1170: }
1171:
1172:
1173: LOCAL void
1174: dofinquire()
1175: {
1176: register expptr p;
1177: if(p = V(IOSUNIT))
1178: {
1179: if( V(IOSFILE) )
1180: err("inquire by unit or by file, not both");
1181: ioset(TYIOINT, XUNIT, cpexpr(p) );
1182: }
1183: else if( ! V(IOSFILE) )
1184: err("must inquire by unit or by file");
1185: iosetlc(IOSFILE, XFILE, XFILELEN);
1186: iosetip(IOSEXISTS, XEXISTS);
1187: iosetip(IOSOPENED, XOPEN);
1188: iosetip(IOSNUMBER, XNUMBER);
1189: iosetip(IOSNAMED, XNAMED);
1190: iosetlc(IOSNAME, XNAME, XNAMELEN);
1191: iosetlc(IOSACCESS, XQACCESS, XQACCLEN);
1192: iosetlc(IOSSEQUENTIAL, XSEQ, XSEQLEN);
1193: iosetlc(IOSDIRECT, XDIRECT, XDIRLEN);
1194: iosetlc(IOSFORM, XFORM, XFORMLEN);
1195: iosetlc(IOSFORMATTED, XFMTED, XFMTEDLEN);
1196: iosetlc(IOSUNFORMATTED, XUNFMT, XUNFMTLEN);
1197: iosetip(IOSRECL, XQRECL);
1198: iosetip(IOSNEXTREC, XNEXTREC);
1199: iosetlc(IOSBLANK, XQBLANK, XQBLANKLEN);
1200:
1201: putiocall( call1(TYINT, "f_inqu", cpexpr((expptr)ioblkp) ));
1202: }
1203:
1204:
1205:
1206: LOCAL void
1207: dofmove(subname)
1208: char *subname;
1209: {
1210: register expptr p;
1211:
1212: if( (p = V(IOSUNIT)) && ISINT(p->headblock.vtype) )
1213: {
1214: ioset(TYIOINT, XUNIT, cpexpr(p) );
1215: putiocall( call1(TYINT, subname, cpexpr((expptr)ioblkp) ));
1216: }
1217: else
1218: err("bad unit in I/O motion statement");
1219: }
1220:
1221: static int ioset_assign = OPASSIGN;
1222:
1223: LOCAL void
1224: ioset(type, offset, p)
1225: int type, offset;
1226: register expptr p;
1227: {
1228: offset /= SZLONG;
1229: if(statstruct && ISCONST(p)) {
1230: register char *s;
1231: switch(type) {
1232: case TYADDR: /* stmt label */
1233: s = "fmt_";
1234: break;
1235: case TYIOINT:
1236: s = "";
1237: break;
1238: default:
1239: badtype("ioset", type);
1240: }
1241: iob_list->fields[offset] =
1242: string_num(s, p->constblock.Const.ci);
1243: frexpr(p);
1244: }
1245: else {
1246: register Addrp q;
1247:
1248: q = ALLOC(Addrblock);
1249: q->tag = TADDR;
1250: q->vtype = type;
1251: q->vstg = STGAUTO;
1252: q->ntempelt = 1;
1253: q->isarray = 0;
1254: q->memoffset = ICON(0);
1255: q->uname_tag = UNAM_IDENT;
1256: sprintf(q->user.ident, "%s.%s",
1257: statstruct ? iob_list->name : ioblkp->user.ident,
1258: io_fields[offset + 1]);
1259: if (type == TYADDR && p->tag == TCONST
1260: && p->constblock.vtype == TYADDR) {
1261: /* kludge */
1262: register Addrp p1;
1263: p1 = ALLOC(Addrblock);
1264: p1->tag = TADDR;
1265: p1->vtype = type;
1266: p1->vstg = STGAUTO; /* wrong, but who cares? */
1267: p1->ntempelt = 1;
1268: p1->isarray = 0;
1269: p1->memoffset = ICON(0);
1270: p1->uname_tag = UNAM_IDENT;
1271: sprintf(p1->user.ident, "fmt_%ld",
1272: p->constblock.Const.ci);
1273: frexpr(p);
1274: p = (expptr)p1;
1275: }
1276: if (type == TYADDR && p->headblock.vtype == TYCHAR)
1277: q->vtype = TYCHAR;
1278: putexpr(mkexpr(ioset_assign, (expptr)q, p));
1279: }
1280: }
1281:
1282:
1283:
1284:
1285: LOCAL void
1286: iosetc(offset, p)
1287: int offset;
1288: register expptr p;
1289: {
1290: extern Addrp putchop();
1291:
1292: if(p == NULL)
1293: ioset(TYADDR, offset, ICON(0) );
1294: else if(p->headblock.vtype == TYCHAR) {
1295: p = putx(fixtype((expptr)putchop(cpexpr(p))));
1296: ioset(TYADDR, offset, addrof(p));
1297: }
1298: else
1299: err("non-character control clause");
1300: }
1301:
1302:
1303:
1304: LOCAL void
1305: ioseta(offset, p)
1306: int offset;
1307: register Addrp p;
1308: {
1309: char *s, *s1;
1310: static char who[] = "ioseta";
1311: expptr e, mo;
1312: Namep np;
1313: ftnint ci;
1314: int k;
1315: char buf[24], buf1[24];
1316: Extsym *comm;
1317: extern int usedefsforcommon;
1318:
1319: if(statstruct)
1320: {
1321: if (!p)
1322: return;
1323: if (p->tag != TADDR)
1324: badtag(who, p->tag);
1325: offset /= SZLONG;
1326: switch(p->uname_tag) {
1327: case UNAM_NAME:
1328: mo = p->memoffset;
1329: if (mo->tag != TCONST)
1330: badtag("ioseta/memoffset", mo->tag);
1331: np = p->user.name;
1332: np->visused = 1;
1333: ci = mo->constblock.Const.ci - np->voffset;
1334: if (np->vstg == STGCOMMON
1335: && !np->vcommequiv
1336: && !usedefsforcommon) {
1337: comm = &extsymtab[np->vardesc.varno];
1338: sprintf(buf, "%d.", comm->curno);
1339: k = strlen(buf) + strlen(comm->cextname)
1340: + strlen(np->cvarname);
1341: if (ci) {
1342: sprintf(buf1, "+%ld", ci);
1343: k += strlen(buf1);
1344: }
1345: else
1346: buf1[0] = 0;
1347: s = mem(k + 1, 0);
1348: sprintf(s, "%s%s%s%s", comm->cextname, buf,
1349: np->cvarname, buf1);
1350: }
1351: else if (ci) {
1352: sprintf(buf,"%ld", ci);
1353: s1 = p->user.name->cvarname;
1354: k = strlen(buf) + strlen(s1);
1355: sprintf(s = mem(k+2,0), "%s+%s", s1, buf);
1356: }
1357: else
1358: s = cpstring(np->cvarname);
1359: break;
1360: case UNAM_CONST:
1361: s = tostring(p->user.Const.ccp1.ccp0,
1362: (int)p->vleng->constblock.Const.ci);
1363: break;
1364: default:
1365: badthing("uname_tag", who, p->uname_tag);
1366: }
1367: /* kludge for Hollerith */
1368: if (p->vtype != TYCHAR) {
1369: s1 = mem(strlen(s)+10,0);
1370: sprintf(s1, "(char *)%s%s", p->isarray ? "" : "&", s);
1371: s = s1;
1372: }
1373: iob_list->fields[offset] = s;
1374: }
1375: else {
1376: if (!p)
1377: e = ICON(0);
1378: else if (p->vtype != TYCHAR) {
1379: NOEXT("non-character variable as format or internal unit");
1380: e = mkexpr(OPCHARCAST, (expptr)p, ENULL);
1381: }
1382: else
1383: e = addrof((expptr)p);
1384: ioset(TYADDR, offset, e);
1385: }
1386: }
1387:
1388:
1389:
1390:
1391: LOCAL void
1392: iosetip(i, offset)
1393: int i, offset;
1394: {
1395: register expptr p;
1396:
1397: if(p = V(i))
1398: if(p->tag==TADDR &&
1399: ONEOF(p->addrblock.vtype, inqmask) ) {
1400: ioset_assign = OPASSIGNI;
1401: ioset(TYADDR, offset, addrof(cpexpr(p)) );
1402: ioset_assign = OPASSIGN;
1403: }
1404: else
1405: errstr("impossible inquire parameter %s", ioc[i].iocname);
1406: else
1407: ioset(TYADDR, offset, ICON(0) );
1408: }
1409:
1410:
1411:
1412: LOCAL void
1413: iosetlc(i, offp, offl)
1414: int i, offp, offl;
1415: {
1416: register expptr p;
1417: if( (p = V(i)) && p->headblock.vtype==TYCHAR)
1418: ioset(TYIOINT, offl, cpexpr(p->headblock.vleng) );
1419: iosetc(offp, p);
1420: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.