⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 expr.c

📁 unix v7是最后一个广泛发布的研究型UNIX版本
💻 C
📖 第 1 页 / 共 3 页
字号:
		q = intrcall(np, p->argsp, nargs);		break;	case PSTFUNCT:		q = stfcall(np, p->argsp);		break;	case PTHISPROC:		warn("recursive call");		for(ep = entries ; ep ; ep = ep->nextp)			if(ep->enamep == np)				break;		if(ep == NULL)			fatal("mkfunct: impossible recursion");		ap = builtin(np->vtype, varstr(XL, ep->entryname->extname) );		goto call;	default:		fatal1("mkfunct: impossible vprocclass %d", np->vprocclass);	}free(p);return(q);error:	frexpr(p);	return( errnode() );}LOCAL struct exprblock *stfcall(np, actlist)struct nameblock *np;struct listblock *actlist;{register chainp actuals;int nargs;chainp oactp, formals;int type;struct exprblock *q, *rhs;expptr ap;register struct rplblock *rp;struct rplblock *tlist;if(actlist)	{	actuals = actlist->listp;	free(actlist);	}else	actuals = NULL;oactp = actuals;nargs = 0;tlist = NULL;type = np->vtype;formals = np->vardesc.vstfdesc->datap;rhs = np->vardesc.vstfdesc->nextp;/* copy actual arguments into temporaries */while(actuals!=NULL && formals!=NULL)	{	rp = ALLOC(rplblock);	rp->rplnp = q = formals->datap;	ap = fixtype(actuals->datap);	if(q->vtype==ap->vtype && q->vtype!=TYCHAR	   && (ap->tag==TCONST || ap->tag==TADDR) )		{		rp->rplvp = ap;		rp->rplxp = NULL;		rp->rpltag = ap->tag;		}	else	{		rp->rplvp = mktemp(q->vtype, q->vleng);		rp->rplxp = fixtype( mkexpr(OPASSIGN, cpexpr(rp->rplvp), ap) );		if( (rp->rpltag = rp->rplxp->tag) == TERROR)			err("disagreement of argument types in statement function call");		}	rp->nextp = tlist;	tlist = rp;	actuals = actuals->nextp;	formals = formals->nextp;	++nargs;	}if(actuals!=NULL || formals!=NULL)	err("statement function definition and argument list differ");/*   now push down names involved in formal argument list, then   evaluate rhs of statement function definition in this environment*/rpllist = hookup(tlist, rpllist);q = mkconv(type, fixtype(cpexpr(rhs)) );/* now generate the tree ( t1=a1, (t2=a2,... , f))))) */while(--nargs >= 0)	{	if(rpllist->rplxp)		q = mkexpr(OPCOMMA, rpllist->rplxp, q);	rp = rpllist->nextp;	frexpr(rpllist->rplvp);	free(rpllist);	rpllist = rp;	}frchain( &oactp );return(q);}struct addrblock *mklhs(p)register struct primblock * p;{register struct addrblock *s;expptr suboffset();struct nameblock *np;register struct rplblock *rp;int regn;/* first fixup name */if(p->tag != TPRIM)	return(p);np = p->namep;/* is name on the replace list? */for(rp = rpllist ; rp ; rp = rp->nextp)	{	if(np == rp->rplnp)		{		if(rp->rpltag == TNAME)			{			np = p->namep = rp->rplvp;			break;			}		else	return( cpexpr(rp->rplvp) );		}	}/* is variable a DO index in a register ? */if(np->vdovar && ( (regn = inregister(np)) >= 0) )	if(np->vtype == TYERROR)		return( errnode() );	else		{		s = ALLOC(addrblock);		s->tag = TADDR;		s->vstg = STGREG;		s->vtype = TYIREG;		s->memno = regn;		s->memoffset = ICON(0);		return(s);		}vardcl(np);s = mkaddr(np);s->memoffset = mkexpr(OPPLUS, s->memoffset, suboffset(p) );frexpr(p->argsp);p->argsp = NULL;/* now do substring part */if(p->fcharp || p->lcharp)	{	if(np->vtype != TYCHAR)		err1("substring of noncharacter %s", varstr(VL,np->varname));	else	{		if(p->lcharp == NULL)			p->lcharp = cpexpr(s->vleng);		if(p->fcharp)			s->vleng = mkexpr(OPMINUS, p->lcharp,				mkexpr(OPMINUS, p->fcharp, ICON(1) ));		else	{			frexpr(s->vleng);			s->vleng = p->lcharp;			}		}	}s->vleng = fixtype( s->vleng );s->memoffset = fixtype( s->memoffset );free(p);return(s);}deregister(np)struct nameblock *np;{if(nregvar>0 && regnamep[nregvar-1]==np)	{	--nregvar;#if FAMILY == DMR	putnreg();#endif	}}struct addrblock *memversion(np)register struct nameblock *np;{register struct addrblock *s;if(np->vdovar==NO || (inregister(np)<0) )	return(NULL);np->vdovar = NO;s = mklhs( mkprim(np, 0,0,0) );np->vdovar = YES;return(s);}inregister(np)register struct nameblock *np;{register int i;for(i = 0 ; i < nregvar ; ++i)	if(regnamep[i] == np)		return( regnum[i] );return(-1);}enregister(np)struct nameblock *np;{if( inregister(np) >= 0)	return(YES);if(nregvar >= maxregvar)	return(NO);vardcl(np);if( ONEOF(np->vtype, MSKIREG) )	{	regnamep[nregvar++] = np;	if(nregvar > highregvar)		highregvar = nregvar;#if FAMILY == DMR	putnreg();#endif	return(YES);	}else	return(NO);}expptr suboffset(p)register struct primblock *p;{int n;expptr size;chainp cp;expptr offp, prod;expptr subcheck();struct dimblock *dimp;expptr sub[8];register struct nameblock *np;np = p->namep;offp = ICON(0);n = 0;if(p->argsp)	for(cp = p->argsp->listp ; cp ; cp = cp->nextp)		{		sub[n++] = fixtype(cpexpr(cp->datap));		if(n > 7)			{			err("more than 7 subscripts");			break;			}		}dimp = np->vdim;if(n>0 && dimp==NULL)	err("subscripts on scalar variable");else if(dimp && dimp->ndim!=n)	err1("wrong number of subscripts on %s",		varstr(VL, np->varname) );else if(n > 0)	{	prod = sub[--n];	while( --n >= 0)		prod = mkexpr(OPPLUS, sub[n],			mkexpr(OPSTAR, prod, cpexpr(dimp->dims[n].dimsize)) );#if TARGET == VAX	if(checksubs || np->vstg!=STGARG)		prod = mkexpr(OPMINUS, prod, cpexpr(dimp->baseoffset));#else	prod = mkexpr(OPMINUS, prod, cpexpr(dimp->baseoffset));#endif	if(checksubs)		prod = subcheck(np, prod);	if(np->vtype == TYCHAR)		size = cpexpr(np->vleng);	else	size = ICON( typesize[np->vtype] );	prod = mkexpr(OPSTAR, prod, size);	offp = mkexpr(OPPLUS, offp, prod);	}if(p->fcharp && np->vtype==TYCHAR)	offp = mkexpr(OPPLUS, offp, mkexpr(OPMINUS, cpexpr(p->fcharp), ICON(1) ));return(offp);}expptr subcheck(np, p)struct nameblock *np;register expptr p;{struct dimblock *dimp;expptr t, checkvar, checkcond, badcall;dimp = np->vdim;if(dimp->nelt == NULL)	return(p);	/* don't check arrays with * bounds */checkvar = NULL;checkcond = NULL;if( ISICON(p) )	{	if(p->const.ci < 0)		goto badsub;	if( ISICON(dimp->nelt) )		if(p->const.ci < dimp->nelt->const.ci)			return(p);		else			goto badsub;	}if(p->tag==TADDR && p->vstg==STGREG)	{	checkvar = cpexpr(p);	t = p;	}else	{	checkvar = mktemp(p->vtype, NULL);	t = mkexpr(OPASSIGN, cpexpr(checkvar), p);	}checkcond = mkexpr(OPLT, t, cpexpr(dimp->nelt) );if( ! ISICON(p) )	checkcond = mkexpr(OPAND, checkcond,			mkexpr(OPLE, ICON(0), cpexpr(checkvar)) );badcall = call4(p->vtype, "s_rnge", mkstrcon(VL, np->varname),		mkconv(TYLONG,  cpexpr(checkvar)),		mkstrcon(XL, procname), ICON(lineno));badcall->opcode = OPCCALL;p = mkexpr(OPQUEST, checkcond,	mkexpr(OPCOLON, checkvar, badcall));return(p);badsub:	frexpr(p);	err1("subscript on variable %s out of range", varstr(VL,np->varname));	return ( ICON(0) );}struct addrblock *mkaddr(p)register struct nameblock *p;{struct extsym *mkext(), *extp;register struct addrblock *t;struct addrblock *intraddr();switch( p->vstg)	{	case STGUNKNOWN:		if(p->vclass != CLPROC)			break;		extp = mkext( varunder(VL, p->varname) );		extp->extstg = STGEXT;		p->vstg = STGEXT;		p->vardesc.varno = extp - extsymtab;		p->vprocclass = PEXTERNAL;	case STGCOMMON:	case STGEXT:	case STGBSS:	case STGINIT:	case STGEQUIV:	case STGARG:	case STGLENG:	case STGAUTO:		t = ALLOC(addrblock);		t->tag = TADDR;		if(p->vclass==CLPROC && p->vprocclass==PTHISPROC)			t->vclass = CLVAR;		else			t->vclass = p->vclass;		t->vtype = p->vtype;		t->vstg = p->vstg;		t->memno = p->vardesc.varno;		t->memoffset = ICON(p->voffset);		if(p->vleng)			t->vleng = cpexpr(p->vleng);		return(t);	case STGINTR:		return( intraddr(p) );	}/*debug*/ fprintf(diagfile, "mkaddr. vtype=%d, vclass=%d\n", p->vtype, p->vclass);fatal1("mkaddr: impossible storage tag %d", p->vstg);/* NOTREACHED */}mkarg(type, argno)int type, argno;{register struct addrblock *p;p = ALLOC(addrblock);p->tag = TADDR;p->vtype = type;p->vclass = CLVAR;p->vstg = (type==TYLENG ? STGLENG : STGARG);p->memno = argno;return(p);}tagptr mkprim(v, args, lstr, rstr)register union { struct paramblock; struct nameblock; } *v;struct listblock *args;expptr lstr, rstr;{register struct primblock *p;if(v->vclass == CLPARAM)	{	if(args || lstr || rstr)		{		err1("no qualifiers on parameter name", varstr(VL,v->varname));		frexpr(args);		frexpr(lstr);		frexpr(rstr);		frexpr(v);		return( errnode() );		}	return( cpexpr(v->paramval) );	}p = ALLOC(primblock);p->tag = TPRIM;p->vtype = v->vtype;p->namep = v;p->argsp = args;p->fcharp = lstr;p->lcharp = rstr;return(p);}vardcl(v)register struct nameblock *v;{int nelt;struct dimblock *t;struct addrblock *p;expptr neltp;if(v->vdcldone) return;if(v->vtype == TYUNKNOWN)	impldcl(v);if(v->vclass == CLUNKNOWN)	v->vclass = CLVAR;else if(v->vclass!=CLVAR && v->vprocclass!=PTHISPROC)	{	dclerr("used as variable", v);	return;	}if(v->vstg==STGUNKNOWN)	v->vstg = implstg[ letter(v->varname[0]) ];switch(v->vstg)	{	case STGBSS:		v->vardesc.varno = ++lastvarno;		break;	case STGAUTO:		if(v->vclass==CLPROC && v->vprocclass==PTHISPROC)			break;		nelt = 1;		if(t = v->vdim)			if( (neltp = t->nelt) && ISCONST(neltp) )				nelt = neltp->const.ci;			else				dclerr("adjustable automatic array", v);		p = autovar(nelt, v->vtype, v->vleng);		v->voffset = p->memoffset->const.ci;		frexpr(p);		break;	default:		break;	}v->vdcldone = YES;}impldcl(p)register struct nameblock *p;{register int k;int type, leng;if(p->vdcldone || (p->vclass==CLPROC && p->vprocclass==PINTRINSIC) )	return;if(p->vtype == TYUNKNOWN)	{	k = letter(p->varname[0]);	type = impltype[ k ];	leng = implleng[ k ];	if(type == TYUNKNOWN)		{		if(p->vclass == CLPROC)			return;		dclerr("attempt to use undefined variable", p);		type = TYERROR;		leng = 1;		}	settype(p, type, leng);	}}LOCAL letter(c)register int c;{if( isupper(c) )	c = tolower(c);return(c - 'a');}#define ICONEQ(z, c)  (ISICON(z) && z->const.ci==c)#define COMMUTE	{ e = lp;  lp = rp;  rp = e; }expptr mkexpr(opcode, lp, rp)int opcode;register expptr lp, rp;{register struct exprblock *e, *e1;int etype;int ltype, rtype;int ltag, rtag;expptr fold();ltype = lp->vtype;ltag = lp->tag;if(rp && opcode!=OPCALL && opcode!=OPCCALL)	{	rtype = rp->vtype;	rtag = rp->tag;	}else  rtype = 0;etype = cktype(opcode, ltype, rtype);if(etype == TYERROR)	goto error;switch(opcode)	{	/* check for multiplication by 0 and 1 and addition to 0 */	case OPSTAR:		if( ISCONST(lp) )			COMMUTE		if( ISICON(rp) )			{			if(rp->const.ci == 0)				goto retright;			goto mulop;			}		break;	case OPSLASH:	case OPMOD:		if( ICONEQ(rp, 0) )			{			err("attempted division by zero");			rp = ICON(1);			break;			}		if(opcode == OPMOD)			break;	mulop:		if( ISICON(rp) )			{			if(rp->const.ci == 1)				goto retleft;			if(rp->const.ci == -1)				{				frexpr(rp);				return( mkexpr(OPNEG, lp, 0) );				}			}		if( ISSTAROP(lp) && ISICON(lp->rightp) )			{			if(opcode == OPSTAR)				e = mkexpr(OPSTAR, lp->rightp, rp);			else  if(ISICON(rp) && lp->rightp->const.ci % rp->const.ci == 0)				e = mkexpr(OPSLASH, lp->rightp, rp);			else	break;			e1 = lp->leftp;			free(lp);			return( mkexpr(OPSTAR, e1, e) );			}		break;	case OPPLUS:		if( ISCONST(lp) )			COMMUTE		goto addop;	case OPMINUS:		if( ICONEQ(lp, 0) )			{			frexpr(lp);			return( mkexpr(OPNEG, rp, 0) );			}		if( ISCONST(rp) )			{			opcode = OPPLUS;			consnegop(rp);			}	addop:		if( ISICON(rp) )			{			if(rp->const.ci == 0)				goto retleft;			if( ISPLUSOP(lp) && ISICON(lp->rightp) )				{				e = mkexpr(OPPLUS, lp->rightp, rp);				e1 = lp->leftp;				free(lp);				return( mkexpr(OPPLUS, e1, e) );				}			}		break;	case OPPOWER:		break;	case OPNEG:		if(ltag==TEXPR && lp->opcode==OPNEG)			{			e = lp->leftp;			free(lp);			return(e);			}		break;	case OPNOT:		if(ltag==TEXPR && lp->opcode==OPNOT)			{			e = lp->leftp;			free(lp);			return(e);			}		break;	case OPCALL:	case OPCCALL:		etype = ltype;		if(rp!=NULL && rp->listp==NULL)			{			free(rp);			rp = NULL;			}		break;	case OPAND:	case OPOR:		if( ISCONST(lp) )			COMMUTE		if( ISCONST(rp) )			{			if(rp->const.ci == 0)				if(opcode == OPOR)					goto retleft;				else					goto retright;			else if(opcode == OPOR)				goto retright;			else				goto retleft;			}	case OPEQV:	case OPNEQV:	case OPBITAND:	case OPBITOR:	case OPBITXOR:	case OPBITNOT:	case OPLSHIFT:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -