summaryrefslogtreecommitdiff
path: root/dmake/getinp.c
diff options
context:
space:
mode:
Diffstat (limited to 'dmake/getinp.c')
-rw-r--r--dmake/getinp.c854
1 files changed, 0 insertions, 854 deletions
diff --git a/dmake/getinp.c b/dmake/getinp.c
deleted file mode 100644
index 033374e4c..000000000
--- a/dmake/getinp.c
+++ /dev/null
@@ -1,854 +0,0 @@
-/* RCS $Id: getinp.c,v 1.10 2007-10-15 15:39:23 ihi Exp $
---
--- SYNOPSIS
--- Handle reading of input.
---
--- DESCRIPTION
--- The code in this file reads the input from the specified stream
--- into the provided buffer of size Buffer_size. In doing so it deletes
--- comments. Comments are delimited by the #, and
--- <nl> character sequences. An exception is \# which
--- is replaced by # in the input. Line continuations are signalled
--- at the end of a line and are recognized inside comments.
--- The line continuation is always <\><nl>.
---
--- If the file to read is NIL(FILE) then the Get_line routine returns the
--- next rule from the builtin rule table (Rule_tab from ruletab.c) if
--- there is one.
---
--- AUTHOR
--- Dennis Vadura, dvadura@dmake.wticorp.com
---
--- WWW
--- http://dmake.wticorp.com/
---
--- COPYRIGHT
--- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
---
--- This program is NOT free software; you can redistribute it and/or
--- modify it under the terms of the Software License Agreement Provided
--- in the file <distribution-root>/readme/license.txt.
---
--- LOG
--- Use cvs log to obtain detailed change logs.
-*/
-
-#include "extern.h"
-
-#define IS_WHITE(A) ((A == ' ') || (A == '\t') || (A == '\n') || (A == '\r'))
-#define SCAN_WHITE(A) \
- while( IS_WHITE(*A) ) A++;
-
-static int _is_conditional ANSI((char*));
-static int _handle_conditional ANSI((int, TKSTRPTR));
-
-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
-Get_line( buf, fil )/*
-======================
- Read a line of input from the file stripping off comments. The routine
- returns TRUE if EOF. If fil equals NIL(FILE) then the next line from
- *Rule_tab[] is used. Rule_tab is either the buildin rule table or points
- to the current environment (used by ReadEnvironment()).
- The function returns TRUE if the input file/buffer was read to the end
- and FALSE otherwise. */
-char *buf;
-FILE *fil;
-{
- extern char **Rule_tab;
- register char *p;
- register char *c;
- char *q;
- char *buf_org;
- static int ignore = FALSE;
- int cont = FALSE;
- int pos = 0;
- int res = 0;
- register char *tmp = NIL(char);
-
- DB_ENTER( "Get_line" );
-
- if( Skip_to_eof ) {
- Skip_to_eof = FALSE;
- rule_ind = 0;
-
- if( Verbose & V_MAKE )
- Warning("Ignoring remainder of file %s", Filename());
-
- DB_RETURN(TRUE);
- }
-
- if( fil == NIL(FILE) ) {
- /* Reading the internal rule table. Set rule_ind to zero after the
- * last entry so that ReadEnvironment() works as expected every time. */
-
- while( (p = Rule_tab[ rule_ind++ ]) != NIL(char) ) {
- /* The last test in this if *p != '~', handles the environment
- * passing conventions used by MKS to pass arguments. We want to
- * skip those environment entries. Also CYGWIN likes to export '!'
- * prefixed environment variables that cause severe pain, axe them too.
- * And finally it is possible to do "env 'GGG HHH'='some value' bash"
- * which causes that there are env variables with spaces in the name
- * defined which causes dmake to malfunction too */
- char *equal = strchr(p,'=');
- char *space = strchr(p,' ');
- if( !Readenv || (Readenv && (equal != NIL(char)) && (space == NIL(char) || space > equal) && *p!='~' && *p!='!')){
- strcpy( buf, p );
-
- DB_PRINT( "io", ("Returning [%s]", buf) );
- DB_RETURN( FALSE );
- }
- }
-
- rule_ind = 0;
-
- DB_PRINT( "io", ("Done Ruletab") );
- DB_RETURN( TRUE );
- }
-
- buf_org = buf;
-
-do_again:
- do {
- p = buf+pos;
- /* fgets() reads at most one less than Buffer_size-pos characters. */
- if(feof( fil ) || (fgets( p, Buffer_size-pos, fil ) == NIL(char)))
- DB_RETURN( TRUE );
-
-#ifdef _MPW
- if ( p[0] == 10 && p[1] == COMMENT_CHAR)
- p[0] = ' ';
-#endif
-
- Line_number++;
-
- /* Set q to the last char in p before the \n\0. */
- q = p+strlen(p)-2;
- if( q >= p ) { /* Only check for special cases if p points
- * to a non-empty line. */
-
- /* ignore each RETURN at the end of a line before any further
- * processing */
- if( q[0] == '\r' && q[1] == '\n' ) {
- q[0] = '\n';
- q[1] = '\0';
- q--;
- }
- /* you also have to deal with END_OF_FILE chars to process raw
- * DOS-Files. Normally they are the last chars in file, but after
- * working on these file with vi, there is an additional NEWLINE
- * after the last END_OF_FILE. So if the second last char in the
- * actual line is END_OF_FILE, you can skip the last char. Then
- * you can search the line back until you find no more END_OF_FILE
- * and nuke each you found by string termination. */
- if( q[0] == '\032' )
- q--;
- while( q[1] == '\032' ) {
- q[1] = '\0';
- q--;
- }
-
- /* ignore input if ignore flag set and line ends in a continuation
- character. */
-
- if( ignore ) {
- if( q[0] != CONTINUATION_CHAR || q[1] != '\n' ) ignore = FALSE;
- *p = '\0';
- continue;
- }
-
- /* If a comment is found the line does not end in \n anymore. */
- c = Do_comment(p, &q, Group || (*buf == '\t') || (Notabs && *buf ==' '));
-
- /* Does the end of the line end in a continuation sequence? */
-
- if( (q[0] == CONTINUATION_CHAR) && (q[1] == '\n')) {
- /* If the continuation was at the end of a comment then ignore the
- * next input line, (or lines until we get one ending in just <nl>)
- * else it's a continuation, so build the input line from several
- * text lines on input. The maximum size of this is governened by
- * Buffer_size */
- if( q != p && q[-1] == CONTINUATION_CHAR ) {
- size_t len = strlen(q+1)+1;
- memmove( q, q+1, len );
- q--;
- cont = FALSE;
- }
- else if( c != NIL(char) )
- ignore = TRUE;
- else
- cont = TRUE; /* Keep the \<nl>. */
- }
- else {
- cont = FALSE;
- }
-
- q = ( c == NIL(char) ) ? q+2 : c;
- }
- else { /* empty line or "" */
- cont = FALSE;
- ignore = FALSE;
- q = p+strlen(p); /* strlen(p) is 1 or 0 */
- }
-
- pos += q-p;
- }
- while( (cont || !*buf) && (pos < Buffer_size-1) );
-
- if( pos >= Buffer_size-1 )
- Fatal( "Input line too long, increase MAXLINELENGTH" );
-
- /* Lines that had comments don't contain \n anymore. */
- /* ??? Continued lines that are followed by an empty or comment only
- * line will end in \<nl>. */
- if( (q > p) && (buf[ pos-1 ] == '\n') )
- buf[ --pos ] = '\0'; /* Remove the final \n. */
-
- /* STUPID AUGMAKE uses "include" at the start of a line as
- * a signal to include a new file, so let's look for it.
- * if we see it replace it by .INCLUDE: and stick this back
- * into the buffer. We also allow GNU make if[n]eq/else/endif.
- *
- * These substitutions are made only if we are not parsing a group
- * recipe. */
- if( (p = DmStrSpn(buf, " \t\r\n")) == NIL(char) )
- p = buf;
-
- if (!Group) {
- if( !strncmp( "include", p, 7 ) &&
- (p[7] == ' ' || p[7] == '\t') )
- tmp = DmStrJoin( ".INCLUDE:", p+7, -1, FALSE );
- else if( !strncmp( "ifeq", p, 4 ) &&
- (p[4] == ' ' || p[4] == '\t') )
- tmp = DmStrJoin( ".IFEQ", p+4, -1, FALSE );
- else if( !strncmp( "ifneq", p, 5 ) &&
- (p[5] == ' ' || p[5] == '\t') )
- tmp = DmStrJoin( ".IFNEQ", p+5, -1, FALSE );
- else if( !strncmp( "elif", p, 4 ) &&
- (p[4] == ' ' || p[4] == '\t') )
- tmp = DmStrJoin( ".ELIF", p+4, -1, FALSE );
- else if( !strncmp( "else", p, 4 ) &&
- (p[4] == ' ' || p[4] == '\t' || p[4] == '\0') )
- tmp = DmStrJoin( ".ELSE", p+4, -1, FALSE );
- else if( !strncmp( "endif", p, 5 ) &&
- (p[5] == ' ' || p[5] == '\t' || p[5] == '\0') )
- tmp = DmStrJoin( ".END", p+5, -1, FALSE );
- }
-
- if( tmp != NIL(char)) {
- strcpy( buf, tmp );
- FREE( tmp );
- tmp = NIL(char);
- }
-
- /* Now that we have the next line of input to make, we should check to
- * see if it is a conditional expression. If it is then process it,
- * otherwise pass it on to the parser. */
-
- if( *(p = DmStrSpn(buf, " \t\r\n")) == CONDSTART ) {
- TKSTR token;
-
- SET_TOKEN( &token, p );
-
- p = Get_token( &token, "", FALSE );
-
- if( (res = _is_conditional(p)) != 0 ) /* ignore non-control special */
- { /* targets */
- res = _handle_conditional( res, &token );
- skip = TRUE;
- }
- else {
- CLEAR_TOKEN( &token );
- res = TRUE;
- }
- }
-
- if( skip ) {
- buf = buf_org; /* ignore line just read in */
- pos = 0;
- skip = res;
- goto do_again;
- }
-
- DB_PRINT( "io", ("Returning [%s]", buf) );
- DB_RETURN( FALSE );
-}
-
-
-PUBLIC char *
-Do_comment(str, pend, keep)/*
-=============================
- Search the input string looking for comment chars. If it contains
- comment chars then NUKE the remainder of the line, if the comment
- char is preceeded by \ then shift the remainder of the line left
- by one char. */
-char *str;
-char **pend;
-int keep;
-{
- char *c = str;
-
- while( (c = strchr(c, COMMENT_CHAR)) != NIL(char) ) {
- if( Comment || State == NORMAL_SCAN )
- if( c != str && c[-1] == ESCAPE_CHAR ) {
- size_t len = strlen(c)+1;
- memmove( c-1, c, len ); /* copy it left, due to \# */
- if( pend ) (*pend)--; /* shift tail pointer left */
- }
- else {
- /* Check/execute if shebang command is present. */
- if( !No_exec
- && c == str
- && c[1] == '!'
- && Line_number == 1
- && Nestlevel() == 1 ) {
- char *cmnd;
-
- cmnd = Expand(c+2);
- cmnd[strlen(cmnd)-1] = '\0'; /* strip last newline */
- Current_target = Root;
-#if defined(MSDOS)
- Swap_on_exec = TRUE;
-#endif
- Wait_for_completion = TRUE;
- Do_cmnd(&cmnd, FALSE, TRUE, Current_target, A_DEFAULT, TRUE);
-#if defined(MSDOS)
- Swap_on_exec = FALSE;
-#endif
- Wait_for_completion = FALSE;
- FREE(cmnd);
- }
-
- *c = '\0'; /* a true comment so break */
- break;
- }
- else {
- if( keep )
- c = NIL(char);
- else
- *c = '\0';
-
- break;
- }
- }
-
- return(c);
-}
-
-
-PUBLIC char *
-Get_token( string, brk, anchor )/*
-==================================
- Return the next token in string.
-
- Returns empty string when no more tokens in string.
- brk is a list of chars that also cause breaks in addition to space and
- tab, but are themselves returned as tokens. if brk is NULL then the
- remainder of the line is returned as a single token.
-
- 'anchor' if 1, says break on chars in the brk list, but only if
- the entire token begins with the first char of the brk list, if
- 0 then any char of brk will cause a break to occurr.
-
- If 'anchor' is 2, then break only seeing the first char in the break
- list allowing only chars in the break list to form the prefix. */
-
-TKSTRPTR string;
-char *brk;
-int anchor;
-{
- register char *s;
- register char *curp = 0;
- register char *t;
- int done = FALSE;
- char space[100];
-
- DB_ENTER( "Get_token" );
-
- s = string->tk_str; /* Get string parameters */
- *s = string->tk_cchar; /* ... and strip leading w/s */
-
- SCAN_WHITE( s );
-
- DB_PRINT( "tok", ("What's left [%s]", s) );
-
- if( !*s ) {
- DB_PRINT( "tok", ("Returning NULL token") );
- DB_RETURN( "" );
- }
-
-
- /* Build the space list. space contains all those chars that may possibly
- * cause breaks. This includes the brk list as well as white space. */
-
- if( brk != NIL(char) ) {
- strcpy( space, " \t\r\n" );
- strcat( space, brk );
- }
- else {
- space[0] = 0xff; /* a char we know will not show up */
- space[1] = 0;
- }
-
-
- /* Handle processing of quoted tokens. Note that this is disabled if
- * brk is equal to NIL */
-
- while( *s == '\"' && ((brk != NIL(char)) || !string->tk_quote) ) {
- s++;
- if( string->tk_quote ) {
- curp = s-1;
- do { curp = strchr( curp+1, '\"' ); }
- while( (curp != NIL(char)) && (*(curp+1) == '\"'));
-
- if( curp == NIL(char) ) Fatal( "Unmatched quote in token" );
- string->tk_quote = !string->tk_quote;
-
- /* Check for "" case, and if found ignore it */
- if( curp == s ) continue;
- goto found_token;
- }
- else
- SCAN_WHITE( s );
-
- string->tk_quote = !string->tk_quote;
- }
-
-
- /* Check for a token break character at the beginning of the token.
- * If found return the next set of break chars as a token. */
-
- if( anchor == 2 && brk != NIL(char) ) {
- curp = s;
- while( *curp && (strchr(brk,*curp)!=NIL(char)) && (*curp!=*brk) ) curp++;
- done = (*brk == *curp++);
- }
- else if( (brk != NIL(char)) && (strchr( brk, *s ) != NIL(char)) ) {
- curp = DmStrSpn( s, brk );
- done = (anchor == 0) ? TRUE :
- ((anchor == 1)?(*s == *brk) : (*brk == curp[-1]));
- }
-
-
- /* Scan for the next token in the list and return it less the break char
- * that was used to terminate the token. It will possibly be returned in
- * the next call to Get_token */
-
- if( !done ) {
- SCAN_WHITE( s );
-
- t = s;
- do {
- done = TRUE;
- curp = DmStrPbrk(t, space);
-
- if( anchor && *curp && !IS_WHITE( *curp ) )
- if( ((anchor == 1)?*curp:DmStrSpn(curp,brk)[-1]) != *brk ) {
- t++;
- done = FALSE;
- }
- }
- while( !done );
-
- if( (curp == s) && (strchr(brk, *curp) != NIL(char)) ) curp++;
- }
-
-found_token:
- string->tk_str = curp;
- string->tk_cchar = *curp;
- *curp = '\0';
-
- DB_PRINT( "tok", ("Returning [%s]", s) );
- DB_RETURN( s );
-}
-
-
-static int
-_is_conditional( tg )/*
-=======================
- Look at tg and return it's value if it is a conditional identifier
- otherwise return 0. */
-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;
-
- case 'E':
- 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;
- }
-
- DB_RETURN( 0 );
-}
-
-
-
-#define SEEN_END 0x00
-#define SEEN_IF 0x01
-#define SEEN_ELSE 0x02
-#define SEEN_ELIF 0x04
-
-#define ACCEPT_IF 0x10
-#define ACCEPT_ELIF 0x20
-
-static int
-_handle_conditional( opcode, tg )
- int opcode;
- TKSTRPTR tg;
-{
- static short action[MAX_COND_DEPTH];
- static char ifcntl[MAX_COND_DEPTH];
- char *cst;
- char *lhs, *expr, *expr_end;
- char *lop;
- int result;
-
- DB_ENTER( "_handle_conditional" );
-
- switch( opcode ) {
- case ST_ELIF:
- if( !(ifcntl[Nest_level] & SEEN_IF) || (ifcntl[Nest_level]&SEEN_ELSE) )
- Fatal(".ELIF without a preceeding .IF" );
- /*FALLTHRU*/
-
- case ST_IF:
- case ST_IFEQ:
- case ST_IFNEQ:
- if( opcode != ST_ELIF && (Nest_level+1) == MAX_COND_DEPTH )
- Fatal( ".IF .ELSE ... .END nesting too deep" );
-
- If_expand = TRUE;
- expr = Expand( Get_token( tg, NIL(char), FALSE ));
- If_expand = FALSE;
-
- /* Remove CONTINUATION_CHAR<nl> and replace with " " so that line
- * continuations are recognized as whitespace. */
- for( cst=strchr(expr,CONTINUATION_CHAR); cst != NIL(char); cst=strchr(cst,CONTINUATION_CHAR) )
- if( cst[1] == '\n' ) {
- *cst = ' ';
- cst[1] = ' ';
- }
- else
- cst++;
-
- 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 );
-
- if( expr != NIL(char) ) FREE( expr );
-
- if( opcode != ST_ELIF ) {
- Nest_level++;
- action[Nest_level] = 1;
- }
- ifcntl[Nest_level] |= (opcode==ST_ELIF)?SEEN_ELIF:SEEN_IF;
-
- if( result ) {
- if( !(ifcntl[Nest_level] & (ACCEPT_IF|ACCEPT_ELIF)) ) {
- action[ Nest_level ] = action[ Nest_level-1 ];
- ifcntl[Nest_level] |= (opcode==ST_ELIF)?ACCEPT_ELIF:ACCEPT_IF;
- }
- else
- action[Nest_level] = 1;
- }
- else
- action[Nest_level] = 1;
- break;
-
- case ST_ELSE:
- if( Nest_level <= 0 ) Fatal( ".ELSE without .IF" );
- if( ifcntl[Nest_level] & SEEN_ELSE )
- Fatal( "Missing .IF or .ELIF before .ELSE" );
-
- if( ifcntl[Nest_level] & (ACCEPT_IF|ACCEPT_ELIF) )
- action[Nest_level] = 1;
- else if( action[ Nest_level-1 ] != 1 )
- action[ Nest_level ] ^= 0x1; /* flip between 0 and 1 */
-
- ifcntl[Nest_level] |= SEEN_ELSE;
- break;
-
- case ST_END:
- ifcntl[Nest_level] = SEEN_END;
- Nest_level--;
- if( Nest_level < 0 ) Fatal( "Unmatched .END[IF]" );
- break;
- }
-
- 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 ): Opcode: %d\n", n, expr, opcode );
- #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;
- const int localopscount=4;
- char* localops[] = { "==", "!=", "<=", ">=" };
- int lint, rint;
-
-#define EQUAL 0
-#define NOTEQUAL 1
-#define LESS_EQUAL 2
-#define GREATER_EQUAL 3
-
- #ifdef PARSE_DEBUG
- printf( "eval: %s\n", lhs);
- #endif
-
- opsind = 0;
- if( opcode == ST_IFEQ || opcode == ST_IFNEQ )
- {
- /* 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 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 != '\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];
-
- #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); /* Left hand side is empty. */
-
- /* Jump over the operation so we can grab the right half of the expression */
- if( opcode == ST_IFEQ || opcode == ST_IFNEQ )
- op--;
- else
- op++;
-
- /* Isolate the right half of the expression */
- rhs = DmStrSpn( op+1, " \t" );
- if( !*rhs ) rhs = NIL(char);
-
- #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 && lhs[0] == '"' ) lhs++;
- if ( rhs && rhs[0] == '"' ) rhs++;
-
- /* Empty strings evaluate to zero. */
- lint = lhs ? atoi( lhs ) : 0;
- rint = rhs ? atoi( rhs ) : 0;
- result = ( lint >= rint ) ? TRUE : FALSE;
- if ( opsind == LESS_EQUAL && lint != rint )
- result = !result;
- break;
- default:
- result = FALSE;
- }
- }
- else
- {
- /* Use a simple string compare to determine equality */
- if( (rhs == NIL(char)) || (lhs == NIL(char)) )
- 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--);
- tok[1] = '\0';
-
- result = (strcmp( lhs, rhs ) == 0) ? TRUE : FALSE;
- }
-
- if( *op == '!' || opcode == ST_IFNEQ ) result = !result;
- }
- }
-
- #ifdef PARSE_DEBUG
- printf("partresult %d\n\n",result);
- #endif
- return result;
-}
-