BSD 4_3_Reno development
[unix-history] / usr / src / old / efl / io.c
CommitLineData
64836102
C
1#include <ctype.h>
2
3#include "defs"
4
5static int lastfmtchar;
6static int writeop;
7static int needcomma;
8
9
10ptr mkiost(kwd,unit,list)
11int kwd;
12ptr unit;
13ptr list;
14{
15register ptr p;
16
17if(unit!=NULL && unit->vtype!=TYINT)
18 {
19 execerr("I/O unit must be an integer", "");
20 return(NULL);
21 }
22p = allexpblock();
23p->tag = TIOSTAT;
24p->vtype = TYINT;
25p->iokwd = kwd;
26p->iounit = unit;
27p->iolist = list;
28
29return(p);
30}
31
32
33
34
35struct iogroup *mkiogroup(list, format, dop)
36ptr list;
37char *format;
38ptr dop;
39{
40register struct iogroup *p;
41
42p = ALLOC(iogroup);
43p->tag = TIOGROUP;
44p->doptr = dop;
45p->iofmt = format;
46p->ioitems = list;
47return(p);
48}
49\f
50ptr exio(iostp, errhandle)
51struct iostblock *iostp;
52int errhandle;
53{
54ptr unit, list;
55int fmtlabel, errlabel, endlabel, jumplabel;
56ptr errval;
57int fmtio;
58
59if(iostp == NULL)
60 return( errnode() );
61unit = iostp->iounit;
62list = iostp->iolist;
63
64/* kwd= 0 binary input 2 formatted input
65 1 binary output 3 formatted output
66*/
67
68writeop = iostp->iokwd & 01;
69if( fmtio = (iostp->iokwd & 02) )
70 fmtlabel = nextlab() ;
71frexpblock(iostp);
72
73errval = 0;
74endlabel = 0;
75if(errhandle)
76 {
77 switch(tailor.errmode)
78 {
79 default:
80 execerr("no error handling ", "");
81 return( errnode() );
82
83 case IOERRIBM: /* ibm: err=, end= */
84 jumplabel = nextlab();
85 break;
86
87 case IOERRFORT77: /* New Fortran Standard: iostat= */
88 break;
89
90 }
91 errval = gent(TYINT, PNULL);
92 }
93if(unit)
94 unit = simple(RVAL, unit);
95else unit = mkint(writeop ? tailor.ftnout : tailor.ftnin);
96
97if(unit->tag!=TCONST && (unit->tag!=TNAME || unit->vsubs!=0))
98 unit = simple(LVAL, mknode(TASGNOP,OPASGN,gent(TYINT,PNULL),unit));
99
100simlist(list);
101
102exlab(0);
103putic(ICKEYWORD, (writeop ? FWRITE : FREAD) );
104putic(ICOP, OPLPAR);
105prexpr(unit);
106frexpr(unit);
107
108if( fmtio )
109 {
110 putic(ICOP, OPCOMMA);
111 putic(ICLABEL, fmtlabel);
112 }
113
114if(errhandle) switch(tailor.errmode)
115 {
116 case IOERRIBM:
117 putic(ICOP,OPCOMMA);
118 putsii(ICCONST, "err =");
119 putic(ICLABEL, errlabel = nextlab() );
120 if(!writeop)
121 {
122 putic(ICOP,OPCOMMA);
123 putsii(ICCONST, "end =");
124 putic(ICLABEL, endlabel = nextlab() );
125 }
126 break;
127
128 case IOERRFORT77:
129 putic(ICOP,OPCOMMA);
130 putsii(ICCONST, "iostat =");
131 putname(errval);
132 break;
133 }
134
135putic(ICOP,OPRPAR);
136putic(ICBLANK, 1);
137
138needcomma = NO;
139doiolist(list);
140if(fmtio)
141 {
142 exlab(fmtlabel);
143 putic(ICKEYWORD, FFORMAT);
144 putic(ICOP, OPLPAR);
145 lastfmtchar = '(';
146 doformat(1, list);
147 putic(ICOP, OPRPAR);
148 }
149friolist(list);
150
151if(errhandle && tailor.errmode==IOERRIBM)
152 {
153 exasgn(cpexpr(errval), OPASGN, mkint(0) );
154 exgoto(jumplabel);
155 exlab(errlabel);
156 exasgn(cpexpr(errval), OPASGN, mkint(1) );
157 if(endlabel)
158 {
159 exgoto(jumplabel);
160 exlab(endlabel);
161 exasgn(cpexpr(errval), OPASGN,
162 mknode(TNEGOP,OPMINUS,mkint(1),PNULL) );
163 }
164 exlab(jumplabel);
165 }
166
167return( errval );
168}
169\f
170doiolist(list)
171ptr list;
172{
173register ptr p, q;
174register struct doblock *dop;
175for(p = list ; p ; p = p->nextp)
176 {
177 switch( (q = p->datap) ->tag)
178 {
179 case TIOGROUP:
180 if(dop = q->doptr)
181 {
182 if(needcomma)
183 putic(ICOP, OPCOMMA);
184 putic(ICOP, OPLPAR);
185 needcomma = NO;
186 }
187 doiolist(q->ioitems);
188 if(dop)
189 {
190 putic(ICOP,OPCOMMA);
191 prexpr(dop->dovar);
192 putic(ICOP, OPEQUALS);
193 prexpr(dop->dopar[0]);
194 putic(ICOP, OPCOMMA);
195 prexpr(dop->dopar[1]);
196 if(dop->dopar[2])
197 {
198 putic(ICOP, OPCOMMA);
199 prexpr(dop->dopar[2]);
200 }
201 putic(ICOP, OPRPAR);
202 needcomma = YES;
203 }
204 break;
205
206 case TIOITEM:
207 if(q->ioexpr)
208 {
209 if(needcomma)
210 putic(ICOP, OPCOMMA);
211 prexpr(q->ioexpr);
212 needcomma = YES;
213 }
214 break;
215
216 default:
217 badtag("doiolist", q->tag);
218 }
219 }
220}
221\f
222doformat(nrep, list)
223int nrep;
224ptr list;
225{
226register ptr p, q;
227int k;
228ptr arrsize();
229
230if(nrep > 1)
231 {
232 fmtnum(nrep);
233 fmtop(OPLPAR);
234 }
235
236for(p = list ; p ; p = p->nextp)
237 switch( (q = p->datap) ->tag)
238 {
239 case TIOGROUP:
240 if(q->iofmt)
241 prfmt(q->nrep, q->iofmt);
242 else {
243 doformat(q->nrep>0 ? q->nrep :
244 (q->doptr ? repfac(q->doptr) : 1),
245 q->ioitems);
246 }
247 break;
248
249 case TIOITEM:
250 if(q->iofmt == NULL)
251 break;
252
253 if(q->nrep==0 && q->ioexpr && q->ioexpr->vdim)
254 {
255 if( ! isicon(arrsize(q->ioexpr), &k) )
256 execerr("io of adjustable array", "");
257 else
258 prfmt(k, q->iofmt);
259 }
260 else
261 prfmt(q->nrep, q->iofmt);
262 }
263if(nrep > 1)
264 fmtop(OPRPAR);
265}
266\f
267fmtop(op)
268register int op;
269{
270register c;
271
272c = (op==OPLPAR ? '(' : (op==OPRPAR ? ')' : 'x') );
273fmtcom(c);
274putic(ICOP, op);
275lastfmtchar = c;
276}
277
278
279
280
281fmtnum(k)
282int k;
283{
284fmtcom('1');
285prexpr( mkint(k) );
286lastfmtchar = ','; /* prevent further comma after factor*/
287}
288
289
290
291
292
293
294
295
296/* separate formats with comma unless already a slash*/
297fmtcom(c)
298int c;
299{
300if( c!='/' && c!=')' && lastfmtchar!='/' && lastfmtchar!='(' && lastfmtchar!=',' )
301 {
302 putic(ICOP, OPCOMMA);
303 lastfmtchar = ',';
304 }
305}
306\f
307prfmt(nrep, str)
308int nrep;
309char *str;
310{
311char fmt[20];
312register int k, k0, k1, k2;
313register char *t;
314
315fmtcom(nrep>1 ? '1' : str[0]);
316
317if(nrep > 1)
318 {
319 fmtnum(nrep);
320 fmtop(OPLPAR);
321 }
322
323switch(str[0])
324 {
325 case 'd':
326 case 'e':
327 case 'g':
328 if(writeop)
329 {
330 putsii(ICCONST, "1p");
331 break;
332 }
333
334 case 'f':
335 putsii(ICCONST, "0p");
336 break;
337
338 case 'c':
339 k = convci(str+1);
340 k0 = tailor.ftnchwd;
341 k1 = k / k0;
342 k2 = k % k0;
343 if(k1>0 && k2>0)
344 sprintf(fmt, "(%da%d,a%d)",k1,k0,k2);
345 else if(k1>1)
346 sprintf(fmt, "(%da%d)", k1, k0);
347 else sprintf(fmt, "a%d", k);
348 putsii(ICCONST, fmt);
349 lastfmtchar = 'f'; /* last char isnt operator */
350 goto close;
351
352 default:
353 break;
354 }
355putsii(ICCONST,str);
356/* if the format is an nH, act as if it ended with a non-operator character */
357if( isdigit(str[0]) )
358 {
359 for(t = str+1 ; isdigit(*t) ; ++t);
360 ;
361 if(*t=='h' || *t=='H')
362 {
363 lastfmtchar = 'f';
364 goto close;
365 }
366 }
367lastfmtchar = str[ strlen(str)-1 ];
368
369close:
370 if(nrep > 1)
371 fmtop(OPRPAR);
372}
373\f
374friolist(list)
375ptr list;
376{
377register ptr p, q;
378register struct doblock *dop;
379
380for(p = list; p; p = p->nextp)
381 {
382 switch ( (q = p->datap) ->tag)
383 {
384 case TIOGROUP:
385 if(dop = q->doptr)
386 {
387 frexpr(dop->dovar);
388 frexpr(dop->dopar[0]);
389 frexpr(dop->dopar[1]);
390 if(dop->dopar[2])
391 frexpr(dop->dopar[2]);
392 cfree(dop);
393 }
394 friolist(q->ioitems);
395 break;
396
397 case TIOITEM:
398 if(q->ioexpr)
399 frexpr(q->ioexpr);
400 break;
401
402 default:
403 badtag("friolist", q->tag);
404 }
405 if(q->iofmt)
406 cfree(q->iofmt);
407 cfree(q);
408 }
409frchain( &list );
410}
411\f
412simlist(p)
413register ptr p;
414{
415register ptr q, ep;
416struct iogroup *enloop();
417
418for( ; p ; p = p->nextp)
419 switch( (q = p->datap) ->tag )
420 {
421 case TIOGROUP:
422 simlist(q->ioitems);
423 break;
424
425 case TIOITEM:
426 if(ep = q->ioexpr)
427 {
428 /* if element is a subaggregate, need
429 an implied do loop */
430 if( (ep->voffset || ep->vsubs) &&
431 (ep->vdim || ep->vtypep) )
432 p->datap = enloop(q);
433 else
434 q->ioexpr = simple(LVAL,ep);
435 }
436 break;
437
438 default:
439 badtag("ioblock", q->tag);
440 }
441}
442
443
444
445
446/* replace an aggregate by an implied do loop of elements */
447
448struct iogroup *enloop(p)
449struct ioitem *p;
450{
451register struct doblock *dop;
452struct iogroup *gp;
453ptr np, q, v, arrsize(), mkioitem();
454int nrep, k, nwd;
455
456q = p->ioexpr;
457np = arrsize(q);
458if( ! isicon(np, &nrep) )
459 nrep = 0;
460
461if(q->vtype == TYCHAR)
462 {
463 nwd = ceil(conval(q->vtypep), tailor.ftnchwd);
464 if(nwd != 1)
465 np = simple(LVAL, mknode(TAROP,OPSTAR,np,mkint(nwd)));
466 }
467else
468 nwd = 0;
469
470if( isicon(np, &k) && k==1)
471 return(p);
472
473dop = ALLOC(doblock);
474dop->tag = TDOBLOCK;
475
476dop->dovar = v = gent(TYINT, PNULL);
477dop->dopar[0] = mkint(1);
478dop->dopar[1] = simple(SUBVAL, np);
479dop->dopar[2] = NULL;
480
481q = simple(LVAL, q);
482if(q->vsubs == NULL)
483 q->vsubs = mknode(TLIST,0, mkchain(cpexpr(v),CHNULL), PNULL);
484else
485 q->vsubs->leftp->datap = simple(SUBVAL, mknode(TAROP,OPPLUS, cpexpr(v),
486 mknode(TAROP,OPMINUS,q->vsubs->leftp->datap,mkint(1))));
487q->vdim = NULL;
488gp = mkiogroup( mkchain(mkioitem(q,CNULL), CHNULL), p->iofmt, dop);
489gp->nrep = nrep;
490cfree(p);
491return(gp);
492}
493\f
494ptr mkformat(letter, n1, n2)
495char letter;
496register ptr n1, n2;
497{
498char f[20], *fp, *s;
499int k;
500
501if(letter == 's')
502 {
503 if(n1)
504 {
505 k = conval(n1);
506 frexpr(n1);
507 }
508 else k = 1;
509
510 for(fp = f; k-->0 ; )
511 *fp++ = '/';
512 *fp = '\0';
513 return( copys(f) );
514 }
515
516f[0] = letter;
517fp = f+1;
518
519if(n1) {
520 n1 = simple(RVAL,n1);
521 if(n1->tag==TCONST && n1->vtype==TYINT)
522 {
523 for(s = n1->leftp ; *s; )
524 *fp++ = *s++;
525 }
526 else execerr("bad format component %s", n1->leftp);
527 frexpr(n1);
528 }
529
530if(n2) {
531 if(n2->tag==TCONST && n2->vtype==TYINT)
532 {
533 *fp++ = '.';
534 for(s = n2->leftp ; *s; )
535 *fp++ = *s++;
536 }
537 else execerr("bad format component %s", n2->leftp);
538 frexpr(n2);
539 }
540
541if( letter == 'x' )
542 {
543 if(n1 == 0)
544 *fp++ = '1';
545 fp[0] = 'x';
546 fp[1] = '\0';
547 return( copys(f+1) );
548 }
549else {
550 *fp = '\0';
551 return( copys(f) );
552 }
553}
554\f
555ptr mkioitem(e,f)
556register ptr e;
557char *f;
558{
559register ptr p;
560char fmt[10];
561ptr gentemp();
562
563p = ALLOC(ioitem);
564p->tag = TIOITEM;
565if(e!=NULL && e->tag==TCONST)
566 if(e->vtype==TYCHAR && (f==0 || (f[0]=='c' && f[1]=='\0') ))
567 {
568 p->ioexpr = 0;
569 sprintf(msg, "%dh%s", strlen(e->leftp), e->leftp);
570 p->iofmt = copys(msg);
571 frexpr(e);
572 return(p);
573 }
574 else e = mknode(TASGNOP,OPASGN,gentemp(e),e);
575
576if(e && e->vtype==TYCHAR && f && f[0]=='c' && f[1]=='\0')
577 f = NULL;
578if(f == NULL)
579 {
580 switch(e->vtype)
581 {
582 case TYINT:
583 case TYREAL:
584 case TYLREAL:
585 case TYCOMPLEX:
586 case TYLOG:
587 f = copys( tailor.dfltfmt[e->vtype] );
588 break;
589
590 case TYCHAR:
591 if(e->vtypep->tag != TCONST)
592 {
593 execerr("no adjustable character formats", "");
594 f = 0;
595 }
596 else {
597 sprintf(fmt, "c%s", e->vtypep->leftp);
598 f = copys(fmt);
599 }
600 break;
601
602 default:
603 execerr("cannot do I/O on structures", "");
604 f = 0;
605 break;
606 }
607 }
608
609p->ioexpr = e;
610p->iofmt = f;
611return(p);
612}
613
614
615
616ptr arrsize(p)
617ptr p;
618{
619register ptr b;
620ptr f, q;
621
622q = mkint(1);
623
624if(b = p->vdim)
625 for(b = b->datap ; b ; b = b->nextp)
626 {
627 if(b->upperb == 0) continue;
628 f = cpexpr(b->upperb);
629 if(b->lowerb)
630 f = mknode(TAROP,OPPLUS,f,
631 mknode(TAROP,OPMINUS,mkint(1),cpexpr(b->lowerb)));
632 q = simple(RVAL, mknode(TAROP,OPSTAR,q,f));
633 }
634return(q);
635}
636
637
638
639
640repfac(dop)
641register struct doblock *dop;
642{
643int m1, m2, m3;
644
645m3 = 1;
646if( isicon(dop->dopar[0],&m1) && isicon(dop->dopar[1],&m2) &&
647 (dop->dopar[2]==NULL || isicon(dop->dopar[2],&m3)) )
648 {
649 if(m3 > 0)
650 return(1 + (m2-m1)/m3);
651 }
652else execerr("nonconstant implied do", "");
653return(1);
654}
655
656
657
658ioop(s)
659char *s;
660{
661if( equals(s, "backspace") )
662 return(FBACKSPACE);
663if( equals(s, "rewind") )
664 return(FREWIND);
665if( equals(s, "endfile") )
666 return(FENDFILE);
667return(0);
668}
669
670
671
672
673ptr exioop(p, errcheck)
674register struct exprblock *p;
675int errcheck;
676{
677register ptr q, t;
678
679if( (q = p->rightp)==NULL || (q = q->leftp)==NULL )
680 {
681 execerr("bad I/O operation", "");
682 return(NULL);
683 }
684q = simple(LVAL, cpexpr(q->datap) );
685
686exlab(0);
687putic(ICKEYWORD, ioop(p->leftp->sthead->namep));
688
689if(errcheck)
690 {
691 if(tailor.errmode != IOERRFORT77)
692 {
693 execerr("cannot test value of IOOP without ftn77", "");
694 return( errnode() );
695 }
696 putic(ICOP, OPLPAR);
697 prexpr(q);
698 putic(ICOP, OPCOMMA);
699 putsii(ICCONST, "iostat =");
700 prexpr(cpexpr( t = gent(TYINT,PNULL)));
701 putic(ICOP, OPRPAR);
702 return( t );
703 }
704else {
705 putic(ICBLANK, 1);
706 prexpr(q);
707 }
708}