#ifdef MODULE
#include <linux/string.h>
#ifdef RTAI
#include <linux/kernel.h>
#include <linux/module.h>
#include "rtai.h"
#endif
#else
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#endif
#include "classicladder.h"
#include "global.h"
#include "vars_access.h"
#ifdef GTK_INTERFACE
#include "vars_names.h"
#endif
#include "arithm_eval.h"
char * Expr;
char * ErrorDesc;
char * VerifyErrorDesc;
int UnderVerify;
#if defined( MODULE )
int atoi(const char *p)
{
int n=0;
while(*p>='0' && *p<='9')
n = n*10 + *p++-'0';
return n;
}
#endif
int pow_int(int a,int b)
{
int x;
for (x=1;x<=b;x++)
a = a*a;
return a;
}
void SyntaxError(void)
{
if (UnderVerify)
VerifyErrorDesc = ErrorDesc;
else
debug_printf("Syntax error : '%s' , at %s !!!!!\n",ErrorDesc,Expr);
}
arithmtype Constant(void)
{
arithmtype Res = 0;
char cIsNeg = FALSE;
if ( *Expr=='-' )
{
cIsNeg = TRUE;
Expr++;
}
if (*Expr=='$' )
{
Expr++;
while( (*Expr>='0' && *Expr<='9') || (*Expr>='A' && *Expr<='F') || (*Expr>='a' && *Expr<='f') )
{
char Carac = *Expr;
if ( Carac>='A' && Carac<='F' )
Carac = Carac-'A'+10;
else
if ( Carac>='a' && Carac<='f' )
Carac = Carac-'a'+10;
else
Carac = Carac-'0';
Res = 16*Res + Carac;
Expr++;
}
}
else
{
while(*Expr>='0' && *Expr<='9')
{
Res = 10*Res + (*Expr-'0');
Expr++;
}
}
if ( cIsNeg )
Res = Res * -1;
return Res;
}
int IdentifyVarContent( char **PtrStartExpr, int * ResType,int * ResOffset )
{
int VarType,VarOffset;
char * StartExpr = *PtrStartExpr;
char * SearchSep = StartExpr;
do
{
SearchSep++;
}
while( (*SearchSep!='/') && (*SearchSep!='\0') );
if (*SearchSep=='/')
{
VarType = atoi(StartExpr);
SearchSep++;
StartExpr = SearchSep;
do
{
StartExpr++;
}
while( (*StartExpr!='@') && (*StartExpr!='[') && (*StartExpr!='\0') );
if (*StartExpr=='@' || *StartExpr=='[')
{
VarOffset = atoi(SearchSep);
*ResType = VarType;
*ResOffset = VarOffset;
*PtrStartExpr = StartExpr;
return TRUE;
}
else
{
ErrorDesc = "Bad var coding (err=2), should be @xx/yy@";
SyntaxError();
return FALSE;
}
}
else
{
ErrorDesc = "Bad var coding (err=1), should have a / for xx/yy form";
}
SyntaxError();
return FALSE;
}
int IdentifyVarIndexedOrNot(char *StartExpr,int * ResType,int * ResOffset, int * ResIndexType,int * ResIndexOffset)
{
int VarType,VarOffset;
char * ScanExpr = StartExpr;
if (*ScanExpr!='@')
{
ErrorDesc = "Bad var coding (err=0), should start with @ for @xx/yy@ form";
SyntaxError();
return FALSE;
}
ScanExpr++;
*ResIndexType = -1;
*ResIndexOffset = -1;
if ( IdentifyVarContent( &ScanExpr, &VarType, &VarOffset ) )
{
*ResType = VarType;
*ResOffset = VarOffset;
if ( *ScanExpr=='[')
{
ScanExpr++;
if ( IdentifyVarContent( &ScanExpr, &VarType, &VarOffset ) )
{
*ResIndexType = VarType;
*ResIndexOffset = VarOffset;
return TRUE;
}
}
else
{
return TRUE;
}
}
ErrorDesc = "Bad var coding (unknown variable)";
SyntaxError();
return FALSE;
}
int IdentifyFinalVar( char *StartExpr, int * ResType,int * ResOffset )
{
int IndexVarType,IndexVarOffset;
int SyntaxOk = IdentifyVarIndexedOrNot( StartExpr, ResType, ResOffset, &IndexVarType, &IndexVarOffset );
if ( SyntaxOk )
{
if ( IndexVarType!=-1 && IndexVarOffset!=-1 )
{
int IndexValue = ReadVar( IndexVarType, IndexVarOffset );
*ResOffset = *ResOffset + IndexValue;
}
}
return SyntaxOk;
}
arithmtype Variable(void)
{
int VarType,VarOffset;
if (IdentifyFinalVar(Expr, &VarType,&VarOffset))
{
Expr++;
do
{
Expr++;
}
while( (*Expr!='@') && (*Expr!='\0') );
Expr++;
return (arithmtype)ReadVar(VarType,VarOffset);
}
else
{
return 0;
}
}
arithmtype Function(void)
{
char tcFonc[ 20 ], *pFonc;
int Res = 0;
pFonc = tcFonc;
while((unsigned int)(pFonc-tcFonc)<sizeof(tcFonc)-1 && *Expr>='A' && *Expr<='Z')
{
*pFonc++ = *Expr;
Expr++;
}
*pFonc = '\0';
if ( !strcmp(tcFonc, "ABS") )
{
Expr++;
Res = Variable( );
if ( Res<0 )
Res = Res * -1;
Expr++;
return Res;
}
if ( !strcmp(tcFonc, "MINI") )
{
Res = 0x7FFFFFFF;
do
{
int iValVar;
Expr++;
iValVar = Variable( );
if ( iValVar<Res )
Res = iValVar;
}
while( *Expr!=')' );
Expr++;
return Res;
}
if ( !strcmp(tcFonc, "MAXI") )
{
Res = 0x80000000;
do
{
int iValVar;
Expr++;
iValVar = Variable( );
if ( iValVar>Res )
Res = iValVar;
}
while( *Expr!=')' );
Expr++;
return Res;
}
if ( !strcmp(tcFonc, "MOY") || !strcmp(tcFonc, "AVG") )
{
int NbrVars = 0;
do
{
int ValVar;
Expr++;
ValVar = Variable( );
NbrVars++;
Res = Res + ValVar;
}
while( *Expr!=')' );
Expr++;
Res = Res/NbrVars;
return Res;
}
ErrorDesc = "Unknown function";
SyntaxError();
return 0;
}
arithmtype Term(void)
{
if (*Expr=='(')
{
arithmtype Res;
Expr++;
Res = Or();
if (*Expr!=')')
{
ErrorDesc = "Missing parenthesis";
SyntaxError();
}
Expr++;
return Res;
}
else if ( (*Expr>='0' && *Expr<='9') || (*Expr=='$') || (*Expr=='-') )
return Constant();
else if (*Expr>='A' && *Expr<='Z')
return Function();
else if (*Expr=='@')
{
return Variable();
}
else if (*Expr=='!')
{
Expr++;
return Term()?0:1;
}
else
{
if (UnderVerify)
rtapi_print("TermERROR!_ExprHere=%s\n",Expr);
ErrorDesc = "Unknown term";
SyntaxError();
return 0;
}
return 0;
}
arithmtype Pow(void)
{
arithmtype Q,Res = Term();
while(*Expr=='^')
{
if ( ErrorDesc )
break;
Expr++;
Q = Pow();
Res = pow_int(Res,Q);
}
return Res;
}
arithmtype MulDivMod(void)
{
int Val=0;
arithmtype Res = Pow();
while(1)
{
if ( ErrorDesc )
break;
if (*Expr=='*')
{
Expr++;
Res = Res * Pow();
}
else
if (*Expr=='/')
{
Expr++;
Val = Pow();
if ( ErrorDesc==NULL )
Res = Res / Val;
}
else
if (*Expr=='%')
{
Expr++;
Val = Pow();
if ( ErrorDesc==NULL )
Res = Res % Val;
}
else
{
break;
}
}
return Res;
}
arithmtype AddSub(void)
{
arithmtype Res = MulDivMod();
while(1)
{
if ( ErrorDesc )
break;
if (*Expr=='+')
{
Expr++;
Res = Res + MulDivMod();
}
else
if (*Expr=='-')
{
Expr++;
Res = Res - MulDivMod();
}
else
{
break;
}
}
return Res;
}
arithmtype And(void)
{
arithmtype Res = AddSub();
while(1)
{
if ( ErrorDesc )
break;
if (*Expr=='&')
{
Expr++;
Res = Res & AddSub();
}
else
{
break;
}
}
return Res;
}
arithmtype Xor(void)
{
arithmtype Res = And();
while(1)
{
if ( ErrorDesc )
break;
if (*Expr=='^')
{
Expr++;
Res = Res ^ And();
}
else
{
break;
}
}
return Res;
}
arithmtype Or(void)
{
arithmtype Res = Xor();
while(1)
{
if ( ErrorDesc )
break;
if (*Expr=='|')
{
Expr++;
Res = Res | Xor();
}
else
{
break;
}
}
return Res;
}
arithmtype EvalExpression(char * ExprString)
{
arithmtype Res;
Expr = ExprString;
ErrorDesc = NULL;
Res = Or();
return Res;
}
int EvalCompare(char * CompareString)
{
char * FirstExpr,* SecondExpr = NULL;
char StrCopy[ARITHM_EXPR_SIZE+1];
char * SearchSep;
char * CutFirst;
int Found = FALSE;
int BoolRes = 0;
if (*CompareString=='\0' || *CompareString=='#')
return BoolRes;
strcpy(StrCopy,CompareString);
CutFirst = FirstExpr = StrCopy;
SearchSep = CompareString;
do
{
if ( (*SearchSep=='>') || (*SearchSep=='<') || (*SearchSep=='=') )
{
Found = TRUE;
*CutFirst = '\0';
CutFirst++;
SecondExpr = CutFirst;
if ( *CutFirst=='=' || *CutFirst=='>')
{
CutFirst++;
SecondExpr = CutFirst;
}
}
else
{
SearchSep++;
CutFirst++;
}
}
while (*SearchSep!='\0' && !Found);
if (Found)
{
arithmtype EvalFirst,EvalSecond;
EvalFirst = EvalExpression(FirstExpr);
EvalSecond = EvalExpression(SecondExpr);
if ( *SearchSep=='>' && EvalFirst>EvalSecond )
BoolRes = 1;
if ( *SearchSep=='<' && *(SearchSep+1)!='>' && EvalFirst<EvalSecond )
BoolRes = 1;
if ( *SearchSep=='<' && *(SearchSep+1)=='>' && EvalFirst!=EvalSecond )
BoolRes = 1;
if ( (*SearchSep=='=' || *(SearchSep+1)=='=') && EvalFirst==EvalSecond )
BoolRes = 1;
}
else
{
ErrorDesc = "Missing < or > or = or ... to make compare";
SyntaxError();
}
return BoolRes;
}
void MakeCalc(char * CalcString,int VerifyMode)
{
char StrCopy[ARITHM_EXPR_SIZE+1];
int TargetVarType,TargetVarOffset;
int Found = FALSE;
if (*CalcString=='\0' || *CalcString=='#')
return;
strcpy(StrCopy,CalcString);
Expr = StrCopy;
if (IdentifyFinalVar(Expr,&TargetVarType,&TargetVarOffset))
{
Expr++;
do
{
Expr++;
}
while( (*Expr!='@') && (*Expr!='\0') );
Expr++;
do
{
if (*Expr==':')
Expr++;
if (*Expr=='=')
{
Found = TRUE;
Expr++;
}
if (*Expr==' ')
Expr++;
}
while( !Found && *Expr!='\0' );
while( *Expr==' ')
Expr++;
if (Found)
{
arithmtype EvalExpr;
EvalExpr = EvalExpression(Expr);
if (!VerifyMode)
{
WriteVar(TargetVarType,TargetVarOffset,(int)EvalExpr);
}
#ifdef GTK_INTERFACE
else
{
if ( !TestVarIsReadWrite( TargetVarType, TargetVarOffset ) )
{
ErrorDesc = "Target variable must be read/write !";
SyntaxError();
}
}
#endif
}
else
{
ErrorDesc = "Missing := to make operate";
SyntaxError();
}
}
}
char * VerifySyntaxForEvalCompare(char * StringToVerify)
{
UnderVerify = TRUE;
VerifyErrorDesc = NULL;
EvalCompare(StringToVerify);
UnderVerify = FALSE;
return VerifyErrorDesc;
}
char * VerifySyntaxForMakeCalc(char * StringToVerify)
{
UnderVerify = TRUE;
VerifyErrorDesc = NULL;
MakeCalc(StringToVerify,TRUE );
UnderVerify = FALSE;
return VerifyErrorDesc;
}