]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - unit-tests/cond-func-empty.mk
Import bmake-20230909
[FreeBSD/FreeBSD.git] / unit-tests / cond-func-empty.mk
1 # $NetBSD: cond-func-empty.mk,v 1.22 2023/08/11 05:01:12 rillig Exp $
2 #
3 # Tests for the empty() function in .if conditions, which tests a variable
4 # expression for emptiness.
5 #
6 # Note that the argument in the parentheses is a variable name, not a variable
7 # expression.  That name may be followed by ':...' modifiers.
8 #
9
10 .undef UNDEF
11 EMPTY=  # empty
12 SPACE=  ${:U }
13 ZERO=   0
14 WORD=   word
15
16 # An undefined variable counts as empty.
17 .if !empty(UNDEF)
18 .  error
19 .endif
20
21 # An undefined variable has the empty string as the value, and the :M
22 # variable modifier does not change that.
23 #
24 .if !empty(UNDEF:M*)
25 .  error
26 .endif
27
28 # The :S modifier replaces the empty value with an actual word.  After
29 # applying the :S modifier to the expression, its value is 'empty', so it is
30 # no longer empty, but it is still based on an undefined variable.  There are
31 # a few modifiers that turn an undefined expression into a defined expression,
32 # among them :U and :D, but not :S.  Therefore, at the end of evaluating the
33 # expression, the expression is still undefined, so its final value becomes an
34 # empty string.
35 #
36 # XXX: This is hard to explain to someone who doesn't know these
37 # implementation details.
38 #
39 .if !empty(UNDEF:S,^$,value,W)
40 .  error
41 .endif
42
43 # The :U modifier changes the state of a previously undefined expression from
44 # DEF_UNDEF to DEF_DEFINED.  This marks the expression as "being interesting
45 # enough to be further processed".
46 #
47 .if empty(UNDEF:S,^$,value,W:Ufallback)
48 .  error
49 .endif
50
51 # When an expression is based on an undefined variable, its modifiers interact
52 # in sometimes surprising ways.  Applying the :S modifier to the undefined
53 # expression makes its value non-empty, but doesn't change that the expression
54 # is based on an undefined variable.  The :U modifier that follows only looks
55 # at the definedness state to decide whether the variable is defined or not.
56 # This kind of makes sense since the :U modifier tests the _variable_, not the
57 # _expression_.
58 #
59 # Since the variable was undefined to begin with, the fallback value from the
60 # :U modifier is used in this expression, instead of keeping the 'value' from
61 # the :S modifier.
62 #
63 .if ${UNDEF:S,^$,value,W:Ufallback} != "fallback"
64 .  error
65 .endif
66
67 # The variable EMPTY is completely empty (0 characters).
68 .if !empty(EMPTY)
69 .  error
70 .endif
71
72 # The variable SPACE has a single space, which counts as being empty.
73 .if !empty(SPACE)
74 .  error
75 .endif
76
77 # The variable .newline has a single newline, which counts as being empty.
78 .if !empty(.newline)
79 .  error
80 .endif
81
82 # The variable ZERO has the numeric value 0, but is not empty.  This is a
83 # subtle difference between using either 'empty(ZERO)' or the expression
84 # '${ZERO}' in a condition.
85 .if empty(ZERO)
86 .  error
87 .elif ${ZERO}
88 .  error
89 .elif ${ZERO} == ""
90 .  error
91 .endif
92
93 # The following example constructs an expression with the variable name ""
94 # and the value " ".  This expression counts as empty since the value contains
95 # only whitespace.
96 #
97 # Contrary to the other functions in conditionals, the trailing space is not
98 # stripped off, as can be seen in the -dv debug log.  If the space had been
99 # stripped, it wouldn't make a difference in this case, but in other cases.
100 #
101 .if !empty(:U )
102 .  error
103 .endif
104
105 # Now the variable named " " gets a non-empty value, which demonstrates that
106 # neither leading nor trailing spaces are trimmed in the argument of the
107 # function.  If the spaces were trimmed, the variable name would be "" and
108 # that variable is indeed undefined.  Since CondParser_FuncCallEmpty calls
109 # Var_Parse without VARE_UNDEFERR, the value of the undefined variable ""
110 # would be returned as an empty string.
111 ${:U }= space
112 .if empty( )
113 .  error
114 .endif
115
116 # The value of the following expression is " word", which is not empty.  To be
117 # empty, _all_ characters in the expression value have to be whitespace, not
118 # only the first.
119 .if empty(:U word)
120 .  error
121 .endif
122
123 # The :L modifier creates a variable expression that has the same value as
124 # its name, which both are "VAR" in this case.  The value is therefore not
125 # empty.
126 .if empty(VAR:L)
127 .  error
128 .endif
129
130 # The variable WORD has the value "word", which does not count as empty.
131 .if empty(WORD)
132 .  error
133 .endif
134
135 # The expression ${} for a variable with the empty name always evaluates
136 # to an empty string (see Var_Parse, varUndefined).
137 .if !empty()
138 .  error
139 .endif
140
141 # Ensure that variable expressions that appear as part of the function call
142 # argument are properly parsed.  Typical use cases for this are .for loops,
143 # which are expanded to exactly these ${:U} expressions.
144 #
145 # The argument expands to "WORD", and that variable is defined at the
146 # beginning of this file.  The surrounding 'W' and 'D' ensure that
147 # CondParser_FuncCallEmpty keeps track of the parsing position, both before
148 # and after the call to Var_Parse.
149 .if empty(W${:UOR}D)
150 .  error
151 .endif
152
153 # There may be spaces outside the parentheses.
154 # Spaces inside the parentheses are interpreted as part of the variable name.
155 .if ! empty ( WORD )
156 .  error
157 .endif
158
159 ${:U WORD }=    variable name with spaces
160
161 # Now there is a variable named " WORD ", and it is not empty.
162 .if empty ( WORD )
163 .  error
164 .endif
165
166 # expect+2: Unclosed variable "WORD"
167 # expect+1: Malformed conditional (empty(WORD)
168 .if empty(WORD
169 .  error
170 .else
171 .  error
172 .endif
173
174 # Since cond.c 1.76 from 2020-06-28 and before var.c 1.226 from 2020-07-02,
175 # the following example generated a wrong error message "Variable VARNAME is
176 # recursive".
177 #
178 # Since at least 1993, the manual page claimed that irrelevant parts of
179 # conditions were not evaluated, but that was wrong for a long time.  The
180 # expressions in irrelevant parts of the condition were actually evaluated,
181 # they just allowed undefined variables to be used in the conditions.  These
182 # unnecessary evaluations were fixed in several commits, starting with var.c
183 # 1.226 from 2020-07-02.
184 #
185 # In this example, the variable "VARNAME2" is not defined, so evaluation of
186 # the condition should have stopped at this point, and the rest of the
187 # condition should have been processed in parse-only mode.  The right-hand
188 # side containing the '!empty' was evaluated though, as it had always been.
189 #
190 # When evaluating the !empty condition, the variable name was parsed as
191 # "VARNAME${:U2}", but without expanding any nested variable expression, in
192 # this case the ${:U2}.  The expression '${:U2}' was replaced with an empty
193 # string, the resulting variable name was thus "VARNAME".  This conceptually
194 # wrong variable name should have been discarded quickly after parsing it, to
195 # prevent it from doing any harm.
196 #
197 # The variable expression was expanded though, and this was wrong.  The
198 # expansion was done without VARE_WANTRES (called VARF_WANTRES back then)
199 # though.  This had the effect that the ${:U1} from the value of VARNAME
200 # expanded to an empty string.  This in turn created the seemingly recursive
201 # definition VARNAME=${VARNAME}, and that definition was never meant to be
202 # expanded.
203 #
204 # This was fixed by expanding nested variable expressions in the variable name
205 # only if the flag VARE_WANTRES is given.
206 VARNAME=        ${VARNAME${:U1}}
207 .if defined(VARNAME${:U2}) && !empty(VARNAME${:U2})
208 .endif
209
210
211 # If the word 'empty' is not followed by '(', it is not a function call but an
212 # ordinary bare word.  This bare word is interpreted as 'defined(empty)', and
213 # since there is no variable named 'empty', the condition evaluates to false.
214 .if empty
215 .  error
216 .endif
217
218 empty=          # defined but empty
219 .if empty
220 .else
221 .  error
222 .endif