diff options
Diffstat (limited to 'contrib/bmake/unit-tests/cond-token-plain.mk')
-rw-r--r-- | contrib/bmake/unit-tests/cond-token-plain.mk | 109 |
1 files changed, 92 insertions, 17 deletions
diff --git a/contrib/bmake/unit-tests/cond-token-plain.mk b/contrib/bmake/unit-tests/cond-token-plain.mk index 89f2247e077c..79fcc771a855 100644 --- a/contrib/bmake/unit-tests/cond-token-plain.mk +++ b/contrib/bmake/unit-tests/cond-token-plain.mk @@ -1,17 +1,18 @@ -# $NetBSD: cond-token-plain.mk,v 1.10 2021/01/21 14:08:09 rillig Exp $ +# $NetBSD: cond-token-plain.mk,v 1.19 2023/11/19 21:47:52 rillig Exp $ # # Tests for plain tokens (that is, string literals without quotes) -# in .if conditions. +# in .if conditions. These are also called bare words. .MAKEFLAGS: -dc +# The word 'value' after the '!=' is a bare word. .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. +# Using a '#' in a string literal in a condition leads to a malformed +# condition since comment parsing is done in an early phase and removes the +# '#' and everything after 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 '"', before unescaping. @@ -32,7 +33,10 @@ # in a very early parsing phase. # # See https://gnats.netbsd.org/19596 for example makefiles demonstrating the -# original problems. This workaround is probably not needed anymore. +# original problems. At that time, the parser didn't recognize the comment in +# the line '.else # comment3'. This workaround is not needed anymore since +# comments are stripped in an earlier phase. See "case '#'" in +# CondParser_Token. # # XXX: Missing error message for the malformed condition. The right-hand # side before unescaping is double-quotes, backslash, backslash. @@ -59,10 +63,10 @@ # 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 +.if ${0 \# comment:?yes:no} != no . error .endif -.if ${1 \# comment :?yes:no} != yes +.if ${1 \# comment:?yes:no} != yes . error .endif @@ -85,7 +89,7 @@ # a coincidence that the '!' is both used in the '!=' comparison operator # as well as for negating a comparison result. # -# The boolean operators '&' and '|' don't terminate a comparison operand. +# The characters '&' and '|' are part of the comparison operand. .if ${:Uvar}&&name != "var&&name" . error .endif @@ -93,24 +97,27 @@ . error .endif -# A bare word may appear alone in a condition, without any comparison -# operator. It is implicitly converted into defined(bare). +# A bare word may occur alone in a condition, without any comparison +# operator. It is interpreted as the function call 'defined(bare)'. .if bare . error .else +# expect+1: A bare word is treated like defined(...), and the variable 'bare' is not defined. . info A bare word is treated like defined(...), and the variable $\ 'bare' is not defined. .endif VAR= defined .if VAR +# expect+1: A bare word is treated like defined(...). . info A bare word is treated like defined(...). .else . error .endif -# Bare words may be intermixed with variable expressions. +# Bare words may be intermixed with expressions. .if V${:UA}R +# expect+1: ok . info ok .else . error @@ -119,6 +126,7 @@ VAR= defined # In bare words, even undefined variables are allowed. Without the bare # words, undefined variables are not allowed. That feels inconsistent. .if V${UNDEF}AR +# expect+1: Undefined variables in bare words expand to an empty string. . info Undefined variables in bare words expand to an empty string. .else . error @@ -127,16 +135,19 @@ VAR= defined .if 0${:Ux00} . error .else -. info Numbers can be composed from literals and variable expressions. +# expect+1: Numbers can be composed from literals and expressions. +. info Numbers can be composed from literals and expressions. .endif .if 0${:Ux01} -. info Numbers can be composed from literals and variable expressions. +# expect+1: Numbers can be composed from literals and expressions. +. info Numbers can be composed from literals and expressions. .else . error .endif # If the right-hand side is missing, it's a parse error. +# expect+1: Missing right-hand side of operator '==' .if "" == . error .else @@ -145,6 +156,7 @@ VAR= defined # If the left-hand side is missing, it's a parse error as well, but without # a specific error message. +# expect+1: Malformed conditional (== "") .if == "" . error .else @@ -152,7 +164,7 @@ VAR= defined .endif # The '\\' is not a line continuation. Neither is it an unquoted string -# literal. Instead, it is parsed as a function argument (ParseFuncArg), +# literal. Instead, it is parsed as a bare word (ParseWord), # and in that context, the backslash is just an ordinary character. The # function argument thus stays '\\' (2 backslashes). This string is passed # to FuncDefined, and since there is no variable named '\\', the condition @@ -160,11 +172,13 @@ VAR= defined .if \\ . error .else +# expect+1: The variable '\\' is not defined. . info The variable '\\' is not defined. .endif ${:U\\\\}= backslash .if \\ +# expect+1: Now the variable '\\' is defined. . info Now the variable '\\' is defined. .else . error @@ -179,14 +193,75 @@ ${:U\\\\}= backslash # FIXME: In CondParser_String, Var_Parse returns var_Error without a # corresponding error message. +# expect+1: Malformed conditional ($$$$$$$$ != "") .if $$$$$$$$ != "" . error .else . error .endif +# In a condition in an .if directive, the left-hand side must not be an +# unquoted string literal. +# expect+1: Malformed conditional (left == right) +.if left == right +.endif +# Before cond.c 1.276 from 2021-09-21, an expression containing the +# modifier ':?:' allowed unquoted string literals for the rest of the +# condition. This was an unintended implementation mistake. +# expect+1: Malformed conditional (${0:?:} || left == right) +.if ${0:?:} || left == right +.endif +# This affected only the comparisons after the expression, so the following +# was still a syntax error. +# expect+1: Malformed conditional (left == right || ${0:?:}) +.if left == right || ${0:?:} +.endif + # 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 an 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 |