Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/usr.bin/make tests/make: demonstrate edge case that evaluate...
details: https://anonhg.NetBSD.org/src/rev/ca2f7157d2b1
branches: trunk
changeset: 1029286:ca2f7157d2b1
user: rillig <rillig%NetBSD.org@localhost>
date: Thu Dec 30 02:14:55 2021 +0000
description:
tests/make: demonstrate edge case that evaluates an expression twice
diffstat:
usr.bin/make/cond.c | 8 ++--
usr.bin/make/unit-tests/cond-token-plain.exp | 1 +
usr.bin/make/unit-tests/cond-token-plain.mk | 49 ++++++++++++++++++++++++++-
3 files changed, 51 insertions(+), 7 deletions(-)
diffs (100 lines):
diff -r c8942620c29f -r ca2f7157d2b1 usr.bin/make/cond.c
--- a/usr.bin/make/cond.c Thu Dec 30 01:34:26 2021 +0000
+++ b/usr.bin/make/cond.c Thu Dec 30 02:14:55 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: cond.c,v 1.320 2021/12/30 01:34:26 rillig Exp $ */
+/* $NetBSD: cond.c,v 1.321 2021/12/30 02:14:55 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.320 2021/12/30 01:34:26 rillig Exp $");
+MAKE_RCSID("$NetBSD: cond.c,v 1.321 2021/12/30 02:14:55 rillig Exp $");
/*
* The parsing of conditional expressions is based on this grammar:
@@ -793,8 +793,8 @@
* as an expression.
*/
/*
- * XXX: Is it possible to have a variable expression evaluated twice
- * at this point?
+ * XXX: In edge cases, a variable expression may be evaluated twice,
+ * see cond-token-plain.mk, keyword 'twice'.
*/
arg = ParseWord(&cp, doEval);
assert(arg[0] != '\0');
diff -r c8942620c29f -r ca2f7157d2b1 usr.bin/make/unit-tests/cond-token-plain.exp
--- a/usr.bin/make/unit-tests/cond-token-plain.exp Thu Dec 30 01:34:26 2021 +0000
+++ b/usr.bin/make/unit-tests/cond-token-plain.exp Thu Dec 30 02:14:55 2021 +0000
@@ -56,6 +56,7 @@
make: "cond-token-plain.mk" line 201: Malformed conditional (${0:?:} || left == right)
CondParser_Eval: left == right || ${0:?:}
make: "cond-token-plain.mk" line 206: Malformed conditional (left == right || ${0:?:})
+make: "cond-token-plain.mk" line 225: Malformed conditional (VAR.${IF_COUNT::+=1} != "")
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
exit status 1
diff -r c8942620c29f -r ca2f7157d2b1 usr.bin/make/unit-tests/cond-token-plain.mk
--- a/usr.bin/make/unit-tests/cond-token-plain.mk Thu Dec 30 01:34:26 2021 +0000
+++ b/usr.bin/make/unit-tests/cond-token-plain.mk Thu Dec 30 02:14:55 2021 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: cond-token-plain.mk,v 1.14 2021/12/12 09:36:00 rillig Exp $
+# $NetBSD: cond-token-plain.mk,v 1.15 2021/12/30 02:14:55 rillig Exp $
#
# Tests for plain tokens (that is, string literals without quotes)
# in .if conditions. These are also called bare words.
@@ -209,5 +209,48 @@
# See cond-token-string.mk for similar tests where the condition is enclosed
# in "quotes".
-all:
- @:;
+.MAKEFLAGS: -d0
+
+
+# As of cond.c 1.320 from 2021-12-30, the code in CondParser_ComparisonOrLeaf
+# looks suspicious of evaluating the expression twice: first for parsing a
+# bare word and second for parsing the left-hand side of a comparison.
+#
+# In '.if' directives, the left-hand side of a comparison must not be a bare
+# word though, and this keeps CondParser_Leaf from evaluating the expression
+# for the second time. The right-hand side of a comparison may be a bare
+# word, but that side has no risk of being parsed more than once.
+#
+# expect+1: Malformed conditional (VAR.${IF_COUNT::+=1} != "")
+.if VAR.${IF_COUNT::+=1} != ""
+. error
+.else
+. error
+.endif
+.if ${IF_COUNT} != "1"
+. error
+.endif
+
+# A different situation is when CondParser.leftUnquotedOK is true. This
+# situation arises in expressions of the form ${cond:?yes:no}. As of
+# 2021-12-30, the condition in such an expression is evaluated before parsing
+# the condition, see varmod-ifelse.mk. To pass a variable expression to the
+# condition parser, it needs to be escaped. This rarely happens in practice,
+# in most cases the conditions are simple enough that it doesn't matter
+# whether the condition is first evaluated and then parsed, or vice versa.
+# A half-baked attempt at hiding this implementation detail is
+# CondParser.leftUnquotedOK, but that is a rather leaky abstraction.
+
+#.MAKEFLAGS: -dcv
+COND= VAR.$${MOD_COUNT::+=1}
+.if ${${COND} == "VAR.":?yes:no} != "yes"
+. error
+.endif
+
+# The value "1 1" demonstrates that the expression ${MOD_COUNT::+=1} was
+# evaluated twice. In practice, expressions that occur in conditions do not
+# have side effects, making this problem rather academic, but it is there.
+.if ${MOD_COUNT} != "1 1"
+. error
+.endif
+#.MAKEFLAGS: -d0
Home |
Main Index |
Thread Index |
Old Index