xref: /csrg-svn/usr.bin/f77/pass1.vax/io.c (revision 26511)
122836Smckusick /*
222836Smckusick  * Copyright (c) 1980 Regents of the University of California.
322836Smckusick  * All rights reserved.  The Berkeley software License Agreement
422836Smckusick  * specifies the terms and conditions for redistribution.
522836Smckusick  */
622836Smckusick 
722836Smckusick #ifndef lint
8*26511Sdonn static	char *sccsid = "@(#)io.c	5.3 (Berkeley) 03/09/86";
922836Smckusick #endif
1022836Smckusick 
1122836Smckusick /*
1222836Smckusick  * io.c
1322836Smckusick  *
1422836Smckusick  * Routines to generate code for I/O statements.
1522836Smckusick  * Some corrections and improvements due to David Wasley, U. C. Berkeley
1622836Smckusick  *
1722836Smckusick  * University of Utah CS Dept modification history:
1822836Smckusick  *
19*26511Sdonn  * $Header: io.c,v 5.3 86/03/04 17:45:33 donn Exp $
2022836Smckusick  * $Log:	io.c,v $
21*26511Sdonn  * Revision 5.3  86/03/04  17:45:33  donn
22*26511Sdonn  * Change the order of length and offset code in startrw() -- always emit
23*26511Sdonn  * the memoffset first, since it may define a temporary which is used in
24*26511Sdonn  * the length expression.
25*26511Sdonn  *
2625741Sdonn  * Revision 5.2  85/12/19  17:22:35  donn
2725741Sdonn  * Don't permit more than one 'positional iocontrol' parameter unless we
2825741Sdonn  * are doing a READ or a WRITE.
2925741Sdonn  *
3025741Sdonn  * Revision 5.1  85/08/10  03:47:42  donn
3125741Sdonn  * 4.3 alpha
3225741Sdonn  *
3322836Smckusick  * Revision 2.4  85/02/23  21:09:02  donn
3422836Smckusick  * Jerry Berkman's compiled format fixes move setfmt into a separate file.
3522836Smckusick  *
3622836Smckusick  * Revision 2.3  85/01/10  22:33:41  donn
3722836Smckusick  * Added some strategic cpexpr()s to prevent memory management bugs.
3822836Smckusick  *
3922836Smckusick  * Revision 2.2  84/08/04  21:15:47  donn
4022836Smckusick  * Removed code that creates extra statement labels, per Jerry Berkman's
4122836Smckusick  * fixes to make ASSIGNs work right.
4222836Smckusick  *
4322836Smckusick  * Revision 2.1  84/07/19  12:03:33  donn
4422836Smckusick  * Changed comment headers for UofU.
4522836Smckusick  *
4622836Smckusick  * Revision 1.2  84/02/26  06:35:57  donn
4722836Smckusick  * Added Berkeley changes necessary for shortening offsets to data.
4822836Smckusick  *
4922836Smckusick  */
5022836Smckusick 
5122836Smckusick /* TEMPORARY */
5222836Smckusick #define TYIOINT TYLONG
5322836Smckusick #define SZIOINT SZLONG
5422836Smckusick 
5522836Smckusick #include "defs.h"
5622836Smckusick #include "io.h"
5722836Smckusick 
5822836Smckusick 
5922836Smckusick LOCAL char ioroutine[XL+1];
6022836Smckusick 
6122836Smckusick LOCAL int ioendlab;
6222836Smckusick LOCAL int ioerrlab;
6322836Smckusick LOCAL int endbit;
6422836Smckusick LOCAL int errbit;
6522836Smckusick LOCAL int jumplab;
6622836Smckusick LOCAL int skiplab;
6722836Smckusick LOCAL int ioformatted;
6822836Smckusick LOCAL int statstruct = NO;
6922836Smckusick LOCAL ftnint blklen;
7022836Smckusick 
7122836Smckusick LOCAL offsetlist *mkiodata();
7222836Smckusick 
7322836Smckusick 
7422836Smckusick #define UNFORMATTED 0
7522836Smckusick #define FORMATTED 1
7622836Smckusick #define LISTDIRECTED 2
7722836Smckusick #define NAMEDIRECTED 3
7822836Smckusick 
7922836Smckusick #define V(z)	ioc[z].iocval
8022836Smckusick 
8122836Smckusick #define IOALL 07777
8222836Smckusick 
8322836Smckusick LOCAL struct Ioclist
8422836Smckusick 	{
8522836Smckusick 	char *iocname;
8622836Smckusick 	int iotype;
8722836Smckusick 	expptr iocval;
8822836Smckusick 	} ioc[ ] =
8922836Smckusick 	{
9022836Smckusick 		{ "", 0 },
9122836Smckusick 		{ "unit", IOALL },
9222836Smckusick 		{ "fmt", M(IOREAD) | M(IOWRITE) },
9322836Smckusick 		{ "err", IOALL },
9422836Smckusick 		{ "end", M(IOREAD) },
9522836Smckusick 		{ "iostat", IOALL },
9622836Smckusick 		{ "rec", M(IOREAD) | M(IOWRITE) },
9722836Smckusick 		{ "recl", M(IOOPEN) | M(IOINQUIRE) },
9822836Smckusick 		{ "file", M(IOOPEN) | M(IOINQUIRE) },
9922836Smckusick 		{ "status", M(IOOPEN) | M(IOCLOSE) },
10022836Smckusick 		{ "access", M(IOOPEN) | M(IOINQUIRE) },
10122836Smckusick 		{ "form", M(IOOPEN) | M(IOINQUIRE) },
10222836Smckusick 		{ "blank", M(IOOPEN) | M(IOINQUIRE) },
10322836Smckusick 		{ "exist", M(IOINQUIRE) },
10422836Smckusick 		{ "opened", M(IOINQUIRE) },
10522836Smckusick 		{ "number", M(IOINQUIRE) },
10622836Smckusick 		{ "named", M(IOINQUIRE) },
10722836Smckusick 		{ "name", M(IOINQUIRE) },
10822836Smckusick 		{ "sequential", M(IOINQUIRE) },
10922836Smckusick 		{ "direct", M(IOINQUIRE) },
11022836Smckusick 		{ "formatted", M(IOINQUIRE) },
11122836Smckusick 		{ "unformatted", M(IOINQUIRE) },
11222836Smckusick 		{ "nextrec", M(IOINQUIRE) }
11322836Smckusick 	} ;
11422836Smckusick 
11522836Smckusick #define NIOS (sizeof(ioc)/sizeof(struct Ioclist) - 1)
11622836Smckusick #define MAXIO	SZFLAG + 10*SZIOINT + 15*SZADDR
11722836Smckusick 
11822836Smckusick #define IOSUNIT 1
11922836Smckusick #define IOSFMT 2
12022836Smckusick #define IOSERR 3
12122836Smckusick #define IOSEND 4
12222836Smckusick #define IOSIOSTAT 5
12322836Smckusick #define IOSREC 6
12422836Smckusick #define IOSRECL 7
12522836Smckusick #define IOSFILE 8
12622836Smckusick #define IOSSTATUS 9
12722836Smckusick #define IOSACCESS 10
12822836Smckusick #define IOSFORM 11
12922836Smckusick #define IOSBLANK 12
13022836Smckusick #define IOSEXISTS 13
13122836Smckusick #define IOSOPENED 14
13222836Smckusick #define IOSNUMBER 15
13322836Smckusick #define IOSNAMED 16
13422836Smckusick #define IOSNAME 17
13522836Smckusick #define IOSSEQUENTIAL 18
13622836Smckusick #define IOSDIRECT 19
13722836Smckusick #define IOSFORMATTED 20
13822836Smckusick #define IOSUNFORMATTED 21
13922836Smckusick #define IOSNEXTREC 22
14022836Smckusick 
14122836Smckusick #define IOSTP V(IOSIOSTAT)
14222836Smckusick 
14322836Smckusick 
14422836Smckusick /* offsets in generated structures */
14522836Smckusick 
14622836Smckusick #define SZFLAG SZIOINT
14722836Smckusick 
14822836Smckusick /* offsets for external READ and WRITE statements */
14922836Smckusick 
15022836Smckusick #define XERR 0
15122836Smckusick #define XUNIT	SZFLAG
15222836Smckusick #define XEND	SZFLAG + SZIOINT
15322836Smckusick #define XFMT	2*SZFLAG + SZIOINT
15422836Smckusick #define XREC	2*SZFLAG + SZIOINT + SZADDR
15522836Smckusick #define XRLEN	2*SZFLAG + 2*SZADDR
15622836Smckusick #define XRNUM	2*SZFLAG + 2*SZADDR + SZIOINT
15722836Smckusick 
15822836Smckusick /* offsets for internal READ and WRITE statements */
15922836Smckusick 
16022836Smckusick #define XIERR	0
16122836Smckusick #define XIUNIT	SZFLAG
16222836Smckusick #define XIEND	SZFLAG + SZADDR
16322836Smckusick #define XIFMT	2*SZFLAG + SZADDR
16422836Smckusick #define XIRLEN	2*SZFLAG + 2*SZADDR
16522836Smckusick #define XIRNUM	2*SZFLAG + 2*SZADDR + SZIOINT
16622836Smckusick #define XIREC	2*SZFLAG + 2*SZADDR + 2*SZIOINT
16722836Smckusick 
16822836Smckusick /* offsets for OPEN statements */
16922836Smckusick 
17022836Smckusick #define XFNAME	SZFLAG + SZIOINT
17122836Smckusick #define XFNAMELEN	SZFLAG + SZIOINT + SZADDR
17222836Smckusick #define XSTATUS	SZFLAG + 2*SZIOINT + SZADDR
17322836Smckusick #define XACCESS	SZFLAG + 2*SZIOINT + 2*SZADDR
17422836Smckusick #define XFORMATTED	SZFLAG + 2*SZIOINT + 3*SZADDR
17522836Smckusick #define XRECLEN	SZFLAG + 2*SZIOINT + 4*SZADDR
17622836Smckusick #define XBLANK	SZFLAG + 3*SZIOINT + 4*SZADDR
17722836Smckusick 
17822836Smckusick /* offset for CLOSE statement */
17922836Smckusick 
18022836Smckusick #define XCLSTATUS	SZFLAG + SZIOINT
18122836Smckusick 
18222836Smckusick /* offsets for INQUIRE statement */
18322836Smckusick 
18422836Smckusick #define XFILE	SZFLAG + SZIOINT
18522836Smckusick #define XFILELEN	SZFLAG + SZIOINT + SZADDR
18622836Smckusick #define XEXISTS	SZFLAG + 2*SZIOINT + SZADDR
18722836Smckusick #define XOPEN	SZFLAG + 2*SZIOINT + 2*SZADDR
18822836Smckusick #define XNUMBER	SZFLAG + 2*SZIOINT + 3*SZADDR
18922836Smckusick #define XNAMED	SZFLAG + 2*SZIOINT + 4*SZADDR
19022836Smckusick #define XNAME	SZFLAG + 2*SZIOINT + 5*SZADDR
19122836Smckusick #define XNAMELEN	SZFLAG + 2*SZIOINT + 6*SZADDR
19222836Smckusick #define XQACCESS	SZFLAG + 3*SZIOINT + 6*SZADDR
19322836Smckusick #define XQACCLEN	SZFLAG + 3*SZIOINT + 7*SZADDR
19422836Smckusick #define XSEQ	SZFLAG + 4*SZIOINT + 7*SZADDR
19522836Smckusick #define XSEQLEN	SZFLAG + 4*SZIOINT + 8*SZADDR
19622836Smckusick #define XDIRECT	SZFLAG + 5*SZIOINT + 8*SZADDR
19722836Smckusick #define XDIRLEN	SZFLAG + 5*SZIOINT + 9*SZADDR
19822836Smckusick #define XFORM	SZFLAG + 6*SZIOINT + 9*SZADDR
19922836Smckusick #define XFORMLEN	SZFLAG + 6*SZIOINT + 10*SZADDR
20022836Smckusick #define XFMTED	SZFLAG + 7*SZIOINT + 10*SZADDR
20122836Smckusick #define XFMTEDLEN	SZFLAG + 7*SZIOINT + 11*SZADDR
20222836Smckusick #define XUNFMT	SZFLAG + 8*SZIOINT + 11*SZADDR
20322836Smckusick #define XUNFMTLEN	SZFLAG + 8*SZIOINT + 12*SZADDR
20422836Smckusick #define XQRECL	SZFLAG + 9*SZIOINT + 12*SZADDR
20522836Smckusick #define XNEXTREC	SZFLAG + 9*SZIOINT + 13*SZADDR
20622836Smckusick #define XQBLANK	SZFLAG + 9*SZIOINT + 14*SZADDR
20722836Smckusick #define XQBLANKLEN	SZFLAG + 9*SZIOINT + 15*SZADDR
20822836Smckusick 
20922836Smckusick fmtstmt(lp)
21022836Smckusick register struct Labelblock *lp;
21122836Smckusick {
21222836Smckusick if(lp == NULL)
21322836Smckusick 	{
21422836Smckusick 	execerr("unlabeled format statement" , CNULL);
21522836Smckusick 	return(-1);
21622836Smckusick 	}
21722836Smckusick if(lp->labtype == LABUNKNOWN)
21822836Smckusick 	lp->labtype = LABFORMAT;
21922836Smckusick else if(lp->labtype != LABFORMAT)
22022836Smckusick 	{
22122836Smckusick 	execerr("bad format number", CNULL);
22222836Smckusick 	return(-1);
22322836Smckusick 	}
22422836Smckusick return(lp->labelno);
22522836Smckusick }
22622836Smckusick 
22722836Smckusick 
22822836Smckusick 
22922836Smckusick startioctl()
23022836Smckusick {
23122836Smckusick register int i;
23222836Smckusick 
23322836Smckusick inioctl = YES;
23422836Smckusick nioctl = 0;
23522836Smckusick ioformatted = UNFORMATTED;
23622836Smckusick for(i = 1 ; i<=NIOS ; ++i)
23722836Smckusick 	V(i) = NULL;
23822836Smckusick }
23922836Smckusick 
24022836Smckusick 
24122836Smckusick 
24222836Smckusick endioctl()
24322836Smckusick {
24422836Smckusick int i;
24522836Smckusick expptr p;
24622836Smckusick 
24722836Smckusick inioctl = NO;
24822836Smckusick 
24922836Smckusick /* set up for error recovery */
25022836Smckusick 
25122836Smckusick ioerrlab = ioendlab = skiplab = jumplab = 0;
25222836Smckusick 
25322836Smckusick if(p = V(IOSEND))
25422836Smckusick 	if(ISICON(p))
25522836Smckusick 		ioendlab = execlab(p->constblock.const.ci) ->labelno;
25622836Smckusick 	else
25722836Smckusick 		err("bad end= clause");
25822836Smckusick 
25922836Smckusick if(p = V(IOSERR))
26022836Smckusick 	if(ISICON(p))
26122836Smckusick 		ioerrlab = execlab(p->constblock.const.ci) ->labelno;
26222836Smckusick 	else
26322836Smckusick 		err("bad err= clause");
26422836Smckusick 
26522836Smckusick if(IOSTP)
26622836Smckusick 	if(IOSTP->tag!=TADDR || ! ISINT(IOSTP->addrblock.vtype) )
26722836Smckusick 		{
26822836Smckusick 		err("iostat must be an integer variable");
26922836Smckusick 		frexpr(IOSTP);
27022836Smckusick 		IOSTP = NULL;
27122836Smckusick 		}
27222836Smckusick 
27322836Smckusick if(iostmt == IOREAD)
27422836Smckusick 	{
27522836Smckusick 	if(IOSTP)
27622836Smckusick 		{
27722836Smckusick 		if(ioerrlab && ioendlab && ioerrlab==ioendlab)
27822836Smckusick 			jumplab = ioerrlab;
27922836Smckusick 		else
28022836Smckusick 			skiplab = jumplab = newlabel();
28122836Smckusick 		}
28222836Smckusick 	else	{
28322836Smckusick 		if(ioerrlab && ioendlab && ioerrlab!=ioendlab)
28422836Smckusick 			{
28522836Smckusick 			IOSTP = (expptr) mktemp(TYINT, PNULL);
28622836Smckusick 			skiplab = jumplab = newlabel();
28722836Smckusick 			}
28822836Smckusick 		else
28922836Smckusick 			jumplab = (ioerrlab ? ioerrlab : ioendlab);
29022836Smckusick 		}
29122836Smckusick 	}
29222836Smckusick else if(iostmt == IOWRITE)
29322836Smckusick 	{
29422836Smckusick 	if(IOSTP && !ioerrlab)
29522836Smckusick 		skiplab = jumplab = newlabel();
29622836Smckusick 	else
29722836Smckusick 		jumplab = ioerrlab;
29822836Smckusick 	}
29922836Smckusick else
30022836Smckusick 	jumplab = ioerrlab;
30122836Smckusick 
30222836Smckusick endbit = IOSTP!=NULL || ioendlab!=0;	/* for use in startrw() */
30322836Smckusick errbit = IOSTP!=NULL || ioerrlab!=0;
30422836Smckusick if(iostmt!=IOREAD && iostmt!=IOWRITE)
30522836Smckusick 	{
30622836Smckusick 	if(ioblkp == NULL)
30722836Smckusick 		ioblkp = autovar( (MAXIO+SZIOINT-1)/SZIOINT , TYIOINT, PNULL);
30822836Smckusick 	ioset(TYIOINT, XERR, ICON(errbit));
30922836Smckusick 	}
31022836Smckusick 
31122836Smckusick switch(iostmt)
31222836Smckusick 	{
31322836Smckusick 	case IOOPEN:
31422836Smckusick 		dofopen();  break;
31522836Smckusick 
31622836Smckusick 	case IOCLOSE:
31722836Smckusick 		dofclose();  break;
31822836Smckusick 
31922836Smckusick 	case IOINQUIRE:
32022836Smckusick 		dofinquire();  break;
32122836Smckusick 
32222836Smckusick 	case IOBACKSPACE:
32322836Smckusick 		dofmove("f_back"); break;
32422836Smckusick 
32522836Smckusick 	case IOREWIND:
32622836Smckusick 		dofmove("f_rew");  break;
32722836Smckusick 
32822836Smckusick 	case IOENDFILE:
32922836Smckusick 		dofmove("f_end");  break;
33022836Smckusick 
33122836Smckusick 	case IOREAD:
33222836Smckusick 	case IOWRITE:
33322836Smckusick 		startrw();  break;
33422836Smckusick 
33522836Smckusick 	default:
33622836Smckusick 		fatali("impossible iostmt %d", iostmt);
33722836Smckusick 	}
33822836Smckusick for(i = 1 ; i<=NIOS ; ++i)
33922836Smckusick 	if(i!=IOSIOSTAT && V(i)!=NULL)
34022836Smckusick 		frexpr(V(i));
34122836Smckusick }
34222836Smckusick 
34322836Smckusick 
34422836Smckusick 
34522836Smckusick iocname()
34622836Smckusick {
34722836Smckusick register int i;
34822836Smckusick int found, mask;
34922836Smckusick 
35022836Smckusick found = 0;
35122836Smckusick mask = M(iostmt);
35222836Smckusick for(i = 1 ; i <= NIOS ; ++i)
35322836Smckusick 	if(toklen==strlen(ioc[i].iocname) && eqn(toklen, token, ioc[i].iocname))
35422836Smckusick 		if(ioc[i].iotype & mask)
35522836Smckusick 			return(i);
35622836Smckusick 		else	found = i;
35722836Smckusick if(found)
35822836Smckusick 	errstr("invalid control %s for statement", ioc[found].iocname);
35922836Smckusick else
36022836Smckusick 	errstr("unknown iocontrol %s", varstr(toklen, token) );
36122836Smckusick return(IOSBAD);
36222836Smckusick }
36322836Smckusick 
36422836Smckusick 
36522836Smckusick ioclause(n, p)
36622836Smckusick register int n;
36722836Smckusick register expptr p;
36822836Smckusick {
36922836Smckusick struct Ioclist *iocp;
37022836Smckusick 
37122836Smckusick ++nioctl;
37222836Smckusick if(n == IOSBAD)
37322836Smckusick 	return;
37422836Smckusick if(n == IOSPOSITIONAL)
37522836Smckusick 	{
37625741Sdonn 	if(nioctl > IOSFMT ||
37725741Sdonn 	   nioctl > IOSUNIT && !(iostmt == IOREAD || iostmt == IOWRITE))
37822836Smckusick 		{
37922836Smckusick 		err("illegal positional iocontrol");
38022836Smckusick 		return;
38122836Smckusick 		}
38222836Smckusick 	n = nioctl;
38322836Smckusick 	}
38422836Smckusick 
38522836Smckusick if(p == NULL)
38622836Smckusick 	{
38722836Smckusick 	if(n == IOSUNIT)
38822836Smckusick 		p = (expptr) (iostmt==IOREAD ? IOSTDIN : IOSTDOUT);
38922836Smckusick 	else if(n != IOSFMT)
39022836Smckusick 		{
39122836Smckusick 		err("illegal * iocontrol");
39222836Smckusick 		return;
39322836Smckusick 		}
39422836Smckusick 	}
39522836Smckusick if(n == IOSFMT)
39622836Smckusick 	ioformatted = (p==NULL ? LISTDIRECTED : FORMATTED);
39722836Smckusick 
39822836Smckusick iocp = & ioc[n];
39922836Smckusick if(iocp->iocval == NULL)
40022836Smckusick 	{
40122836Smckusick 	p = (expptr) cpexpr(p);
40222836Smckusick 	if(n!=IOSFMT && ( n!=IOSUNIT || (p!=NULL && p->headblock.vtype!=TYCHAR) ) )
40322836Smckusick 		p = fixtype(p);
40422836Smckusick 	if(p!=NULL && ISCONST(p) && p->constblock.vtype==TYCHAR)
40522836Smckusick 		p = (expptr) putconst(p);
40622836Smckusick 	iocp->iocval = p;
40722836Smckusick }
40822836Smckusick else
40922836Smckusick 	errstr("iocontrol %s repeated", iocp->iocname);
41022836Smckusick }
41122836Smckusick 
41222836Smckusick /* io list item */
41322836Smckusick 
41422836Smckusick doio(list)
41522836Smckusick chainp list;
41622836Smckusick {
41722836Smckusick expptr call0();
41822836Smckusick 
41922836Smckusick if(ioformatted == NAMEDIRECTED)
42022836Smckusick 	{
42122836Smckusick 	if(list)
42222836Smckusick 		err("no I/O list allowed in NAMELIST read/write");
42322836Smckusick 	}
42422836Smckusick else
42522836Smckusick 	{
42622836Smckusick 	doiolist(list);
42722836Smckusick 	ioroutine[0] = 'e';
42822836Smckusick 	putiocall( call0(TYINT, ioroutine) );
42922836Smckusick 	}
43022836Smckusick }
43122836Smckusick 
43222836Smckusick 
43322836Smckusick 
43422836Smckusick 
43522836Smckusick 
43622836Smckusick LOCAL doiolist(p0)
43722836Smckusick chainp p0;
43822836Smckusick {
43922836Smckusick chainp p;
44022836Smckusick register tagptr q;
44122836Smckusick register expptr qe;
44222836Smckusick register Namep qn;
44322836Smckusick Addrp tp, mkscalar();
44422836Smckusick int range;
44522836Smckusick expptr expr;
44622836Smckusick 
44722836Smckusick for (p = p0 ; p ; p = p->nextp)
44822836Smckusick 	{
44922836Smckusick 	q = p->datap;
45022836Smckusick 	if(q->tag == TIMPLDO)
45122836Smckusick 		{
45222836Smckusick 		exdo(range=newlabel(), q->impldoblock.impdospec);
45322836Smckusick 		doiolist(q->impldoblock.datalist);
45422836Smckusick 		enddo(range);
45522836Smckusick 		free( (charptr) q);
45622836Smckusick 		}
45722836Smckusick 	else	{
45822836Smckusick 		if(q->tag==TPRIM && q->primblock.argsp==NULL
45922836Smckusick 		    && q->primblock.namep->vdim!=NULL)
46022836Smckusick 			{
46122836Smckusick 			vardcl(qn = q->primblock.namep);
46222836Smckusick 			if(qn->vdim->nelt)
46322836Smckusick 				putio( fixtype(cpexpr(qn->vdim->nelt)),
46422836Smckusick 					mkscalar(qn) );
46522836Smckusick 			else
46622836Smckusick 				err("attempt to i/o array of unknown size");
46722836Smckusick 			}
46822836Smckusick 		else if(q->tag==TPRIM && q->primblock.argsp==NULL &&
46922836Smckusick 		    (qe = (expptr) memversion(q->primblock.namep)) )
47022836Smckusick 			putio(ICON(1),qe);
47122836Smckusick 		else if( (qe = fixtype(cpexpr(q)))->tag==TADDR)
47222836Smckusick 			putio(ICON(1), qe);
47322836Smckusick 		else if(qe->headblock.vtype != TYERROR)
47422836Smckusick 			{
47522836Smckusick 			if(iostmt == IOWRITE)
47622836Smckusick 				{
47722836Smckusick 				ftnint lencat();
47822836Smckusick 				expptr qvl;
47922836Smckusick 				qvl = NULL;
48022836Smckusick 				if( ISCHAR(qe) )
48122836Smckusick 					{
48222836Smckusick 					qvl = (expptr)
48322836Smckusick 						cpexpr(qe->headblock.vleng);
48422836Smckusick 					tp = mktemp(qe->headblock.vtype,
48522836Smckusick 						     ICON(lencat(qe)));
48622836Smckusick 					}
48722836Smckusick 				else
48822836Smckusick 					tp = mktemp(qe->headblock.vtype,
48922836Smckusick 						qe->headblock.vleng);
49022836Smckusick 				if (optimflag)
49122836Smckusick 					{
49222836Smckusick 					expr = mkexpr(OPASSIGN,cpexpr(tp),qe);
49322836Smckusick 					optbuff (SKEQ,expr,0,0);
49422836Smckusick 					}
49522836Smckusick 				else
49622836Smckusick 					puteq (cpexpr(tp),qe);
49722836Smckusick 				if(qvl)	/* put right length on block */
49822836Smckusick 					{
49922836Smckusick 					frexpr(tp->vleng);
50022836Smckusick 					tp->vleng = qvl;
50122836Smckusick 					}
50222836Smckusick 				putio(ICON(1), tp);
50322836Smckusick 				}
50422836Smckusick 			else
50522836Smckusick 				err("non-left side in READ list");
50622836Smckusick 			}
50722836Smckusick 		frexpr(q);
50822836Smckusick 		}
50922836Smckusick 	}
51022836Smckusick frchain( &p0 );
51122836Smckusick }
51222836Smckusick 
51322836Smckusick 
51422836Smckusick 
51522836Smckusick 
51622836Smckusick 
51722836Smckusick LOCAL putio(nelt, addr)
51822836Smckusick expptr nelt;
51922836Smckusick register expptr addr;
52022836Smckusick {
52122836Smckusick int type;
52222836Smckusick register expptr q;
52322836Smckusick 
52422836Smckusick type = addr->headblock.vtype;
52522836Smckusick if(ioformatted!=LISTDIRECTED && ISCOMPLEX(type) )
52622836Smckusick 	{
52722836Smckusick 	nelt = mkexpr(OPSTAR, ICON(2), nelt);
52822836Smckusick 	type -= (TYCOMPLEX-TYREAL);
52922836Smckusick 	}
53022836Smckusick 
53122836Smckusick /* pass a length with every item.  for noncharacter data, fake one */
53222836Smckusick if(type != TYCHAR)
53322836Smckusick 	{
53422836Smckusick 	addr->headblock.vtype = TYCHAR;
53522836Smckusick 	addr->headblock.vleng = ICON( typesize[type] );
53622836Smckusick 	}
53722836Smckusick 
53822836Smckusick nelt = fixtype( mkconv(TYLENG,nelt) );
53922836Smckusick if(ioformatted == LISTDIRECTED)
54022836Smckusick 	q = call3(TYINT, "do_lio", mkconv(TYLONG, ICON(type)), nelt, addr);
54122836Smckusick else
54222836Smckusick 	q = call2(TYINT, (ioformatted==FORMATTED ? "do_fio" : "do_uio"),
54322836Smckusick 		nelt, addr);
54422836Smckusick putiocall(q);
54522836Smckusick }
54622836Smckusick 
54722836Smckusick 
54822836Smckusick 
54922836Smckusick 
55022836Smckusick endio()
55122836Smckusick {
55222836Smckusick if(skiplab)
55322836Smckusick 	{
55422836Smckusick 	if (optimflag)
55522836Smckusick 		optbuff (SKLABEL, 0, skiplab, 0);
55622836Smckusick 	else
55722836Smckusick 		putlabel (skiplab);
55822836Smckusick 	if(ioendlab)
55922836Smckusick 		{
56022836Smckusick 		expptr test;
56122836Smckusick 		test = mkexpr(OPGE, cpexpr(IOSTP), ICON(0));
56222836Smckusick 		if (optimflag)
56322836Smckusick 			optbuff (SKIOIFN,test,ioendlab,0);
56422836Smckusick 		else
56522836Smckusick 			putif (test,ioendlab);
56622836Smckusick 		}
56722836Smckusick 	if(ioerrlab)
56822836Smckusick 		{
56922836Smckusick 		expptr test;
57022836Smckusick 		test = mkexpr
57122836Smckusick 			( ((iostmt==IOREAD||iostmt==IOWRITE) ? OPLE : OPEQ),
57222836Smckusick 			cpexpr(IOSTP), ICON(0));
57322836Smckusick 		if (optimflag)
57422836Smckusick 			optbuff (SKIOIFN,test,ioerrlab,0);
57522836Smckusick 		else
57622836Smckusick 			putif (test,ioerrlab);
57722836Smckusick 		}
57822836Smckusick 	}
57922836Smckusick if(IOSTP)
58022836Smckusick 	frexpr(IOSTP);
58122836Smckusick }
58222836Smckusick 
58322836Smckusick 
58422836Smckusick 
58522836Smckusick LOCAL putiocall(q)
58622836Smckusick register expptr q;
58722836Smckusick {
58822836Smckusick if(IOSTP)
58922836Smckusick 	{
59022836Smckusick 	q->headblock.vtype = TYINT;
59122836Smckusick 	q = fixexpr( mkexpr(OPASSIGN, cpexpr(IOSTP), q));
59222836Smckusick 	}
59322836Smckusick 
59422836Smckusick if(jumplab)
59522836Smckusick 	if (optimflag)
59622836Smckusick 		optbuff (SKIOIFN,mkexpr(OPEQ,q,ICON(0)),jumplab,0);
59722836Smckusick 	else
59822836Smckusick 		putif (mkexpr(OPEQ,q,ICON(0)),jumplab);
59922836Smckusick else
60022836Smckusick 	if (optimflag)
60122836Smckusick 		optbuff (SKEQ, q, 0, 0);
60222836Smckusick 	else
60322836Smckusick 		putexpr(q);
60422836Smckusick }
60522836Smckusick 
60622836Smckusick startrw()
60722836Smckusick {
60822836Smckusick register expptr p;
60922836Smckusick register Namep np;
61022836Smckusick register Addrp unitp, fmtp, recp, tioblkp;
61122836Smckusick register expptr nump;
61222836Smckusick register ioblock *t;
61322836Smckusick Addrp mkscalar();
61422836Smckusick expptr mkaddcon();
61522836Smckusick int k;
61622836Smckusick flag intfile, sequential, ok, varfmt;
61722836Smckusick 
61822836Smckusick /* First look at all the parameters and determine what is to be done */
61922836Smckusick 
62022836Smckusick ok = YES;
62122836Smckusick statstruct = YES;
62222836Smckusick 
62322836Smckusick intfile = NO;
62422836Smckusick if(p = V(IOSUNIT))
62522836Smckusick 	{
62622836Smckusick 	if( ISINT(p->headblock.vtype) )
62722836Smckusick 		unitp = (Addrp) cpexpr(p);
62822836Smckusick 	else if(p->headblock.vtype == TYCHAR)
62922836Smckusick 		{
63022836Smckusick 		intfile = YES;
63122836Smckusick 		if(p->tag==TPRIM && p->primblock.argsp==NULL &&
63222836Smckusick 		    (np = p->primblock.namep)->vdim!=NULL)
63322836Smckusick 			{
63422836Smckusick 			vardcl(np);
63522836Smckusick 			if(np->vdim->nelt)
63622836Smckusick 				{
63722836Smckusick 				nump = (expptr) cpexpr(np->vdim->nelt);
63822836Smckusick 				if( ! ISCONST(nump) )
63922836Smckusick 					statstruct = NO;
64022836Smckusick 				}
64122836Smckusick 			else
64222836Smckusick 				{
64322836Smckusick 				err("attempt to use internal unit array of unknown size");
64422836Smckusick 				ok = NO;
64522836Smckusick 				nump = ICON(1);
64622836Smckusick 				}
64722836Smckusick 			unitp = mkscalar(np);
64822836Smckusick 			}
64922836Smckusick 		else	{
65022836Smckusick 			nump = ICON(1);
65122836Smckusick 			unitp = (Addrp) fixtype(cpexpr(p));
65222836Smckusick 			}
65322836Smckusick 		if(! isstatic(unitp) )
65422836Smckusick 			statstruct = NO;
65522836Smckusick 		}
65622836Smckusick 	else
65722836Smckusick 		{
65822836Smckusick 		err("bad unit specifier type");
65922836Smckusick 		ok = NO;
66022836Smckusick 		}
66122836Smckusick 	}
66222836Smckusick else
66322836Smckusick 	{
66422836Smckusick 	err("bad unit specifier");
66522836Smckusick 	ok = NO;
66622836Smckusick 	}
66722836Smckusick 
66822836Smckusick sequential = YES;
66922836Smckusick if(p = V(IOSREC))
67022836Smckusick 	if( ISINT(p->headblock.vtype) )
67122836Smckusick 		{
67222836Smckusick 		recp = (Addrp) cpexpr(p);
67322836Smckusick 		sequential = NO;
67422836Smckusick 		}
67522836Smckusick 	else	{
67622836Smckusick 		err("bad REC= clause");
67722836Smckusick 		ok = NO;
67822836Smckusick 		}
67922836Smckusick else
68022836Smckusick 	recp = NULL;
68122836Smckusick 
68222836Smckusick 
68322836Smckusick varfmt = YES;
68422836Smckusick fmtp = NULL;
68522836Smckusick if(p = V(IOSFMT))
68622836Smckusick 	{
68722836Smckusick 	if(p->tag==TPRIM && p->primblock.argsp==NULL)
68822836Smckusick 		{
68922836Smckusick 		np = p->primblock.namep;
69022836Smckusick 		if(np->vclass == CLNAMELIST)
69122836Smckusick 			{
69222836Smckusick 			ioformatted = NAMEDIRECTED;
69322836Smckusick 			fmtp = (Addrp) fixtype(cpexpr(p));
69422836Smckusick 			goto endfmt;
69522836Smckusick 			}
69622836Smckusick 		vardcl(np);
69722836Smckusick 		if(np->vdim)
69822836Smckusick 			{
69922836Smckusick 			if( ! ONEOF(np->vstg, MSKSTATIC) )
70022836Smckusick 				statstruct = NO;
70122836Smckusick 			fmtp = mkscalar(np);
70222836Smckusick 			goto endfmt;
70322836Smckusick 			}
70422836Smckusick 		if( ISINT(np->vtype) )	/* ASSIGNed label */
70522836Smckusick 			{
70622836Smckusick 			statstruct = NO;
70722836Smckusick 			varfmt = NO;
70822836Smckusick 			fmtp = (Addrp) fixtype(cpexpr(p));
70922836Smckusick 			goto endfmt;
71022836Smckusick 			}
71122836Smckusick 		}
71222836Smckusick 	p = V(IOSFMT) = fixtype(p);
71322836Smckusick 	if(p->headblock.vtype == TYCHAR)
71422836Smckusick 		{
71522836Smckusick 		if (p->tag == TCONST) p = (expptr) putconst(p);
71622836Smckusick 		if( ! isstatic(p) )
71722836Smckusick 			statstruct = NO;
71822836Smckusick 		fmtp = (Addrp) cpexpr(p);
71922836Smckusick 		}
72022836Smckusick 	else if( ISICON(p) )
72122836Smckusick 		{
72222836Smckusick 		if( (k = fmtstmt( mklabel(p->constblock.const.ci) )) > 0 )
72322836Smckusick 			{
72422836Smckusick 			fmtp = (Addrp) mkaddcon(k);
72522836Smckusick 			varfmt = NO;
72622836Smckusick 			}
72722836Smckusick 		else
72822836Smckusick 			ioformatted = UNFORMATTED;
72922836Smckusick 		}
73022836Smckusick 	else	{
73122836Smckusick 		err("bad format descriptor");
73222836Smckusick 		ioformatted = UNFORMATTED;
73322836Smckusick 		ok = NO;
73422836Smckusick 		}
73522836Smckusick 	}
73622836Smckusick else
73722836Smckusick 	fmtp = NULL;
73822836Smckusick 
73922836Smckusick endfmt:
74022836Smckusick 	if(intfile && ioformatted==UNFORMATTED)
74122836Smckusick 		{
74222836Smckusick 		err("unformatted internal I/O not allowed");
74322836Smckusick 		ok = NO;
74422836Smckusick 		}
74522836Smckusick 	if(!sequential && ioformatted==LISTDIRECTED)
74622836Smckusick 		{
74722836Smckusick 		err("direct list-directed I/O not allowed");
74822836Smckusick 		ok = NO;
74922836Smckusick 		}
75022836Smckusick 	if(!sequential && ioformatted==NAMEDIRECTED)
75122836Smckusick 		{
75222836Smckusick 		err("direct namelist I/O not allowed");
75322836Smckusick 		ok = NO;
75422836Smckusick 		}
75522836Smckusick 
75622836Smckusick if( ! ok )
75722836Smckusick 	return;
75822836Smckusick 
75922836Smckusick if (optimflag && ISCONST (fmtp))
76022836Smckusick 	fmtp = putconst ( (expptr) fmtp);
76122836Smckusick 
76222836Smckusick /*
76322836Smckusick    Now put out the I/O structure, statically if all the clauses
76422836Smckusick    are constants, dynamically otherwise
76522836Smckusick */
76622836Smckusick 
76722836Smckusick if(statstruct)
76822836Smckusick 	{
76922836Smckusick 	tioblkp = ioblkp;
77022836Smckusick 	ioblkp = ALLOC(Addrblock);
77122836Smckusick 	ioblkp->tag = TADDR;
77222836Smckusick 	ioblkp->vtype = TYIOINT;
77322836Smckusick 	ioblkp->vclass = CLVAR;
77422836Smckusick 	ioblkp->vstg = STGINIT;
77522836Smckusick 	ioblkp->memno = ++lastvarno;
77622836Smckusick 	ioblkp->memoffset = ICON(0);
77722836Smckusick 	blklen = (intfile ? XIREC+SZIOINT :
77822836Smckusick 			(sequential ? XFMT+SZADDR : XRNUM+SZIOINT) );
77922836Smckusick 	t = ALLOC(IoBlock);
78022836Smckusick 	t->blkno = ioblkp->memno;
78122836Smckusick 	t->len = blklen;
78222836Smckusick 	t->next = iodata;
78322836Smckusick 	iodata = t;
78422836Smckusick 	}
78522836Smckusick else if(ioblkp == NULL)
78622836Smckusick 	ioblkp = autovar( (MAXIO+SZIOINT-1)/SZIOINT , TYIOINT, PNULL);
78722836Smckusick 
78822836Smckusick ioset(TYIOINT, XERR, ICON(errbit));
78922836Smckusick if(iostmt == IOREAD)
79022836Smckusick 	ioset(TYIOINT, (intfile ? XIEND : XEND), ICON(endbit) );
79122836Smckusick 
79222836Smckusick if(intfile)
79322836Smckusick 	{
79422836Smckusick 	ioset(TYIOINT, XIRNUM, nump);
795*26511Sdonn 	ioseta(XIUNIT, cpexpr(unitp));
79622836Smckusick 	ioset(TYIOINT, XIRLEN, cpexpr(unitp->vleng) );
797*26511Sdonn 	frexpr(unitp);
79822836Smckusick 	}
79922836Smckusick else
80022836Smckusick 	ioset(TYIOINT, XUNIT, (expptr) unitp);
80122836Smckusick 
80222836Smckusick if(recp)
80322836Smckusick 	ioset(TYIOINT, (intfile ? XIREC : XREC) , (expptr) recp);
80422836Smckusick 
80522836Smckusick if(varfmt)
80622836Smckusick 	ioseta( intfile ? XIFMT : XFMT , fmtp);
80722836Smckusick else
80822836Smckusick 	ioset(TYADDR, intfile ? XIFMT : XFMT, (expptr) fmtp);
80922836Smckusick 
81022836Smckusick ioroutine[0] = 's';
81122836Smckusick ioroutine[1] = '_';
81222836Smckusick ioroutine[2] = (iostmt==IOREAD ? 'r' : 'w');
81322836Smckusick ioroutine[3] = (sequential ? 's' : 'd');
81422836Smckusick ioroutine[4] = "ufln" [ioformatted];
81522836Smckusick ioroutine[5] = (intfile ? 'i' : 'e');
81622836Smckusick ioroutine[6] = '\0';
81722836Smckusick 
81822836Smckusick putiocall( call1(TYINT, ioroutine, cpexpr(ioblkp) ));
81922836Smckusick 
82022836Smckusick if(statstruct)
82122836Smckusick 	{
82222836Smckusick 	frexpr(ioblkp);
82322836Smckusick 	ioblkp = tioblkp;
82422836Smckusick 	statstruct = NO;
82522836Smckusick 	}
82622836Smckusick }
82722836Smckusick 
82822836Smckusick 
82922836Smckusick 
83022836Smckusick LOCAL dofopen()
83122836Smckusick {
83222836Smckusick register expptr p;
83322836Smckusick 
83422836Smckusick if( (p = V(IOSUNIT)) && ISINT(p->headblock.vtype) )
83522836Smckusick 	ioset(TYIOINT, XUNIT, cpexpr(p) );
83622836Smckusick else
83722836Smckusick 	err("bad unit in open");
83822836Smckusick if( (p = V(IOSFILE)) )
83922836Smckusick 	if(p->headblock.vtype == TYCHAR)
84022836Smckusick 		ioset(TYIOINT, XFNAMELEN, cpexpr(p->headblock.vleng) );
84122836Smckusick 	else
84222836Smckusick 		err("bad file in open");
84322836Smckusick 
84422836Smckusick iosetc(XFNAME, p);
84522836Smckusick 
84622836Smckusick if(p = V(IOSRECL))
84722836Smckusick 	if( ISINT(p->headblock.vtype) )
84822836Smckusick 		ioset(TYIOINT, XRECLEN, cpexpr(p) );
84922836Smckusick 	else
85022836Smckusick 		err("bad recl");
85122836Smckusick else
85222836Smckusick 	ioset(TYIOINT, XRECLEN, ICON(0) );
85322836Smckusick 
85422836Smckusick iosetc(XSTATUS, V(IOSSTATUS));
85522836Smckusick iosetc(XACCESS, V(IOSACCESS));
85622836Smckusick iosetc(XFORMATTED, V(IOSFORM));
85722836Smckusick iosetc(XBLANK, V(IOSBLANK));
85822836Smckusick 
85922836Smckusick putiocall( call1(TYINT, "f_open", cpexpr(ioblkp) ));
86022836Smckusick }
86122836Smckusick 
86222836Smckusick 
86322836Smckusick LOCAL dofclose()
86422836Smckusick {
86522836Smckusick register expptr p;
86622836Smckusick 
86722836Smckusick if( (p = V(IOSUNIT)) && ISINT(p->headblock.vtype) )
86822836Smckusick 	{
86922836Smckusick 	ioset(TYIOINT, XUNIT, cpexpr(p) );
87022836Smckusick 	iosetc(XCLSTATUS, V(IOSSTATUS));
87122836Smckusick 	putiocall( call1(TYINT, "f_clos", cpexpr(ioblkp)) );
87222836Smckusick 	}
87322836Smckusick else
87422836Smckusick 	err("bad unit in close statement");
87522836Smckusick }
87622836Smckusick 
87722836Smckusick 
87822836Smckusick LOCAL dofinquire()
87922836Smckusick {
88022836Smckusick register expptr p;
88122836Smckusick if(p = V(IOSUNIT))
88222836Smckusick 	{
88322836Smckusick 	if( V(IOSFILE) )
88422836Smckusick 		err("inquire by unit or by file, not both");
88522836Smckusick 	ioset(TYIOINT, XUNIT, cpexpr(p) );
88622836Smckusick 	}
88722836Smckusick else if( ! V(IOSFILE) )
88822836Smckusick 	err("must inquire by unit or by file");
88922836Smckusick iosetlc(IOSFILE, XFILE, XFILELEN);
89022836Smckusick iosetip(IOSEXISTS, XEXISTS);
89122836Smckusick iosetip(IOSOPENED, XOPEN);
89222836Smckusick iosetip(IOSNUMBER, XNUMBER);
89322836Smckusick iosetip(IOSNAMED, XNAMED);
89422836Smckusick iosetlc(IOSNAME, XNAME, XNAMELEN);
89522836Smckusick iosetlc(IOSACCESS, XQACCESS, XQACCLEN);
89622836Smckusick iosetlc(IOSSEQUENTIAL, XSEQ, XSEQLEN);
89722836Smckusick iosetlc(IOSDIRECT, XDIRECT, XDIRLEN);
89822836Smckusick iosetlc(IOSFORM, XFORM, XFORMLEN);
89922836Smckusick iosetlc(IOSFORMATTED, XFMTED, XFMTEDLEN);
90022836Smckusick iosetlc(IOSUNFORMATTED, XUNFMT, XUNFMTLEN);
90122836Smckusick iosetip(IOSRECL, XQRECL);
90222836Smckusick iosetip(IOSNEXTREC, XNEXTREC);
90322836Smckusick iosetlc(IOSBLANK, XQBLANK, XQBLANKLEN);
90422836Smckusick 
90522836Smckusick putiocall( call1(TYINT,  "f_inqu", cpexpr(ioblkp) ));
90622836Smckusick }
90722836Smckusick 
90822836Smckusick 
90922836Smckusick 
91022836Smckusick LOCAL dofmove(subname)
91122836Smckusick char *subname;
91222836Smckusick {
91322836Smckusick register expptr p;
91422836Smckusick 
91522836Smckusick if( (p = V(IOSUNIT)) && ISINT(p->headblock.vtype) )
91622836Smckusick 	{
91722836Smckusick 	ioset(TYIOINT, XUNIT, cpexpr(p) );
91822836Smckusick 	putiocall( call1(TYINT, subname, cpexpr(ioblkp) ));
91922836Smckusick 	}
92022836Smckusick else
92122836Smckusick 	err("bad unit in I/O motion statement");
92222836Smckusick }
92322836Smckusick 
92422836Smckusick 
92522836Smckusick 
92622836Smckusick LOCAL
92722836Smckusick ioset(type, offset, p)
92822836Smckusick int type;
92922836Smckusick int offset;
93022836Smckusick register expptr p;
93122836Smckusick {
93222836Smckusick   static char *badoffset = "badoffset in ioset";
93322836Smckusick 
93422836Smckusick   register Addrp q;
93522836Smckusick   register offsetlist *op;
93622836Smckusick 
93722836Smckusick   q = (Addrp) cpexpr(ioblkp);
93822836Smckusick   q->vtype = type;
93922836Smckusick   q->memoffset = fixtype( mkexpr(OPPLUS, q->memoffset, ICON(offset)) );
94022836Smckusick 
94122836Smckusick   if (statstruct && ISCONST(p))
94222836Smckusick     {
94322836Smckusick       if (!ISICON(q->memoffset))
94422836Smckusick 	fatal(badoffset);
94522836Smckusick 
94622836Smckusick       op = mkiodata(q->memno, q->memoffset->constblock.const.ci, blklen);
94722836Smckusick       if (op->tag != 0)
94822836Smckusick 	fatal(badoffset);
94922836Smckusick 
95022836Smckusick       if (type == TYADDR)
95122836Smckusick 	{
95222836Smckusick 	  op->tag = NDLABEL;
95322836Smckusick 	  op->val.label = p->constblock.const.ci;
95422836Smckusick 	}
95522836Smckusick       else
95622836Smckusick 	{
95722836Smckusick 	  op->tag = NDDATA;
95822836Smckusick 	  op->val.cp = (Constp) convconst(type, 0, p);
95922836Smckusick 	}
96022836Smckusick 
96122836Smckusick       frexpr((tagptr) p);
96222836Smckusick       frexpr((tagptr) q);
96322836Smckusick     }
96422836Smckusick   else
96522836Smckusick     if (optimflag)
96622836Smckusick       optbuff (SKEQ, mkexpr(OPASSIGN,q,p), 0,0);
96722836Smckusick     else
96822836Smckusick       puteq (q,p);
96922836Smckusick 
97022836Smckusick   return;
97122836Smckusick }
97222836Smckusick 
97322836Smckusick 
97422836Smckusick 
97522836Smckusick 
97622836Smckusick LOCAL iosetc(offset, p)
97722836Smckusick int offset;
97822836Smckusick register expptr p;
97922836Smckusick {
98022836Smckusick if(p == NULL)
98122836Smckusick 	ioset(TYADDR, offset, ICON(0) );
98222836Smckusick else if(p->headblock.vtype == TYCHAR)
98322836Smckusick 	ioset(TYADDR, offset, addrof(cpexpr(p) ));
98422836Smckusick else
98522836Smckusick 	err("non-character control clause");
98622836Smckusick }
98722836Smckusick 
98822836Smckusick 
98922836Smckusick 
99022836Smckusick LOCAL ioseta(offset, p)
99122836Smckusick int offset;
99222836Smckusick register Addrp p;
99322836Smckusick {
99422836Smckusick   static char *badoffset = "bad offset in ioseta";
99522836Smckusick 
99622836Smckusick   int blkno;
99722836Smckusick   register offsetlist *op;
99822836Smckusick 
99922836Smckusick   if(statstruct)
100022836Smckusick     {
100122836Smckusick       blkno = ioblkp->memno;
100222836Smckusick       op = mkiodata(blkno, offset, blklen);
100322836Smckusick       if (op->tag != 0)
100422836Smckusick 	fatal(badoffset);
100522836Smckusick 
100622836Smckusick       if (p == NULL)
100722836Smckusick 	op->tag = NDNULL;
100822836Smckusick       else if (p->tag == TADDR)
100922836Smckusick 	{
101022836Smckusick 	  op->tag = NDADDR;
101122836Smckusick 	  op->val.addr.stg = p->vstg;
101222836Smckusick 	  op->val.addr.memno = p->memno;
101322836Smckusick 	  op->val.addr.offset = p->memoffset->constblock.const.ci;
101422836Smckusick 	}
101522836Smckusick       else
101622836Smckusick 	badtag("ioseta", p->tag);
101722836Smckusick     }
101822836Smckusick   else
101922836Smckusick     ioset(TYADDR, offset, p ? addrof(p) : ICON(0) );
102022836Smckusick 
102122836Smckusick   return;
102222836Smckusick }
102322836Smckusick 
102422836Smckusick 
102522836Smckusick 
102622836Smckusick 
102722836Smckusick LOCAL iosetip(i, offset)
102822836Smckusick int i, offset;
102922836Smckusick {
103022836Smckusick register expptr p;
103122836Smckusick 
103222836Smckusick if(p = V(i))
103322836Smckusick 	if(p->tag==TADDR &&
103422836Smckusick 	    ONEOF(p->addrblock.vtype, M(TYLONG)|M(TYLOGICAL)) )
103522836Smckusick 		ioset(TYADDR, offset, addrof(cpexpr(p)) );
103622836Smckusick 	else
103722836Smckusick 		errstr("impossible inquire parameter %s", ioc[i].iocname);
103822836Smckusick else
103922836Smckusick 	ioset(TYADDR, offset, ICON(0) );
104022836Smckusick }
104122836Smckusick 
104222836Smckusick 
104322836Smckusick 
104422836Smckusick LOCAL iosetlc(i, offp, offl)
104522836Smckusick int i, offp, offl;
104622836Smckusick {
104722836Smckusick register expptr p;
104822836Smckusick if( (p = V(i)) && p->headblock.vtype==TYCHAR)
104922836Smckusick 	ioset(TYIOINT, offl, cpexpr(p->headblock.vleng) );
105022836Smckusick iosetc(offp, p);
105122836Smckusick }
105222836Smckusick 
105322836Smckusick 
105422836Smckusick LOCAL offsetlist *
105522836Smckusick mkiodata(blkno, offset, len)
105622836Smckusick int blkno;
105722836Smckusick ftnint offset;
105822836Smckusick ftnint len;
105922836Smckusick {
106022836Smckusick   register offsetlist *p, *q;
106122836Smckusick   register ioblock *t;
106222836Smckusick   register int found;
106322836Smckusick 
106422836Smckusick   found = NO;
106522836Smckusick   t = iodata;
106622836Smckusick 
106722836Smckusick   while (found == NO && t != NULL)
106822836Smckusick     {
106922836Smckusick       if (t->blkno == blkno)
107022836Smckusick 	found = YES;
107122836Smckusick       else
107222836Smckusick 	t = t->next;
107322836Smckusick     }
107422836Smckusick 
107522836Smckusick   if (found == NO)
107622836Smckusick     {
107722836Smckusick       t = ALLOC(IoBlock);
107822836Smckusick       t->blkno = blkno;
107922836Smckusick       t->next = iodata;
108022836Smckusick       iodata = t;
108122836Smckusick     }
108222836Smckusick 
108322836Smckusick   if (len > t->len)
108422836Smckusick     t->len = len;
108522836Smckusick 
108622836Smckusick   p = t->olist;
108722836Smckusick 
108822836Smckusick   if (p == NULL)
108922836Smckusick     {
109022836Smckusick       p = ALLOC(OffsetList);
109122836Smckusick       p->next = NULL;
109222836Smckusick       p->offset = offset;
109322836Smckusick       t->olist = p;
109422836Smckusick       return (p);
109522836Smckusick     }
109622836Smckusick 
109722836Smckusick   for (;;)
109822836Smckusick     {
109922836Smckusick       if (p->offset == offset)
110022836Smckusick 	return (p);
110122836Smckusick       else if (p->next != NULL &&
110222836Smckusick 	       p->next->offset <= offset)
110322836Smckusick 	p = p->next;
110422836Smckusick       else
110522836Smckusick 	{
110622836Smckusick 	  q = ALLOC(OffsetList);
110722836Smckusick 	  q->next = p->next;
110822836Smckusick 	  p->next = q;
110922836Smckusick 	  q->offset = offset;
111022836Smckusick 	  return (q);
111122836Smckusick 	}
111222836Smckusick     }
111322836Smckusick }
111422836Smckusick 
111522836Smckusick 
111622836Smckusick outiodata()
111722836Smckusick {
111822836Smckusick   static char *varfmt = "v.%d:\n";
111922836Smckusick 
112022836Smckusick   register ioblock *p;
112122836Smckusick   register ioblock *t;
112222836Smckusick 
112322836Smckusick   if (iodata == NULL) return;
112422836Smckusick 
112522836Smckusick   p = iodata;
112622836Smckusick 
112722836Smckusick   while (p != NULL)
112822836Smckusick     {
112922836Smckusick       pralign(ALIDOUBLE);
113022836Smckusick       fprintf(initfile, varfmt, p->blkno);
113122836Smckusick       outolist(p->olist, p->len);
113222836Smckusick 
113322836Smckusick       t = p;
113422836Smckusick       p = t->next;
113522836Smckusick       free((char *) t);
113622836Smckusick     }
113722836Smckusick 
113822836Smckusick   iodata = NULL;
113922836Smckusick   return;
114022836Smckusick }
114122836Smckusick 
114222836Smckusick 
114322836Smckusick 
114422836Smckusick LOCAL
114522836Smckusick outolist(op, len)
114622836Smckusick register offsetlist *op;
114722836Smckusick register int len;
114822836Smckusick {
114922836Smckusick   static char *overlap = "overlapping i/o fields in outolist";
115022836Smckusick   static char *toolong = "offset too large in outolist";
115122836Smckusick 
115222836Smckusick   register offsetlist *t;
115322836Smckusick   register ftnint clen;
115422836Smckusick   register Constp cp;
115522836Smckusick   register int type;
115622836Smckusick 
115722836Smckusick   clen = 0;
115822836Smckusick 
115922836Smckusick   while (op != NULL)
116022836Smckusick     {
116122836Smckusick       if (clen > op->offset)
116222836Smckusick 	fatal(overlap);
116322836Smckusick 
116422836Smckusick       if (clen < op->offset)
116522836Smckusick 	{
116622836Smckusick 	  prspace(op->offset - clen);
116722836Smckusick 	  clen = op->offset;
116822836Smckusick 	}
116922836Smckusick 
117022836Smckusick       switch (op->tag)
117122836Smckusick 	{
117222836Smckusick 	default:
117322836Smckusick 	  badtag("outolist", op->tag);
117422836Smckusick 
117522836Smckusick 	case NDDATA:
117622836Smckusick 	  cp = op->val.cp;
117722836Smckusick 	  type = cp->vtype;
117822836Smckusick 	  if (type != TYIOINT)
117922836Smckusick 	    badtype("outolist", type);
118022836Smckusick 	  prconi(initfile, type, cp->const.ci);
118122836Smckusick 	  clen += typesize[type];
118222836Smckusick 	  frexpr((tagptr) cp);
118322836Smckusick 	  break;
118422836Smckusick 
118522836Smckusick 	case NDLABEL:
118622836Smckusick 	  prcona(initfile, op->val.label);
118722836Smckusick 	  clen += typesize[TYADDR];
118822836Smckusick 	  break;
118922836Smckusick 
119022836Smckusick 	case NDADDR:
119122836Smckusick 	  praddr(initfile, op->val.addr.stg, op->val.addr.memno,
119222836Smckusick 		 op->val.addr.offset);
119322836Smckusick 	  clen += typesize[TYADDR];
119422836Smckusick 	  break;
119522836Smckusick 
119622836Smckusick 	case NDNULL:
119722836Smckusick 	  praddr(initfile, STGNULL, 0, (ftnint) 0);
119822836Smckusick 	  clen += typesize[TYADDR];
119922836Smckusick 	  break;
120022836Smckusick 	}
120122836Smckusick 
120222836Smckusick       t = op;
120322836Smckusick       op = t->next;
120422836Smckusick       free((char *) t);
120522836Smckusick     }
120622836Smckusick 
120722836Smckusick   if (clen > len)
120822836Smckusick     fatal(toolong);
120922836Smckusick 
121022836Smckusick   if (clen < len)
121122836Smckusick     prspace(len - clen);
121222836Smckusick 
121322836Smckusick   return;
121422836Smckusick }
1215