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