Subject: Re: make(1) question; purpose of ${ :? : }
To: Luke Mewburn <lukem@NetBSD.org>
From: Simon Gerraty <sjg@juniper.net>
List: tech-toolchain
Date: 01/09/2004 15:46:14
Not sure this is a good idea... CondToken is in need of
restructuring I suspect... 

Anyway, the patch below allows you to do expressions like

string == string
N > M

etc, which are not currently supported unless the lhs is a variable
expression.

Ie. with this you can actually do 

x:
	@echo "The answer for '$A' is ${$A :? yes : no}"

$ make -f /homes/sjg/make-tests/ternary A='1 > 2'
The answer for '1 > 2' is no
$ make -f /homes/sjg/make-tests/ternary A='3 > 2'
The answer for '3 > 2' is yes
$ make -f /homes/sjg/make-tests/ternary A='defined(USER) && ${USER} == "sjg"'
The answer for 'defined(USER) && sjg == sjg' is yes
$ make -f /homes/sjg/make-tests/ternary A='defined(USER) && ${USER} == "root"'
The answer for 'defined(USER) && sjg == root' is no
$

--sjg

--- cond.c~	Mon Jan  5 17:18:52 2004
+++ cond.c	Fri Jan  9 15:24:10 2004
@@ -542,6 +542,13 @@
 CondToken(Boolean doEval)
 {
     Token	  t;
+    Boolean	doFree;
+    Boolean	rawSymbol;
+    char *lhs;
+    char *rhs;
+    char *op;
+
+    rawSymbol = False;
 
     if (condPushBack == None) {
 	while (*condExpr == ' ' || *condExpr == '\t') {
@@ -580,11 +587,7 @@
 		t = EndOfFile;
 		break;
 	    case '$': {
-		char	*lhs;
-		char	*rhs;
-		char	*op;
 		int	varSpecLen;
-		Boolean	doFree;
 
 		/*
 		 * Parse the variable spec and skip over it, saving its
@@ -601,6 +604,7 @@
 		}
 		condExpr += varSpecLen;
 
+	    do_expr:
 		if (!isspace((unsigned char) *condExpr) &&
 		    strchr("!=><", *condExpr) == NULL) {
 		    Buffer buf;
@@ -950,10 +954,28 @@
 		     * binary operator) and set to invert the evaluation
 		     * function if condInvert is TRUE.
 		     */
+		    rawSymbol = True;
 		use_default:
 		    invert = condInvert;
 		    evalProc = condDefProc;
 		    arglen = CondGetArg(&condExpr, &arg, "", FALSE);
+
+		    if (rawSymbol) {
+			char *cp = condExpr;
+
+			while (isspace((unsigned char) *cp)) {
+			    cp++;
+			}	
+			switch (*cp) {
+			case '!':
+			case '=':
+			case '<':
+			case '>':
+			    doFree = (arglen > 0);
+			    lhs = arg;
+			    goto do_expr;
+			}
+		    }
 		}
 
 		/*