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): add tests for really strange edge case...



details:   https://anonhg.NetBSD.org/src/rev/993676f7a993
branches:  trunk
changeset: 976024:993676f7a993
user:      rillig <rillig%NetBSD.org@localhost>
date:      Fri Sep 11 06:47:42 2020 +0000

description:
make(1): add tests for really strange edge cases in conditions

diffstat:

 usr.bin/make/cond.c                          |  29 +++++++-----
 usr.bin/make/unit-tests/cond-token-plain.exp |  17 +++++++
 usr.bin/make/unit-tests/cond-token-plain.mk  |  62 +++++++++++++++++++++++++++-
 3 files changed, 94 insertions(+), 14 deletions(-)

diffs (184 lines):

diff -r 277eae7eb433 -r 993676f7a993 usr.bin/make/cond.c
--- a/usr.bin/make/cond.c       Fri Sep 11 06:40:25 2020 +0000
+++ b/usr.bin/make/cond.c       Fri Sep 11 06:47:42 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: cond.c,v 1.127 2020/09/11 06:08:10 rillig Exp $        */
+/*     $NetBSD: cond.c,v 1.128 2020/09/11 06:47:42 rillig Exp $        */
 
 /*
  * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -70,14 +70,14 @@
  */
 
 #ifndef MAKE_NATIVE
-static char rcsid[] = "$NetBSD: cond.c,v 1.127 2020/09/11 06:08:10 rillig Exp $";
+static char rcsid[] = "$NetBSD: cond.c,v 1.128 2020/09/11 06:47:42 rillig Exp $";
 #else
 #include <sys/cdefs.h>
 #ifndef lint
 #if 0
 static char sccsid[] = "@(#)cond.c     8.2 (Berkeley) 1/2/94";
 #else
-__RCSID("$NetBSD: cond.c,v 1.127 2020/09/11 06:08:10 rillig Exp $");
+__RCSID("$NetBSD: cond.c,v 1.128 2020/09/11 06:47:42 rillig Exp $");
 #endif
 #endif /* not lint */
 #endif
@@ -985,7 +985,12 @@
 static CondEvalResult
 CondParser_Eval(CondParser *par, Boolean *value)
 {
-    Token res = CondParser_Expr(par, TRUE);
+    Token res;
+
+    if (DEBUG(COND))
+       fprintf(debug_file, "CondParser_Eval: %s\n", par->p);
+
+    res = CondParser_Expr(par, TRUE);
     if (res != TOK_FALSE && res != TOK_TRUE)
         return COND_INVALID;
 
@@ -996,9 +1001,9 @@
     return COND_PARSE;
 }
 
-/* Evaluate the condition in the passed line, including any side effects from
- * the variable expressions in the condition. The condition consists of &&,
- * ||, !, function(arg), comparisons and parenthetical groupings thereof.
+/* Evaluate the condition, including any side effects from the variable
+ * expressions in the condition. The condition consists of &&, ||, !,
+ * function(arg), comparisons and parenthetical groupings thereof.
  *
  * Results:
  *     COND_PARSE      if the condition was valid grammatically
@@ -1007,7 +1012,7 @@
  *     (*value) is set to the boolean value of the condition
  */
 CondEvalResult
-Cond_EvalExpression(const struct If *info, const char *line, Boolean *value,
+Cond_EvalExpression(const struct If *info, const char *cond, Boolean *value,
                    int eprint, Boolean strictLHS)
 {
     static const struct If *dflt_info;
@@ -1016,8 +1021,8 @@
 
     lhsStrict = strictLHS;
 
-    while (*line == ' ' || *line == '\t')
-       line++;
+    while (*cond == ' ' || *cond == '\t')
+       cond++;
 
     if (info == NULL && (info = dflt_info) == NULL) {
        /* Scan for the entry for .if - it can't be first */
@@ -1029,13 +1034,13 @@
     assert(info != NULL);
 
     par.if_info = info;
-    par.p = line;
+    par.p = cond;
     par.curr = TOK_NONE;
 
     rval = CondParser_Eval(&par, value);
 
     if (rval == COND_INVALID && eprint)
-       Parse_Error(PARSE_FATAL, "Malformed conditional (%s)", line);
+       Parse_Error(PARSE_FATAL, "Malformed conditional (%s)", cond);
 
     return rval;
 }
diff -r 277eae7eb433 -r 993676f7a993 usr.bin/make/unit-tests/cond-token-plain.exp
--- a/usr.bin/make/unit-tests/cond-token-plain.exp      Fri Sep 11 06:40:25 2020 +0000
+++ b/usr.bin/make/unit-tests/cond-token-plain.exp      Fri Sep 11 06:47:42 2020 +0000
@@ -1,1 +1,18 @@
+CondParser_Eval: ${:Uvalue} != value
+lhs = "value", rhs = "value", op = !=
+CondParser_Eval: ${:U} != "
+lhs = "", rhs = "", op = !=
+CondParser_Eval: ${:U#hash} != "#hash"
+lhs = "#hash", rhs = "#hash", op = !=
+CondParser_Eval: ${:U\\} != "\\
+lhs = "\", rhs = "\", op = !=
+CondParser_Eval: ${:U#hash} != #hash
+lhs = "#hash", rhs = "#hash", op = !=
+CondParser_Eval: 0 # This is treated as a comment, but why?
+CondParser_Eval: ${0 # comment :?yes:no} != no
+CondParser_Eval: 0 # comment 
+lhs = "no", rhs = "no", op = !=
+CondParser_Eval: ${1 # comment :?yes:no} != yes
+CondParser_Eval: 1 # comment 
+lhs = "yes", rhs = "yes", op = !=
 exit status 0
diff -r 277eae7eb433 -r 993676f7a993 usr.bin/make/unit-tests/cond-token-plain.mk
--- a/usr.bin/make/unit-tests/cond-token-plain.mk       Fri Sep 11 06:40:25 2020 +0000
+++ b/usr.bin/make/unit-tests/cond-token-plain.mk       Fri Sep 11 06:47:42 2020 +0000
@@ -1,9 +1,67 @@
-# $NetBSD: cond-token-plain.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $
+# $NetBSD: cond-token-plain.mk,v 1.3 2020/09/11 06:47:42 rillig Exp $
 #
 # Tests for plain tokens (that is, string literals without quotes)
 # in .if conditions.
 
-# TODO: Implementation
+.MAKEFLAGS: -dc
+
+.if ${:Uvalue} != value
+.  error
+.endif
+
+# Malformed condition since comment parsing is done in an early phase
+# and removes the '#' and everything behind it long before the condition
+# parser gets to see it.
+#
+# XXX: The error message is missing for this malformed condition.
+# The right-hand side of the comparison is just a '"'.
+.if ${:U} != "#hash"
+.  error
+.endif
+
+# To get a '#' into a condition, it has to be escaped using a backslash.
+# This prevents the comment parser from removing it, and in turn, it becomes
+# visible to CondParser_String.
+.if ${:U\#hash} != "\#hash"
+.  error
+.endif
+
+# Since 2002-12-30, and still as of 2020-09-11, CondParser_Token handles
+# the '#' specially, even though at this point, there should be no need for
+# comment handling anymore.  The comments are supposed to be stripped off
+# in a very early parsing phase.
+#
+# XXX: Missing error message for the malformed condition. The right-hand
+# side is double-quotes, backslash, backslash.
+# XXX: It is unexpected that the right-hand side evaluates to a single
+# backslash.
+.if ${:U\\} != "\\#hash"
+.  error
+.endif
+
+# The right-hand side of a comparison is not parsed as a token, therefore
+# the code from CondParser_Token does not apply to it.
+.if ${:U\#hash} != \#hash
+.  error
+.endif
+
+# XXX: What is the purpose of treating an escaped '#' in the following
+# condition as a comment?  And why only at the beginning of a token,
+# just as in the shell?
+.if 0 \# This is treated as a comment, but why?
+.  error
+.endif
+
+# Ah, ok, this can be used to add an end-of-condition comment.  But does
+# anybody really use this?  This is neither documented nor obvious since
+# the '#' is escaped.  It's much clearer to write a comment in the line
+# above the condition.
+.if ${0 \# comment :?yes:no} != no
+.  error
+.endif
+.if ${1 \# comment :?yes:no} != yes
+.  error
+.endif
 
 all:
        @:;



Home | Main Index | Thread Index | Old Index