68816572414e4ed16e804dc394f326b73d4ed8c4
* Copyright (c) 1980 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
static char *sccsid
= "@(#)io.c 5.4 (Berkeley) %G%";
* Routines to generate code for I/O statements.
* Some corrections and improvements due to David Wasley, U. C. Berkeley
* University of Utah CS Dept modification history:
* $Header: io.c,v 5.3 86/03/04 17:45:33 donn Exp $
* Revision 5.3 86/03/04 17:45:33 donn
* Change the order of length and offset code in startrw() -- always emit
* the memoffset first, since it may define a temporary which is used in
* Revision 5.2 85/12/19 17:22:35 donn
* Don't permit more than one 'positional iocontrol' parameter unless we
* are doing a READ or a WRITE.
* Revision 5.1 85/08/10 03:47:42 donn
* Revision 2.4 85/02/23 21:09:02 donn
* Jerry Berkman's compiled format fixes move setfmt into a separate file.
* Revision 2.3 85/01/10 22:33:41 donn
* Added some strategic cpexpr()s to prevent memory management bugs.
* Revision 2.2 84/08/04 21:15:47 donn
* Removed code that creates extra statement labels, per Jerry Berkman's
* fixes to make ASSIGNs work right.
* Revision 2.1 84/07/19 12:03:33 donn
* Changed comment headers for UofU.
* Revision 1.2 84/02/26 06:35:57 donn
* Added Berkeley changes necessary for shortening offsets to data.
LOCAL
char ioroutine
[XL
+1];
LOCAL
int statstruct
= NO
;
LOCAL offsetlist
*mkiodata();
#define V(z) ioc[z].iocval
{ "fmt", M(IOREAD
) | M(IOWRITE
) },
{ "rec", M(IOREAD
) | M(IOWRITE
) },
{ "recl", M(IOOPEN
) | M(IOINQUIRE
) },
{ "file", M(IOOPEN
) | M(IOINQUIRE
) },
{ "status", M(IOOPEN
) | M(IOCLOSE
) },
{ "access", M(IOOPEN
) | M(IOINQUIRE
) },
{ "form", M(IOOPEN
) | M(IOINQUIRE
) },
{ "blank", M(IOOPEN
) | M(IOINQUIRE
) },
{ "exist", M(IOINQUIRE
) },
{ "opened", M(IOINQUIRE
) },
{ "number", M(IOINQUIRE
) },
{ "named", M(IOINQUIRE
) },
{ "name", M(IOINQUIRE
) },
{ "sequential", M(IOINQUIRE
) },
{ "direct", M(IOINQUIRE
) },
{ "formatted", M(IOINQUIRE
) },
{ "unformatted", M(IOINQUIRE
) },
{ "nextrec", M(IOINQUIRE
) }
#define NIOS (sizeof(ioc)/sizeof(struct Ioclist) - 1)
#define MAXIO SZFLAG + 10*SZIOINT + 15*SZADDR
#define IOSUNFORMATTED 21
#define IOSTP V(IOSIOSTAT)
/* offsets in generated structures */
/* offsets for external READ and WRITE statements */
#define XEND SZFLAG + SZIOINT
#define XFMT 2*SZFLAG + SZIOINT
#define XREC 2*SZFLAG + SZIOINT + SZADDR
#define XRLEN 2*SZFLAG + 2*SZADDR
#define XRNUM 2*SZFLAG + 2*SZADDR + SZIOINT
/* offsets for internal READ and WRITE statements */
#define XIEND SZFLAG + SZADDR
#define XIFMT 2*SZFLAG + SZADDR
#define XIRLEN 2*SZFLAG + 2*SZADDR
#define XIRNUM 2*SZFLAG + 2*SZADDR + SZIOINT
#define XIREC 2*SZFLAG + 2*SZADDR + 2*SZIOINT
/* offsets for OPEN statements */
#define XFNAME SZFLAG + SZIOINT
#define XFNAMELEN SZFLAG + SZIOINT + SZADDR
#define XSTATUS SZFLAG + 2*SZIOINT + SZADDR
#define XACCESS SZFLAG + 2*SZIOINT + 2*SZADDR
#define XFORMATTED SZFLAG + 2*SZIOINT + 3*SZADDR
#define XRECLEN SZFLAG + 2*SZIOINT + 4*SZADDR
#define XBLANK SZFLAG + 3*SZIOINT + 4*SZADDR
/* offset for CLOSE statement */
#define XCLSTATUS SZFLAG + SZIOINT
/* offsets for INQUIRE statement */
#define XFILE SZFLAG + SZIOINT
#define XFILELEN SZFLAG + SZIOINT + SZADDR
#define XEXISTS SZFLAG + 2*SZIOINT + SZADDR
#define XOPEN SZFLAG + 2*SZIOINT + 2*SZADDR
#define XNUMBER SZFLAG + 2*SZIOINT + 3*SZADDR
#define XNAMED SZFLAG + 2*SZIOINT + 4*SZADDR
#define XNAME SZFLAG + 2*SZIOINT + 5*SZADDR
#define XNAMELEN SZFLAG + 2*SZIOINT + 6*SZADDR
#define XQACCESS SZFLAG + 3*SZIOINT + 6*SZADDR
#define XQACCLEN SZFLAG + 3*SZIOINT + 7*SZADDR
#define XSEQ SZFLAG + 4*SZIOINT + 7*SZADDR
#define XSEQLEN SZFLAG + 4*SZIOINT + 8*SZADDR
#define XDIRECT SZFLAG + 5*SZIOINT + 8*SZADDR
#define XDIRLEN SZFLAG + 5*SZIOINT + 9*SZADDR
#define XFORM SZFLAG + 6*SZIOINT + 9*SZADDR
#define XFORMLEN SZFLAG + 6*SZIOINT + 10*SZADDR
#define XFMTED SZFLAG + 7*SZIOINT + 10*SZADDR
#define XFMTEDLEN SZFLAG + 7*SZIOINT + 11*SZADDR
#define XUNFMT SZFLAG + 8*SZIOINT + 11*SZADDR
#define XUNFMTLEN SZFLAG + 8*SZIOINT + 12*SZADDR
#define XQRECL SZFLAG + 9*SZIOINT + 12*SZADDR
#define XNEXTREC SZFLAG + 9*SZIOINT + 13*SZADDR
#define XQBLANK SZFLAG + 9*SZIOINT + 14*SZADDR
#define XQBLANKLEN SZFLAG + 9*SZIOINT + 15*SZADDR
register struct Labelblock
*lp
;
execerr("unlabeled format statement" , CNULL
);
if(lp
->labtype
== LABUNKNOWN
)
else if(lp
->labtype
!= LABFORMAT
)
execerr("bad format number", CNULL
);
ioformatted
= UNFORMATTED
;
for(i
= 1 ; i
<=NIOS
; ++i
)
/* set up for error recovery */
ioerrlab
= ioendlab
= skiplab
= jumplab
= 0;
ioendlab
= execlab(p
->constblock
.constant
.ci
) ->labelno
;
ioerrlab
= execlab(p
->constblock
.constant
.ci
) ->labelno
;
if(IOSTP
->tag
!=TADDR
|| ! ISINT(IOSTP
->addrblock
.vtype
) )
err("iostat must be an integer variable");
if(ioerrlab
&& ioendlab
&& ioerrlab
==ioendlab
)
skiplab
= jumplab
= newlabel();
if(ioerrlab
&& ioendlab
&& ioerrlab
!=ioendlab
)
IOSTP
= (expptr
) mktemp(TYINT
, PNULL
);
skiplab
= jumplab
= newlabel();
jumplab
= (ioerrlab
? ioerrlab
: ioendlab
);
else if(iostmt
== IOWRITE
)
skiplab
= jumplab
= newlabel();
endbit
= IOSTP
!=NULL
|| ioendlab
!=0; /* for use in startrw() */
errbit
= IOSTP
!=NULL
|| ioerrlab
!=0;
if(iostmt
!=IOREAD
&& iostmt
!=IOWRITE
)
ioblkp
= autovar( (MAXIO
+SZIOINT
-1)/SZIOINT
, TYIOINT
, PNULL
);
ioset(TYIOINT
, XERR
, ICON(errbit
));
dofmove("f_back"); break;
fatali("impossible iostmt %d", iostmt
);
for(i
= 1 ; i
<=NIOS
; ++i
)
if(i
!=IOSIOSTAT
&& V(i
)!=NULL
)
for(i
= 1 ; i
<= NIOS
; ++i
)
if(toklen
==strlen(ioc
[i
].iocname
) && eqn(toklen
, token
, ioc
[i
].iocname
))
errstr("invalid control %s for statement", ioc
[found
].iocname
);
errstr("unknown iocontrol %s", varstr(toklen
, token
) );
nioctl
> IOSUNIT
&& !(iostmt
== IOREAD
|| iostmt
== IOWRITE
))
err("illegal positional iocontrol");
p
= (expptr
) (iostmt
==IOREAD
? IOSTDIN
: IOSTDOUT
);
err("illegal * iocontrol");
ioformatted
= (p
==NULL
? LISTDIRECTED
: FORMATTED
);
if(n
!=IOSFMT
&& ( n
!=IOSUNIT
|| (p
!=NULL
&& p
->headblock
.vtype
!=TYCHAR
) ) )
if(p
!=NULL
&& ISCONST(p
) && p
->constblock
.vtype
==TYCHAR
)
p
= (expptr
) putconst(p
);
errstr("iocontrol %s repeated", iocp
->iocname
);
if(ioformatted
== NAMEDIRECTED
)
err("no I/O list allowed in NAMELIST read/write");
putiocall( call0(TYINT
, ioroutine
) );
for (p
= p0
; p
; p
= p
->nextp
)
exdo(range
=newlabel(), q
->impldoblock
.impdospec
);
doiolist(q
->impldoblock
.datalist
);
if(q
->tag
==TPRIM
&& q
->primblock
.argsp
==NULL
&& q
->primblock
.namep
->vdim
!=NULL
)
vardcl(qn
= q
->primblock
.namep
);
putio( fixtype(cpexpr(qn
->vdim
->nelt
)),
err("attempt to i/o array of unknown size");
else if(q
->tag
==TPRIM
&& q
->primblock
.argsp
==NULL
&&
(qe
= (expptr
) memversion(q
->primblock
.namep
)) )
else if( (qe
= fixtype(cpexpr(q
)))->tag
==TADDR
)
else if(qe
->headblock
.vtype
!= TYERROR
)
cpexpr(qe
->headblock
.vleng
);
tp
= mktemp(qe
->headblock
.vtype
,
tp
= mktemp(qe
->headblock
.vtype
,
expr
= mkexpr(OPASSIGN
,cpexpr(tp
),qe
);
if(qvl
) /* put right length on block */
err("non-left side in READ list");
type
= addr
->headblock
.vtype
;
if(ioformatted
!=LISTDIRECTED
&& ISCOMPLEX(type
) )
nelt
= mkexpr(OPSTAR
, ICON(2), nelt
);
type
-= (TYCOMPLEX
-TYREAL
);
/* pass a length with every item. for noncharacter data, fake one */
addr
->headblock
.vtype
= TYCHAR
;
addr
->headblock
.vleng
= ICON( typesize
[type
] );
nelt
= fixtype( mkconv(TYLENG
,nelt
) );
if(ioformatted
== LISTDIRECTED
)
q
= call3(TYINT
, "do_lio", mkconv(TYLONG
, ICON(type
)), nelt
, addr
);
q
= call2(TYINT
, (ioformatted
==FORMATTED
? "do_fio" : "do_uio"),
optbuff (SKLABEL
, 0, skiplab
, 0);
test
= mkexpr(OPGE
, cpexpr(IOSTP
), ICON(0));
optbuff (SKIOIFN
,test
,ioendlab
,0);
( ((iostmt
==IOREAD
||iostmt
==IOWRITE
) ? OPLE
: OPEQ
),
optbuff (SKIOIFN
,test
,ioerrlab
,0);
q
->headblock
.vtype
= TYINT
;
q
= fixexpr( mkexpr(OPASSIGN
, cpexpr(IOSTP
), q
));
optbuff (SKIOIFN
,mkexpr(OPEQ
,q
,ICON(0)),jumplab
,0);
putif (mkexpr(OPEQ
,q
,ICON(0)),jumplab
);
register Addrp unitp
, fmtp
, recp
, tioblkp
;
flag intfile
, sequential
, ok
, varfmt
;
/* First look at all the parameters and determine what is to be done */
if( ISINT(p
->headblock
.vtype
) )
unitp
= (Addrp
) cpexpr(p
);
else if(p
->headblock
.vtype
== TYCHAR
)
if(p
->tag
==TPRIM
&& p
->primblock
.argsp
==NULL
&&
(np
= p
->primblock
.namep
)->vdim
!=NULL
)
nump
= (expptr
) cpexpr(np
->vdim
->nelt
);
err("attempt to use internal unit array of unknown size");
unitp
= (Addrp
) fixtype(cpexpr(p
));
err("bad unit specifier type");
err("bad unit specifier");
if( ISINT(p
->headblock
.vtype
) )
recp
= (Addrp
) cpexpr(p
);
if(p
->tag
==TPRIM
&& p
->primblock
.argsp
==NULL
)
if(np
->vclass
== CLNAMELIST
)
ioformatted
= NAMEDIRECTED
;
fmtp
= (Addrp
) fixtype(cpexpr(p
));
if( ! ONEOF(np
->vstg
, MSKSTATIC
) )
if( ISINT(np
->vtype
) ) /* ASSIGNed label */
fmtp
= (Addrp
) fixtype(cpexpr(p
));
p
= V(IOSFMT
) = fixtype(p
);
if(p
->headblock
.vtype
== TYCHAR
)
if (p
->tag
== TCONST
) p
= (expptr
) putconst(p
);
fmtp
= (Addrp
) cpexpr(p
);
if( (k
= fmtstmt( mklabel(p
->constblock
.constant
.ci
) )) > 0 )
fmtp
= (Addrp
) mkaddcon(k
);
ioformatted
= UNFORMATTED
;
err("bad format descriptor");
ioformatted
= UNFORMATTED
;
if(intfile
&& ioformatted
==UNFORMATTED
)
err("unformatted internal I/O not allowed");
if(!sequential
&& ioformatted
==LISTDIRECTED
)
err("direct list-directed I/O not allowed");
if(!sequential
&& ioformatted
==NAMEDIRECTED
)
err("direct namelist I/O not allowed");
if (optimflag
&& ISCONST (fmtp
))
fmtp
= putconst ( (expptr
) fmtp
);
Now put out the I/O structure, statically if all the clauses
are constants, dynamically otherwise
ioblkp
= ALLOC(Addrblock
);
ioblkp
->memno
= ++lastvarno
;
ioblkp
->memoffset
= ICON(0);
blklen
= (intfile
? XIREC
+SZIOINT
:
(sequential
? XFMT
+SZADDR
: XRNUM
+SZIOINT
) );
t
->blkno
= ioblkp
->memno
;
ioblkp
= autovar( (MAXIO
+SZIOINT
-1)/SZIOINT
, TYIOINT
, PNULL
);
ioset(TYIOINT
, XERR
, ICON(errbit
));
ioset(TYIOINT
, (intfile
? XIEND
: XEND
), ICON(endbit
) );
ioset(TYIOINT
, XIRNUM
, nump
);
ioseta(XIUNIT
, cpexpr(unitp
));
ioset(TYIOINT
, XIRLEN
, cpexpr(unitp
->vleng
) );
ioset(TYIOINT
, XUNIT
, (expptr
) unitp
);
ioset(TYIOINT
, (intfile
? XIREC
: XREC
) , (expptr
) recp
);
ioseta( intfile
? XIFMT
: XFMT
, fmtp
);
ioset(TYADDR
, intfile
? XIFMT
: XFMT
, (expptr
) fmtp
);
ioroutine
[2] = (iostmt
==IOREAD
? 'r' : 'w');
ioroutine
[3] = (sequential
? 's' : 'd');
ioroutine
[4] = "ufln" [ioformatted
];
ioroutine
[5] = (intfile
? 'i' : 'e');
putiocall( call1(TYINT
, ioroutine
, cpexpr(ioblkp
) ));
if( (p
= V(IOSUNIT
)) && ISINT(p
->headblock
.vtype
) )
ioset(TYIOINT
, XUNIT
, cpexpr(p
) );
if(p
->headblock
.vtype
== TYCHAR
)
ioset(TYIOINT
, XFNAMELEN
, cpexpr(p
->headblock
.vleng
) );
if( ISINT(p
->headblock
.vtype
) )
ioset(TYIOINT
, XRECLEN
, cpexpr(p
) );
ioset(TYIOINT
, XRECLEN
, ICON(0) );
iosetc(XSTATUS
, V(IOSSTATUS
));
iosetc(XACCESS
, V(IOSACCESS
));
iosetc(XFORMATTED
, V(IOSFORM
));
iosetc(XBLANK
, V(IOSBLANK
));
putiocall( call1(TYINT
, "f_open", cpexpr(ioblkp
) ));
if( (p
= V(IOSUNIT
)) && ISINT(p
->headblock
.vtype
) )
ioset(TYIOINT
, XUNIT
, cpexpr(p
) );
iosetc(XCLSTATUS
, V(IOSSTATUS
));
putiocall( call1(TYINT
, "f_clos", cpexpr(ioblkp
)) );
err("bad unit in close statement");
err("inquire by unit or by file, not both");
ioset(TYIOINT
, XUNIT
, cpexpr(p
) );
err("must inquire by unit or by file");
iosetlc(IOSFILE
, XFILE
, XFILELEN
);
iosetip(IOSEXISTS
, XEXISTS
);
iosetip(IOSOPENED
, XOPEN
);
iosetip(IOSNUMBER
, XNUMBER
);
iosetip(IOSNAMED
, XNAMED
);
iosetlc(IOSNAME
, XNAME
, XNAMELEN
);
iosetlc(IOSACCESS
, XQACCESS
, XQACCLEN
);
iosetlc(IOSSEQUENTIAL
, XSEQ
, XSEQLEN
);
iosetlc(IOSDIRECT
, XDIRECT
, XDIRLEN
);
iosetlc(IOSFORM
, XFORM
, XFORMLEN
);
iosetlc(IOSFORMATTED
, XFMTED
, XFMTEDLEN
);
iosetlc(IOSUNFORMATTED
, XUNFMT
, XUNFMTLEN
);
iosetip(IOSRECL
, XQRECL
);
iosetip(IOSNEXTREC
, XNEXTREC
);
iosetlc(IOSBLANK
, XQBLANK
, XQBLANKLEN
);
putiocall( call1(TYINT
, "f_inqu", cpexpr(ioblkp
) ));
if( (p
= V(IOSUNIT
)) && ISINT(p
->headblock
.vtype
) )
ioset(TYIOINT
, XUNIT
, cpexpr(p
) );
putiocall( call1(TYINT
, subname
, cpexpr(ioblkp
) ));
err("bad unit in I/O motion statement");
static char *badoffset
= "badoffset in ioset";
q
= (Addrp
) cpexpr(ioblkp
);
q
->memoffset
= fixtype( mkexpr(OPPLUS
, q
->memoffset
, ICON(offset
)) );
if (statstruct
&& ISCONST(p
))
if (!ISICON(q
->memoffset
))
op
= mkiodata(q
->memno
, q
->memoffset
->constblock
.constant
.ci
, blklen
);
op
->val
.label
= p
->constblock
.constant
.ci
;
op
->val
.cp
= (Constp
) convconst(type
, 0, p
);
optbuff (SKEQ
, mkexpr(OPASSIGN
,q
,p
), 0,0);
ioset(TYADDR
, offset
, ICON(0) );
else if(p
->headblock
.vtype
== TYCHAR
)
ioset(TYADDR
, offset
, addrof(cpexpr(p
) ));
err("non-character control clause");
static char *badoffset
= "bad offset in ioseta";
op
= mkiodata(blkno
, offset
, blklen
);
else if (p
->tag
== TADDR
)
op
->val
.addr
.stg
= p
->vstg
;
op
->val
.addr
.memno
= p
->memno
;
op
->val
.addr
.offset
= p
->memoffset
->constblock
.constant
.ci
;
badtag("ioseta", p
->tag
);
ioset(TYADDR
, offset
, p
? addrof(p
) : ICON(0) );
ONEOF(p
->addrblock
.vtype
, M(TYLONG
)|M(TYLOGICAL
)) )
ioset(TYADDR
, offset
, addrof(cpexpr(p
)) );
errstr("impossible inquire parameter %s", ioc
[i
].iocname
);
ioset(TYADDR
, offset
, ICON(0) );
LOCAL
iosetlc(i
, offp
, offl
)
if( (p
= V(i
)) && p
->headblock
.vtype
==TYCHAR
)
ioset(TYIOINT
, offl
, cpexpr(p
->headblock
.vleng
) );
mkiodata(blkno
, offset
, len
)
register offsetlist
*p
, *q
;
while (found
== NO
&& t
!= NULL
)
else if (p
->next
!= NULL
&&
p
->next
->offset
<= offset
)
static char *varfmt
= "v.%d:\n";
if (iodata
== NULL
) return;
fprintf(initfile
, varfmt
, p
->blkno
);
outolist(p
->olist
, p
->len
);
static char *overlap
= "overlapping i/o fields in outolist";
static char *toolong
= "offset too large in outolist";
prspace(op
->offset
- clen
);
badtag("outolist", op
->tag
);
badtype("outolist", type
);
prconi(initfile
, type
, cp
->constant
.ci
);
prcona(initfile
, op
->val
.label
);
clen
+= typesize
[TYADDR
];
praddr(initfile
, op
->val
.addr
.stg
, op
->val
.addr
.memno
,
clen
+= typesize
[TYADDR
];
praddr(initfile
, STGNULL
, 0, (ftnint
) 0);
clen
+= typesize
[TYADDR
];