Module Name: src Committed By: rillig Date: Sat Feb 18 18:23:58 UTC 2023
Modified Files: src/usr.bin/make/unit-tests: varmod-ifelse.exp varmod-ifelse.mk Log Message: tests/make: document why ':?' cannot parse its operands in balanced mode To generate a diff of this commit: cvs rdiff -u -r1.14 -r1.15 src/usr.bin/make/unit-tests/varmod-ifelse.exp cvs rdiff -u -r1.20 -r1.21 src/usr.bin/make/unit-tests/varmod-ifelse.mk 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/unit-tests/varmod-ifelse.exp diff -u src/usr.bin/make/unit-tests/varmod-ifelse.exp:1.14 src/usr.bin/make/unit-tests/varmod-ifelse.exp:1.15 --- src/usr.bin/make/unit-tests/varmod-ifelse.exp:1.14 Sun Sep 25 12:51:37 2022 +++ src/usr.bin/make/unit-tests/varmod-ifelse.exp Sat Feb 18 18:23:58 2023 @@ -27,6 +27,13 @@ make: "varmod-ifelse.mk" line 167: true make: "varmod-ifelse.mk" line 169: false make: Bad conditional expression ' ' in ' ?true:false' make: "varmod-ifelse.mk" line 171: +CondParser_Eval: 0 && ${1:?${:Uthen0:S,}},,}:${:Uelse0:S,}},,}} != "not evaluated" +CondParser_Eval: 1 && ${0:?${:Uthen1:S,}},,}:${:Uelse1:S,}},,}} != "else1" +CondParser_Eval: 0 +Comparing "else1" != "else1" +CondParser_Eval: 2 && ${1:?${:Uthen2:S,}},,}:${:Uelse2:S,}},,}} != "then2" +CondParser_Eval: 1 +Comparing "then2" != "then2" make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 Index: src/usr.bin/make/unit-tests/varmod-ifelse.mk diff -u src/usr.bin/make/unit-tests/varmod-ifelse.mk:1.20 src/usr.bin/make/unit-tests/varmod-ifelse.mk:1.21 --- src/usr.bin/make/unit-tests/varmod-ifelse.mk:1.20 Sun Sep 25 12:51:37 2022 +++ src/usr.bin/make/unit-tests/varmod-ifelse.mk Sat Feb 18 18:23:58 2023 @@ -1,4 +1,4 @@ -# $NetBSD: varmod-ifelse.mk,v 1.20 2022/09/25 12:51:37 rillig Exp $ +# $NetBSD: varmod-ifelse.mk,v 1.21 2023/02/18 18:23:58 rillig Exp $ # # Tests for the ${cond:?then:else} variable modifier, which evaluates either # the then-expression or the else-expression, depending on the condition. @@ -182,3 +182,67 @@ PRIMES= 2 3 5 7 11 "1:not_prime 2:prime 3:prime 4:not_prime 5:prime" . error .endif + +# When parsing the modifier ':?', there are 3 possible cases: +# +# 1. The whole expression is only parsed. +# 2. The expression is parsed and the 'then' branch is evaluated. +# 3. The expression is parsed and the 'else' branch is evaluated. +# +# In all of these cases, the expression must be parsed in the same way, +# especially when one of the branches contains unbalanced '{}' braces. +# +# At 2020-01-01, the expressions from the 'then' and 'else' branches were +# parsed differently, depending on whether the branch was taken or not. When +# the branch was taken, the parser recognized that in the modifier ':S,}},,', +# the '}}' were ordinary characters. When the branch was not taken, the +# parser only counted balanced '{' and '}', ignoring any escaping or other +# changes in the interpretation. +# +# In var.c 1.285 from 2020-07-20, the parsing of the expressions changed so +# that in both cases the expression is parsed in the same way, taking the +# unbalanced braces in the ':S' modifiers into account. This change was not +# on purpose, the commit message mentioned 'has the same effect', which was a +# wrong assumption. +# +# In var.c 1.323 from 2020-07-26, the unintended fix from var.c 1.285 was +# reverted, still not knowing about the difference between regular parsing and +# balanced-mode parsing. +# +# In var.c 1.1028 from 2022-08-08, there was another attempt at fixing this +# inconsistency in parsing, but since that broke parsing of the modifier ':@', +# it was reverted in var.c 1.1029 from 2022-08-23. +# +# In var.c 1.1047 from 2023-02-18, the inconsistency in parsing was finally +# fixed. The modifier ':@' now parses the body in balanced mode, while +# everywhere else the modifier parts have their subexpressions parsed in the +# same way, no matter whether they are evaluated or not. +# +# The modifiers ':@' and ':?' are similar in that they conceptually contain +# text to be evaluated later or conditionally, still they parse that text +# differently. The crucial difference is that the body of the modifier ':@' +# is always parsed using balanced mode. The modifier ':?', on the other hand, +# must parse both of its branches in the same way, no matter whether they are +# evaluated or not. Since balanced mode and standard mode are incompatible, +# it's impossible to use balanced mode in the modifier ':?'. +.MAKEFLAGS: -dc +.if 0 && ${1:?${:Uthen0:S,}},,}:${:Uelse0:S,}},,}} != "not evaluated" +# At 2020-01-07, the expression evaluated to 'then0,,}}', even though it was +# irrelevant as the '0' had already been evaluated to 'false'. +. error +.endif +.if 1 && ${0:?${:Uthen1:S,}},,}:${:Uelse1:S,}},,}} != "else1" +. error +.endif +.if 2 && ${1:?${:Uthen2:S,}},,}:${:Uelse2:S,}},,}} != "then2" +# At 2020-01-07, the whole expression evaluated to 'then2,,}}' instead of the +# expected 'then2'. The 'then' branch of the ':?' modifier was parsed +# normally, parsing and evaluating the ':S' modifier, thereby treating the +# '}}' as ordinary characters and resulting in 'then2'. The 'else' branch was +# parsed in balanced mode, ignoring that the inner '}}' were ordinary +# characters. The '}}' were thus interpreted as the end of the 'else' branch +# and the whole expression. This left the trailing ',,}}', which together +# with the 'then2' formed the result 'then2,,}}'. +. error +.endif +.MAKEFLAGS: -d0