Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/usr.bin/make make(1): fix debug output for comparison operat...



details:   https://anonhg.NetBSD.org/src/rev/548614f0953e
branches:  trunk
changeset: 958839:548614f0953e
user:      rillig <rillig%NetBSD.org@localhost>
date:      Thu Jan 21 23:25:08 2021 +0000

description:
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.

diffstat:

 usr.bin/make/cond.c                             |  116 ++++++++++++++---------
 usr.bin/make/unit-tests/cond-cmp-numeric-eq.exp |    1 -
 usr.bin/make/unit-tests/cond-cmp-numeric.exp    |    2 -
 usr.bin/make/unit-tests/cond-cmp-string.exp     |    1 -
 usr.bin/make/unit-tests/cond-token-plain.exp    |    4 +-
 5 files changed, 70 insertions(+), 54 deletions(-)

diffs (236 lines):

diff -r 8dd3b580c1a2 -r 548614f0953e usr.bin/make/cond.c
--- a/usr.bin/make/cond.c       Thu Jan 21 23:06:06 2021 +0000
+++ b/usr.bin/make/cond.c       Thu Jan 21 23:25:08 2021 +0000
@@ -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 @@
        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 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 @@
 }
 
 /* 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 @@
 {
        Token t = TOK_ERROR;
        FStr lhs, rhs;
-       const char *op;
+       ComparisonOp op;
        Boolean lhsQuoted, rhsQuoted;
 
        /*
@@ -660,18 +691,7 @@
 
        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;
diff -r 8dd3b580c1a2 -r 548614f0953e usr.bin/make/unit-tests/cond-cmp-numeric-eq.exp
--- a/usr.bin/make/unit-tests/cond-cmp-numeric-eq.exp   Thu Jan 21 23:06:06 2021 +0000
+++ b/usr.bin/make/unit-tests/cond-cmp-numeric-eq.exp   Thu Jan 21 23:25:08 2021 +0000
@@ -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
diff -r 8dd3b580c1a2 -r 548614f0953e usr.bin/make/unit-tests/cond-cmp-numeric.exp
--- a/usr.bin/make/unit-tests/cond-cmp-numeric.exp      Thu Jan 21 23:06:06 2021 +0000
+++ b/usr.bin/make/unit-tests/cond-cmp-numeric.exp      Thu Jan 21 23:25:08 2021 +0000
@@ -7,8 +7,6 @@
 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
diff -r 8dd3b580c1a2 -r 548614f0953e usr.bin/make/unit-tests/cond-cmp-string.exp
--- a/usr.bin/make/unit-tests/cond-cmp-string.exp       Thu Jan 21 23:06:06 2021 +0000
+++ b/usr.bin/make/unit-tests/cond-cmp-string.exp       Thu Jan 21 23:25:08 2021 +0000
@@ -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 !=
diff -r 8dd3b580c1a2 -r 548614f0953e usr.bin/make/unit-tests/cond-token-plain.exp
--- a/usr.bin/make/unit-tests/cond-token-plain.exp      Thu Jan 21 23:06:06 2021 +0000
+++ b/usr.bin/make/unit-tests/cond-token-plain.exp      Thu Jan 21 23:25:08 2021 +0000
@@ -18,9 +18,9 @@
 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 = !=



Home | Main Index | Thread Index | Old Index