Kaydet (Commit) b15cfb2e authored tarafından Hans-Joachim Lankenau's avatar Hans-Joachim Lankenau

#i17992# applied patch to enable komplex logic in .IF statements

üst 9ef2c623
/* RCS $Id: getinp.c,v 1.3 2002-10-11 13:42:43 waratah Exp $ /* RCS $Id: getinp.c,v 1.4 2004-01-28 13:21:11 hjs Exp $
-- --
-- SYNOPSIS -- SYNOPSIS
-- Handle reading of input. -- Handle reading of input.
...@@ -45,6 +45,7 @@ static int rule_ind = 0; /* index of rule when reading Rule_tab */ ...@@ -45,6 +45,7 @@ static int rule_ind = 0; /* index of rule when reading Rule_tab */
static int skip = FALSE; /* if true the skip input */ static int skip = FALSE; /* if true the skip input */
int partcomp( char* lhs, int opcode ); int partcomp( char* lhs, int opcode );
int parse_complex_expression( char *expr, char **expr_end, int opcode );
PUBLIC int PUBLIC int
...@@ -441,17 +442,20 @@ char *tg; ...@@ -441,17 +442,20 @@ char *tg;
DB_ENTER( "_is_conditional" ); DB_ENTER( "_is_conditional" );
tg++; tg++;
switch( *tg ) { switch( *tg )
case 'I': if( !strcmp( tg, "IF" )) DB_RETURN( ST_IF ); {
else if( !strcmp( tg, "IFEQ" )) DB_RETURN( ST_IFEQ ); case 'I':
else if( !strcmp( tg, "IFNEQ" )) DB_RETURN( ST_IFNEQ ); break; if( !strcmp( tg, "IF" )) DB_RETURN( ST_IF );
else if( !strcmp( tg, "IFEQ" )) DB_RETURN( ST_IFEQ );
else if( !strcmp( tg, "IFNEQ" )) DB_RETURN( ST_IFNEQ );
break;
case 'E': case 'E':
if( !strcmp( tg, "END" )) DB_RETURN( ST_END ); if( !strcmp( tg, "END" )) DB_RETURN( ST_END );
else if( !strcmp( tg, "ENDIF")) DB_RETURN( ST_END ); else if( !strcmp( tg, "ENDIF")) DB_RETURN( ST_END );
else if( !strcmp( tg, "ELSE" )) DB_RETURN( ST_ELSE ); else if( !strcmp( tg, "ELSE" )) DB_RETURN( ST_ELSE );
else if( !strcmp( tg, "ELIF" )) DB_RETURN( ST_ELIF ); else if( !strcmp( tg, "ELIF" )) DB_RETURN( ST_ELIF );
break; break;
} }
DB_RETURN( 0 ); DB_RETURN( 0 );
...@@ -468,19 +472,15 @@ char *tg; ...@@ -468,19 +472,15 @@ char *tg;
#define ACCEPT_ELIF 0x20 #define ACCEPT_ELIF 0x20
static int static int
_handle_conditional( opcode, tg )/* _handle_conditional( opcode, tg )
=================================== int opcode;
Perform the necessary processing for .IF conditinal targets. TKSTRPTR tg;
Someday this should be modified to do bracketted expressions ala
CPP... sigh */
int opcode;
TKSTRPTR tg;
{ {
static short action[MAX_COND_DEPTH]; static short action[MAX_COND_DEPTH];
static char ifcntl[MAX_COND_DEPTH]; static char ifcntl[MAX_COND_DEPTH];
char *lhs, *expr; char *lhs, *expr, *expr_end;
char *lop, *partstr; char *lop, *partstr;
int result, n, m; int result, n, m;
DB_ENTER( "_handle_conditional" ); DB_ENTER( "_handle_conditional" );
...@@ -502,40 +502,17 @@ TKSTRPTR tg; ...@@ -502,40 +502,17 @@ TKSTRPTR tg;
lhs = DmStrSpn( expr, " \t" ); lhs = DmStrSpn( expr, " \t" );
if( !*lhs ) lhs = NIL(char); if( !*lhs ) lhs = NIL(char);
if ( (lop = DmStrStr(lhs, "&&" )) != NIL(char) ) /* Don't support C-style define keyword */
Fatal( ".IF do not support && " );
if ( (lop = DmStrStr(lhs, "defined" )) != NIL(char) ) if ( (lop = DmStrStr(lhs, "defined" )) != NIL(char) )
Fatal( ".IF do not support defined " ); Fatal( ".IF do not support defined " );
if ( (lop = DmStrStr(lhs, "DEFINED" )) != NIL(char) ) if ( (lop = DmStrStr(lhs, "DEFINED" )) != NIL(char) )
Fatal( ".IF do not support defined " ); Fatal( ".IF do not support defined " );
/*-----------------18.03.99 14:38-------------------
* hjs - simple OR fixed and less code lhs = expr;
--------------------------------------------------*/ SCAN_WHITE( lhs );
if ( (lop = DmStrStr(lhs, "||" )) != NIL(char) ) /* Parse the expression and get its logical result */
{ if ( ((lop = DmStrStr(lhs, "||" )) != NIL(char)) || ((lop = DmStrStr(lhs, "&&" )) != NIL(char)) )
/* printf("todo: %s\n", expr ); */ result = parse_complex_expression( lhs, &expr_end, opcode );
partstr = MALLOC( strlen (lhs ) + 5, char);
result = FALSE;
while(( lop = DmStrStr(lhs, "||" )) != NIL(char) )
{
n = strlen( lop );
m = strlen( lhs );
strncpy( partstr, lhs, m - n );
partstr[ m - n ] = '\0';
result |= partcomp( partstr, opcode);
lhs = lop+2;
lhs = DmStrSpn( lhs, " \t" );
}
result |= partcomp( lhs, opcode );
/*
if ( result )
printf("TRUE\n\n");
else
printf("false\n\n");
FREE( partstr );
*/
}
/*--------------------------------------------------*/
else else
result = partcomp( lhs, opcode ); result = partcomp( lhs, opcode );
...@@ -582,65 +559,219 @@ TKSTRPTR tg; ...@@ -582,65 +559,219 @@ TKSTRPTR tg;
DB_RETURN( action[ Nest_level ] ); DB_RETURN( action[ Nest_level ] );
} }
/* uncomment to turn on expression debug statements */
/*#define PARSE_DEBUG /* */
#define PARSE_SKIP_WHITE(A) while( *A && ((*A==' ') || (*A=='\t')) ) A++;
#define OP_NONE 0
#define OP_AND 1
#define OP_OR 2
static int n = 1;
int parse_complex_expression( char *expr, char **expr_end, int opcode )
{
char *p = expr;
char *term_start = p;
char *term_end;
int local_term;
char *part;
int term_result = FALSE;
int final_result = TRUE;
unsigned int term_len;
unsigned int last_op = OP_NONE;
#ifdef PARSE_DEBUG
printf( "%d: parse_complex_expression( %s ): %d\n", n, expr, match_paren );
#endif
while ( 1 )
{
/* A new sub-expression */
local_term = TRUE;
if ( *p == '(' )
{
n++;
term_result = parse_complex_expression( p+1, &p, opcode );
n--;
PARSE_SKIP_WHITE( p );
term_start = p;
term_end = p;
local_term = FALSE;
}
else
term_end = p;
/* Lets do an operation!! */
if ( !(*p) /* at the end of the entire line */
|| ((*p == '&') && (*(p+1) && (*(p+1)=='&'))) /* found an && */
|| ((*p == '|') && (*(p+1) && (*(p+1)=='|'))) /* found an || */
|| (*p == ')') ) /* at the end of our term */
{
/* Grab the sub-expression if we parsed it. Otherwise,
* it was a () subexpression and we don't need to evaluate
* it since that was already done.
*/
if ( local_term == TRUE )
{
/* Back up 1 to the end of the actual term */
term_end--;
/* Evaluate the term */
PARSE_SKIP_WHITE( term_start );
term_len = term_end - term_start + 1;
part = MALLOC( term_len + 1, char );
strncpy( part, term_start, term_len );
*(part+term_len) = '\0';
#ifdef PARSE_DEBUG
printf( "%d: evaling '%s'\n", n, part );
#endif
term_result = partcomp( part, opcode );
#ifdef PARSE_DEBUG
printf( "%d: evaled, result %d\n", n, term_result );
#endif
FREE( part );
}
/* Do the actual logical operation using the _preceding_
* logical operator, NOT the one we just found.
*/
if ( last_op == OP_AND )
final_result = final_result && term_result;
else if ( last_op == OP_OR )
final_result = final_result || term_result;
else
final_result = term_result;
#ifdef PARSE_DEBUG
printf( "%d: final_result:%d\n", n, final_result );
#endif
/* If we're not at the end of the line, just keep going */
if ( *p )
{
/* Recognize the operator we just found above */
if ( *p == '&' )
last_op = OP_AND;
else if ( *p == '|' )
last_op = OP_OR;
if ( *p != ')' )
p += 2;
/* Get the start of the next term */
PARSE_SKIP_WHITE( p );
term_start = p;
/* If this is the close of a term, we are done and return
* to our caller.
*/
if ( *p == ')' )
{
p++;
break;
}
}
else break; /* At end of line, all done */
}
else if ( local_term == TRUE ) p++; /* Advance to next char in expression */
}
*expr_end = p;
#ifdef PARSE_DEBUG
printf( "%d: done, returning '%s', result %d\n", n, *expr_end, final_result );
#endif
return( final_result );
}
int partcomp( char* lhs, int opcode ) int partcomp( char* lhs, int opcode )
{ {
char *tok, *rhs, *op = 0; char *tok, *rhs, *op = 0;
int result, opsind; int result, opsind;
const int localopscount=4; const int localopscount=4;
char* localops[]={"==","!=","<=",">="}; char* localops[] = { "==", "!=", "<=", ">=" };
int lint, rint; int lint, rint;
#define EQUAL 0 #define EQUAL 0
#define NOTEQUAL 1 #define NOTEQUAL 1
#define LESS_EQUAL 2 #define LESS_EQUAL 2
#define GREATER_EQUAL 3 #define GREATER_EQUAL 3
opsind=0; #ifdef PARSE_DEBUG
/* printf( "eval: %s\n", lhs);*/ printf( "eval: %s\n", lhs);
if( opcode == ST_IFEQ || opcode == ST_IFNEQ ) { /* no == */ #endif
for( op = lhs; ((*op)&&(*op != ' ')&&(*op != '\t')); op++ );
if( *op ) opsind = 0;
op++; if( opcode == ST_IFEQ || opcode == ST_IFNEQ )
else
op = NIL(char);
} else while ( opsind < localopscount && (op = DmStrStr( lhs, localops[opsind] )) == NIL(char))
{ {
/* printf("%d %s\n", opsind, localops[opsind]);*/ /* IF[N]EQ syntax is: .IF[N]EQ <1> <2>
opsind++; * Here, step over first argument and get to <2> if it exists.
*/
for( op = lhs; ((*op)&&(*op != ' ')&&(*op != '\t')); op++ );
if( *op ) op++; /* position op at start of <2> */
else op = NIL(char); /* only 1 argument given */
} }
else
{
/* Find which logical operator we are to use for this expression,
* and jump to it */
while ( (opsind < localopscount) && ((op = DmStrStr(lhs, localops[opsind])) == NIL(char)) )
opsind++;
#ifdef PARSE_DEBUG
printf(" found op %d: %s\n", opsind, localops[opsind]);
#endif
}
/* if ( opsind == localopscount ) /* If the opcode was IFEQ or IFNEQ and only 1 argument was given,
Fatal( "Unknown Operator\n" );*/ * or an unknown logical operator was encountered,
* return false if argument is empty string, true if !empty
*/
if( op == NIL(char) ) if( op == NIL(char) )
result = (lhs != NIL(char)); result = (*lhs != '\0');
else { else
/* printf("op#%s\n",op);*/ {
if( opcode != ST_IFEQ && opcode != ST_IFNEQ ) /* no == */ /* Make both characters of the operation the same, replacing the = in op[1]
* Its easier to deal with this way???
*/
if( opcode != ST_IFEQ && opcode != ST_IFNEQ )
op[1] = op[0]; op[1] = op[0];
/* printf("op#%s\n",op);*/
if( lhs != op ) { #ifdef PARSE_DEBUG
for( tok = op-1; (tok != lhs) && ((*tok == ' ')||(*tok == '\t')); printf(" op:%s\n", op);
tok-- ); #endif
tok[1] = '\0';
/* Isolate the left half of the expression */
if( lhs != op )
{
for( tok = op-1; (tok != lhs) && ((*tok == ' ')||(*tok == '\t')); tok-- );
tok[1] = '\0';
} }
else else
lhs = NIL(char); lhs = NIL(char);
if( opcode == ST_IFEQ || opcode == ST_IFNEQ ) /* no == */ /* Jump over the operation so we can grab the right half of the expression */
op--; if( opcode == ST_IFEQ || opcode == ST_IFNEQ )
op--;
else else
op++; op++;
/* Isolate the right half of the expression */
rhs = DmStrSpn( op+1, " \t" ); rhs = DmStrSpn( op+1, " \t" );
if( !*rhs ) rhs = NIL(char); if( !*rhs ) rhs = NIL(char);
if ( opsind > NOTEQUAL ) { #ifdef PARSE_DEBUG
/* printf("new ops\n");*/ printf(" lhs:%s, rhs:%s\n", lhs, rhs);
switch( opsind ){ #endif
/* Do the actual logical operation on the expression */
if ( opsind > NOTEQUAL )
{
switch( opsind )
{
case LESS_EQUAL: case LESS_EQUAL:
case GREATER_EQUAL: case GREATER_EQUAL:
/* Ignore quotes around the arguments */
if ( lhs[0] == '"' ) lhs++; if ( lhs[0] == '"' ) lhs++;
if ( rhs[0] == '"' ) rhs++; if ( rhs[0] == '"' ) rhs++;
lint = atoi( lhs ); lint = atoi( lhs );
...@@ -653,21 +784,28 @@ int partcomp( char* lhs, int opcode ) ...@@ -653,21 +784,28 @@ int partcomp( char* lhs, int opcode )
result = FALSE; result = FALSE;
} }
} }
else { else
{
/* Use a simple string compare to determine equality */
if( (rhs == NIL(char)) || (lhs == NIL(char)) ) if( (rhs == NIL(char)) || (lhs == NIL(char)) )
result = (rhs == lhs) ? TRUE : FALSE; result = (rhs == lhs) ? TRUE : FALSE;
else { else
{
/* String off whitespace at the end of the right half of the expression */
tok = rhs + strlen( rhs ); tok = rhs + strlen( rhs );
for( tok=tok-1; (tok != lhs) && ((*tok == ' ')||(*tok == '\t')); for( tok=tok-1; (tok != lhs) && ((*tok == ' ')||(*tok == '\t')); tok--);
tok--);
tok[1] = '\0'; tok[1] = '\0';
result = (strcmp( lhs, rhs ) == 0) ? TRUE : FALSE; result = (strcmp( lhs, rhs ) == 0) ? TRUE : FALSE;
} }
if( *op == '!' || opcode == ST_IFNEQ ) result = !result; if( *op == '!' || opcode == ST_IFNEQ ) result = !result;
} }
} }
/* printf("partresult %d\n",result);*/
#ifdef PARSE_DEBUG
printf("partresult %d\n\n",result);
#endif
return result; return result;
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment