#include "defines.h"
#include "amacro.h"
#include "vsiki.h"

extern	VSSYS	Vsikis;

int Enzan(int (*func)(),VARSYS *var,int *err)
/* 演算＆符号処理（代入は外部のfuncで処理）*/
{
long v1,v2;
unsint e;
	if (Vsikis.vs==0) {
		*err=VSILL;
		return(-1); /* error:ここにはこないはず */
	}
	
	/* 第２項取り出し */
	v2=Vsikis.vstack[--Vsikis.vs];
	/* 演算子取り出し */
	e=Vsikis.estack[--Vsikis.es];
	
	/* 単項演算子 */
	{int f=0;
	switch (e) {
		/* 単項演算子はスタック段数の変更はない */
		case VMINUS: /* 負号 */
			f=1;
			v2=-v2;
			break;
		case '~': /* bit-NOT */
			f=1;
			v2=~v2;
			break;
		case '!': /* NOT */
			f=1;
			v2=!v2;
			break;
		case VINC: /* ++ */
			f=1;
			++v2;
			break;
		case VDEC: /* -- */
			f=1;
			--v2;
			break;
	}
	if (f) { // 単項演算子であった
		Vsikis.vstack[Vsikis.vs++]=v2;
		return(e);
	}
	}
	
	/** ２項演算子 **/
	if (Vsikis.vs==0) {
		*err=VSILL;
		return(-1); /* error : 第１項がない */
	}
	/* 第１項取り出し */
	v1=Vsikis.vstack[Vsikis.vs-1];
	
	/* 演算 */
	switch (e) {
		case '=':	/* 代入は外部処理 */
				if (func==NULL) {
					*err=VSILL;
					return(-1); /* 代入無し */
				}
				{int ret;
				ret=func(v2,var);
				if (ret) return(ret); /* error */
				}
				v1=v2; // 代入はその値そのものを返す
				break;
		case '+':	v1+=v2; 	break;
		case '-':	v1-=v2; 	break;
		case '*':	v1*=v2; 	break;
		case '/':	if (v2==0) {*err=VS0DIV; return(-1);}
				v1/=v2; 	break;
		case '\\':	if (v2==0) {*err=VS0DIV; return(-1);}
				v1%=v2;		break;
		case '&':	v1&=v2;		break;
		case '|':	v1|=v2;		break;
		case '^':	v1^=v2;		break;
		case '>':	v1=(v1>v2); 	break;
		case '<':	v1=(v1<v2); 	break;
		case VEQU:	v1=(v1==v2);	break;
		case VNE :	v1=(v1!=v2);	break;
		case VGE :	v1=(v1>=v2);	break;
		case VLE :	v1=(v1<=v2);	break;
		case VAND:	v1=(v1&&v2);	break;
		case VOR:	v1=(v1||v2);	break;
		case VRSHIFT:	v1=(unsigned long)v1>>v2;	break;
		case VLSHIFT:	v1=(unsigned long)v1<<v2;	break;
		case VRROT:	v1=(unsigned long)_rotr((unsigned long)v1,v2);	break;
		case VLROT:	v1=(unsigned long)_rotl((unsigned long)v1,v2);	break;
	}
	Vsikis.vstack[Vsikis.vs-1]=v1;
	return(e);
}
