%{
/*
Auto:		smake MCalc
*/

#include	"y.tab.h"

#undef	malloc
#define	malloc(x)	AllocVecPool(ParsePool, x)

#undef	free
#define	free(x)		FreeVecPool(ParsePool, x)

#undef	YYLMAX
#define	YYLMAX 1000

#undef	ECHO
#define	ECHO

#undef	YY_FATAL_ERROR
#define	YY_FATAL_ERROR(x)\
	do\
	{\
		PError = ERR_PARSE;\
	}\
	while(0)

#undef	YY_USER_INIT
#define	YY_USER_INIT \
{\
	PCharRead	= 0; \
	PColumn		= 0; \
	PError		= 0; \
	NonDouble	= FALSE; \
}


/**********************************************************************/
/*          This is our YYINPUT for scanning the inputbuffer          */
/**********************************************************************/
#undef	YY_INPUT
#define	YY_INPUT(buf, result, max_size)\
		{\
			char c = ParseInput[PCharRead++];\
			result = (c == '\0') ? YY_NULL : (buf[0] = c, 1);\
		}


extern	APTR	ParsePool;
extern	UWORD	PError;
extern	UWORD	IntType;
extern	UWORD	IntBase;
extern	UWORD	IntSign;
extern	char	*ParseInput;
extern	double	XMem, YMem, ZMem;
UWORD	PCharRead;
UWORD	PColumn = 0;
UWORD	NonDouble;
%}


%%
"Abs"						{ count(); return(MY_ABS); }
"Cos"						{ count(); return(COS); }
"Sin"						{ count(); return(SIN); }
"Tan"						{ count(); return(TAN); }
"ACos"						{ count(); return(ACOS); }
"ASin"						{ count(); return(ASIN); }
"ATan"						{ count(); return(ATAN); }
"Sinh"						{ count(); return(SINH); }
"Cosh"						{ count(); return(COSH); }
"Tanh"						{ count(); return(TANH); }
"Cot"						{ count(); return(COT); }
"Exp"						{ count(); return(EXP); }
"^"						{ count(); return(POW); }
"Log"						{ count(); return(LOG); }
"Log10"						{ count(); return(LOG10); }
"Sqrt"						{ count(); return(SQRT); }
"Asl"						{ count(); return(ASL); }
"Asr"						{ count(); return(ASR); }
"Lsl"						{ count(); return(LSL); }
"Lsr"						{ count(); return(LSR); }
"Rol"						{ count(); return(ROL); }
"Ror"						{ count(); return(ROR); }
"And"						{ count(); return(AND_OP); }
"Or"						{ count(); return(OR_OP); }
"XOr"						{ count(); return(XOR_OP); }
"Not"						{ count(); return(NOT_OP); }
"!"						{ count(); return(FAK); }


[0-9]+						{ count(); calc_int_value(&yytext[0]); return(INT_CONSTANT); }
"$"[0-9a-fA-F]+					{	if(yyleng > 9)
								return(-1);
							else
							{
								count();
								calc_hex_value(&yytext[1], yyleng - 1);
								return(INT_CONSTANT);
							}
						}
"0x"[0-9a-fA-F]+				{	if(yyleng > 10)
								return(-1);
							else
							{
								count();
								calc_hex_value(&yytext[2], yyleng - 2);
								return(INT_CONSTANT);
							}
						}
"\\"[0-7]+					{	if(yyleng > 13)
								return(-1);
							else
							{
								count();
								calc_oct_value(&yytext[1]);
								return(INT_CONSTANT);
							}
						}
"%"[0-1]+					{	if(yyleng > 33)
								return(-1);
							else
							{
								count();
								calc_bin_value(&yytext[1]);
								return(INT_CONSTANT);
							}
						}
[0-9]*"."[0-9]+					{ count(); calc_dbl_value(&yytext[0]); return(INT_CONSTANT); }
[0-9]*"."[0-9]*[eE][+-]?[0-9]+			{ count(); calc_dbl_value(&yytext[0]); return(INT_CONSTANT); }

"Pi"						{ count(); yylval.Real = PI; return(INT_CONSTANT); }
"E"						{ count(); yylval.Real = 2.718281828; return(INT_CONSTANT); }
"X"						{ count(); yylval.Real = XMem; return(X_MEM); }
"Y"						{ count(); yylval.Real = YMem; return(Y_MEM); }
"Z"						{ count(); yylval.Real = ZMem; return(Z_MEM); }

"("						{ count(); return(OPEN_OP); }
")"						{ count(); return(CLOSE_OP); }
"-"						{ count(); return(SUB_OP); }
"+"						{ count(); return(ADD_OP); }
"*"						{ count(); return(MUL_OP); }
"/"						{ count(); return(DIV_OP); }
"Mod"						{ count(); return(MOD_OP); }
"="						{ count(); return(EQU_OP); }

[ \t]						{ count(); }
\n						{ return(0); }
.						{ count(); PError = ERR_UNKNOWN_CHR; return(-1); }

%%



/**********************************************************************/
/*                            Count column                            */
/**********************************************************************/
void count(void)
{
	PError		= 0;
	PColumn		+= yyleng;
}




/**********************************************************************/
/*                            Calc integer                            */
/**********************************************************************/
int calc_int_value(char *s)
{
	char	*p;

	yylval.Real = strtod(s, &p);
	return(0);
}



/**********************************************************************/
/*                           Calc Hex-Value                           */
/**********************************************************************/
int calc_hex_value(char *s, int leng)
{
	int	i, NumParse;
	double	MaxVal;

	switch(IntBase)
	{
		case ID_8BIT :
		{
			NumParse	= 2;
			MaxVal		= 255.0;
			break;
		}
		case ID_16BIT :
		{
			NumParse	= 4;
			MaxVal		= 65535.0;
			break;
		}
		case ID_32BIT :
		{
			NumParse	= 8;
			MaxVal		= 4294967295.0;
			break;
		}
	}

	yylval.Real	= 0;

	for(i = 0; ((i < leng) && (i < NumParse)); i++)
	{
		yylval.Real		*= 16.0;

		if((*s >= 'a') && (*s <= 'f'))
			yylval.Real	+= (double)(*s - 'a' + 10);
		else if((*s >= 'A') && (*s <= 'F'))
			yylval.Real	+= (double)(*s - 'A' + 10);
		else
			yylval.Real	+= (double)(*s - '0');

		s++;
	}

	if(IntType != ID_DECIMAL)
	{
		if(yylval.Real > MaxVal)
			yylval.Real = MaxVal;
	}
	else if(IntSign == ID_SIGNED)
	{
		if(yylval.Real >= ((MaxVal + 1.0) / 2))
			yylval.Real = -(MaxVal - yylval.Real + 1.0);
	}

	return(0);
}


/**********************************************************************/
/*                         Calc Binary value                          */
/**********************************************************************/
int calc_bin_value(char *s)
{
	int	i, NumParse;
	double	MaxVal;

		// Check for how many bits to check for ;)

	switch(IntBase)
	{
		case ID_8BIT :
		{
			NumParse	= 8;
			MaxVal		= 255.0;
			break;
		}
		case ID_16BIT :
		{
			NumParse	= 16;
			MaxVal		= 65535.0;
			break;
		}
		case ID_32BIT :
		{
			NumParse	= 32;
			MaxVal		= 4294967295.0;
			break;
		}
	}

		// get to end of input

	yylval.Real	= 0;

		// Convert to double

	for(i = 0; ((i < (yyleng - 1)) && (i < NumParse)); i++)
	{
		yylval.Real	*= 2.0;
		if(*s++ == '1')
			yylval.Real	+= 1.0;
	}

	if(IntType != ID_DECIMAL)
	{
		if(yylval.Real > MaxVal)
			yylval.Real = MaxVal;
	}
	else if(IntSign == ID_SIGNED)
	{
		if(yylval.Real >= ((MaxVal + 1.0) / 2))
			yylval.Real = -(MaxVal - yylval.Real + 1.0);
	}

	return(0);
}




/**********************************************************************/
/*                          Calc octal value                          */
/**********************************************************************/
int calc_oct_value(char *s)
{
	int	i, NumParse;
	double	MaxVal;

	switch(IntBase)
	{
		case ID_8BIT :
		{
			NumParse	= 3;
			MaxVal		= 255.0;
			break;
		}
		case ID_16BIT :
		{
			NumParse	= 6;
			MaxVal		= 65535.0;
			break;
		}
		case ID_32BIT :
		{
			NumParse	= 11;
			MaxVal		= 4294967295.0;
			break;
		}
	}

	yylval.Real	= 0;
	for(i = 0; ((i < (yyleng - 1)) && (i < NumParse)); i++)
	{
		yylval.Real	*= 8.0;
		yylval.Real	+= (double)(*s - '0');

		s++;
	}

	if(IntType != ID_DECIMAL)
	{
		if(yylval.Real > MaxVal)
			yylval.Real = MaxVal;
	}
	else if(IntSign == ID_SIGNED)
	{
		if(yylval.Real >= ((MaxVal + 1.0) / 2))
			yylval.Real = -(MaxVal - yylval.Real + 1.0);
	}

	return(0);
}




/**********************************************************************/
/*                            Calc double                             */
/**********************************************************************/
int calc_dbl_value(char *s)
{
	char	*p;

	yylval.Real = strtod(s, &p);
	return(0);
}
