static char rcsid[] = "$Header:field.c 12.0$";
#include "defs"



ptr mkfield(q)
register ptr q;
{
register ptr p;

if(!instruct)
	goto err;
else if(((struct dimblock *)q)->upperb == 0)
	dclerr("must have upper bound in field spcification", "");
else
	{
	p = (ptr)ALLOC(fieldspec);
	((struct headbits *)p)->tag = TFIELD;
	if(((struct dimblock *)q)->lowerb)
		{
		((struct fieldspec *)p)->flbound = ((struct dimblock *)q)->lowerb;
		((struct fieldspec *)p)->frange = mknode(TAROP,OPPLUS,mknode(TAROP,OPMINUS,
				((struct dimblock *)q)->upperb, cpexpr(((struct dimblock *)q)->lowerb)),
				mkconst(TYINT,"1") );
		}
	else	{
		((struct fieldspec *)p)->flbound = mkconst(TYINT,"1");
		((struct fieldspec *)p)->frange = ((struct dimblock *)q)->upperb;
		}
	((struct fieldspec *)p)->frange = simple(RVAL,((struct fieldspec *)p)->frange);
	if(((struct headbits *)((struct fieldspec *)p)->frange)->tag != TCONST)
		{
		dclerr("field range must be constant", "");
		cfree(p);
		goto err;
		}
	cfree(q);
	return(p);
	}

err:
	cfree(q);
	return( errnode() );
}





ptr extrfield(p)
register ptr p;
{
register ptr t;

t = ((struct varblock *)p)->vtypep;
((struct varblock *)p)->vtype = TYINT;
((struct varblock *)p)->vtypep = 0;

if(((struct fieldspec *)t)->frshift)
	p = mknode(TAROP,OPSLASH, p, cpexpr(((struct fieldspec *)t)->frshift));
if(((struct fieldspec *)t)->fanymore)
	p = mkcall(builtin(TYINT, "mod"), arg2(p, cpexpr(((struct fieldspec *)t)->frange)) );
p = mknode(TAROP,OPPLUS, p, cpexpr(((struct fieldspec *)t)->flbound));
return(p);
}




ptr setfield(e)
ptr e;
{
ptr lp, rp;
register ptr f, p;
int subt;

lp = cpexpr(((struct exprblock *)e)->leftp);
rp = ((struct exprblock *)e)->rightp;
subt = ((struct headbits *)e)->subtype;
f = ((struct varblock *)lp)->vtypep;
((struct varblock *)lp)->vtype = TYINT;
((struct varblock *)lp)->vtypep = 0;

if(subt==OPPLUS || subt==OPMINUS)
	{
	if(((struct fieldspec *)f)->frshift)
		rp = mknode(TAROP,OPSTAR,rp,cpexpr(((struct fieldspec *)f)->frshift));
	}
else	{
	if(subt != OPASGN)
		{
		rp = mknode(TAROP,subt, extrfield(cpexpr(((struct exprblock *)e)->leftp)), rp);
		subt = OPASGN;
		}
	rp = coerce(TYINT,rp);
	if(((struct fieldspec *)f)->flbound)
		rp = simple(RVAL, mknode(TAROP,OPMINUS,rp,cpexpr(((struct fieldspec *)f)->flbound)) );
	
	if(((struct fieldspec *)f)->frshift==0)
		{
		if(((struct fieldspec *)f)->fanymore)
			{
			p = mknode(TAROP,OPSLASH,cpexpr(lp),cpexpr(((struct fieldspec *)f)->frange));
			((struct varblock *)p)->needpar = YES;
			p = mknode(TAROP,OPSTAR,cpexpr(((struct fieldspec *)f)->frange),p);
			rp = mknode(TAROP,OPPLUS,p,rp);
			}
		}
	else if(((struct fieldspec *)f)->fanymore==0)
		{
		rp = mknode(TAROP,OPSTAR,cpexpr(((struct fieldspec *)f)->frshift),rp);
		p = mkcall(builtin(TYINT,"mod"),
			arg2(cpexpr(lp),cpexpr(((struct fieldspec *)f)->frshift)) );
		rp = mknode(TAROP,OPPLUS, p,rp);
		}
	else	{
		p = mknode(TAROP,OPSLASH,cpexpr(lp),cpexpr(((struct fieldspec *)f)->frshift));
		p = mkcall(builtin(TYINT,"mod"), 
			arg2(p, cpexpr(((struct fieldspec *)f)->frange)) );
		if( ((struct headbits *)rp)->tag!=TCONST || !equals(((struct exprblock *)rp)->leftp, "0") )
			p = mknode(TAROP,OPMINUS, p, rp);
		rp = mknode(TAROP,OPSTAR, cpexpr(((struct fieldspec *)f)->frshift), p);
		rp = mknode(TAROP,OPMINUS, cpexpr(lp), rp);
		}
	}
frexpr( simple(LVAL, mknode(TASGNOP,subt,lp,rp) ));
return(extrfield(((struct exprblock *)e)->leftp));
}
