summaryrefslogtreecommitdiff
path: root/dmake/getinp.c
diff options
context:
space:
mode:
authorHans-Joachim Lankenau <hjs@openoffice.org>2004-01-28 12:21:11 +0000
committerHans-Joachim Lankenau <hjs@openoffice.org>2004-01-28 12:21:11 +0000
commitb15cfb2ed8167a99073cdba016f7ecca3a41f51f (patch)
tree5f7293182392ef086a6718ad9dc86ffe6e6d6c7e /dmake/getinp.c
parent9ef2c623fb456b2c0625713c9a2008264df0e565 (diff)
#i17992# applied patch to enable komplex logic in .IF statements
Diffstat (limited to 'dmake/getinp.c')
-rw-r--r--dmake/getinp.c314
1 files changed, 226 insertions, 88 deletions
diff --git a/dmake/getinp.c b/dmake/getinp.c
index c2d0302bd096..2f9f1b7a4c08 100644
--- a/dmake/getinp.c
+++ b/dmake/getinp.c
@@ -1,4 +1,4 @@
-/* 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
-- Handle reading of input.
@@ -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 */
int partcomp( char* lhs, int opcode );
+int parse_complex_expression( char *expr, char **expr_end, int opcode );
PUBLIC int
@@ -441,17 +442,20 @@ char *tg;
DB_ENTER( "_is_conditional" );
tg++;
- switch( *tg ) {
- case 'I': 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;
+ switch( *tg )
+ {
+ case 'I':
+ 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':
- 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, "ELSE" )) DB_RETURN( ST_ELSE );
else if( !strcmp( tg, "ELIF" )) DB_RETURN( ST_ELIF );
- break;
+ break;
}
DB_RETURN( 0 );
@@ -468,19 +472,15 @@ char *tg;
#define ACCEPT_ELIF 0x20
static int
-_handle_conditional( opcode, tg )/*
-===================================
- Perform the necessary processing for .IF conditinal targets.
- Someday this should be modified to do bracketted expressions ala
- CPP... sigh */
-int opcode;
-TKSTRPTR tg;
+_handle_conditional( opcode, tg )
+ int opcode;
+ TKSTRPTR tg;
{
static short action[MAX_COND_DEPTH];
- static char ifcntl[MAX_COND_DEPTH];
- char *lhs, *expr;
- char *lop, *partstr;
- int result, n, m;
+ static char ifcntl[MAX_COND_DEPTH];
+ char *lhs, *expr, *expr_end;
+ char *lop, *partstr;
+ int result, n, m;
DB_ENTER( "_handle_conditional" );
@@ -502,40 +502,17 @@ TKSTRPTR tg;
lhs = DmStrSpn( expr, " \t" );
if( !*lhs ) lhs = NIL(char);
- if ( (lop = DmStrStr(lhs, "&&" )) != NIL(char) )
- Fatal( ".IF do not support && " );
+ /* Don't support C-style define keyword */
if ( (lop = DmStrStr(lhs, "defined" )) != NIL(char) )
Fatal( ".IF do not support defined " );
if ( (lop = DmStrStr(lhs, "DEFINED" )) != NIL(char) )
Fatal( ".IF do not support defined " );
-/*-----------------18.03.99 14:38-------------------
- * hjs - simple OR fixed and less code
---------------------------------------------------*/
- if ( (lop = DmStrStr(lhs, "||" )) != NIL(char) )
- {
-/* printf("todo: %s\n", expr ); */
- 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 );
-*/
- }
-/*--------------------------------------------------*/
+
+ lhs = expr;
+ SCAN_WHITE( lhs );
+ /* Parse the expression and get its logical result */
+ if ( ((lop = DmStrStr(lhs, "||" )) != NIL(char)) || ((lop = DmStrStr(lhs, "&&" )) != NIL(char)) )
+ result = parse_complex_expression( lhs, &expr_end, opcode );
else
result = partcomp( lhs, opcode );
@@ -582,65 +559,219 @@ TKSTRPTR tg;
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 )
{
char *tok, *rhs, *op = 0;
- int result, opsind;
+ int result, opsind;
const int localopscount=4;
- char* localops[]={"==","!=","<=",">="};
- int lint, rint;
+ char* localops[] = { "==", "!=", "<=", ">=" };
+ int lint, rint;
#define EQUAL 0
#define NOTEQUAL 1
#define LESS_EQUAL 2
#define GREATER_EQUAL 3
- opsind=0;
-/* printf( "eval: %s\n", lhs);*/
- if( opcode == ST_IFEQ || opcode == ST_IFNEQ ) { /* no == */
- for( op = lhs; ((*op)&&(*op != ' ')&&(*op != '\t')); op++ );
- if( *op )
- op++;
- else
- op = NIL(char);
- } else while ( opsind < localopscount && (op = DmStrStr( lhs, localops[opsind] )) == NIL(char))
+ #ifdef PARSE_DEBUG
+ printf( "eval: %s\n", lhs);
+ #endif
+
+ opsind = 0;
+ if( opcode == ST_IFEQ || opcode == ST_IFNEQ )
{
-/* printf("%d %s\n", opsind, localops[opsind]);*/
- opsind++;
+ /* IF[N]EQ syntax is: .IF[N]EQ <1> <2>
+ * 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 )
- Fatal( "Unknown Operator\n" );*/
-
+ /* If the opcode was IFEQ or IFNEQ and only 1 argument was given,
+ * or an unknown logical operator was encountered,
+ * return false if argument is empty string, true if !empty
+ */
if( op == NIL(char) )
- result = (lhs != NIL(char));
- else {
-/* printf("op#%s\n",op);*/
- if( opcode != ST_IFEQ && opcode != ST_IFNEQ ) /* no == */
+ result = (*lhs != '\0');
+ else
+ {
+ /* 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];
-/* printf("op#%s\n",op);*/
- if( lhs != op ) {
- for( tok = op-1; (tok != lhs) && ((*tok == ' ')||(*tok == '\t'));
- tok-- );
- tok[1] = '\0';
+
+ #ifdef PARSE_DEBUG
+ printf(" op:%s\n", op);
+ #endif
+
+ /* Isolate the left half of the expression */
+ if( lhs != op )
+ {
+ for( tok = op-1; (tok != lhs) && ((*tok == ' ')||(*tok == '\t')); tok-- );
+ tok[1] = '\0';
}
else
- lhs = NIL(char);
+ lhs = NIL(char);
- if( opcode == ST_IFEQ || opcode == ST_IFNEQ ) /* no == */
- op--;
+ /* Jump over the operation so we can grab the right half of the expression */
+ if( opcode == ST_IFEQ || opcode == ST_IFNEQ )
+ op--;
else
- op++;
+ op++;
+
+ /* Isolate the right half of the expression */
rhs = DmStrSpn( op+1, " \t" );
if( !*rhs ) rhs = NIL(char);
- if ( opsind > NOTEQUAL ) {
-/* printf("new ops\n");*/
- switch( opsind ){
+ #ifdef PARSE_DEBUG
+ printf(" lhs:%s, rhs:%s\n", lhs, rhs);
+ #endif
+
+ /* Do the actual logical operation on the expression */
+ if ( opsind > NOTEQUAL )
+ {
+ switch( opsind )
+ {
case LESS_EQUAL:
case GREATER_EQUAL:
+ /* Ignore quotes around the arguments */
if ( lhs[0] == '"' ) lhs++;
if ( rhs[0] == '"' ) rhs++;
lint = atoi( lhs );
@@ -653,21 +784,28 @@ int partcomp( char* lhs, int opcode )
result = FALSE;
}
}
- else {
+ else
+ {
+ /* Use a simple string compare to determine equality */
if( (rhs == NIL(char)) || (lhs == NIL(char)) )
- result = (rhs == lhs) ? TRUE : FALSE;
- else {
+ result = (rhs == lhs) ? TRUE : FALSE;
+ else
+ {
+ /* String off whitespace at the end of the right half of the expression */
tok = rhs + strlen( rhs );
- for( tok=tok-1; (tok != lhs) && ((*tok == ' ')||(*tok == '\t'));
- tok--);
+ for( tok=tok-1; (tok != lhs) && ((*tok == ' ')||(*tok == '\t')); tok--);
tok[1] = '\0';
- result = (strcmp( lhs, rhs ) == 0) ? TRUE : FALSE;
+ result = (strcmp( lhs, rhs ) == 0) ? TRUE : FALSE;
}
+
if( *op == '!' || opcode == ST_IFNEQ ) result = !result;
}
}
-/* printf("partresult %d\n",result);*/
+
+ #ifdef PARSE_DEBUG
+ printf("partresult %d\n\n",result);
+ #endif
return result;
}