Module Name:    src
Committed By:   rillig
Date:           Thu Jan 21 23:25:08 UTC 2021

Modified Files:
        src/usr.bin/make: cond.c
        src/usr.bin/make/unit-tests: cond-cmp-numeric-eq.exp
            cond-cmp-numeric.exp cond-cmp-string.exp cond-token-plain.exp

Log Message:
make(1): fix debug output for comparison operators in conditionals

This produces fewer warnings than before, but these were edge cases that
probably didn't matter in practice.  The "Malformaed conditional" is
still generated, the set of accepted conditionals is still the same.


To generate a diff of this commit:
cvs rdiff -u -r1.250 -r1.251 src/usr.bin/make/cond.c
cvs rdiff -u -r1.3 -r1.4 src/usr.bin/make/unit-tests/cond-cmp-numeric-eq.exp \
    src/usr.bin/make/unit-tests/cond-cmp-numeric.exp
cvs rdiff -u -r1.9 -r1.10 src/usr.bin/make/unit-tests/cond-cmp-string.exp
cvs rdiff -u -r1.7 -r1.8 src/usr.bin/make/unit-tests/cond-token-plain.exp

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.bin/make/cond.c
diff -u src/usr.bin/make/cond.c:1.250 src/usr.bin/make/cond.c:1.251
--- src/usr.bin/make/cond.c:1.250	Thu Jan 21 23:06:06 2021
+++ src/usr.bin/make/cond.c	Thu Jan 21 23:25:08 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: cond.c,v 1.250 2021/01/21 23:06:06 rillig Exp $	*/
+/*	$NetBSD: cond.c,v 1.251 2021/01/21 23:25:08 rillig Exp $	*/
 
 /*
  * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -95,7 +95,7 @@
 #include "dir.h"
 
 /*	"@(#)cond.c	8.2 (Berkeley) 1/2/94"	*/
-MAKE_RCSID("$NetBSD: cond.c,v 1.250 2021/01/21 23:06:06 rillig Exp $");
+MAKE_RCSID("$NetBSD: cond.c,v 1.251 2021/01/21 23:25:08 rillig Exp $");
 
 /*
  * The parsing of conditional expressions is based on this grammar:
@@ -137,6 +137,10 @@ typedef enum CondResult {
 	CR_FALSE, CR_TRUE, CR_ERROR
 } CondResult;
 
+typedef enum ComparisonOp {
+	LT, LE, GT, GE, EQ, NE
+} ComparisonOp;
+
 typedef struct CondParser {
 
 	/*
@@ -167,6 +171,8 @@ static CondResult CondParser_Or(CondPars
 static unsigned int cond_depth = 0;	/* current .if nesting level */
 static unsigned int cond_min_depth = 0;	/* depth at makefile open */
 
+static const char *opname[] = { "<", "<=", ">", ">=", "==", "!=" };
+
 /*
  * Indicate when we should be strict about lhs of comparisons.
  * In strict mode, the lhs must be a variable expression or a string literal
@@ -575,65 +581,90 @@ EvalNotEmpty(CondParser *par, const char
 }
 
 /* Evaluate a numerical comparison, such as in ".if ${VAR} >= 9". */
-static Token
-EvalCompareNum(double lhs, const char *op, double rhs)
+static Boolean
+EvalCompareNum(double lhs, ComparisonOp op, double rhs)
 {
-	/* FIXME: %2.s is cheated and produces wrong output. */
-	DEBUG3(COND, "lhs = %f, rhs = %f, op = %.2s\n", lhs, rhs, op);
+	DEBUG3(COND, "lhs = %f, rhs = %f, op = %.2s\n", lhs, rhs, opname[op]);
 
-	switch (op[0]) {
-	case '!':
-		if (op[1] != '=') {
-			Parse_Error(PARSE_WARNING, "Unknown operator");
-			/* The PARSE_FATAL follows in CondEvalExpression. */
-			return TOK_ERROR;
-		}
-		return ToToken(lhs != rhs);
-	case '=':
-		if (op[1] != '=') {
-			Parse_Error(PARSE_WARNING, "Unknown operator");
-			/* The PARSE_FATAL follows in CondEvalExpression. */
-			return TOK_ERROR;
-		}
-		return ToToken(lhs == rhs);
-	case '<':
-		return ToToken(op[1] == '=' ? lhs <= rhs : lhs < rhs);
-	case '>':
-		return ToToken(op[1] == '=' ? lhs >= rhs : lhs > rhs);
+	switch (op) {
+	case LT:
+		return lhs < rhs;
+	case LE:
+		return lhs <= rhs;
+	case GT:
+		return lhs > rhs;
+	case GE:
+		return lhs >= rhs;
+	case NE:
+		return lhs != rhs;
+	default:
+		return lhs == rhs;
 	}
-	return TOK_ERROR;
 }
 
 static Token
-EvalCompareStr(const char *lhs, const char *op, const char *rhs)
+EvalCompareStr(const char *lhs, ComparisonOp op, const char *rhs)
 {
-	if (!((op[0] == '!' || op[0] == '=') && op[1] == '=')) {
+	if (op != EQ && op != NE) {
 		Parse_Error(PARSE_WARNING,
-			    "String comparison operator "
-			    "must be either == or !=");
+		    "String comparison operator must be either == or !=");
 		/* The PARSE_FATAL follows in CondEvalExpression. */
 		return TOK_ERROR;
 	}
 
-	/* FIXME: %2.s is cheated and produces wrong output. */
-	DEBUG3(COND, "lhs = \"%s\", rhs = \"%s\", op = %.2s\n", lhs, rhs, op);
-	return ToToken((*op == '=') == (strcmp(lhs, rhs) == 0));
+	DEBUG3(COND, "lhs = \"%s\", rhs = \"%s\", op = %.2s\n",
+	    lhs, rhs, opname[op]);
+	return ToToken((op == EQ) == (strcmp(lhs, rhs) == 0));
 }
 
 /* Evaluate a comparison, such as "${VAR} == 12345". */
 static Token
-EvalCompare(const char *lhs, Boolean lhsQuoted, const char *op,
+EvalCompare(const char *lhs, Boolean lhsQuoted, ComparisonOp op,
 	    const char *rhs, Boolean rhsQuoted)
 {
 	double left, right;
 
 	if (!rhsQuoted && !lhsQuoted)
 		if (TryParseNumber(lhs, &left) && TryParseNumber(rhs, &right))
-			return EvalCompareNum(left, op, right);
+			return ToToken(EvalCompareNum(left, op, right));
 
 	return EvalCompareStr(lhs, op, rhs);
 }
 
+static Boolean
+CondParser_ComparisonOp(CondParser *par, ComparisonOp *out_op)
+{
+	const char *p = par->p;
+
+	if (p[0] == '<' && p[1] == '=') {
+		*out_op = LE;
+		goto length_2;
+	} else if (p[0] == '<') {
+		*out_op = LT;
+		goto length_1;
+	} else if (p[0] == '>' && p[1] == '=') {
+		*out_op = GE;
+		goto length_2;
+	} else if (p[0] == '>') {
+		*out_op = GT;
+		goto length_1;
+	} else if (p[0] == '=' && p[1] == '=') {
+		*out_op = EQ;
+		goto length_2;
+	} else if (p[0] == '!' && p[1] == '=') {
+		*out_op = NE;
+		goto length_2;
+	}
+	return FALSE;
+
+length_2:
+	par->p = p + 2;
+	return TRUE;
+length_1:
+	par->p = p + 1;
+	return TRUE;
+}
+
 /*
  * Parse a comparison condition such as:
  *
@@ -647,7 +678,7 @@ CondParser_Comparison(CondParser *par, B
 {
 	Token t = TOK_ERROR;
 	FStr lhs, rhs;
-	const char *op;
+	ComparisonOp op;
 	Boolean lhsQuoted, rhsQuoted;
 
 	/*
@@ -660,18 +691,7 @@ CondParser_Comparison(CondParser *par, B
 
 	CondParser_SkipWhitespace(par);
 
-	op = par->p;
-	switch (par->p[0]) {
-	case '!':
-	case '=':
-	case '<':
-	case '>':
-		if (par->p[1] == '=')
-			par->p += 2;
-		else
-			par->p++;
-		break;
-	default:
+	if (!CondParser_ComparisonOp(par, &op)) {
 		/* Unknown operator, compare against an empty string or 0. */
 		t = ToToken(doEval && EvalNotEmpty(par, lhs.str, lhsQuoted));
 		goto done_lhs;

Index: src/usr.bin/make/unit-tests/cond-cmp-numeric-eq.exp
diff -u src/usr.bin/make/unit-tests/cond-cmp-numeric-eq.exp:1.3 src/usr.bin/make/unit-tests/cond-cmp-numeric-eq.exp:1.4
--- src/usr.bin/make/unit-tests/cond-cmp-numeric-eq.exp:1.3	Sun Nov  8 21:47:59 2020
+++ src/usr.bin/make/unit-tests/cond-cmp-numeric-eq.exp	Thu Jan 21 23:25:08 2021
@@ -1,4 +1,3 @@
-make: "cond-cmp-numeric-eq.mk" line 67: warning: Unknown operator
 make: "cond-cmp-numeric-eq.mk" line 67: Malformed conditional (!(12345 = 12345))
 make: "cond-cmp-numeric-eq.mk" line 74: Malformed conditional (!(12345 === 12345))
 make: Fatal errors encountered -- cannot continue
Index: src/usr.bin/make/unit-tests/cond-cmp-numeric.exp
diff -u src/usr.bin/make/unit-tests/cond-cmp-numeric.exp:1.3 src/usr.bin/make/unit-tests/cond-cmp-numeric.exp:1.4
--- src/usr.bin/make/unit-tests/cond-cmp-numeric.exp:1.3	Sun Nov  8 22:56:16 2020
+++ src/usr.bin/make/unit-tests/cond-cmp-numeric.exp	Thu Jan 21 23:25:08 2021
@@ -7,8 +7,6 @@ make: "cond-cmp-numeric.mk" line 16: Mal
 CondParser_Eval: !(${:UNaN} == NaN)
 lhs = "NaN", rhs = "NaN", op = ==
 CondParser_Eval: 123 ! 123
-lhs = 123.000000, rhs = 123.000000, op = ! 
-make: "cond-cmp-numeric.mk" line 34: warning: Unknown operator
 make: "cond-cmp-numeric.mk" line 34: Malformed conditional (123 ! 123)
 make: Fatal errors encountered -- cannot continue
 make: stopped in unit-tests

Index: src/usr.bin/make/unit-tests/cond-cmp-string.exp
diff -u src/usr.bin/make/unit-tests/cond-cmp-string.exp:1.9 src/usr.bin/make/unit-tests/cond-cmp-string.exp:1.10
--- src/usr.bin/make/unit-tests/cond-cmp-string.exp:1.9	Tue Jan 19 19:54:57 2021
+++ src/usr.bin/make/unit-tests/cond-cmp-string.exp	Thu Jan 21 23:25:08 2021
@@ -1,6 +1,5 @@
 make: "cond-cmp-string.mk" line 18: Malformed conditional (str != str)
 make: "cond-cmp-string.mk" line 42: Malformed conditional ("string" != "str""ing")
-make: "cond-cmp-string.mk" line 49: warning: String comparison operator must be either == or !=
 make: "cond-cmp-string.mk" line 49: Malformed conditional (!("value" = "value"))
 make: "cond-cmp-string.mk" line 56: Malformed conditional (!("value" === "value"))
 make: "cond-cmp-string.mk" line 113: warning: String comparison operator must be either == or !=

Index: src/usr.bin/make/unit-tests/cond-token-plain.exp
diff -u src/usr.bin/make/unit-tests/cond-token-plain.exp:1.7 src/usr.bin/make/unit-tests/cond-token-plain.exp:1.8
--- src/usr.bin/make/unit-tests/cond-token-plain.exp:1.7	Thu Jan 21 14:08:09 2021
+++ src/usr.bin/make/unit-tests/cond-token-plain.exp	Thu Jan 21 23:25:08 2021
@@ -18,9 +18,9 @@ lhs = "yes", rhs = "yes", op = !=
 CondParser_Eval: ${UNDEF:Uundefined}!=undefined
 lhs = "undefined", rhs = "undefined", op = !=
 CondParser_Eval: ${UNDEF:U12345}>12345
-lhs = 12345.000000, rhs = 12345.000000, op = >1
+lhs = 12345.000000, rhs = 12345.000000, op = >
 CondParser_Eval: ${UNDEF:U12345}<12345
-lhs = 12345.000000, rhs = 12345.000000, op = <1
+lhs = 12345.000000, rhs = 12345.000000, op = <
 CondParser_Eval: (${UNDEF:U0})||0
 CondParser_Eval: ${:Uvar}&&name != "var&&name"
 lhs = "var&&name", rhs = "var&&name", op = !=

Reply via email to