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

📄 expr.c

📁 unix v7是最后一个广泛发布的研究型UNIX版本
💻 C
📖 第 1 页 / 共 3 页
字号:
	case OPRSHIFT:	case OPLT:	case OPGT:	case OPLE:	case OPGE:	case OPEQ:	case OPNE:	case OPCONCAT:		break;	case OPMIN:	case OPMAX:	case OPASSIGN:	case OPPLUSEQ:	case OPSTAREQ:	case OPCONV:	case OPADDR:	case OPCOMMA:	case OPQUEST:	case OPCOLON:		break;	default:		fatal1("mkexpr: impossible opcode %d", opcode);	}e = ALLOC(exprblock);e->tag = TEXPR;e->opcode = opcode;e->vtype = etype;e->leftp = lp;e->rightp = rp;if(ltag==TCONST && (rp==0 || rtag==TCONST) )	e = fold(e);return(e);retleft:	frexpr(rp);	return(lp);retright:	frexpr(lp);	return(rp);error:	frexpr(lp);	if(rp && opcode!=OPCALL && opcode!=OPCCALL)		frexpr(rp);	return( errnode() );}#define ERR(s)   { errs = s; goto error; }cktype(op, lt, rt)register int op, lt, rt;{char *errs;if(lt==TYERROR || rt==TYERROR)	goto error1;if(lt==TYUNKNOWN)	return(TYUNKNOWN);if(rt==TYUNKNOWN)	if(op!=OPNOT && op!=OPBITNOT && op!=OPNEG && op!=OPCALL && op!=OPCCALL && op!=OPADDR)		return(TYUNKNOWN);switch(op)	{	case OPPLUS:	case OPMINUS:	case OPSTAR:	case OPSLASH:	case OPPOWER:	case OPMOD:		if( ISNUMERIC(lt) && ISNUMERIC(rt) )			return( maxtype(lt, rt) );		ERR("nonarithmetic operand of arithmetic operator")	case OPNEG:		if( ISNUMERIC(lt) )			return(lt);		ERR("nonarithmetic operand of negation")	case OPNOT:		if(lt == TYLOGICAL)			return(TYLOGICAL);		ERR("NOT of nonlogical")	case OPAND:	case OPOR:	case OPEQV:	case OPNEQV:		if(lt==TYLOGICAL && rt==TYLOGICAL)			return(TYLOGICAL);		ERR("nonlogical operand of logical operator")	case OPLT:	case OPGT:	case OPLE:	case OPGE:	case OPEQ:	case OPNE:		if(lt==TYCHAR || rt==TYCHAR || lt==TYLOGICAL || rt==TYLOGICAL)			{			if(lt != rt)				ERR("illegal comparison")			}		else if( ISCOMPLEX(lt) || ISCOMPLEX(rt) )			{			if(op!=OPEQ && op!=OPNE)				ERR("order comparison of complex data")			}		else if( ! ISNUMERIC(lt) || ! ISNUMERIC(rt) )			ERR("comparison of nonarithmetic data")		return(TYLOGICAL);	case OPCONCAT:		if(lt==TYCHAR && rt==TYCHAR)			return(TYCHAR);		ERR("concatenation of nonchar data")	case OPCALL:	case OPCCALL:		return(lt);	case OPADDR:		return(TYADDR);	case OPCONV:		if(rt == 0)			return(0);		if(lt==TYCHAR && ISINT(rt) )			return(TYCHAR);	case OPASSIGN:	case OPPLUSEQ:	case OPSTAREQ:		if( ISINT(lt) && rt==TYCHAR)			return(lt);		if(lt==TYCHAR || rt==TYCHAR || lt==TYLOGICAL || rt==TYLOGICAL)			if(op!=OPASSIGN || lt!=rt)				{/* debug fprintf(diagfile, " lt=%d, rt=%d, op=%d\n", lt, rt, op); *//* debug fatal("impossible conversion.  possible compiler bug"); */				ERR("impossible conversion")				}		return(lt);	case OPMIN:	case OPMAX:	case OPBITOR:	case OPBITAND:	case OPBITXOR:	case OPBITNOT:	case OPLSHIFT:	case OPRSHIFT:		return(lt);	case OPCOMMA:	case OPQUEST:	case OPCOLON:		return(rt);	default:		fatal1("cktype: impossible opcode %d", op);	}error:	err(errs);error1:	return(TYERROR);}LOCAL expptr fold(e)register struct exprblock *e;{struct constblock *p;#ifdef VERSION6	expptr lp, rp;#else	register expptr lp, rp;#endifint etype, mtype, ltype, rtype, opcode;int i, ll, lr;char *q, *s;union constant lcon, rcon;opcode = e->opcode;etype = e->vtype;lp = e->leftp;ltype = lp->vtype;rp = e->rightp;if(rp == 0)	switch(opcode)		{		case OPNOT:			lp->const.ci = ! lp->const.ci;			return(lp);		case OPBITNOT:			lp->const.ci = ~ lp->const.ci;			return(lp);		case OPNEG:			consnegop(lp);			return(lp);		case OPCONV:		case OPADDR:			return(e);		default:			fatal1("fold: invalid unary operator %d", opcode);		}rtype = rp->vtype;p = ALLOC(constblock);p->tag = TCONST;p->vtype = etype;p->vleng = e->vleng;switch(opcode)	{	case OPCOMMA:	case OPQUEST:	case OPCOLON:		return(e);	case OPAND:		p->const.ci = lp->const.ci && rp->const.ci;		break;	case OPOR:		p->const.ci = lp->const.ci || rp->const.ci;		break;	case OPEQV:		p->const.ci = lp->const.ci == rp->const.ci;		break;	case OPNEQV:		p->const.ci = lp->const.ci != rp->const.ci;		break;	case OPBITAND:		p->const.ci = lp->const.ci & rp->const.ci;		break;	case OPBITOR:		p->const.ci = lp->const.ci | rp->const.ci;		break;	case OPBITXOR:		p->const.ci = lp->const.ci ^ rp->const.ci;		break;	case OPLSHIFT:		p->const.ci = lp->const.ci << rp->const.ci;		break;	case OPRSHIFT:		p->const.ci = lp->const.ci >> rp->const.ci;		break;	case OPCONCAT:		ll = lp->vleng->const.ci;		lr = rp->vleng->const.ci;		p->const.ccp = q = (char *) ckalloc(ll+lr);		p->vleng = ICON(ll+lr);		s = lp->const.ccp;		for(i = 0 ; i < ll ; ++i)			*q++ = *s++;		s = rp->const.ccp;		for(i = 0; i < lr; ++i)			*q++ = *s++;		break;	case OPPOWER:		if( ! ISINT(rtype) )			return(e);		conspower(&(p->const), lp, rp->const.ci);		break;	default:		if(ltype == TYCHAR)			{			lcon.ci = cmpstr(lp->const.ccp, rp->const.ccp,					lp->vleng->const.ci, rp->vleng->const.ci);			rcon.ci = 0;			mtype = tyint;			}		else	{			mtype = maxtype(ltype, rtype);			consconv(mtype, &lcon, ltype, &(lp->const) );			consconv(mtype, &rcon, rtype, &(rp->const) );			}		consbinop(opcode, mtype, &(p->const), &lcon, &rcon);		break;	}frexpr(e);return(p);}/* assign constant l = r , doing coercion */consconv(lt, lv, rt, rv)int lt, rt;register union constant *lv, *rv;{switch(lt)	{	case TYCHAR:		*(lv->ccp = ckalloc(1)) = rv->ci;		break;	case TYSHORT:	case TYLONG:		if(rt == TYCHAR)			lv->ci = rv->ccp[0];		else if( ISINT(rt) )			lv->ci = rv->ci;		else	lv->ci = rv->cd[0];		break;	case TYCOMPLEX:	case TYDCOMPLEX:		switch(rt)			{			case TYSHORT:			case TYLONG:				/* fall through and do real assignment of				   first element				*/			case TYREAL:			case TYDREAL:				lv->cd[1] = 0; break;			case TYCOMPLEX:			case TYDCOMPLEX:				lv->cd[1] = rv->cd[1]; break;			}	case TYREAL:	case TYDREAL:		if( ISINT(rt) )			lv->cd[0] = rv->ci;		else	lv->cd[0] = rv->cd[0];		break;	case TYLOGICAL:		lv->ci = rv->ci;		break;	}}consnegop(p)register struct constblock *p;{switch(p->vtype)	{	case TYSHORT:	case TYLONG:		p->const.ci = - p->const.ci;		break;	case TYCOMPLEX:	case TYDCOMPLEX:		p->const.cd[1] = - p->const.cd[1];		/* fall through and do the real parts */	case TYREAL:	case TYDREAL:		p->const.cd[0] = - p->const.cd[0];		break;	default:		fatal1("consnegop: impossible type %d", p->vtype);	}}LOCAL conspower(powp, ap, n)register union constant *powp;struct constblock *ap;ftnint n;{register int type;union constant x;switch(type = ap->vtype)	/* pow = 1 */ 	{	case TYSHORT:	case TYLONG:		powp->ci = 1;		break;	case TYCOMPLEX:	case TYDCOMPLEX:		powp->cd[1] = 0;	case TYREAL:	case TYDREAL:		powp->cd[0] = 1;		break;	default:		fatal1("conspower: invalid type %d", type);	}if(n == 0)	return;if(n < 0)	{	if( ISINT(type) )		{		err("integer ** negative power ");		return;		}	n = - n;	consbinop(OPSLASH, type, &x, powp, &(ap->const));	}else	consbinop(OPSTAR, type, &x, powp, &(ap->const));for( ; ; )	{	if(n & 01)		consbinop(OPSTAR, type, powp, powp, &x);	if(n >>= 1)		consbinop(OPSTAR, type, &x, &x, &x);	else		break;	}}/* do constant operation cp = a op b */LOCAL consbinop(opcode, type, cp, ap, bp)int opcode, type;register union constant *ap, *bp, *cp;{int k;double temp;switch(opcode)	{	case OPPLUS:		switch(type)			{			case TYSHORT:			case TYLONG:				cp->ci = ap->ci + bp->ci;				break;			case TYCOMPLEX:			case TYDCOMPLEX:				cp->cd[1] = ap->cd[1] + bp->cd[1];			case TYREAL:			case TYDREAL:				cp->cd[0] = ap->cd[0] + bp->cd[0];				break;			}		break;	case OPMINUS:		switch(type)			{			case TYSHORT:			case TYLONG:				cp->ci = ap->ci - bp->ci;				break;			case TYCOMPLEX:			case TYDCOMPLEX:				cp->cd[1] = ap->cd[1] - bp->cd[1];			case TYREAL:			case TYDREAL:				cp->cd[0] = ap->cd[0] - bp->cd[0];				break;			}		break;	case OPSTAR:		switch(type)			{			case TYSHORT:			case TYLONG:				cp->ci = ap->ci * bp->ci;				break;			case TYREAL:			case TYDREAL:				cp->cd[0] = ap->cd[0] * bp->cd[0];				break;			case TYCOMPLEX:			case TYDCOMPLEX:				temp = ap->cd[0] * bp->cd[0] -					    ap->cd[1] * bp->cd[1] ;				cp->cd[1] = ap->cd[0] * bp->cd[1] +					    ap->cd[1] * bp->cd[0] ;				cp->cd[0] = temp;				break;			}		break;	case OPSLASH:		switch(type)			{			case TYSHORT:			case TYLONG:				cp->ci = ap->ci / bp->ci;				break;			case TYREAL:			case TYDREAL:				cp->cd[0] = ap->cd[0] / bp->cd[0];				break;			case TYCOMPLEX:			case TYDCOMPLEX:				zdiv(cp,ap,bp);				break;			}		break;	case OPMOD:		if( ISINT(type) )			{			cp->ci = ap->ci % bp->ci;			break;			}		else			fatal("inline mod of noninteger");	default:	  /* relational ops */		switch(type)			{			case TYSHORT:			case TYLONG:				if(ap->ci < bp->ci)					k = -1;				else if(ap->ci == bp->ci)					k = 0;				else	k = 1;				break;			case TYREAL:			case TYDREAL:				if(ap->cd[0] < bp->cd[0])					k = -1;				else if(ap->cd[0] == bp->cd[0])					k = 0;				else	k = 1;				break;			case TYCOMPLEX:			case TYDCOMPLEX:				if(ap->cd[0] == bp->cd[0] &&				   ap->cd[1] == bp->cd[1] )					k = 0;				else	k = 1;				break;			}		switch(opcode)			{			case OPEQ:				cp->ci = (k == 0);				break;			case OPNE:				cp->ci = (k != 0);				break;			case OPGT:				cp->ci = (k == 1);				break;			case OPLT:				cp->ci = (k == -1);				break;			case OPGE:				cp->ci = (k >= 0);				break;			case OPLE:				cp->ci = (k <= 0);				break;			}		break;	}}conssgn(p)register expptr p;{if( ! ISCONST(p) )	fatal( "sgn(nonconstant)" );switch(p->vtype)	{	case TYSHORT:	case TYLONG:		if(p->const.ci > 0) return(1);		if(p->const.ci < 0) return(-1);		return(0);	case TYREAL:	case TYDREAL:		if(p->const.cd[0] > 0) return(1);		if(p->const.cd[0] < 0) return(-1);		return(0);	case TYCOMPLEX:	case TYDCOMPLEX:		return(p->const.cd[0]!=0 || p->const.cd[1]!=0);	default:		fatal1( "conssgn(type %d)", p->vtype);	}/* NOTREACHED */}char *powint[ ] = { "pow_ii", "pow_ri", "pow_di", "pow_ci", "pow_zi" };LOCAL expptr mkpower(p)register struct exprblock *p;{register expptr q, lp, rp;int ltype, rtype, mtype;lp = p->leftp;rp = p->rightp;ltype = lp->vtype;rtype = rp->vtype;if(ISICON(rp))	{	if(rp->const.ci == 0)		{		frexpr(p);		if( ISINT(ltype) )			return( ICON(1) );		else			return( putconst( mkconv(ltype, ICON(1))) );		}	if(rp->const.ci < 0)		{		if( ISINT(ltype) )			{			frexpr(p);			err("integer**negative");			return( errnode() );			}		rp->const.ci = - rp->const.ci;		p->leftp = lp = fixexpr(mkexpr(OPSLASH, ICON(1), lp));		}	if(rp->const.ci == 1)		{		frexpr(rp);		free(p);		return(lp);		}	if( ONEOF(ltype, MSKINT|MSKREAL) )		{		p->vtype = ltype;		return(p);		}	}if( ISINT(rtype) )	{	if(ltype==TYSHORT && rtype==TYSHORT && (!ISCONST(lp) || tyint==TYSHORT) )		q = call2(TYSHORT, "pow_hh", lp, rp);	else	{		if(ltype == TYSHORT)			{			ltype = TYLONG;			lp = mkconv(TYLONG,lp);			}		q = call2(ltype, powint[ltype-TYLONG], lp, mkconv(TYLONG, rp));		}	}else if( ISREAL( (mtype = maxtype(ltype,rtype)) ))	q = call2(mtype, "pow_dd",		mkconv(TYDREAL,lp), mkconv(TYDREAL,rp));else	{	q = call2(TYDCOMPLEX, "pow_zz",		mkconv(TYDCOMPLEX,lp), mkconv(TYDCOMPLEX,rp));	if(mtype == TYCOMPLEX)		q = mkconv(TYCOMPLEX, q);	}free(p);return(q);}/* Complex Division.  Same code as in Runtime Library*/struct dcomplex { double dreal, dimag; };LOCAL zdiv(c, a, b)register struct dcomplex *a, *b, *c;{double ratio, den;double abr, abi;if( (abr = b->dreal) < 0.)	abr = - abr;if( (abi = b->dimag) < 0.)	abi = - abi;if( abr <= abi )	{	if(abi == 0)		fatal("complex division by zero");	ratio = b->dreal / b->dimag ;	den = b->dimag * (1 + ratio*ratio);	c->dreal = (a->dreal*ratio + a->dimag) / den;	c->dimag = (a->dimag*ratio - a->dreal) / den;	}else	{	ratio = b->dimag / b->dreal ;	den = b->dreal * (1 + ratio*ratio);	c->dreal = (a->dreal + a->dimag*ratio) / den;	c->dimag = (a->dimag - a->dreal*ratio) / den;	}}

⌨️ 快捷键说明

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