summaryrefslogtreecommitdiff
path: root/src/core/xbexp.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/xbexp.cpp')
-rwxr-xr-xsrc/core/xbexp.cpp2661
1 files changed, 0 insertions, 2661 deletions
diff --git a/src/core/xbexp.cpp b/src/core/xbexp.cpp
deleted file mode 100755
index deea53d..0000000
--- a/src/core/xbexp.cpp
+++ /dev/null
@@ -1,2661 +0,0 @@
-/* xbexp.cpp
-
-XBase64 Software Library
-
-Copyright (c) 1997,2003,2014,2017,2021,2022 Gary A Kunkel
-
-The xb64 software library is covered under
-the terms of the GPL Version 3, 2007 license.
-
-Email Contact:
-
- XDB-devel@lists.sourceforge.net
- XDB-users@lists.sourceforge.net
-
-
-This module is part of the expression logic and has the code
-for parsing various tokens out of an expression
-
-*/
-
-#include "xbase.h"
-
-#ifdef XB_EXPRESSION_SUPPORT
-
-namespace xb{
-
-/*************************************************************************/
-//! Constructor
-/*!
- \param x Pointer to xbXBase instance.
-*/
-
-xbExp::xbExp( xbXBase *x ){
- xbase = x;
- dbf = NULL;
- nTree = NULL;
-}
-
-/*************************************************************************/
-//! Constructor
-/*!
- \param x Pointer to xbXBase instance.
- \param d Pointer to xbDbf instance.
-*/
-xbExp::xbExp( xbXBase *x, xbDbf *d ){
- xbase = x;
- dbf = d;
- nTree = NULL;
-}
-
-/*************************************************************************/
-//! Deconstrucor.
-
-xbExp::~xbExp() {
-
- if( nTree )
- delete nTree;
-}
-
-/*************************************************************************/
-//! Calulate expression return length
-/*!
-
- This function returns the maximum possible length of an expression
- The create index functions use this for determining the fixed length keys
- It sets the return length field in the node.
-
- \param n Start node
- \returns <a href="xbretcod_8h.html">Return Codes</a>
-*/
-
-xbInt16 xbExp::CalcFunctionResultLen( xbExpNode * n ) const{
-
- xbInt16 iRc = XB_NO_ERROR;
- xbInt16 iErrorStop = 0;
- xbInt16 iReturnLenCalc = 0;;
- xbInt32 lReturnLenVal = 0;
- xbString sNodeText;
-
-
- try{
-
- n->GetNodeText( sNodeText );
- char cReturnType = 0;
- if(( iRc = xbase->GetFunctionInfo( sNodeText, cReturnType, iReturnLenCalc, lReturnLenVal )) != XB_NO_ERROR ){
- iErrorStop = 100;
- throw iRc;
- }
-
- if( iReturnLenCalc == 1 ){
- // use the value from iReturnLenVal
- n->SetResultLen( (xbUInt32) lReturnLenVal );
- }
- else if( iReturnLenCalc == 2 ){
- // use the length from the child node identified in lReturnLenVal
- xbExpNode *nChild = n->GetChild( (xbUInt32) lReturnLenVal - 1 );
- if( !nChild ){
- iErrorStop = 110;
- iRc = XB_PARSE_ERROR;
- throw iRc;
- }
- n->SetResultLen( nChild->GetResultLen());
- }
-
- else if( iReturnLenCalc == 3 ){
- // use the length from the child node identified in lReturnLenVal
- xbExpNode *nChild = n->GetChild( (xbUInt32) lReturnLenVal - 1 );
- if( !nChild ){
- iErrorStop = 120;
- iRc = XB_PARSE_ERROR;
- throw iRc;
- }
- n->SetResultLen( (xbUInt32) nChild->GetNumericResult());
- }
- else if( iReturnLenCalc == 4 ){
- // use the value from the length in parm 1 multiplied by the value in parm 2 (REPLICATE)
- xbExpNode *nChild1 = n->GetChild( 0 );
- xbExpNode *nChild2 = n->GetChild( 1 );
- if( !nChild1 || !nChild2 ){
- iErrorStop = 130;
- iRc = XB_PARSE_ERROR;
- throw iRc;
- }
- n->SetResultLen( nChild1->GetResultLen() * (xbUInt32) nChild2->GetNumericResult());
- }
- else if( iReturnLenCalc == 5 ){
- // use the larger of the length of the value in parm2 or parm 3 (IIF statement)
- xbExpNode *nChild2 = n->GetChild( 1 );
- xbExpNode *nChild3 = n->GetChild( 2 );
- if( !nChild2 || !nChild3 ){
- iErrorStop = 140;
- iRc = XB_PARSE_ERROR;
- throw iRc;
- }
- if( nChild2->GetResultLen() >= nChild3->GetResultLen())
- n->SetResultLen( nChild2->GetResultLen());
- else
- n->SetResultLen( nChild3->GetResultLen());
- }
-
- else if( iReturnLenCalc == 6 ){
-
- if( n->GetChildCnt() >= 2 ){
- xbExpNode *nChild2 = n->GetChild( 1 );
- n->SetResultLen( (xbUInt32) nChild2->GetNumericResult());
- } else {
- n->SetResultLen( (xbUInt32) lReturnLenVal );
- }
-
- } else {
- iErrorStop = 150;
- iRc = XB_PARSE_ERROR;
- throw iRc;
- }
- }
- catch (xbInt16 iRc ){
- xbString sMsg;
- sMsg.Sprintf( "xbexp::GetFunctionResultLen() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc );
- xbase->WriteLogMessage( sMsg.Str() );
- }
- return iRc;
-}
-
-/*************************************************************************/
-//! Check parens and quotes
-/*!
- This routine looks for unbalanced parens and quotes
-
- \param sExpression Expression to examine.
- \returns <a href="xbretcod_8h.html">Return Codes</a>
-*/
-
-
-xbInt16 xbExp::CheckParensAndQuotes( const xbString &sExpression ){
-
-
- xbInt16 iRc = XB_NO_ERROR;
- xbInt16 iErrorStop = 0;
-
- xbBool bInQuotes = xbFalse;
- xbInt16 iLparenCtr = 0;
- xbInt16 iRparenCtr = 0;
- xbInt16 iQuoteType = 0;
- const char *s = sExpression;
-
- try{
-
- while( *s ){
- if( !bInQuotes ){
- if( *s == '(' ){
- iLparenCtr++;
- } else if( *s == ')' ){
- iRparenCtr++;
- } else if( *s == '\'' ){
- bInQuotes++;
- iQuoteType = 0;
- } else if( *s == '"' ){
- bInQuotes++;
- iQuoteType = 1;
- }
- } else {
- if(( *s == '\'' && iQuoteType == 0 ) || (*s == '"' && iQuoteType == 1 ))
- bInQuotes--;
- }
- s++;
- }
- if( iLparenCtr != iRparenCtr ){
- iErrorStop = 100;
- iRc = XB_UNBALANCED_PARENS;
- throw iRc;
- }
- if( bInQuotes ){
- iErrorStop = 110;
- iRc = XB_UNBALANCED_QUOTES;
- throw iRc;
- }
- }
- catch (xbInt16 iRc ){
- xbString sMsg;
- sMsg.Sprintf( "xbexp::CheckParensAndQuots() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc );
- xbase->WriteLogMessage( sMsg.Str() );
- xbase->WriteLogMessage( sExpression );
- }
- return iRc;
-}
-/*************************************************************************/
-//! Clear tree handle.
-/*!
- This routine clears the expression tree and frees any associated memory.
- \returns void.
-*/
-
-void xbExp::ClearTreeHandle(){
- if( nTree ){
- nTree = NULL;
- }
-}
-
-/*************************************************************************/
-#ifdef XB_DEBUG_SUPPORT
-//! Dump the tree.
-/*!
- \param iOption - Output opton.
- \returns void.
-*/
-
-void xbExp::DumpTree( xbInt16 iOption ){
- nTree->DumpNode( iOption );
-}
-
-//! Dump token
-/*!
- \param iOption - Output opton.
- \returns void.
-*/
-
-
-void xbExp::DumpToken( xbExpToken &t, xbInt16 iOption ){
-
- xbString sMsg;
- sMsg = "Processing Token";
- xbase->WriteLogMessage( sMsg.Str(), iOption );
-
- sMsg.Sprintf( "Expression = [%s]", t.sExpression.Str());
- xbase->WriteLogMessage( sMsg.Str(), iOption );
-
- sMsg.Sprintf( "Token = [%s]", t.sToken.Str());
- xbase->WriteLogMessage( sMsg.Str(), iOption );
-
- sMsg.Sprintf( "NodeType = [%c]", t.cNodeType );
- xbase->WriteLogMessage( sMsg.Str(), iOption );
-
- sMsg.Sprintf( "ReturnType = [%c]", t.cReturnType );
- xbase->WriteLogMessage( sMsg.Str(), iOption );
-
- sMsg.Sprintf( "Sts = [%d]", t.iSts );
- xbase->WriteLogMessage( sMsg.Str(), iOption );
-
- sMsg.Sprintf( "PrevNodeType = [%c]", t.cPrevNodeType );
- xbase->WriteLogMessage( sMsg.Str(), iOption );
-
- sMsg.Sprintf( "PrevReturnType = [%c]", t.cPrevReturnType );
- xbase->WriteLogMessage( sMsg.Str(), iOption );
-}
-
-#endif
-
-/*************************************************************************/
-//! Get date result.
-/*!
- If the expression generates a date return type, this method retrieves the date value.
- \param dtResult - Output date value.
- \returns <a href="xbretcod_8h.html">Return Codes</a>
-*/
-
-xbInt16 xbExp::GetDateResult( xbDate &dtResult ){
- if( nTree ){
- dtResult.JulToDate8( (xbInt32) nTree->GetNumericResult() );
- return XB_NO_ERROR;
- }
- else{
- //dtResult = ?;
- return XB_PARSE_ERROR;
- }
-}
-/*************************************************************************/
-//! Get bool result.
-/*!
- If the expression generates a boolean return type, this method retrieves the boolean value.
- \param bResult - Output boolean value.
- \returns <a href="xbretcod_8h.html">Return Codes</a>
-*/
-xbInt16 xbExp::GetBoolResult( xbBool &bResult){
- if( nTree ){
- bResult = nTree->GetBoolResult();
- return XB_NO_ERROR;
- }
- else{
- return XB_PARSE_ERROR;
- }
-}
-
-/*************************************************************************/
-//! Get the next node in the tree.
-/*!
- \param n Node to starting point. To get the first node of the entire tree, set n = NULL
- \returns Pointer to next node.
-*/
-
-xbExpNode *xbExp::GetNextNode( xbExpNode * n ) const {
-
- // to get the first node of the entire tree, set n = NULL
- // std::cout << "In GetNextNode\n";
-
- if( n == nTree )
- return NULL;
-
- else if( !n ){
- if( !nTree )
- return NULL;
- else
- return nTree->GetFirstNode();
- }
- return n->GetNextNode();
-}
-
-/*************************************************************************/
-//! GetNextToken
-/*! This method returns the next token in an expression of one or more tokens
- \param t Token
- \returns <a href="xbretcod_8h.html">Return Codes</a>
-*/
-
-xbInt16 xbExp::GetNextToken( xbExpToken &t ){
-
- xbInt16 iRc = XB_NO_ERROR;
- xbInt16 iErrorStop = 0;
-
- try{
- t.iSts = XB_NO_ERROR;
- t.sExpression.Ltrim();
-
- if( t.sExpression.Len() == 0 ){
- t.iSts = XB_END_OF_EXPRESSION;
- return XB_NO_ERROR;
- }
-
- // Check for date constant
- if((t.sExpression.Len() >= 10 && t.sExpression[1] == '{' && t.sExpression[4] == '/' && t.sExpression[7] == '/') &&
- (t.sExpression[10] == '}' || (t.sExpression.Len() >= 12 && t.sExpression[12] == '}'))){
- if(( iRc = GetTokenDateConstant( t )) != XB_NO_ERROR ){
- iErrorStop = 100;
- throw iRc;
- }
- }
- // Check for parens
- else if( t.sExpression[1] == '(' || t.sExpression[1] == '{' ){
- if(( iRc = GetTokenParen( t )) != XB_NO_ERROR ){
- iErrorStop = 110;
- throw iRc;
- }
- }
- // Check for a char constant
- else if( t.sExpression[1] == '"' || t.sExpression[1] == '\'' ){
- if(( iRc = GetTokenCharConstant( t )) != XB_NO_ERROR ){
- iErrorStop = 120;
- iRc = XB_PARSE_ERROR;
- throw iRc;
- }
- }
- // Check for logical constant
- else if( IsLogicalConstant( t.sExpression )){
- if(( iRc = GetTokenLogicalConstant( t )) != XB_NO_ERROR ){
- iErrorStop = 130;
- iRc = XB_PARSE_ERROR;
- throw iRc;
- }
- }
- // check for numeric constant
- else if( IsNumericConstant( t.sExpression, t.cPrevNodeType )){
- if(( iRc = GetTokenNumericConstant( t )) != XB_NO_ERROR ){
- iErrorStop = 140;
- iRc = XB_PARSE_ERROR;
- throw iRc;
- }
- }
- // check for operator
- else if( IsOperator( t.sExpression )){
- if(( iRc = GetTokenOperator( t )) != XB_NO_ERROR ){
- iErrorStop = 150;
- iRc = XB_PARSE_ERROR;
- throw iRc;
- }
- }
- // check for function
- else if( IsFunction( t.sExpression, t.cReturnType )){
- if(( iRc = GetTokenFunction( t )) != XB_NO_ERROR ){
- iErrorStop = 160;
- iRc = XB_PARSE_ERROR;
- throw iRc;
- }
- }
- else if(( iRc = GetTokenDatabaseField( t )) != XB_NO_ERROR ){
- iErrorStop = 170;
- iRc = XB_PARSE_ERROR;
- throw iRc;
- }
- }
-
- catch (xbInt16 iRc ){
- xbString sMsg;
- sMsg.Sprintf( "xbexp::GetNextToken() Exception Caught. Error Stop = [%d] iRc = [%d] Expression = [%s]", iErrorStop, iRc, t.sExpression.Str() );sMsg.Sprintf( "xbexp::GetNextToken() Exception Caught. Error Stop = [%d] iRc = [%d] Expression = [%s]", iErrorStop, iRc, t.sExpression.Str() );sMsg.Sprintf( "xbexp::GetNextToken() Exception Caught. Error Stop = [%d] iRc = [%d] Expression = [%s]", iErrorStop, iRc, t.sExpression.Str() );sMsg.Sprintf( "xbexp::GetNextToken() Exception Caught. Error Stop = [%d] iRc = [%d] Expression = [%s]", iErrorStop, iRc, t.sExpression.Str() );
- xbase->WriteLogMessage( sMsg.Str() );
- }
- return iRc;
-}
-
-/*************************************************************************/
-//! Get numeric result.
-/*!
- If the expression generates a numeric return type, this method retrieves the numeric value.
- \param dResult - Output numeric value.
- \returns <a href="xbretcod_8h.html">Return Codes</a>
-*/
-
-xbInt16 xbExp::GetNumericResult( xbDouble &dResult){
- if( nTree ){
- dResult = nTree->GetNumericResult();
- return XB_NO_ERROR;
- }
- else{
- dResult = 0;
- return XB_PARSE_ERROR;
- }
-}
-/*************************************************************************/
-//! Get result length.
-/*!
- This routine returns the result length.
- \returns Result length.
-*/
-
-xbInt16 xbExp::GetResultLen() const{
- if( nTree )
- return nTree->GetResultLen();
- else
- return 0;
-}
-
-/*************************************************************************/
-//! Get return type.
-/*!
- \returns Expression return type.
-*/
-
-char xbExp::GetReturnType() const{
- if( nTree )
- return nTree->GetReturnType();
- else
- return ' ';
-}
-
-/*************************************************************************/
-//! Get string result.
-/*!
- If the expression generates a string return type, this method retrieves the string value.
- \param sResult - Output string value.
- \returns <a href="xbretcod_8h.html">Return Codes</a>
-*/
-
-xbInt16 xbExp::GetStringResult( xbString &sResult){
- if( nTree ){
- sResult = nTree->GetStringResult();
- return XB_NO_ERROR;
- }
- else{
- sResult = "";
- return XB_PARSE_ERROR;
- }
-}
-
-/*************************************************************************/
-//! Get string result.
-/*!
- If the expression generates a string return type, this method retrieves the string value.
- \param vpResult - Pointer to user supplied buffer for result.
- \param ulLen - Max size of buffer.
- \returns <a href="xbretcod_8h.html">Return Codes</a>
-*/
-
-
-xbInt16 xbExp::GetStringResult( char * vpResult, xbUInt32 ulLen ){
- if( nTree ){
- nTree->GetStringResult().strncpy((char *) vpResult, ulLen );
- return XB_NO_ERROR;
- }
- else{
- return XB_PARSE_ERROR;
- }
-}
-
-
-
-/*************************************************************************/
-//! GetTokenCharConstant
-/*! This method returns the character constant in a pair of quotes
-
- This routine returns the tokens inside a set of matching quotes in sOutToken
- If there is nothing between the quotes then sOutToken is returned empty
- sOutRemainder contains whatever remains to the right of the right quote
-
- \param t Token
- \returns <a href="xbretcod_8h.html">Return Codes</a>
-
-*/
-
-xbInt16 xbExp::GetTokenCharConstant( xbExpToken &t ){
-
- const char *s = t.sExpression;
- const char *sToken; // pointer to beginning of token
- xbInt16 iQuoteType;
- xbUInt32 ulTokenLen = 0;
- xbInt16 iRc = XB_NO_ERROR;
- xbInt16 iErrorStop = 0;
- xbBool bDone = xbFalse;
-
- try{
- if( *s == '"' )
- iQuoteType = 0;
- else
- iQuoteType = 1;
- s++;
- sToken = s;
- while( *s && !bDone ){
- if(( *s == '"' && iQuoteType == 0 ) || (*s == '\'' && iQuoteType == 1 ))
- bDone = xbTrue;
- s++;
- ulTokenLen++;
- }
- if( bDone ){ // found matching paren
- t.cNodeType = XB_EXP_CONSTANT;
- t.cReturnType = XB_EXP_CHAR;
- t.sToken.Set( sToken, ulTokenLen - 1 );
- t.sExpression.Ltrunc( ulTokenLen + 1 );
- } else {
- iRc = XB_PARSE_ERROR;
- t.iSts = XB_UNBALANCED_QUOTES;
- iErrorStop = 100;
- throw iRc;
- }
- }
- catch (xbInt16 iRc ){
- xbString sMsg;
- sMsg.Sprintf( "xbexp::GetTokenCharConstant() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc );
- xbase->WriteLogMessage( sMsg.Str() );
- }
- return iRc;
-}
-
-
-/*************************************************************************/
-//! GetTokenDateConstant
-/*! This method returns the date constant in a pair of {}
-
- Date format is one of {mm/dd/yy} or {mm/dd/yyyy}
- \param t Token.
- \returns <a href="xbretcod_8h.html">Return Codes</a>
-*/
-
-xbInt16 xbExp::GetTokenDateConstant( xbExpToken &t ){
-
- xbInt16 iRc = XB_NO_ERROR;
- xbInt16 iErrorStop = 0;
- char wBuf[13];
- xbDate dt;
-
- try{
- memset( wBuf, 0x00, 13 );
- t.cNodeType = XB_EXP_CONSTANT;
- t.cReturnType = XB_EXP_DATE;
-
- if( t.sExpression[10] == '}' ){
- for( xbInt16 i = 0; i < 8; i++ )
- wBuf[i] = t.sExpression[i+2];
-
- if(( iRc = dt.CTOD( wBuf )) != XB_NO_ERROR ){
- iErrorStop = 100;
- throw iRc;
- }
- t.sToken.Set( dt.Str() );
- t.sExpression.Ltrunc( 10 );
-
- } else if( t.sExpression[12] == '}' ){
-
- wBuf[0] = t.sExpression[8];
- wBuf[1] = t.sExpression[9];
- wBuf[2] = t.sExpression[10];
- wBuf[3] = t.sExpression[11];
- wBuf[4] = t.sExpression[2];
- wBuf[5] = t.sExpression[3];
- wBuf[6] = t.sExpression[5];
- wBuf[7] = t.sExpression[6];
-
- t.sToken.Set( wBuf );
- t.sExpression.Ltrunc( 12 );
- } else {
- iRc = XB_PARSE_ERROR;
- t.iSts = XB_INVALID_DATE;
- iErrorStop = 110;
- throw iRc;
- }
- }
- catch (xbInt16 iRc ){
- xbString sMsg;
- sMsg.Sprintf( "xbexp::GetTokenDateConstant() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc );
- xbase->WriteLogMessage( sMsg.Str() );
- }
- return iRc;
-}
-/*************************************************************************/
-//! GetTokenField
-/*! This method gets a database field token
-
- Looks for a xbase field in one of the following formats
-
- FIELDNAME
- or
- TABLENAME->FIELDNAME
-
- \param t Token.
- \returns <a href="xbretcod_8h.html">Return Codes</a>
-*/
-
-xbInt16 xbExp::GetTokenDatabaseField( xbExpToken &t ){
-
- const char *s = t.sExpression;
- xbUInt32 ulTokenLen = 0;
- xbUInt32 ulTokenLen2 = 0;
-
- while( *s && !IsTokenSeparator( *s ) && !IsWhiteSpace( *s )) {
- ulTokenLen++;
- s++;
- }
-
- // go past any white space
- while( *s && !IsTokenSeparator( *s ) && IsWhiteSpace( *s )) {
- ulTokenLen2++;
- s++;
- }
-
- // look for ->
- // remove the table name from before the ->
- if( strncmp( s, "->", 2 ) == 0 ){
- ulTokenLen2+=2;
- s+=2;
-
-/*
- if( strncmp( s, "->", 2 ) == 0 || strncmp( s, ".", 1 ) == 0){
- if( *s == '.' ){
- ulTokenLen2+=1;
- s+=1;
- } else {
- ulTokenLen2+=2;
- s+=2;
- }
-*/
-
- // go past white space
- while( *s && !IsTokenSeparator( *s ) && IsWhiteSpace( *s )) {
- ulTokenLen2++;
- s++;
- }
- // go to the end
- while( *s && !IsTokenSeparator( *s ) && !IsWhiteSpace( *s )) {
- ulTokenLen2++;
- s++;
- }
- ulTokenLen += ulTokenLen2;
- }
- t.cNodeType = XB_EXP_FIELD;
- t.cReturnType = XB_EXP_UNKNOWN;
- t.sToken.Set( t.sExpression, ulTokenLen );
- t.sExpression.Ltrunc( ulTokenLen );
-
- return XB_NO_ERROR;
-}
-
-/*************************************************************************/
-//! GetTokenFunction
-/*!
- This method gets a function and everything between the following quotes
- \param t Token
- \returns <a href="xbretcod_8h.html">Return Codes</a>
-
-*/
-
-xbInt16 xbExp::GetTokenFunction( xbExpToken &t ){
-
- xbUInt32 lPos = t.sExpression.Pos( '(' );
- if( lPos == 0 )
- return XB_PARSE_ERROR;
-
- xbBool bDone = xbFalse;
- xbUInt32 lLen = t.sExpression.Len();
- xbInt16 iDepthCtr = 1;
-
- while( ++lPos <= lLen && !bDone ){
- if( t.sExpression[lPos] == ')' ){
- iDepthCtr--;
- if( iDepthCtr == 0 )
- bDone = xbTrue;
- } else if( t.sExpression[lPos] == '(' ){
- iDepthCtr++;
- }
- }
-
- t.cNodeType = XB_EXP_FUNCTION;
- t.sToken.Set( t.sExpression, lPos-1 );
- t.sExpression.Ltrunc( lPos-1 );
-
-// std::cout << "lPos = [" << lPos << "] done= [" << bDone << "][" << t.sExpression << "] len=[" << lLen << "] return type = [" << t.cReturnType << "]\n";
-
- return XB_NO_ERROR;
-}
-
-/*************************************************************************/
-//! GetTokenCharConstant
-/*! This method returns the character constant in a pair of quotes
-
- This routine returns the tokens inside a set of matching quotes in sOutToken
- If there is nothing between the quotes then sOutToken is returned empty
- sOutRemainder contains whatever remains to the right of the right quote
-
- \param t Token
- \returns <a href="xbretcod_8h.html">Return Codes</a>
-*/
-
-xbInt16 xbExp::GetTokenLogicalConstant( xbExpToken &t ){
-
- t.cNodeType = XB_EXP_CONSTANT;
- t.cReturnType = XB_EXP_LOGICAL;
- t.sToken = t.sExpression[2];
-
- if( t.sExpression[3] == '.' )
- t.sExpression.Ltrunc( 3 );
- else if( t.sExpression[6] == '.' )
- t.sExpression.Ltrunc( 6 );
- else if( t.sExpression[7] == '.' )
- t.sExpression.Ltrunc( 7 );
-
- return XB_NO_ERROR;
-}
-
-
-/*************************************************************************/
-//! GetTokenNumericConstant
-/*! This method returns a numeric constant in
-
- This routine returns a numeric constant token
- sOutRemainder contains whatever remains to the right of the right quote
-
- \param t Token
- \returns <a href="xbretcod_8h.html">Return Codes</a>
-*/
-
-xbInt16 xbExp::GetTokenNumericConstant( xbExpToken &t ){
-
- const char * s = t.sExpression;
- xbUInt32 ulTokenLen = 0;
- t.sToken = "";
-
- t.cNodeType = XB_EXP_CONSTANT;
- t.cReturnType = XB_EXP_NUMERIC;
-
- // capture the leading sign
- if( *s == '-' || *s == '+' || *s == '.' ){
- t.sToken = *s;
- ulTokenLen++;
- s++;
-
- // go past any white space between sign and number
- while( *s && IsWhiteSpace( *s )){
- s++;
- ulTokenLen++;
- }
- }
-
- // add the number to the token
- while( *s && (isdigit( *s ) || *s == '.' )){
- t.sToken += *s;
- s++;
- ulTokenLen++;
- }
- t.sExpression.Ltrunc( ulTokenLen );
- return XB_NO_ERROR;
-}
-
-/*************************************************************************/
-//! GetTokenOperator
-/*! This method returns the operator
-
- \param t Token
- \returns <a href="xbretcod_8h.html">Return Codes</a>
-
-*/
-
-xbInt16 xbExp::GetTokenOperator( xbExpToken &t ){
-
- const char *s = t.sExpression;
-
- // Logical operators
- if((strncmp( s, "<>", 2 ) == 0 ) || (strncmp( s, "!=", 2 ) == 0 ) ||
- (strncmp( s, "<=", 2 ) == 0 ) || (strncmp( s, ">=", 2 ) == 0 )){
- t.cReturnType = XB_EXP_LOGICAL;
- t.sToken.Assign( s, 1, 2 );
- t.sExpression.Ltrunc( 2 );
- t.cNodeType = XB_EXP_OPERATOR;
- return XB_NO_ERROR;
- }
-
- if( *s == '=' || *s == '<' || *s == '>' || *s == '$' || *s == '#' ){
- t.cReturnType = XB_EXP_LOGICAL;
- t.sToken.Assign( s, 1, 1 );
- t.sExpression.Ltrunc( 1 );
- t.cNodeType = XB_EXP_OPERATOR;
- return XB_NO_ERROR;
- }
-
- if( (strncmp( s, ".NOT.", 5 ) == 0 ) || (strncmp( s, ".AND.", 5 ) == 0 )){
- t.cReturnType = XB_EXP_LOGICAL;
- t.sToken.Assign( s, 1, 5 );
- t.sExpression.Ltrunc( 5 );
- t.cNodeType = XB_EXP_OPERATOR;
- return XB_NO_ERROR;
- }
-
- if( (strncmp( s, "NOT ", 4 ) == 0 ) || (strncmp( s, "AND ", 4 ) == 0 )){
- t.cReturnType = XB_EXP_LOGICAL;
- t.sToken.Assign( s, 1, 3 );
- t.sExpression.Ltrunc( 3 );
- t.cNodeType = XB_EXP_OPERATOR;
- return XB_NO_ERROR;
- }
-
- if( strncmp( s, ".OR.", 4 ) == 0 ) {
- t.cReturnType = XB_EXP_LOGICAL;
- t.sToken.Assign( s, 1, 4 );
- t.sExpression.Ltrunc( 4 );
- t.cNodeType = XB_EXP_OPERATOR;
- return XB_NO_ERROR;
- }
-
- if( strncmp( s, "OR ", 3 ) == 0 ) {
- t.cReturnType = XB_EXP_LOGICAL;
- t.sToken.Assign( s, 1, 2 );
- t.sExpression.Ltrunc( 2 );
- t.cNodeType = XB_EXP_OPERATOR;
- return XB_NO_ERROR;
- }
-
- // Numeric operators
- if(( strncmp( s, "**", 2 ) == 0 ) || ( strncmp( s, "+=", 2 ) == 0 ) ||
- ( strncmp( s, "-=", 2 ) == 0 ) || ( strncmp( s, "*=", 2 ) == 0 ) || ( strncmp( s, "/=", 2 ) == 0 )){
- t.cReturnType = XB_EXP_NUMERIC;
- t.sToken.Assign( s, 1, 2 );
- t.sExpression.Ltrunc( 2 );
- t.cNodeType = XB_EXP_OPERATOR;
- return XB_NO_ERROR;
- }
-
- // Pre/post increment/decrement operators ++ or --
- if(( strncmp( s, "--", 2 ) == 0 ) || ( strncmp( s, "++", 2 ) == 0 )){
- t.cReturnType = XB_EXP_NUMERIC;
- t.sToken.Assign( s, 1, 2 );
- t.sExpression.Ltrunc( 2 );
- if( t.sExpression.Len() > 0 && (isdigit( t.sExpression[1] ) || isalpha( t.sExpression[1] )))
- t.cNodeType = XB_EXP_PRE_OPERATOR;
- else
- t.cNodeType = XB_EXP_POST_OPERATOR;
-
- return XB_NO_ERROR;
- }
-
- if( *s == '*' || *s == '/' || *s == '%' || *s == '^' ){
- t.cReturnType = XB_EXP_NUMERIC;
- t.sToken.Assign( s, 1, 1 );
- t.sExpression.Ltrunc( 1 );
- t.cNodeType = XB_EXP_OPERATOR;
- return XB_NO_ERROR;
- }
-
- // multi return type operators
- t.cReturnType = XB_EXP_UNKNOWN;
- if( *s == '+' || *s == '-' ){
- t.sToken.Assign( s, 1, 1 );
- t.sExpression.Ltrunc( 1 );
- t.cNodeType = XB_EXP_OPERATOR;
- return XB_NO_ERROR;
- }
- return XB_PARSE_ERROR;
-}
-
-/*************************************************************************/
-//! GetTokenParen
-/*! This method returns the tokens in a pair of enclosed parens
-
- This routine returns the tokens inside a set of matching parens in sOutToken
- If there is nothing between the parens then sOutToken is returned empty
- sOutRemainder contains whatever remains to the right of the right paren
-
- \param t Token
- \returns <a href="xbretcod_8h.html">Return Codes</a>
-*/
-
-
-xbInt16 xbExp::GetTokenParen( xbExpToken &t ){
-
- const char * s = t.sExpression;
- const char * sToken; // pointer to beginning of token
- xbInt16 iParenType = 0;
- xbInt16 iRc = XB_NO_ERROR;
- xbInt16 iErrorStop = 0;
- xbInt16 iDepthCtr = 0; // depth inside of nested parens
- xbUInt32 ulTokenLen = 0;
- xbBool bDone = xbFalse;
-
- try{
- if( *s == '{' )
- iParenType = 0;
- else
- iParenType = 1;
- iDepthCtr = 1;
- s++;
- sToken = s;
-
- while( *s && !bDone ){
- if(( *s == ')' && iParenType == 1 ) || (*s == '}' && iParenType == 0 )){
- iDepthCtr--;
- if( iDepthCtr == 0 )
- bDone = xbTrue;
- } else if(( *s == '(' && iParenType == 1 ) || (*s == '{' && iParenType == 0 )){
- iDepthCtr++;
- }
- s++;
- ulTokenLen++;
- }
-
- if( bDone ){ // found matching paren
- t.cNodeType = XB_EXP_NOTROOT;
- t.cReturnType = XB_EXP_UNKNOWN;
- t.sToken.Set( sToken, ulTokenLen - 1 );
- t.sExpression.Ltrunc( ulTokenLen + 1 );
- } else {
- t.sToken = "";
- t.cNodeType = XB_EXP_NOTROOT;
- t.cReturnType = XB_EXP_UNKNOWN;
- t.iSts = XB_UNBALANCED_PARENS;
- iRc = XB_PARSE_ERROR;
- iErrorStop = 100;
- throw iRc;
- }
- }
- catch (xbInt16 iRc ){
- xbString sMsg;
- sMsg.Sprintf( "xbexp::GetTokenParen() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc );
- xbase->WriteLogMessage( sMsg );
- }
- return iRc;
-}
-
-/*************************************************************************/
-//! Get the expression tree handle.
-/*!
- \returns Pointer to the top most node in the expression tree.
-*/
-xbExpNode *xbExp::GetTreeHandle(){
- return nTree;
-}
-
-/*************************************************************************/
-//! Is Function
-/*! This method determines if the next token is a function.
-
- \param sExpression - String expression to be evaluated.
- \param cReturnType Output - Return type.
- \returns xbTrue - Is a function.<br>
- xbFalse - Is not a function.
-*/
-
-xbBool xbExp::IsFunction( const xbString & sExpression, char &cReturnType ){
-
- xbInt16 i = 0;
- xbInt32 l = 0;
- if( sExpression.Pos( '(' ) > 0 ){
- if( xbase->GetFunctionInfo( sExpression, cReturnType, i, l ) == XB_NO_ERROR )
- return xbTrue;
- }
- return xbFalse;
-}
-
-/*************************************************************************/
-//! Is Logical constant
-/*! This method determines if the next token is a logical constant (T/F, etc).
-
- \param sExpression - String expression to be evaluated.
- \returns xbTrue - Is a logical constant.<br>
- xbFalse - Is not a logical constant.
-*/
-
-xbBool xbExp::IsLogicalConstant( const xbString & sExpression ){
-
- const char *s = sExpression;
- if(( strncmp( s, ".T.", 3 ) == 0 ) || ( strncmp( s, ".F.", 3 ) == 0 ))
- return xbTrue;
- else if( strncmp( s, ".TRUE.", 6 ) == 0 )
- return xbTrue;
- else if( strncmp( s, ".FALSE.", 7 ) == 0 )
- return xbTrue;
-
- return xbFalse;
-}
-
-/*************************************************************************/
-//! Is Numeric constant
-/*! This method determines if the next token is a numeric constant.
-
- \param sExpression - String expression to be evaluated.
- \param cPrevNodeType - Type of previous node.
- \returns xbTrue - Is a numeric constant.<br>
- xbFalse - Is not a numeric constant.
-*/
-xbBool xbExp::IsNumericConstant( const xbString & sExpression, char cPrevNodeType ){
-
- // check for positive, negative or decimal number constants
-
- const char *s = sExpression;
- if(( *s == '-' && ( cPrevNodeType == 'O' || cPrevNodeType == 0 )) ||
- ( *s == '+' && ( cPrevNodeType == 'O' || cPrevNodeType == 0 ))){
- s++;
- while( *s && IsWhiteSpace( *s ))
- s++;
- }
- if( *s == '.' )
- s++;
-
- if( isdigit( *s ))
- return xbTrue;
- else
- return xbFalse;
-}
-
-/*************************************************************************/
-//! Is Operator.
-/*! This method determines if the next token is an operator.
-
- \param sExpression - String expression to be evaluated.
- \returns xbTrue - Is an operator.<br>
- xbFalse - Is not an operator.
-*/
-xbBool xbExp::IsOperator( const xbString & sExpression ){
-
- const char *s = sExpression;
- if( *s == '+' || *s == '-' || *s == '/' || *s == '^' || *s == '=' || *s == '$' ||
- *s == '#' || *s == '*' || *s == '<' || *s == '>' || *s == '%' )
- return xbTrue;
-
- if( strncmp( s, "!=", 2 ) == 0 )
- return xbTrue;
-
- if((strncmp( s, ".NOT.", 5 ) == 0 ) || (strncmp( s, ".OR.", 4 ) == 0 ) || (strncmp( s, ".AND.", 5 ) == 0 ))
- return xbTrue;
-
- if((strncmp( s, "NOT ", 4 ) == 0 ) || (strncmp( s, "OR ", 3 ) == 0 ) || (strncmp( s, "AND ", 4 ) == 0 ))
- return xbTrue;
-
- return xbFalse;
-}
-
-/*************************************************************************/
-//! Is Token seperator
-/*! This method determines if the next token is a seperator.
-
- \param sExpression - String expression to be evaluated.
- \returns xbTrue - Is a token seperator.<br>
- xbFalse - Is not a token seperator.
-*/
-char xbExp::IsTokenSeparator( char c ){
- if( c == '-' || c == '+' || c == '*' || c == '/' || c == '$' || c == '#' ||
- c == '<' || c == '>' || c == '^' || c == '=' || c == '.' || c == '!' )
- return c;
- else
- return 0;
-}
-/*************************************************************************/
-//! Is White space
-/*! This method determines if a given character is white space.
-
- \param c - Character to be evaluated.
- \returns xbTrue - Is white space.<br>
- xbFalse - Is not white space.
-*/
-xbBool xbExp::IsWhiteSpace( char c ){
- return(( c == 0x20 )? 1 : 0 );
-}
-
-/*************************************************************************/
-//! Get operator weight.
-/*!
- This method determines the priority of an operator
-
- Operator precendence
- 10 .AND. .OR. .NOT. (not really an operator)
- 9 > or < (includes <= or >=)
- 6 unary plus or minus (+,-) -- not passed this routine
- 5 prefix increment and/or decrement (++,--)
- 4 exponentiation ** or ^
- 3 multiplication,division or modulus (*,/,%)
- 2 Addition, subtraction (+,-)
- 1 Postfix increment and/or decrement (++,--)
-
- \param sOper - Operator.
- \returns Operator weight
-
-*/
-
-xbInt16 xbExp::OperatorWeight( const xbString &sOper ){
-
- if( sOper == "" || sOper.Len() > 5 )
- return 0;
-
- else if( sOper == "--0" || sOper == "++0" ) // 0 is prefix
- return 9;
- else if( sOper == "**" || sOper == "^" )
- return 8;
- else if( sOper == "*" || sOper == "/" || sOper == "%" || sOper == "*=" || sOper == "/=" )
- return 7;
- else if( sOper == "+" || sOper == "-" || sOper == "+=" || sOper == "-=" )
- return 6;
- else if( sOper == "--1" || sOper == "++1" ) // 1 is post fix
- return 5;
- else if( sOper == ">" || sOper == ">=" || sOper == "<" || sOper == "<=" ||
- sOper == "<>" || sOper == "!=" || sOper == "#" || sOper == "$" || sOper == "=" )
- return 4;
- else if( sOper == ".NOT." || sOper == "NOT" )
- return 3;
- else if( sOper == ".AND." || sOper == "AND" )
- return 2;
- else if( sOper == ".OR." || sOper == "OR" )
- return 1;
-
- return 0;
-}
-
-
-/*************************************************************************/
-//! Parse expression.
-/*!
- \param sExpression - Expression to parse.
- \returns <a href="xbretcod_8h.html">Return Codes</a>
-*/
-
-xbInt16 xbExp::ParseExpression( const xbString &sExpression ){
- return ParseExpression( sExpression, (xbInt16) 0 );
-}
-
-/*************************************************************************/
-//! Parse expression.
-/*!
- \param dbf - Pointer to xbDbf instance.
- \param sExpression - Expression to parse.
- \returns <a href="xbretcod_8h.html">Return Codes</a>
-*/
-
-xbInt16 xbExp::ParseExpression( xbDbf *dbf, const xbString &sExpression ){
- this->dbf = dbf;
- return ParseExpression( sExpression, (xbInt16) 0 );
-}
-
-/*************************************************************************/
-//! Parse expression.
-/*!
- \param sExpression - Expression to parse.
- \param iWeight.
- \returns <a href="xbretcod_8h.html">Return Codes</a>
-*/
-xbInt16 xbExp::ParseExpression( const xbString &sExpression, xbInt16 iWeight ){
-
- xbExpNode *n;
- xbExpNode *nLastNode = NULL; // pointer to the last node processed
- xbExpToken t;
- xbInt16 iRc = XB_NO_ERROR;
- xbInt16 iErrorStop = 0;
- xbString s;
-
- try {
-
- if( nTree )
- delete nTree;
-
- if(( iRc = CheckParensAndQuotes( sExpression )) != XB_NO_ERROR ){
- iErrorStop = 100;
- throw iRc;
- }
-
- t.sExpression = sExpression;
-
- xbString sOriginalExp;
- while( t.iSts == XB_NO_ERROR && iRc == XB_NO_ERROR ){
-
- sOriginalExp = t.sExpression; // test code
- iRc = GetNextToken( t );
- if( !iRc && !t.iSts ){
-
- // comment / uncomment debug / live
- // DumpToken( t, 0 );
-
- if( t.cNodeType == XB_EXP_NOTROOT ){
- xbExp enr( xbase, dbf );
- if(( iRc = enr.ParseExpression( t.sToken, iWeight + 10 )) != XB_NO_ERROR ){
- iErrorStop = 110;
- throw iRc;
- }
- n = enr.GetTreeHandle();
- enr.ClearTreeHandle();
-
- } else {
-
- switch( t.cNodeType ) {
-
- case XB_EXP_CONSTANT:
- n = new xbExpNode( t.sToken, t.cNodeType );
- if(( iRc = ParseExpressionConstant( t, n )) != XB_NO_ERROR ){
- iErrorStop = 120;
- throw iRc;
- }
- break;
-
- case XB_EXP_FUNCTION:
- n = new xbExpNode( t.cNodeType );
- if(( iRc = ParseExpressionFunction( t, n, iWeight )) != XB_NO_ERROR ){
- iErrorStop = 130;
- throw iRc;
- }
- break;
-
- case XB_EXP_FIELD:
- n = new xbExpNode( t.cNodeType );
- if(( iRc = ParseExpressionField( t, n )) != XB_NO_ERROR ){
- iErrorStop = 140;
- throw iRc;
- }
- break;
-
- case XB_EXP_OPERATOR:
- case XB_EXP_PRE_OPERATOR:
- case XB_EXP_POST_OPERATOR:
- n = new xbExpNode( t.sToken, t.cNodeType );
- if(( iRc = ParseExpressionOperator( t, n, iWeight )) != XB_NO_ERROR ){
- iErrorStop = 150;
- throw iRc;
- }
- break;
-
- default:
- iErrorStop = 160;
- iRc = XB_PARSE_ERROR;
- throw iRc;
- // break;
- }
- }
- t.cPrevNodeType = t.cNodeType;
- t.cPrevReturnType = t.cReturnType;
-
- // determine where in the expression tree to insert the latest node "n"
- // Is this the first node to be added to the tree?
- if( !nTree ){
- nTree = n;
- }
-
- // else if last node was XB_EXB_PRE_OPERATOR then append this as child to last node
- else if( nLastNode && nLastNode->GetNodeType() == XB_EXP_PRE_OPERATOR ){
- n->SetParent( nLastNode );
- nLastNode->AddChild( n );
- }
-
- // else if last node was XB_EXB_POST_OPERATOR then append this as child to last node
- else if( nLastNode && n->GetNodeType() == XB_EXP_POST_OPERATOR ){
- n->AddChild( nLastNode );
- nLastNode->SetParent( n );
- if( nLastNode == nTree ){
- nTree = n;
- } else {
- nLastNode->GetParent()->RemoveLastChild();
- nLastNode->GetParent()->AddChild( n );
- n->SetParent( nLastNode->GetParent() );
- }
- }
-
- else if( n->GetNodeType() == XB_EXP_OPERATOR ){
- xbExpNode * nWorkNode = nLastNode;
- while( nWorkNode && ( nWorkNode->GetNodeType() != XB_EXP_OPERATOR || n->GetWeight() <= nWorkNode->GetWeight())){
- nWorkNode = nWorkNode->GetParent();
- }
-
- if( !nWorkNode ){ // we are at the top
- nTree->SetParent( n );
- n->AddChild( nTree );
- nTree = n;
-
- } else if( nWorkNode->GetChildCnt() == 1 ){
- nWorkNode->AddChild( n );
- n->SetParent( nWorkNode );
-
- } else if( nWorkNode->GetChildCnt() == 2 ){
- xbExpNode * nChild2 = nWorkNode->GetChild(1);
- n->AddChild( nChild2 );
- nWorkNode->RemoveLastChild();
- nWorkNode->AddChild( n );
- n->SetParent( nWorkNode );
-
- } else{
- // should not be stopping on anything but an operator node with one or two children
- iErrorStop = 170;
- iRc = XB_PARSE_ERROR;
- throw iRc;
- }
- } else {
- n->SetParent( nLastNode );
- nLastNode->AddChild( n );
- }
- nLastNode = n;
- n = NULL;
- }
- }
-
- // for each node in the tree, calculate the length if it's not already set
- xbExpNode * nWork = GetNextNode( NULL );
- xbExpNode * nChild1;
- xbExpNode * nChild2;
-
- while( nWork ){
- if( nWork->GetReturnType() == XB_EXP_UNKNOWN ){
- nWork->GetNodeText( s );
-
- // std::cout << "XB_EXP_UNKNOWN logic [" << s << "][" << nWork->GetChildCnt() << "]\n";
- // if this is "-" and child 1 and child 2 are both dates, set this result type to numeric
- if( s == "-" && nWork->GetChildCnt() == 2 &&
- nWork->GetChild(0)->GetReturnType() == XB_EXP_DATE && nWork->GetChild(1)->GetReturnType() == XB_EXP_DATE )
- nWork->SetReturnType( XB_EXP_NUMERIC );
- else if( nWork->GetChildCnt() > 0 )
- nWork->SetReturnType( nWork->GetChild(0)->GetReturnType());
- else{
- iErrorStop = 180;
- iRc = XB_PARSE_ERROR;
- throw iRc;
- }
- }
- if( nWork->GetResultLen() == 0 ){
-
- switch( nWork->GetReturnType() ){
-
- case XB_EXP_NUMERIC:
- nWork->SetResultLen( 4 );
- break;
-
- case XB_EXP_CHAR:
- if( nWork->GetNodeType() != XB_EXP_OPERATOR ){
- iErrorStop = 190;
- iRc = XB_PARSE_ERROR;
- throw iRc;
- }
- if( nWork->GetChildCnt() < 2 ){
- iErrorStop = 200;
- iRc = XB_PARSE_ERROR;
- throw iRc;
- }
- nChild1 = nWork->GetChild( 0 );
- nChild2 = nWork->GetChild( 1 );
- nWork->SetResultLen( nChild1->GetResultLen() + nChild2->GetResultLen());
- break;
-
- case XB_EXP_DATE:
- nWork->SetResultLen( 8 );
- break;
-
- case XB_EXP_LOGICAL:
- nWork->SetResultLen( 1 );
- break;
-
- default:
- iErrorStop = 210;
- iRc = XB_PARSE_ERROR;
- throw iRc;
- // break;
- }
- }
- if( nWork->IsUnaryOperator() ){
- if( nWork->GetChildCnt() != 1 ){
- iErrorStop = 220;
- iRc = XB_PARSE_ERROR;
- throw iRc;
- }
- } else if( nWork->IsOperator() && nWork->GetChildCnt() != 2 ){
- iErrorStop = 230;
- iRc = XB_PARSE_ERROR;
- throw iRc;
- }
- nWork = GetNextNode( nWork );
- }
- }
- catch (xbInt16 iRc ){
- xbString sMsg;
- sMsg.Sprintf( "xbexp::ParseExpression() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc );
- xbase->WriteLogMessage( sMsg.Str() );
- }
- return iRc;
-}
-/*************************************************************************/
-//! Parse expression constant.
-/*!
- \param t - Token.
- \param n - Node.
- \returns <a href="xbretcod_8h.html">Return Codes</a>
-*/
-xbInt16 xbExp::ParseExpressionConstant( xbExpToken &t, xbExpNode *n ){
-
- xbDate dtWork;
- n->SetReturnType( t.cReturnType );
-
- // std::cout << "parse expression constant[" << t.sToken << "]\n";
-
- switch( t.cReturnType ){
- case XB_EXP_CHAR:
- n->SetResultLen( t.sToken.Len() );
- n->SetResult( t.sToken );
- break;
-
- case XB_EXP_DATE:
- n->SetResultLen( 8 );
- dtWork.Set( t.sToken );
- n->SetResult( dtWork );
- break;
-
- case XB_EXP_LOGICAL:
- n->SetResultLen( 1 );
- if( strncmp( t.sToken, "T", 1 ) == 0 )
- n->SetResult( (xbBool) xbTrue );
- else
- n->SetResult( (xbBool) xbFalse );
- break;
-
- case XB_EXP_NUMERIC:
- n->SetResultLen( 4 );
- n->SetResult( strtod( t.sToken, 0 ));
- n->SetResult( t.sToken );
- break;
-
- default:
- return XB_PARSE_ERROR;
- // break;
- }
- return XB_NO_ERROR;
-}
-
-/*************************************************************************/
-//! Parse expression field.
-/*!
- \param t - Token.
- \param n - Node.
- \returns <a href="xbretcod_8h.html">Return Codes</a>
-*/
-xbInt16 xbExp::ParseExpressionField( xbExpToken &t, xbExpNode *n ){
-
- xbInt16 iRc = XB_NO_ERROR;
- xbInt16 iErrorStop = 0;
- xbDbf * pDbf;
- xbString sFieldName;
-
- // do the db lookup and set the field number for the field
-
- try{
-
- xbUInt32 lPos;
-
- if(( lPos = t.sToken.Pos( "->" )) > 0 ){
- // table name is part of the token
- xbString sTableName = t.sToken;
- sTableName.Left( lPos-1 );
- sFieldName = t.sToken;
- sFieldName.Mid( lPos + 2, t.sToken.Len() - lPos - 1 );
- pDbf = (xbDbf *) xbase->GetDbfPtr( sTableName );
-
-
-/*
- // updated 1/2/23 to support either table.field or table->field
- if((( lPos = t.sToken.Pos( "->" )) > 0) || (( lPos = t.sToken.Pos( "." )) > 0) ){
- // table name is part of the token
- xbString sTableName = t.sToken;
- sTableName.Left( lPos-1 );
- sFieldName = t.sToken;
- if( t.sToken[lPos] == '.' )
- sFieldName.Mid( lPos + 1, t.sToken.Len() - lPos );
- else // ->
- sFieldName.Mid( lPos + 2, t.sToken.Len() - lPos - 1 );
- pDbf = (xbDbf *) xbase->GetDbfPtr( sTableName );
-*/
-
- } else {
- // table name is not part of the token
- pDbf = dbf;
- sFieldName = t.sToken;
- }
- if( !pDbf ){
- iErrorStop = 100;
- iRc = XB_INVALID_FIELD;
- throw iRc;
- }
- xbInt16 iFieldNo = 0;
-
- if(( iRc = pDbf->GetFieldNo( sFieldName, iFieldNo )) != XB_NO_ERROR ){
- iErrorStop = 110;
- throw iRc;
- }
- char cFieldType;
- if(( iRc = pDbf->GetFieldType( iFieldNo, cFieldType )) != XB_NO_ERROR ){
- iErrorStop = 120;
- throw iRc;
- }
- n->SetDbfInfo( pDbf, iFieldNo );
- switch( cFieldType ){
- case XB_CHAR_FLD:
- n->SetReturnType( XB_EXP_CHAR );
- break;
-
- case XB_LOGICAL_FLD:
- n->SetReturnType( XB_EXP_LOGICAL );
- break;
-
- case XB_NUMERIC_FLD:
- case XB_FLOAT_FLD:
- n->SetReturnType( XB_EXP_NUMERIC );
- break;
-
- case XB_DATE_FLD:
- n->SetReturnType( XB_EXP_DATE );
- break;
-
- case XB_MEMO_FLD:
- default:
- iErrorStop = 130;
- iRc = XB_PARSE_ERROR;
- throw iRc;
- // break;
- }
- n->SetNodeText( sFieldName );
- xbInt16 iResultLen = 0;
- if(( iRc = pDbf->GetFieldLen( iFieldNo, iResultLen )) != XB_NO_ERROR ){
- iErrorStop = 140;
- throw iRc;
- }
- n->SetResultLen( (xbUInt32) iResultLen );
- }
- catch (xbInt16 iRc ){
- xbString sMsg;
- sMsg.Sprintf( "xbexp::ParseExpressionField() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc );
- xbase->WriteLogMessage( sMsg.Str() );
- }
- return iRc;
-}
-
-/*************************************************************************/
-//! Parse expression function.
-/*!
- \param t - Token.
- \param n - Node.
- \param iWeight
- \returns <a href="xbretcod_8h.html">Return Codes</a>
-*/
-xbInt16 xbExp::ParseExpressionFunction( xbExpToken &t, xbExpNode *n, xbInt16 iWeight ){
-
- xbInt16 iRc = XB_NO_ERROR;
- xbInt16 iErrorStop = 0;
-
- try{
- // find the first "("
- xbUInt32 lPos = t.sToken.Pos( '(' );
- if( lPos == 0 ){
- iErrorStop = 100;
- iRc = XB_INVALID_FUNCTION;
- throw iRc;
- }
- // Get the function name and look it up in the table
-
-
- xbString sFunc = t.sToken;
- sFunc.Left( lPos - 1 ).Trim();
- char cReturnType;
- xbInt16 i = 0;
- xbInt32 l = 0;
- if(( iRc = xbase->GetFunctionInfo( sFunc, cReturnType, i, l )) != XB_NO_ERROR ){
- iErrorStop = 110;
- throw iRc;
- }
- n->SetNodeText( sFunc );
-
-
- // Get the function parms
- xbString sParms = t.sToken;
- sParms.Mid( lPos+1, t.sToken.Len() - lPos );
- lPos = sParms.GetLastPos( ')' );
- if( lPos == 0 ){
- iErrorStop = 120;
- iRc = XB_INVALID_FUNCTION;
- throw iRc;
- }
-
- // remove the trailing ")" paren
- sParms.Left( lPos - 1 ).Trim();
-
- // if this function has parms, put them in the tree
- if( sParms.Len() > 0 ){
- xbExp enr( xbase, dbf );
-
- // create a linked list of parms
- xbLinkList<xbString> llParms;
- if(( iRc = ParseExpressionFunctionParms( sParms, llParms )) != XB_NO_ERROR ){
- iErrorStop = 130;
- throw iRc;
- }
-
- // for each function parm, recursively process it
- xbLinkListNode<xbString> * llN = llParms.GetHeadNode();
- xbString sParm;
- while( llN ){
- sParm = llN->GetKey();
- if(( iRc = enr.ParseExpression( sParm, iWeight + 10 )) != XB_NO_ERROR ){
- iErrorStop = 140;
- throw iRc;
- }
- n->AddChild( enr.GetTreeHandle());
- enr.ClearTreeHandle();
- llN = llN->GetNextNode();
- }
- llParms.Clear();
- }
-
- if( cReturnType == '1' ){
- if( n->GetChildCnt() > 0 ){
- xbExpNode *n1 = n->GetChild( 0 );
- n->SetReturnType( n1->GetReturnType());
- }
-
- } else {
- n->SetReturnType( cReturnType );
- }
-
- if(( iRc = CalcFunctionResultLen( n )) != XB_NO_ERROR ){
- iErrorStop = 150;
- throw iRc;
- }
- }
- catch (xbInt16 iRc ){
- xbString sMsg;
- sMsg.Sprintf( "xbexp::ParseExpressionFunction() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc );
- xbase->WriteLogMessage( sMsg.Str() );
- }
- return iRc;
-}
-
-/*************************************************************************/
-//! Parse expression function.
-/*!
-
- Creates a linked list of function parms as xbStrings
- This function pulls out the parms and addresses embedded parens and quotes within the parms
-
- \param sParms
- \param lParms
- \returns <a href="xbretcod_8h.html">Return Codes</a>
-*/
-
-xbInt16 xbExp::ParseExpressionFunctionParms( const xbString &sParms, xbLinkList<xbString> & llParms ){
-
- xbInt16 iRc = XB_NO_ERROR;
- xbInt16 iErrorStop = 0;
- xbInt16 iParenCtr = 0;
- xbInt16 iInQuotes = 0;
- xbInt16 iDoubleQuotes = 0;
- xbInt16 iSingleQuotes = 0;
- xbInt32 lStartPos = 0;
- xbInt32 lParmLen = 0;
-
- xbString sParm;
-
- try{
- const char *sp = sParms;
-
- while( *sp ){
- if( *sp == '(')
- iParenCtr++;
- else if( *sp == ')' )
- iParenCtr--;
- else if( !iInQuotes && *sp == '"' ){
- iInQuotes++;
- iDoubleQuotes++;
- } else if( iInQuotes && *sp == '"' ){
- iInQuotes--;
- iDoubleQuotes--;
- }
- else if( !iInQuotes && *sp == '\'' ){
- iInQuotes++;
- iSingleQuotes++;
- } else if( iInQuotes && *sp == '\'' ){
- iInQuotes--;
- iSingleQuotes--;
-
- } else if( !iInQuotes && !iParenCtr && *sp == ',' ){
- // found a valid comma - at the end of a parm
- // add it to the end of the linked list
- sParm = sParms;
- sParm.Mid( (xbUInt32) lStartPos + 1, (xbUInt32) lParmLen ).Trim(); // mid is one based
- llParms.InsertAtEnd( sParm );
-
- // set the start pos for the next one on the list
- lStartPos += lParmLen + 1;
- lParmLen = -1;
- // lParmLen = 0;
- }
- lParmLen++;
- sp++;
- }
- if( lParmLen > 0 ){
- // get the last parm, it didn't end with a comma
- sParm = sParms;
- sParm.Mid( (xbUInt32) lStartPos + 1, (xbUInt32) lParmLen ).Trim();
- llParms.InsertAtEnd( sParm );
- }
-
- }
- // try / catch not used in this method, structure added for potential future use
- catch (xbInt16 iRc ){
- xbString sMsg;
- sMsg.Sprintf( "xbexp::ParseExpressionFunctionParms() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc );
- xbase->WriteLogMessage( sMsg.Str() );
- }
- return iRc;
-}
-/*************************************************************************/
-//! Parse expression operator.
-/*!
- \param t - Token.
- \param n - Node.
- \param iWeight
- \returns <a href="xbretcod_8h.html">Return Codes</a>
-*/
-
-xbInt16 xbExp::ParseExpressionOperator( xbExpToken &t, xbExpNode *n, xbInt16 iWeight ){
-
- n->SetResult( t.sToken );
- n->SetWeight( iWeight + OperatorWeight( t.sToken) );
-
-// std::cout << "ParseExpressionOperator [" << t.cPrevNodeType << "][" << t.sToken << "] Weight = [" << iWeight;
-// std::cout << "] PrevReturnType [" << t.cPrevReturnType;
-// std::cout << "] Operator weight [" << OperatorWeight( t.sToken ) << "] getweight [" << n->GetWeight() << "]\n";
-
- if( t.sToken == "**" || t.sToken == "^" ||
- t.sToken == "*" || t.sToken == "/" || t.sToken == "%" || t.sToken == "*=" || t.sToken == "/=" )
- n->SetReturnType( XB_EXP_NUMERIC );
-
- else if( t.sToken == "--" || t.sToken == "++" || t.sToken == "+=" || t.sToken == "-=" ) // could be date or numeric
- n->SetReturnType( XB_EXP_UNKNOWN );
-
- else if( t.cPrevReturnType == XB_EXP_CHAR && ( t.sToken == "+" || t.sToken == "-" ))
- n->SetReturnType( XB_EXP_CHAR );
-
- else if( t.sToken == ".AND." || t.sToken == ".OR." || t.sToken == ".NOT." ||
- t.sToken == "AND" || t.sToken == "OR" || t.sToken == "NOT" ||
- t.sToken == ">" || t.sToken == ">=" || t.sToken == "<" ||
- t.sToken == "<=" || t.sToken == "<>" || t.sToken == "!=" ||
- t.sToken == "$" || t.sToken == "#" || t.sToken == "=" )
- n->SetReturnType( XB_EXP_LOGICAL );
-
-
- else if( t.cPrevReturnType == XB_EXP_UNKNOWN )
- n->SetReturnType( XB_EXP_UNKNOWN );
-
- // added for date constant logic 10/28/17
- else if(( t.sToken == "+" || t.sToken == "-" ) && t.cPrevReturnType == XB_EXP_DATE )
- n->SetReturnType( XB_EXP_DATE );
-
- else if( t.sToken == "+" || t.sToken == "-" )
- n->SetReturnType( XB_EXP_NUMERIC );
-
- return XB_NO_ERROR;
-}
-
-
-/************************************************************************/
-//! ProcessExpression
-/*! This method processes an expression tree leaving the result in the
- root node of the tree
-*/
-xbInt16 xbExp::ProcessExpression(){
- return ProcessExpression( 0 );
-}
-/************************************************************************/
-//! ProcessExpression
-/*! This method processes a parsed expression tree leaving the result in the
- root node of the tree
- \param iRecBufSw Record buffer to use when evaluating expression.<br>
- 0 - Current record buffer.<br>
- 1 - Original record buffer.
-*/
-
-xbInt16 xbExp::ProcessExpression( xbInt16 iRecBufSw ){
-
-// iRecBufSw 0 - Record Buffer
-// 1 - Original Record Buffer
-
- xbInt16 iRc = XB_NO_ERROR;
- xbInt16 iErrorStop = 0;
-
- try{
-
- xbExpNode * nWork = GetNextNode( NULL );
- xbExpNode * nChild1;
- xbDbf * dbf;
- xbString sWork1;
- xbString sWork2;
- xbString sOperator;
- xbDate dtWork1;
-
- xbBool bWork;
- xbDouble dWork;
-
- while( nWork ){
- switch( nWork->GetNodeType() ){
-
- case XB_EXP_CONSTANT:
- break;
-
- case XB_EXP_PRE_OPERATOR: // increment value before setting in head node
- if( nWork->GetChildCnt() != 1 ){
- iErrorStop = 100;
- iRc = XB_PARSE_ERROR;
- throw iRc;
- }
- nChild1 = nWork->GetChild( 0 );
- //if( nChild1->GetReturnType() == XB_EXP_DATE )
- // nChild1->SetResult( (xbDouble) nChild1->GetDateResult().JulianDays());
-
- nWork->GetNodeText( sWork1 );
- if( sWork1 == "++" )
- nChild1->SetResult( nChild1->GetNumericResult() + 1 );
- else
- nChild1->SetResult( nChild1->GetNumericResult() - 1 );
-
- nWork->SetResult( nChild1->GetNumericResult());
-
- //if( nChild1->GetReturnType() == XB_EXP_DATE ){
- // dtWork1.JulToDate8( (xbInt32) nChild1->GetNumericResult());
- // nChild1->SetResult( dtWork1 );
- // nWork->SetResult( dtWork1 );
- // }
- break;
-
- case XB_EXP_POST_OPERATOR: // increment value after setting in head node
- if( nWork->GetChildCnt() != 1 ){
- iErrorStop = 110;
- iRc = XB_PARSE_ERROR;
- throw iRc;
- }
- nChild1 = nWork->GetChild( 0 );
- //if( nChild1->GetReturnType() == XB_EXP_DATE ){
- // nWork->SetResult( nChild1->GetDateResult());
- // nChild1->SetResult( (xbDouble) nChild1->GetDateResult().JulianDays());
- //}
- //else
- nWork->SetResult( nChild1->GetNumericResult());
-
- nWork->GetNodeText( sWork1 );
- if( sWork1 == "++" )
- nChild1->SetResult( nChild1->GetNumericResult() + 1 );
- else
- nChild1->SetResult( nChild1->GetNumericResult() - 1 );
-
- //if( nChild1->GetReturnType() == XB_EXP_DATE ){
- // dtWork1.JulToDate8( (xbInt32) nChild1->GetNumericResult());
- // nChild1->SetResult( dtWork1 );
- // }
- break;
-
- case XB_EXP_FIELD:
-
- if(( dbf = nWork->GetDbf()) == NULL ){
- iErrorStop = 120;
- iRc = XB_PARSE_ERROR;
- throw iRc;
- }
- switch( nWork->GetReturnType()){
- case XB_EXP_CHAR:
- if(( iRc = dbf->GetField( nWork->GetFieldNo(), sWork1, iRecBufSw )) < XB_NO_ERROR ){
- iErrorStop = 130;
- throw iRc;
- }
- nWork->SetResult( sWork1 );
- break;
-
- case XB_EXP_DATE:
-
- if(( iRc = dbf->GetField( nWork->GetFieldNo(), sWork1, iRecBufSw )) < XB_NO_ERROR ){
- iErrorStop = 140;
- throw iRc;
- }
- if( sWork1 == " " ){
- nWork->SetResult( (xbDouble) 21474835648 ); // dbase sets a date value in ndx to this if spaces on dbf record
- } else {
- dtWork1.Set( sWork1 );
- nWork->SetResult( (xbDouble) dtWork1.JulianDays() );
- }
- break;
-
- case XB_EXP_LOGICAL:
- if(( iRc = dbf->GetLogicalField( nWork->GetFieldNo(), bWork, iRecBufSw )) != XB_NO_ERROR ){
- iErrorStop = 150;
- throw iRc;
- }
- nWork->SetResult( bWork );
- break;
-
- case XB_EXP_NUMERIC:
- if(( iRc = dbf->GetDoubleField( nWork->GetFieldNo(), dWork, iRecBufSw )) != XB_NO_ERROR ){
- iErrorStop = 160;
- throw iRc;
- }
- nWork->SetResult( dWork );
- break;
-
- default:
- iErrorStop = 170;
- iRc = XB_PARSE_ERROR;
- throw iRc;
- // break;
- }
- break;
-
-
- case XB_EXP_OPERATOR:
- if(( iRc = ProcessExpressionOperator( nWork )) != XB_NO_ERROR ){
- iErrorStop = 180;
- throw iRc;
- }
-
- break;
-
- case XB_EXP_FUNCTION:
- if(( iRc = ProcessExpressionFunction( nWork, iRecBufSw )) != XB_NO_ERROR ){
- iErrorStop = 190;
- throw iRc;
- }
- break;
-
- default:
- iErrorStop = 200;
- iRc = XB_PARSE_ERROR;
- throw iRc;
- // break;
- }
- nWork = GetNextNode( nWork );
- }
- }
- catch (xbInt16 iRc ){
- xbString sMsg;
- sMsg.Sprintf( "xbexp::ProcessExpression() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc );
- xbase->WriteLogMessage( sMsg.Str() );
- }
- return iRc;
-}
-/*************************************************************************/
-//! ProcessExpression
-/*! This method processes an expression tree for a given node.
-*/
-
-xbInt16 xbExp::ProcessExpressionFunction( xbExpNode * n, xbInt16 iRecBufSw ){
-
- xbInt16 iRc = XB_NO_ERROR;
- xbInt16 iErrorStop = 0;
-
- try{
-
- xbString sFunction;
- xbString sResult;
- xbDouble dResult;
- xbDate dtResult;
- xbBool bResult;
-
- n->GetNodeText( sFunction );
-
- // process functions with no children first
- xbExpNode * nChild1;
- if( n->GetChildCnt() == 0 ){
- if( sFunction == "DATE" ){
- if(( iRc = xbase->DATE( dtResult )) != XB_NO_ERROR ){
- iErrorStop = 100;
- throw iRc;
- }
- n->SetResult( dtResult );
- } else if( sFunction == "DEL" ){
- if(( iRc = xbase->DEL( dbf, sResult, iRecBufSw )) != XB_NO_ERROR ){
- iErrorStop = 110;
- throw iRc;
- }
- n->SetResult( sResult );
- } else if( sFunction == "DELETED" ){
- if(( iRc = xbase->DELETED( dbf, bResult, iRecBufSw )) != XB_NO_ERROR ){
- iErrorStop = 120;
- throw iRc;
- }
- n->SetResult( bResult );
- } else if( sFunction == "RECCOUNT" ){
- if(( iRc = xbase->RECCOUNT( dbf, dResult )) != XB_NO_ERROR ){
- iErrorStop = 130;
- throw iRc;
- }
- n->SetResult( dResult );
- } else if( sFunction == "RECNO" ){
- if(( iRc = xbase->RECNO( dbf, dResult )) != XB_NO_ERROR ){
- iErrorStop = 140;
- throw iRc;
- }
- n->SetResult( dResult );
- }
- // process functions with one child
- } else if( n->GetChildCnt() == 1 ){
-
- nChild1 = n->GetChild( 0 );
-
- if( sFunction == "ABS" ){
- if(( iRc = xbase->ABS( nChild1->GetNumericResult(), dResult )) != XB_NO_ERROR ){
- iErrorStop = 200;
- throw iRc;
- }
- n->SetResult( dResult );
- } else if( sFunction == "ALLTRIM" ){
- if(( iRc = xbase->ALLTRIM( nChild1->GetStringResult(), sResult )) != XB_NO_ERROR ){
- iErrorStop = 210;
- throw iRc;
- }
- n->SetResult( sResult );
- } else if( sFunction == "ASC" ){
- if(( iRc = xbase->ASC( nChild1->GetStringResult(), dResult )) != XB_NO_ERROR ){
- iErrorStop = 220;
- throw iRc;
- }
- n->SetResult( dResult );
- } else if( sFunction == "CDOW" ){
- xbDate d( (xbInt32) nChild1->GetNumericResult());
- if(( iRc = xbase->CDOW( d, sResult )) != XB_NO_ERROR ){
- iErrorStop = 230;
- throw iRc;
- }
- n->SetResult( sResult );
- } else if( sFunction == "CHR" ){
- if(( iRc = xbase->CHR( nChild1->GetNumericResult(), sResult )) != XB_NO_ERROR ){
- iErrorStop = 240;
- throw iRc;
- }
- n->SetResult( sResult );
- } else if( sFunction == "CMONTH" ){
- xbDate d( (xbInt32) nChild1->GetNumericResult());
- if(( iRc = xbase->CMONTH( d, sResult )) != XB_NO_ERROR ){
- iErrorStop = 250;
- throw iRc;
- }
- n->SetResult( sResult );
- } else if( sFunction == "CTOD" ){
- if(( iRc = xbase->CTOD( nChild1->GetStringResult(), dtResult )) != XB_NO_ERROR ){
- iErrorStop = 260;
- throw iRc;
- }
- n->SetResult( dtResult );
- } else if( sFunction == "DAY" ){
- xbDate d( (xbInt32) nChild1->GetNumericResult());
- if(( iRc = xbase->DAY( d, dResult )) != XB_NO_ERROR ){
- iErrorStop = 270;
- throw iRc;
- }
- n->SetResult( dResult );
- } else if( sFunction == "DESCEND" ){
-
- if( n->GetReturnType() == XB_EXP_CHAR ){
- if(( iRc = xbase->DESCEND( nChild1->GetStringResult(), sResult )) != XB_NO_ERROR ){
- iErrorStop = 280;
- throw iRc;
- }
- n->SetResult( sResult );
-
- } else if( n->GetReturnType() == XB_EXP_DATE ){
- xbDate d( (xbInt32) nChild1->GetNumericResult());
- if(( iRc = xbase->DESCEND( d, dtResult )) != XB_NO_ERROR ){
- iErrorStop = 290;
- throw iRc;
- }
- n->SetResult( dtResult );
-
- } else if( n->GetReturnType() == XB_EXP_NUMERIC ){
- if(( iRc = xbase->DESCEND( nChild1->GetNumericResult(), dResult )) != XB_NO_ERROR ){
- iErrorStop = 300;
- throw iRc;
- }
- n->SetResult( dResult );
-
- } else {
- iErrorStop = 310;
- iRc = XB_PARSE_ERROR;
- throw iRc;
- }
-
- } else if( sFunction == "DOW" ){
- xbDate d( (xbInt32) nChild1->GetNumericResult());
- if(( iRc = xbase->DOW( d, dResult )) != XB_NO_ERROR ){
- iErrorStop = 320;
- throw iRc;
- }
- n->SetResult( dResult );
- } else if( sFunction == "DTOC" ){
- xbDate d( (xbInt32) nChild1->GetNumericResult());
- if(( iRc = xbase->DTOC( d, sResult )) != XB_NO_ERROR ){
- iErrorStop = 330;
- throw iRc;
- }
- n->SetResult( sResult );
- } else if( sFunction == "DTOS" ){
- xbDate d( (xbInt32) nChild1->GetNumericResult());
- if(( iRc = xbase->DTOS( d, sResult )) != XB_NO_ERROR ){
- iErrorStop = 340;
- throw iRc;
- }
- n->SetResult( sResult );
- } else if( sFunction == "EXP" ){
- if(( iRc = xbase->EXP( nChild1->GetNumericResult(), dResult )) != XB_NO_ERROR ){
- iErrorStop = 350;
- throw iRc;
- }
- n->SetResult( dResult );
- } else if( sFunction == "INT" ){
- if(( iRc = xbase->INT( nChild1->GetNumericResult(), dResult )) != XB_NO_ERROR ){
- iErrorStop = 360;
- throw iRc;
- }
- n->SetResult( dResult );
- } else if( sFunction == "ISALPHA" ){
- if(( iRc = xbase->ISALPHA( nChild1->GetStringResult(), bResult )) != XB_NO_ERROR ){
- iErrorStop = 370;
- throw iRc;
- }
- n->SetResult( bResult );
- } else if( sFunction == "ISLOWER" ){
- if(( iRc = xbase->ISLOWER( nChild1->GetStringResult(), bResult )) != XB_NO_ERROR ){
- iErrorStop = 380;
- throw iRc;
- }
- n->SetResult( bResult );
- } else if( sFunction == "ISUPPER" ){
- if(( iRc = xbase->ISUPPER( nChild1->GetStringResult(), bResult )) != XB_NO_ERROR ){
- iErrorStop = 390;
- throw iRc;
- }
- n->SetResult( bResult );
- } else if( sFunction == "LEN" ){
- if(( iRc = xbase->LEN( nChild1->GetStringResult(), dResult )) != XB_NO_ERROR ){
- iErrorStop = 400;
- throw iRc;
- }
- n->SetResult( dResult );
- } else if( sFunction == "LOG" ){
- if(( iRc = xbase->LOG( nChild1->GetNumericResult(), dResult )) != XB_NO_ERROR ){
- iErrorStop = 410;
- throw iRc;
- }
- n->SetResult( dResult );
- } else if( sFunction == "LTRIM" ){
- if(( iRc = xbase->LTRIM( nChild1->GetStringResult(), sResult )) != XB_NO_ERROR ){
- iErrorStop = 420;
- throw iRc;
- }
- n->SetResult( sResult );
- } else if( sFunction == "LOWER" ){
- if(( iRc = xbase->LOWER( nChild1->GetStringResult(), sResult )) != XB_NO_ERROR ){
- iErrorStop = 430;
- throw iRc;
- }
- n->SetResult( sResult );
- } else if( sFunction == "MONTH" ){
- xbDate d( (xbInt32) nChild1->GetNumericResult());
- if(( iRc = xbase->MONTH( d, dResult )) != XB_NO_ERROR ){
- iErrorStop = 440;
- throw iRc;
- }
- n->SetResult( dResult );
- } else if( sFunction == "RTRIM" ){
- if(( iRc = xbase->RTRIM( nChild1->GetStringResult(), sResult )) != XB_NO_ERROR ){
- iErrorStop = 450;
- throw iRc;
- }
- n->SetResult( sResult );
- } else if( sFunction == "STOD" ){
- if(( iRc = xbase->STOD( nChild1->GetStringResult(), dtResult )) != XB_NO_ERROR ){
- iErrorStop = 460;
- throw iRc;
- }
- n->SetResult( dtResult );
- } else if( sFunction == "SPACE" ){
- if(( iRc = xbase->SPACE( (xbInt32) nChild1->GetNumericResult(), sResult )) != XB_NO_ERROR ){
- iErrorStop = 470;
- throw iRc;
- }
- n->SetResult( sResult );
- } else if( sFunction == "SQRT" ){
- if(( iRc = xbase->SQRT( nChild1->GetNumericResult(), dResult )) != XB_NO_ERROR ){
- iErrorStop = 480;
- throw iRc;
- }
- n->SetResult( dResult );
- } else if( sFunction == "STR" ){
- if(( iRc = xbase->STR( nChild1->GetNumericResult(), sResult )) != XB_NO_ERROR ){
- iErrorStop = 490;
- throw iRc;
- }
- n->SetResult( sResult );
- } else if( sFunction == "TRIM" ){
- if(( iRc = xbase->TRIM( nChild1->GetStringResult(), sResult )) != XB_NO_ERROR ){
- iErrorStop = 500;
- throw iRc;
- }
- n->SetResult( sResult );
- } else if( sFunction == "UPPER" ){
- if(( iRc = xbase->UPPER( nChild1->GetStringResult(), sResult )) != XB_NO_ERROR ){
- iErrorStop = 510;
- throw iRc;
- }
- n->SetResult( sResult );
- } else if( sFunction == "VAL" ){
- if(( iRc = xbase->VAL( nChild1->GetStringResult(), dResult )) != XB_NO_ERROR ){
- iErrorStop = 520;
- throw iRc;
- }
- n->SetResult( dResult );
- } else if( sFunction == "YEAR" ){
- xbDate d( (xbInt32) nChild1->GetNumericResult());
- if(( iRc = xbase->YEAR( d, dResult )) != XB_NO_ERROR ){
- iErrorStop = 530;
- throw iRc;
- }
- n->SetResult( dResult );
- } else {
- iErrorStop = 540;
- iRc = XB_PARSE_ERROR;
- throw iRc;
- }
- } else if( n->GetChildCnt() == 2 ){
- xbExpNode * nChild2;
- nChild1 = n->GetChild( 0 );
- nChild2 = n->GetChild( 1 );
-
- if( sFunction == "AT" ){
- if(( iRc = xbase->AT( nChild1->GetStringResult(), nChild2->GetStringResult(), dResult )) != XB_NO_ERROR ){
- iErrorStop = 700;
- throw iRc;
- }
- n->SetResult( dResult );
- } else if( sFunction == "LEFT" ){
- if(( iRc = xbase->LEFT( nChild1->GetStringResult(), (xbUInt32) nChild2->GetNumericResult(), sResult )) != XB_NO_ERROR ){
- iErrorStop = 710;
- throw iRc;
- }
- n->SetResult( sResult );
- } else if( sFunction == "MAX" ){
- if(( iRc = xbase->MAX( nChild1->GetNumericResult(), nChild2->GetNumericResult(), dResult )) != XB_NO_ERROR ){
- iErrorStop = 720;
- throw iRc;
- }
- n->SetResult( dResult );
- } else if( sFunction == "MIN" ){
- if(( iRc = xbase->MIN( nChild1->GetNumericResult(), nChild2->GetNumericResult(), dResult )) != XB_NO_ERROR ){
- iErrorStop = 730;
- throw iRc;
- }
- n->SetResult( dResult );
- }
- else if( sFunction == "REPLICATE" ){
- if(( iRc = xbase->REPLICATE( nChild1->GetStringResult(), (xbUInt32) nChild2->GetNumericResult(), sResult )) != XB_NO_ERROR ){
- iErrorStop = 800;
- throw iRc;
- }
- n->SetResult( sResult );
- } else if( sFunction == "RIGHT" ){
- if(( iRc = xbase->RIGHT( nChild1->GetStringResult(), (xbUInt32) nChild2->GetNumericResult(), sResult )) != XB_NO_ERROR ){
- iErrorStop = 810;
- throw iRc;
- }
- n->SetResult( sResult );
- } else if( sFunction == "STR" ){
- if(( iRc = xbase->STR( nChild1->GetNumericResult(), (xbUInt32) nChild2->GetNumericResult(), sResult )) != XB_NO_ERROR ){
- iErrorStop = 820;
- throw iRc;
- }
- n->SetResult( sResult );
- } else {
- iErrorStop = 830;
- iRc = XB_PARSE_ERROR;
- throw iRc;
- }
- } else if( n->GetChildCnt() == 3 ){
- xbExpNode * nChild2;
- xbExpNode * nChild3;
- nChild1 = n->GetChild( 0 );
- nChild2 = n->GetChild( 1 );
- nChild3 = n->GetChild( 2 );
-
- if( sFunction == "IIF" ){
- if(( iRc = xbase->IIF( nChild1->GetBoolResult(), nChild2->GetStringResult(), nChild3->GetStringResult(), sResult )) != XB_NO_ERROR ){
- iErrorStop = 900;
- throw iRc;
- }
- n->SetResult( sResult );
- } else if( sFunction == "STR" ){
- if(( iRc = xbase->STR( nChild1->GetNumericResult(), (xbUInt32) nChild2->GetNumericResult(), (xbUInt32) nChild3->GetNumericResult(), sResult )) != XB_NO_ERROR ){
- iErrorStop = 910;
- throw iRc;
- }
- n->SetResult( sResult );
- } else if( sFunction == "STRZERO" ){
- if(( iRc = xbase->STRZERO( nChild1->GetNumericResult(), (xbUInt32) nChild2->GetNumericResult(), (xbUInt32) nChild3->GetNumericResult(), sResult )) != XB_NO_ERROR ){
- iErrorStop = 920;
- throw iRc;
- }
- n->SetResult( sResult );
- } else if( sFunction == "SUBSTR" ){
- if(( iRc = xbase->SUBSTR( nChild1->GetStringResult(), (xbUInt32) nChild2->GetNumericResult(), (xbUInt32) nChild3->GetNumericResult(), sResult )) != XB_NO_ERROR ){
- iErrorStop = 930;
- throw iRc;
- }
- n->SetResult( sResult );
- } else {
- iErrorStop = 950;
- iRc = XB_PARSE_ERROR;
- throw iRc;
- }
- } else if( n->GetChildCnt() == 4 ){
- xbExpNode * nChild2;
- xbExpNode * nChild3;
- xbExpNode * nChild4;
- nChild1 = n->GetChild( 0 );
- nChild2 = n->GetChild( 1 );
- nChild3 = n->GetChild( 2 );
- nChild4 = n->GetChild( 3 );
-
- if( sFunction == "STR" ){
- if(( iRc = xbase->STR( nChild1->GetNumericResult(), (xbUInt32) nChild2->GetNumericResult(),
- (xbUInt32) nChild3->GetNumericResult(), nChild4->GetStringResult(), sResult )) != XB_NO_ERROR ){
- iErrorStop = 1000;
- throw iRc;
- }
- n->SetResult( sResult );
- } else {
- iErrorStop = 1010;
- iRc = XB_PARSE_ERROR;
- throw iRc;
- }
-
- } else {
- iErrorStop = 2000;
- iRc = XB_PARSE_ERROR;
- throw iRc;
- }
-
- }
- catch (xbInt16 iRc ){
- xbString sMsg;
- sMsg.Sprintf( "xbexp::ProcessExpressionFunction() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc );
- xbase->WriteLogMessage( sMsg.Str() );
- }
- return iRc;
-}
-/*************************************************************************/
-//! Process Expression Operator
-/*! This method processes an expression operator for a given node.
-*/
-
-xbInt16 xbExp::ProcessExpressionOperator( xbExpNode * n ){
-
- xbInt16 iRc = XB_NO_ERROR;
- xbInt16 iErrorStop = 0;
-
- xbExpNode * nChild1 = NULL;
- xbExpNode * nChild2 = NULL;
- xbString sOperator;
- xbString sWork1;
- xbString sWork2;
- xbDate dtWork1;
-
- xbString sMsg;
-
- try{
-
- n->GetNodeText( sOperator );
- nChild1 = n->GetChild( 0 );
- if( !n->IsUnaryOperator())
- nChild2 = n->GetChild( 1 );
-
- switch( n->GetReturnType()){
- case XB_EXP_CHAR:
- if( sOperator == "+" ){
- sWork1 = nChild1->GetStringResult();
- sWork1 += nChild2->GetStringResult();
- n->SetResult( sWork1 );
- } else if( sOperator == "-" ){
- sWork1 = nChild1->GetStringResult();
- sWork1.Rtrim();
- sWork1 += nChild2->GetStringResult();
- sWork1.PadRight( ' ', n->GetResultLen());
- n->SetResult( sWork1 );
- } else {
- iErrorStop = 100;
- iRc = XB_PARSE_ERROR;
- throw iRc;
- }
- break;
-
- case XB_EXP_NUMERIC:
- if( sOperator == "+" )
- n->SetResult( nChild1->GetNumericResult() + nChild2->GetNumericResult());
- else if( sOperator == "-" ){
- n->SetResult( nChild1->GetNumericResult() - nChild2->GetNumericResult());
-
- }
- else if( sOperator == "*" )
- n->SetResult( nChild1->GetNumericResult() * nChild2->GetNumericResult());
- else if( sOperator == "/" )
- n->SetResult( nChild1->GetNumericResult() / nChild2->GetNumericResult());
- else if( sOperator == "^" || sOperator == "**" )
- n->SetResult( pow( nChild1->GetNumericResult(), nChild2->GetNumericResult()));
- else if( sOperator == "+=" ){
- n->SetResult( nChild1->GetNumericResult() + nChild2->GetNumericResult());
- nChild1->SetResult( n->GetNumericResult() );
- }
- else if( sOperator == "-=" ){
- n->SetResult( nChild1->GetNumericResult() - nChild2->GetNumericResult());
- nChild1->SetResult( n->GetNumericResult() );
- }
- else if( sOperator == "*=" ){
- n->SetResult( nChild1->GetNumericResult() * nChild2->GetNumericResult());
- nChild1->SetResult( n->GetNumericResult() );
- }
- else if( sOperator == "/=" ){
- n->SetResult( nChild1->GetNumericResult() / nChild2->GetNumericResult());
- nChild1->SetResult( n->GetNumericResult() );
- } else {
- iErrorStop = 200;
- iRc = XB_PARSE_ERROR;
- throw iRc;
- }
- break;
-
-
- case XB_EXP_DATE:
- // if date values in the leaf nodes, convert to numeric for operator logic
-
- if( sOperator == "+" )
- n->SetResult( nChild1->GetNumericResult() + nChild2->GetNumericResult());
- else if( sOperator == "-" ){
- n->SetResult( nChild1->GetNumericResult() - nChild2->GetNumericResult());
- xbDate d( (xbInt32) n->GetNumericResult());
- }
- else if( sOperator == "+=" ){
- n->SetResult( nChild1->GetNumericResult() + nChild2->GetNumericResult());
- nChild1->SetResult( n->GetNumericResult() );
- }
- else if( sOperator == "-=" ){
- n->SetResult( nChild1->GetNumericResult() - nChild2->GetNumericResult());
- nChild1->SetResult( n->GetNumericResult() );
- } else {
- iErrorStop = 300;
- iRc = XB_PARSE_ERROR;
- throw iRc;
- }
- break;
-
- case XB_EXP_LOGICAL:
-
- if( !n->IsUnaryOperator() && (nChild1->GetReturnType() != nChild2->GetReturnType())){
- iErrorStop = 400;
- iRc = XB_INCOMPATIBLE_OPERANDS;
- throw iRc;
- }
-
- if( sOperator == ".AND." || sOperator == "AND" )
- n->SetResult((xbBool) (nChild1->GetBoolResult() && nChild2->GetBoolResult()) );
-
- else if( sOperator == ".OR." || sOperator == "OR" )
- n->SetResult((xbBool) (nChild1->GetBoolResult() || nChild2->GetBoolResult()) );
-
- else if( sOperator == ".NOT." || sOperator == "NOT" ){
- if( nChild1->GetBoolResult())
- n->SetResult((xbBool) xbFalse );
- else
- n->SetResult((xbBool) xbTrue );
- }
-
- else if( sOperator == ">" ){
-
- if( nChild1->GetReturnType() == XB_EXP_CHAR )
- n->SetResult((xbBool)(nChild1->GetStringResult() > nChild2->GetStringResult()));
- else if( nChild1->GetReturnType() == XB_EXP_NUMERIC || nChild1->GetReturnType() == XB_EXP_DATE )
- n->SetResult((xbBool)(nChild1->GetNumericResult() > nChild2->GetNumericResult()));
-
- else {
- iErrorStop = 410;
- iRc = XB_PARSE_ERROR;
- throw iRc;
- }
- }
-
- else if( sOperator == ">=" ){
- if( nChild1->GetReturnType() == XB_EXP_CHAR )
- n->SetResult((xbBool)(nChild1->GetStringResult() >= nChild2->GetStringResult()));
-
- else if( nChild1->GetReturnType() == XB_EXP_NUMERIC || nChild1->GetReturnType() == XB_EXP_DATE )
- n->SetResult((xbBool)(nChild1->GetNumericResult() >= nChild2->GetNumericResult()));
-
- else {
- iErrorStop = 420;
- iRc = XB_PARSE_ERROR;
- throw iRc;
- }
- }
-
- else if( sOperator == "<" ){
-
- if( nChild1->GetReturnType() == XB_EXP_CHAR )
- n->SetResult((xbBool)( nChild1->GetStringResult() < nChild2->GetStringResult()));
-
- else if( nChild1->GetReturnType() == XB_EXP_NUMERIC || nChild1->GetReturnType() == XB_EXP_DATE )
- n->SetResult((xbBool)( nChild1->GetNumericResult() < nChild2->GetNumericResult()));
-
- else {
- iErrorStop = 430;
- iRc = XB_PARSE_ERROR;
- throw iRc;
- }
- }
-
- else if( sOperator == "<=" ){
-
- if( nChild1->GetReturnType() == XB_EXP_CHAR )
- n->SetResult((xbBool)( nChild1->GetStringResult() <= nChild2->GetStringResult()));
-
- else if( nChild1->GetReturnType() == XB_EXP_NUMERIC || nChild1->GetReturnType() == XB_EXP_DATE )
- n->SetResult((xbBool)( nChild1->GetNumericResult() <= nChild2->GetNumericResult()));
-
- else {
- iErrorStop = 440;
- iRc = XB_PARSE_ERROR;
- throw iRc;
- }
- }
-
- else if( sOperator == "<>" || sOperator == "#" || sOperator == "!=" ){
-
- if( nChild1->GetReturnType() == XB_EXP_CHAR )
- n->SetResult((xbBool)( nChild1->GetStringResult() != nChild2->GetStringResult()));
-
- else if( nChild1->GetReturnType() == XB_EXP_NUMERIC || nChild1->GetReturnType() == XB_EXP_DATE )
- n->SetResult((xbBool)( nChild1->GetNumericResult() != nChild2->GetNumericResult()));
-
- else {
- iErrorStop = 450;
- iRc = XB_PARSE_ERROR;
- throw iRc;
- }
- }
-
- else if( sOperator == "$" ){
- if( nChild1->GetReturnType() == XB_EXP_CHAR )
- if( nChild2->GetStringResult().Pos( nChild1->GetStringResult()) > 0 )
- n->SetResult((xbBool) xbTrue );
- else
- n->SetResult((xbBool) xbFalse );
- else {
- iErrorStop = 460;
- iRc = XB_INCOMPATIBLE_OPERANDS;
- throw iRc;
- }
- }
-
- else if( sOperator == "=" ){
-
- if( nChild1->GetReturnType() == XB_EXP_CHAR ){
- xbString sChld1 = nChild1->GetStringResult();
- xbString sChld2 = nChild2->GetStringResult();
- sChld1.Rtrim();
- sChld2.Rtrim();
- n->SetResult((xbBool)( sChld1 == sChld2 ));
-
- } else if( nChild1->GetReturnType() == XB_EXP_NUMERIC || nChild1->GetReturnType() == XB_EXP_DATE )
- n->SetResult((xbBool)( nChild1->GetNumericResult() == nChild2->GetNumericResult()));
-
- else {
- iErrorStop = 470;
- iRc = XB_PARSE_ERROR;
- throw iRc;
- }
-
- } else {
- iErrorStop = 500;
- iRc = XB_PARSE_ERROR;
- throw iRc;
- }
-
- break;
-
- default:
- iErrorStop = 600;
- iRc = XB_PARSE_ERROR;
- throw iRc;
- // break;
- }
- }
- catch (xbInt16 iRc ){
- xbString sMsg;
- sMsg.Sprintf( "xbexp::ProcessExpressionOperator() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc );
- xbase->WriteLogMessage( sMsg.Str() );
- }
- return iRc;
-}
-
-/*************************************************************************/
-}; // namespace
-#endif // XB_EXPRESSION_SUPPORT
-/*************************************************************************/