436 lines
		
	
	
	
		
			9.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			436 lines
		
	
	
	
		
			9.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/****************************************************************
 | 
						|
Copyright 1990 by AT&T Bell Laboratories and Bellcore.
 | 
						|
 | 
						|
Permission to use, copy, modify, and distribute this software
 | 
						|
and its documentation for any purpose and without fee is hereby
 | 
						|
granted, provided that the above copyright notice appear in all
 | 
						|
copies and that both that the copyright notice and this
 | 
						|
permission notice and warranty disclaimer appear in supporting
 | 
						|
documentation, and that the names of AT&T Bell Laboratories or
 | 
						|
Bellcore or any of their entities not be used in advertising or
 | 
						|
publicity pertaining to distribution of the software without
 | 
						|
specific, written prior permission.
 | 
						|
 | 
						|
AT&T and Bellcore disclaim all warranties with regard to this
 | 
						|
software, including all implied warranties of merchantability
 | 
						|
and fitness.  In no event shall AT&T or Bellcore be liable for
 | 
						|
any special, indirect or consequential damages or any damages
 | 
						|
whatsoever resulting from loss of use, data or profits, whether
 | 
						|
in an action of contract, negligence or other tortious action,
 | 
						|
arising out of or in connection with the use or performance of
 | 
						|
this software.
 | 
						|
****************************************************************/
 | 
						|
 | 
						|
#include "defs.h"
 | 
						|
 | 
						|
/* ROUTINES CALLED DURING DATA AND PARAMETER STATEMENT PROCESSING */
 | 
						|
 | 
						|
static char datafmt[] = "%s\t%09ld\t%d";
 | 
						|
static char *cur_varname;
 | 
						|
 | 
						|
/* another initializer, called from parser */
 | 
						|
dataval(repp, valp)
 | 
						|
register expptr repp, valp;
 | 
						|
{
 | 
						|
	int i, nrep;
 | 
						|
	ftnint elen;
 | 
						|
	register Addrp p;
 | 
						|
	Addrp nextdata();
 | 
						|
 | 
						|
	if (parstate < INDATA) {
 | 
						|
		frexpr(repp);
 | 
						|
		goto ret;
 | 
						|
		}
 | 
						|
	if(repp == NULL)
 | 
						|
		nrep = 1;
 | 
						|
	else if (ISICON(repp) && repp->constblock.Const.ci >= 0)
 | 
						|
		nrep = repp->constblock.Const.ci;
 | 
						|
	else
 | 
						|
	{
 | 
						|
		err("invalid repetition count in DATA statement");
 | 
						|
		frexpr(repp);
 | 
						|
		goto ret;
 | 
						|
	}
 | 
						|
	frexpr(repp);
 | 
						|
 | 
						|
	if( ! ISCONST(valp) )
 | 
						|
	{
 | 
						|
		err("non-constant initializer");
 | 
						|
		goto ret;
 | 
						|
	}
 | 
						|
 | 
						|
	if(toomanyinit) goto ret;
 | 
						|
	for(i = 0 ; i < nrep ; ++i)
 | 
						|
	{
 | 
						|
		p = nextdata(&elen);
 | 
						|
		if(p == NULL)
 | 
						|
		{
 | 
						|
			err("too many initializers");
 | 
						|
			toomanyinit = YES;
 | 
						|
			goto ret;
 | 
						|
		}
 | 
						|
		setdata((Addrp)p, (Constp)valp, elen);
 | 
						|
		frexpr((expptr)p);
 | 
						|
	}
 | 
						|
 | 
						|
ret:
 | 
						|
	frexpr(valp);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
Addrp nextdata(elenp)
 | 
						|
ftnint *elenp;
 | 
						|
{
 | 
						|
	register struct Impldoblock *ip;
 | 
						|
	struct Primblock *pp;
 | 
						|
	register Namep np;
 | 
						|
	register struct Rplblock *rp;
 | 
						|
	tagptr p;
 | 
						|
	expptr neltp;
 | 
						|
	register expptr q;
 | 
						|
	int skip;
 | 
						|
	ftnint off, vlen;
 | 
						|
 | 
						|
	while(curdtp)
 | 
						|
	{
 | 
						|
		p = (tagptr)curdtp->datap;
 | 
						|
		if(p->tag == TIMPLDO)
 | 
						|
		{
 | 
						|
			ip = &(p->impldoblock);
 | 
						|
			if(ip->implb==NULL || ip->impub==NULL || ip->varnp==NULL)
 | 
						|
				fatali("bad impldoblock 0%o", (int) ip);
 | 
						|
			if(ip->isactive)
 | 
						|
				ip->varvp->Const.ci += ip->impdiff;
 | 
						|
			else
 | 
						|
			{
 | 
						|
				q = fixtype(cpexpr(ip->implb));
 | 
						|
				if( ! ISICON(q) )
 | 
						|
					goto doerr;
 | 
						|
				ip->varvp = (Constp) q;
 | 
						|
 | 
						|
				if(ip->impstep)
 | 
						|
				{
 | 
						|
					q = fixtype(cpexpr(ip->impstep));
 | 
						|
					if( ! ISICON(q) )
 | 
						|
						goto doerr;
 | 
						|
					ip->impdiff = q->constblock.Const.ci;
 | 
						|
					frexpr(q);
 | 
						|
				}
 | 
						|
				else
 | 
						|
					ip->impdiff = 1;
 | 
						|
 | 
						|
				q = fixtype(cpexpr(ip->impub));
 | 
						|
				if(! ISICON(q))
 | 
						|
					goto doerr;
 | 
						|
				ip->implim = q->constblock.Const.ci;
 | 
						|
				frexpr(q);
 | 
						|
 | 
						|
				ip->isactive = YES;
 | 
						|
				rp = ALLOC(Rplblock);
 | 
						|
				rp->rplnextp = rpllist;
 | 
						|
				rpllist = rp;
 | 
						|
				rp->rplnp = ip->varnp;
 | 
						|
				rp->rplvp = (expptr) (ip->varvp);
 | 
						|
				rp->rpltag = TCONST;
 | 
						|
			}
 | 
						|
 | 
						|
			if( (ip->impdiff>0 && (ip->varvp->Const.ci <= ip->implim))
 | 
						|
			    || (ip->impdiff<0 && (ip->varvp->Const.ci >= ip->implim)) )
 | 
						|
			{ /* start new loop */
 | 
						|
				curdtp = ip->datalist;
 | 
						|
				goto next;
 | 
						|
			}
 | 
						|
 | 
						|
			/* clean up loop */
 | 
						|
 | 
						|
			if(rpllist)
 | 
						|
			{
 | 
						|
				rp = rpllist;
 | 
						|
				rpllist = rpllist->rplnextp;
 | 
						|
				free( (charptr) rp);
 | 
						|
			}
 | 
						|
			else
 | 
						|
				Fatal("rpllist empty");
 | 
						|
 | 
						|
			frexpr((expptr)ip->varvp);
 | 
						|
			ip->isactive = NO;
 | 
						|
			curdtp = curdtp->nextp;
 | 
						|
			goto next;
 | 
						|
		}
 | 
						|
 | 
						|
		pp = (struct Primblock *) p;
 | 
						|
		np = pp->namep;
 | 
						|
		cur_varname = np->fvarname;
 | 
						|
		skip = YES;
 | 
						|
 | 
						|
		if(p->primblock.argsp==NULL && np->vdim!=NULL)
 | 
						|
		{   /* array initialization */
 | 
						|
			q = (expptr) mkaddr(np);
 | 
						|
			off = typesize[np->vtype] * curdtelt;
 | 
						|
			if(np->vtype == TYCHAR)
 | 
						|
				off *= np->vleng->constblock.Const.ci;
 | 
						|
			q->addrblock.memoffset =
 | 
						|
			    mkexpr(OPPLUS, q->addrblock.memoffset, mkintcon(off) );
 | 
						|
			if( (neltp = np->vdim->nelt) && ISCONST(neltp))
 | 
						|
			{
 | 
						|
				if(++curdtelt < neltp->constblock.Const.ci)
 | 
						|
					skip = NO;
 | 
						|
			}
 | 
						|
			else
 | 
						|
				err("attempt to initialize adjustable array");
 | 
						|
		}
 | 
						|
		else
 | 
						|
			q = mklhs( (struct Primblock *)cpexpr((expptr)pp) );
 | 
						|
		if(skip)
 | 
						|
		{
 | 
						|
			curdtp = curdtp->nextp;
 | 
						|
			curdtelt = 0;
 | 
						|
		}
 | 
						|
		if(q->headblock.vtype == TYCHAR)
 | 
						|
			if(ISICON(q->headblock.vleng))
 | 
						|
				*elenp = q->headblock.vleng->constblock.Const.ci;
 | 
						|
			else	{
 | 
						|
				err("initialization of string of nonconstant length");
 | 
						|
				continue;
 | 
						|
			}
 | 
						|
		else	*elenp = typesize[q->headblock.vtype];
 | 
						|
 | 
						|
		if (np->vstg == STGBSS) {
 | 
						|
			vlen = np->vtype==TYCHAR
 | 
						|
				? np->vleng->constblock.Const.ci
 | 
						|
				: typesize[np->vtype];
 | 
						|
			if(vlen > 0)
 | 
						|
				np->vstg = STGINIT;
 | 
						|
			}
 | 
						|
		return( (Addrp) q );
 | 
						|
 | 
						|
doerr:
 | 
						|
		err("nonconstant implied DO parameter");
 | 
						|
		frexpr(q);
 | 
						|
		curdtp = curdtp->nextp;
 | 
						|
 | 
						|
next:
 | 
						|
		curdtelt = 0;
 | 
						|
	}
 | 
						|
 | 
						|
	return(NULL);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
LOCAL FILEP dfile;
 | 
						|
 | 
						|
 | 
						|
setdata(varp, valp, elen)
 | 
						|
register Addrp varp;
 | 
						|
ftnint elen;
 | 
						|
register Constp valp;
 | 
						|
{
 | 
						|
	struct Constblock con;
 | 
						|
	register int type;
 | 
						|
	int i, k, valtype;
 | 
						|
	ftnint offset;
 | 
						|
	char *dataname(), *varname;
 | 
						|
	static Addrp badvar;
 | 
						|
	register unsigned char *s;
 | 
						|
	static int last_lineno;
 | 
						|
	static char *last_varname;
 | 
						|
 | 
						|
	if (varp->vstg == STGCOMMON) {
 | 
						|
		if (!(dfile = blkdfile))
 | 
						|
			dfile = blkdfile = opf(blkdfname, textwrite);
 | 
						|
		}
 | 
						|
	else {
 | 
						|
		if (procclass == CLBLOCK) {
 | 
						|
			if (varp != badvar) {
 | 
						|
				badvar = varp;
 | 
						|
				warn1("%s is not in a COMMON block",
 | 
						|
					varp->uname_tag == UNAM_NAME
 | 
						|
					? varp->user.name->fvarname
 | 
						|
					: "???");
 | 
						|
				}
 | 
						|
			return;
 | 
						|
			}
 | 
						|
		if (!(dfile = initfile))
 | 
						|
			dfile = initfile = opf(initfname, textwrite);
 | 
						|
		}
 | 
						|
	varname = dataname(varp->vstg, varp->memno);
 | 
						|
	offset = varp->memoffset->constblock.Const.ci;
 | 
						|
	type = varp->vtype;
 | 
						|
	valtype = valp->vtype;
 | 
						|
	if(type!=TYCHAR && valtype==TYCHAR)
 | 
						|
	{
 | 
						|
		if(! ftn66flag
 | 
						|
		&& (last_varname != cur_varname || last_lineno != lineno)) {
 | 
						|
			/* prevent multiple warnings */
 | 
						|
			last_lineno = lineno;
 | 
						|
			warn1(
 | 
						|
	"non-character datum %.42s initialized with character string",
 | 
						|
				last_varname = cur_varname);
 | 
						|
			}
 | 
						|
		varp->vleng = ICON(typesize[type]);
 | 
						|
		varp->vtype = type = TYCHAR;
 | 
						|
	}
 | 
						|
	else if( (type==TYCHAR && valtype!=TYCHAR) ||
 | 
						|
	    (cktype(OPASSIGN,type,valtype) == TYERROR) )
 | 
						|
	{
 | 
						|
		err("incompatible types in initialization");
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	if(type == TYADDR)
 | 
						|
		con.Const.ci = valp->Const.ci;
 | 
						|
	else if(type != TYCHAR)
 | 
						|
	{
 | 
						|
		if(valtype == TYUNKNOWN)
 | 
						|
			con.Const.ci = valp->Const.ci;
 | 
						|
		else	consconv(type, &con, valp);
 | 
						|
	}
 | 
						|
 | 
						|
	k = 1;
 | 
						|
 | 
						|
	switch(type)
 | 
						|
	{
 | 
						|
	case TYLOGICAL:
 | 
						|
		if (tylogical != TYLONG)
 | 
						|
			type = tylogical;
 | 
						|
	case TYSHORT:
 | 
						|
	case TYLONG:
 | 
						|
		dataline(varname, offset, type);
 | 
						|
		prconi(dfile, con.Const.ci);
 | 
						|
		break;
 | 
						|
 | 
						|
	case TYADDR:
 | 
						|
		dataline(varname, offset, type);
 | 
						|
		prcona(dfile, con.Const.ci);
 | 
						|
		break;
 | 
						|
 | 
						|
	case TYCOMPLEX:
 | 
						|
	case TYDCOMPLEX:
 | 
						|
		k = 2;
 | 
						|
	case TYREAL:
 | 
						|
	case TYDREAL:
 | 
						|
		dataline(varname, offset, type);
 | 
						|
		prconr(dfile, &con, k);
 | 
						|
		break;
 | 
						|
 | 
						|
	case TYCHAR:
 | 
						|
		k = valp -> vleng -> constblock.Const.ci;
 | 
						|
		if (elen < k)
 | 
						|
			k = elen;
 | 
						|
		s = (unsigned char *)valp->Const.ccp;
 | 
						|
		for(i = 0 ; i < k ; ++i) {
 | 
						|
			dataline(varname, offset++, TYCHAR);
 | 
						|
			fprintf(dfile, "\t%d\n", *s++);
 | 
						|
			}
 | 
						|
		k = elen - valp->vleng->constblock.Const.ci;
 | 
						|
		if(k > 0) {
 | 
						|
			dataline(varname, offset, TYBLANK);
 | 
						|
			fprintf(dfile, "\t%d\n", k);
 | 
						|
			}
 | 
						|
		break;
 | 
						|
 | 
						|
	default:
 | 
						|
		badtype("setdata", type);
 | 
						|
	}
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
   output form of name is padded with blanks and preceded
 | 
						|
   with a storage class digit
 | 
						|
*/
 | 
						|
char *dataname(stg,memno)
 | 
						|
 int stg;
 | 
						|
 long memno;
 | 
						|
{
 | 
						|
	static char varname[64];
 | 
						|
	register char *s, *t;
 | 
						|
	char buf[16], *memname();
 | 
						|
 | 
						|
	if (stg == STGCOMMON) {
 | 
						|
		varname[0] = '2';
 | 
						|
		sprintf(s = buf, "Q.%ld", memno);
 | 
						|
		}
 | 
						|
	else {
 | 
						|
		varname[0] = stg==STGEQUIV ? '1' : '0';
 | 
						|
		s = memname(stg, memno);
 | 
						|
		}
 | 
						|
	t = varname + 1;
 | 
						|
	while(*t++ = *s++);
 | 
						|
	*t = 0;
 | 
						|
	return(varname);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
frdata(p0)
 | 
						|
chainp p0;
 | 
						|
{
 | 
						|
	register struct Chain *p;
 | 
						|
	register tagptr q;
 | 
						|
 | 
						|
	for(p = p0 ; p ; p = p->nextp)
 | 
						|
	{
 | 
						|
		q = (tagptr)p->datap;
 | 
						|
		if(q->tag == TIMPLDO)
 | 
						|
		{
 | 
						|
			if(q->impldoblock.isbusy)
 | 
						|
				return;	/* circular chain completed */
 | 
						|
			q->impldoblock.isbusy = YES;
 | 
						|
			frdata(q->impldoblock.datalist);
 | 
						|
			free( (charptr) q);
 | 
						|
		}
 | 
						|
		else
 | 
						|
			frexpr(q);
 | 
						|
	}
 | 
						|
 | 
						|
	frchain( &p0);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
dataline(varname, offset, type)
 | 
						|
char *varname;
 | 
						|
ftnint offset;
 | 
						|
int type;
 | 
						|
{
 | 
						|
	fprintf(dfile, datafmt, varname, offset, type);
 | 
						|
}
 | 
						|
 | 
						|
 void
 | 
						|
make_param(p, e)
 | 
						|
 register struct Paramblock *p;
 | 
						|
 expptr e;
 | 
						|
{
 | 
						|
	register expptr q;
 | 
						|
 | 
						|
	p->vclass = CLPARAM;
 | 
						|
	impldcl((Namep)p);
 | 
						|
	p->paramval = q = mkconv(p->vtype, e);
 | 
						|
	if (p->vtype == TYCHAR) {
 | 
						|
		if (q->tag == TEXPR)
 | 
						|
			p->paramval = q = fixexpr(q);
 | 
						|
		if (!ISCONST(q) || q->constblock.vtype != TYCHAR) {
 | 
						|
			errstr("invalid value for character parameter %s",
 | 
						|
				p->fvarname);
 | 
						|
			return;
 | 
						|
			}
 | 
						|
		if (!(e = p->vleng))
 | 
						|
			p->vleng = ICON(q->constblock.vleng->constblock.Const.ci
 | 
						|
					+ q->constblock.Const.ccp1.blanks);
 | 
						|
		else if (q->constblock.vleng->constblock.Const.ci
 | 
						|
				> e->constblock.Const.ci) {
 | 
						|
			q->constblock.vleng->constblock.Const.ci
 | 
						|
				= e->constblock.Const.ci;
 | 
						|
			q->constblock.Const.ccp1.blanks = 0;
 | 
						|
			}
 | 
						|
		else
 | 
						|
			q->constblock.Const.ccp1.blanks
 | 
						|
				= e->constblock.Const.ci
 | 
						|
				- q->constblock.vleng->constblock.Const.ci;
 | 
						|
		}
 | 
						|
	}
 |