Subject: make: cond.c improvement?
To: None <tech-toolchain@netbsd.org>
From: Simon Gerraty <sjg@juniper.net>
List: tech-toolchain
Date: 01/05/2004 16:14:48
I was trying to use bmake to see why a freebsd ports build was
failing, but bmake vomits on an expression like:

.if exists(/usr/bin/perl5) && ${OSVERSION} >= 300000 && ${OSVERSION} < 500036

Adding () doesn't help either.
The patch below allows the following test case to perform as expected
for various values of A.

A?=42

all:
.if $A == 42
	@echo "life; don't talk to me about life!"
.elif $A >= 0 && $A < 4
	@echo sane
.else
	@echo reality is over rated
.endif

FreeBSD's CondCvtArg also returns a char *, but they then have to test
for it being empty.  Returning NULL for that case seems simpler.

--sjg

--- cond.c~	Mon Jan  5 15:15:49 2004
+++ cond.c	Mon Jan  5 16:12:20 2004
@@ -145,7 +145,7 @@
 static Boolean CondDoExists(int, char *);
 static Boolean CondDoTarget(int, char *);
 static Boolean CondDoCommands(int, char *);
-static Boolean CondCvtArg(char *, double *);
+static char * CondCvtArg(char *, double *);
 static Token CondToken(Boolean);
 static Token CondT(Boolean);
 static Token CondF(Boolean);
@@ -491,7 +491,8 @@
  *
  * Results:
  *	Sets 'value' to double value of string.
- *	Returns true if the string was a valid number, false o.w.
+ *	Returns NULL if string was fully consumed,
+ *	else returns remaining input.
  *
  * Side Effects:
  *	Can change 'value' even if string is not a valid number.
@@ -499,7 +500,7 @@
  *
  *-----------------------------------------------------------------------
  */
-static Boolean
+static char *
 CondCvtArg(char *str, double *value)
 {
     if ((*str == '0') && (str[1] == 'x')) {
@@ -512,16 +513,15 @@
 	    else if (isxdigit((unsigned char) *str))
 		x = 10 + *str - isupper((unsigned char) *str) ? 'A' : 'a';
 	    else
-		return FALSE;
+		break;
 	    i = (i << 4) + x;
 	}
 	*value = (double) i;
-	return TRUE;
-    }
-    else {
+	return *str ? str : NULL;
+    } else {
 	char *eptr;
 	*value = strtod(str, &eptr);
-	return *eptr == '\0';
+	return *eptr ? eptr : NULL;
     }
 }
 
@@ -747,7 +747,7 @@
 		    double  	left, right;
 		    char    	*string;
 
-		    if (!CondCvtArg(lhs, &left))
+		    if (CondCvtArg(lhs, &left))
 			goto do_string_compare;
 		    if (*rhs == '$') {
 			int 	len;
@@ -757,7 +757,7 @@
 			if (string == var_Error) {
 			    right = 0.0;
 			} else {
-			    if (!CondCvtArg(string, &right)) {
+			    if (CondCvtArg(string, &right)) {
 				if (freeIt)
 				    free(string);
 				goto do_string_compare;
@@ -768,16 +768,19 @@
 				condExpr += len;
 			}
 		    } else {
-			if (!CondCvtArg(rhs, &right))
+			char *cp;
+
+			if ((cp = CondCvtArg(rhs, &right)) &&
+			    cp == rhs)
 			    goto do_string_compare;
 			if (rhs == condExpr) {
 			    /*
 			     * Skip over the right-hand side
 			     */
-			    while(!isspace((unsigned char) *condExpr) &&
-				  (*condExpr != '\0')) {
-				condExpr++;
-			    }
+			    if (cp)
+				condExpr = cp;
+			    else
+				condExpr = strchr(rhs, '\0');	
 			}
 		    }