📄 io.c
字号:
#include <ctype.h>#include "defs"static int lastfmtchar;static int writeop;static int needcomma;ptr mkiost(kwd,unit,list)int kwd;ptr unit;ptr list;{register ptr p;if(unit!=NULL && unit->vtype!=TYINT) { execerr("I/O unit must be an integer", ""); return(NULL); }p = allexpblock();p->tag = TIOSTAT;p->vtype = TYINT;p->iokwd = kwd;p->iounit = unit;p->iolist = list;return(p);}struct iogroup *mkiogroup(list, format, dop)ptr list;char *format;ptr dop;{register struct iogroup *p;p = ALLOC(iogroup);p->tag = TIOGROUP;p->doptr = dop;p->iofmt = format;p->ioitems = list;return(p);}ptr exio(iostp, errhandle)struct iostblock *iostp;int errhandle;{ptr unit, list;int fmtlabel, errlabel, endlabel, jumplabel;ptr errval;int fmtio;if(iostp == NULL) return( errnode() );unit = iostp->iounit;list = iostp->iolist;/* kwd= 0 binary input 2 formatted input 1 binary output 3 formatted output*/writeop = iostp->iokwd & 01;if( fmtio = (iostp->iokwd & 02) ) fmtlabel = nextlab() ;frexpblock(iostp);errval = 0;endlabel = 0;if(errhandle) { switch(tailor.errmode) { default: execerr("no error handling ", ""); return( errnode() ); case IOERRIBM: /* ibm: err=, end= */ jumplabel = nextlab(); break; case IOERRFORT77: /* New Fortran Standard: iostat= */ break; } errval = gent(TYINT, PNULL); }if(unit) unit = simple(RVAL, unit);else unit = mkint(writeop ? tailor.ftnout : tailor.ftnin);if(unit->tag!=TCONST && (unit->tag!=TNAME || unit->vsubs!=0)) unit = simple(LVAL, mknode(TASGNOP,OPASGN,gent(TYINT,PNULL),unit));simlist(list);exlab(0);putic(ICKEYWORD, (writeop ? FWRITE : FREAD) );putic(ICOP, OPLPAR);prexpr(unit);frexpr(unit);if( fmtio ) { putic(ICOP, OPCOMMA); putic(ICLABEL, fmtlabel); }if(errhandle) switch(tailor.errmode) { case IOERRIBM: putic(ICOP,OPCOMMA); putsii(ICCONST, "err ="); putic(ICLABEL, errlabel = nextlab() ); if(!writeop) { putic(ICOP,OPCOMMA); putsii(ICCONST, "end ="); putic(ICLABEL, endlabel = nextlab() ); } break; case IOERRFORT77: putic(ICOP,OPCOMMA); putsii(ICCONST, "iostat ="); putname(errval); break; }putic(ICOP,OPRPAR);putic(ICBLANK, 1);needcomma = NO;doiolist(list);if(fmtio) { exlab(fmtlabel); putic(ICKEYWORD, FFORMAT); putic(ICOP, OPLPAR); lastfmtchar = '('; doformat(1, list); putic(ICOP, OPRPAR); }friolist(list);if(errhandle && tailor.errmode==IOERRIBM) { exasgn(cpexpr(errval), OPASGN, mkint(0) ); exgoto(jumplabel); exlab(errlabel); exasgn(cpexpr(errval), OPASGN, mkint(1) ); if(endlabel) { exgoto(jumplabel); exlab(endlabel); exasgn(cpexpr(errval), OPASGN, mknode(TNEGOP,OPMINUS,mkint(1),PNULL) ); } exlab(jumplabel); }return( errval );}doiolist(list)ptr list;{register ptr p, q;register struct doblock *dop;for(p = list ; p ; p = p->nextp) { switch( (q = p->datap) ->tag) { case TIOGROUP: if(dop = q->doptr) { if(needcomma) putic(ICOP, OPCOMMA); putic(ICOP, OPLPAR); needcomma = NO; } doiolist(q->ioitems); if(dop) { putic(ICOP,OPCOMMA); prexpr(dop->dovar); putic(ICOP, OPEQUALS); prexpr(dop->dopar[0]); putic(ICOP, OPCOMMA); prexpr(dop->dopar[1]); if(dop->dopar[2]) { putic(ICOP, OPCOMMA); prexpr(dop->dopar[2]); } putic(ICOP, OPRPAR); needcomma = YES; } break; case TIOITEM: if(q->ioexpr) { if(needcomma) putic(ICOP, OPCOMMA); prexpr(q->ioexpr); needcomma = YES; } break; default: badtag("doiolist", q->tag); } }}doformat(nrep, list)int nrep;ptr list;{register ptr p, q;int k;ptr arrsize();if(nrep > 1) { fmtnum(nrep); fmtop(OPLPAR); }for(p = list ; p ; p = p->nextp) switch( (q = p->datap) ->tag) { case TIOGROUP: if(q->iofmt) prfmt(q->nrep, q->iofmt); else { doformat(q->nrep>0 ? q->nrep : (q->doptr ? repfac(q->doptr) : 1), q->ioitems); } break; case TIOITEM: if(q->iofmt == NULL) break; if(q->nrep==0 && q->ioexpr && q->ioexpr->vdim) { if( ! isicon(arrsize(q->ioexpr), &k) ) execerr("io of adjustable array", ""); else prfmt(k, q->iofmt); } else prfmt(q->nrep, q->iofmt); }if(nrep > 1) fmtop(OPRPAR);}fmtop(op)register int op;{register c;c = (op==OPLPAR ? '(' : (op==OPRPAR ? ')' : 'x') );fmtcom(c);putic(ICOP, op);lastfmtchar = c;}fmtnum(k)int k;{fmtcom('1');prexpr( mkint(k) );lastfmtchar = ','; /* prevent further comma after factor*/}/* separate formats with comma unless already a slash*/fmtcom(c)int c;{if( c!='/' && c!=')' && lastfmtchar!='/' && lastfmtchar!='(' && lastfmtchar!=',' ) { putic(ICOP, OPCOMMA); lastfmtchar = ','; }}prfmt(nrep, str)int nrep;char *str;{char fmt[20];register int k, k0, k1, k2;register char *t;fmtcom(nrep>1 ? '1' : str[0]);if(nrep > 1) { fmtnum(nrep); fmtop(OPLPAR); }switch(str[0]) { case 'd': case 'e': case 'g': if(writeop) { putsii(ICCONST, "1p"); break; } case 'f': putsii(ICCONST, "0p"); break; case 'c': k = convci(str+1); k0 = tailor.ftnchwd; k1 = k / k0; k2 = k % k0; if(k1>0 && k2>0) sprintf(fmt, "(%da%d,a%d)",k1,k0,k2); else if(k1>1) sprintf(fmt, "(%da%d)", k1, k0); else sprintf(fmt, "a%d", k); putsii(ICCONST, fmt); lastfmtchar = 'f'; /* last char isnt operator */ goto close; default: break; }putsii(ICCONST,str);/* if the format is an nH, act as if it ended with a non-operator character */if( isdigit(str[0]) ) { for(t = str+1 ; isdigit(*t) ; ++t); ; if(*t=='h' || *t=='H') { lastfmtchar = 'f'; goto close; } }lastfmtchar = str[ strlen(str)-1 ];close: if(nrep > 1) fmtop(OPRPAR);}friolist(list)ptr list;{register ptr p, q;register struct doblock *dop;for(p = list; p; p = p->nextp) { switch ( (q = p->datap) ->tag) { case TIOGROUP: if(dop = q->doptr) { frexpr(dop->dovar); frexpr(dop->dopar[0]); frexpr(dop->dopar[1]); if(dop->dopar[2]) frexpr(dop->dopar[2]); cfree(dop); } friolist(q->ioitems); break; case TIOITEM: if(q->ioexpr) frexpr(q->ioexpr); break; default: badtag("friolist", q->tag); } if(q->iofmt) cfree(q->iofmt); cfree(q); }frchain( &list );}simlist(p)register ptr p;{register ptr q, ep;struct iogroup *enloop();for( ; p ; p = p->nextp) switch( (q = p->datap) ->tag ) { case TIOGROUP: simlist(q->ioitems); break; case TIOITEM: if(ep = q->ioexpr) { /* if element is a subaggregate, need an implied do loop */ if( (ep->voffset || ep->vsubs) && (ep->vdim || ep->vtypep) ) p->datap = enloop(q); else q->ioexpr = simple(LVAL,ep); } break; default: badtag("ioblock", q->tag); }}/* replace an aggregate by an implied do loop of elements */struct iogroup *enloop(p)struct ioitem *p;{register struct doblock *dop;struct iogroup *gp;ptr np, q, v, arrsize(), mkioitem();int nrep, k, nwd;q = p->ioexpr;np = arrsize(q);if( ! isicon(np, &nrep) ) nrep = 0;if(q->vtype == TYCHAR) { nwd = ceil(conval(q->vtypep), tailor.ftnchwd); if(nwd != 1) np = simple(LVAL, mknode(TAROP,OPSTAR,np,mkint(nwd))); }else nwd = 0;if( isicon(np, &k) && k==1) return(p);dop = ALLOC(doblock);dop->tag = TDOBLOCK;dop->dovar = v = gent(TYINT, PNULL);dop->dopar[0] = mkint(1);dop->dopar[1] = simple(SUBVAL, np);dop->dopar[2] = NULL;q = simple(LVAL, q);if(q->vsubs == NULL) q->vsubs = mknode(TLIST,0, mkchain(cpexpr(v),CHNULL), PNULL);else q->vsubs->leftp->datap = simple(SUBVAL, mknode(TAROP,OPPLUS, cpexpr(v), mknode(TAROP,OPMINUS,q->vsubs->leftp->datap,mkint(1))));q->vdim = NULL;gp = mkiogroup( mkchain(mkioitem(q,CNULL), CHNULL), p->iofmt, dop);gp->nrep = nrep;cfree(p);return(gp);}ptr mkformat(letter, n1, n2)char letter;register ptr n1, n2;{char f[20], *fp, *s;int k;if(letter == 's') { if(n1) { k = conval(n1); frexpr(n1); } else k = 1; for(fp = f; k-->0 ; ) *fp++ = '/'; *fp = '\0'; return( copys(f) ); }f[0] = letter;fp = f+1;if(n1) { n1 = simple(RVAL,n1); if(n1->tag==TCONST && n1->vtype==TYINT) { for(s = n1->leftp ; *s; ) *fp++ = *s++; } else execerr("bad format component %s", n1->leftp); frexpr(n1); }if(n2) { if(n2->tag==TCONST && n2->vtype==TYINT) { *fp++ = '.'; for(s = n2->leftp ; *s; ) *fp++ = *s++; } else execerr("bad format component %s", n2->leftp); frexpr(n2); }if( letter == 'x' ) { if(n1 == 0) *fp++ = '1'; fp[0] = 'x'; fp[1] = '\0'; return( copys(f+1) ); }else { *fp = '\0'; return( copys(f) ); }}ptr mkioitem(e,f)register ptr e;char *f;{register ptr p;char fmt[10];ptr gentemp();p = ALLOC(ioitem);p->tag = TIOITEM;if(e!=NULL && e->tag==TCONST) if(e->vtype==TYCHAR && (f==0 || (f[0]=='c' && f[1]=='\0') )) { p->ioexpr = 0; sprintf(msg, "%dh%s", strlen(e->leftp), e->leftp); p->iofmt = copys(msg); frexpr(e); return(p); } else e = mknode(TASGNOP,OPASGN,gentemp(e),e);if(e && e->vtype==TYCHAR && f && f[0]=='c' && f[1]=='\0') f = NULL;if(f == NULL) { switch(e->vtype) { case TYINT: case TYREAL: case TYLREAL: case TYCOMPLEX: case TYLOG: f = copys( tailor.dfltfmt[e->vtype] ); break; case TYCHAR: if(e->vtypep->tag != TCONST) { execerr("no adjustable character formats", ""); f = 0; } else { sprintf(fmt, "c%s", e->vtypep->leftp); f = copys(fmt); } break; default: execerr("cannot do I/O on structures", ""); f = 0; break; } }p->ioexpr = e;p->iofmt = f;return(p);}ptr arrsize(p)ptr p;{register ptr b;ptr f, q;q = mkint(1);if(b = p->vdim) for(b = b->datap ; b ; b = b->nextp) { if(b->upperb == 0) continue; f = cpexpr(b->upperb); if(b->lowerb) f = mknode(TAROP,OPPLUS,f, mknode(TAROP,OPMINUS,mkint(1),cpexpr(b->lowerb))); q = simple(RVAL, mknode(TAROP,OPSTAR,q,f)); }return(q);}repfac(dop)register struct doblock *dop;{int m1, m2, m3;m3 = 1;if( isicon(dop->dopar[0],&m1) && isicon(dop->dopar[1],&m2) && (dop->dopar[2]==NULL || isicon(dop->dopar[2],&m3)) ) { if(m3 > 0) return(1 + (m2-m1)/m3); }else execerr("nonconstant implied do", "");return(1);}ioop(s)char *s;{if( equals(s, "backspace") ) return(FBACKSPACE);if( equals(s, "rewind") ) return(FREWIND);if( equals(s, "endfile") ) return(FENDFILE);return(0);}ptr exioop(p, errcheck)register struct exprblock *p;int errcheck;{register ptr q, t;if( (q = p->rightp)==NULL || (q = q->leftp)==NULL ) { execerr("bad I/O operation", ""); return(NULL); }q = simple(LVAL, cpexpr(q->datap) );exlab(0);putic(ICKEYWORD, ioop(p->leftp->sthead->namep));if(errcheck) { if(tailor.errmode != IOERRFORT77) { execerr("cannot test value of IOOP without ftn77", ""); return( errnode() ); } putic(ICOP, OPLPAR); prexpr(q); putic(ICOP, OPCOMMA); putsii(ICCONST, "iostat ="); prexpr(cpexpr( t = gent(TYINT,PNULL))); putic(ICOP, OPRPAR); return( t ); }else { putic(ICBLANK, 1); prexpr(q); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -