1# $NetBSD: cond-func-empty.mk,v 1.14 2021/04/11 13:35:56 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 indeed a variable name, 7# optionally followed by variable modifiers. 8# 9 10.undef UNDEF 11EMPTY= # empty 12SPACE= ${:U } 13WORD= 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. The 28# expression is now no longer empty, but it is still possible to see whether 29# the expression was based on an undefined variable. The expression has the 30# flag VEF_UNDEF. 31# 32# The expression does not have the flag VEF_DEF though, therefore it is still 33# considered undefined. Yes, indeed, undefined but not empty. There are a 34# few variable modifiers that turn an undefined expression into a defined 35# expression, among them :U and :D, but not :S. 36# 37# XXX: This is hard to explain to someone who doesn't know these 38# implementation details. 39# 40.if !empty(UNDEF:S,^$,value,W) 41. error 42.endif 43 44# The :U modifier modifies expressions based on undefined variables 45# (DEF_UNDEF) by adding the DEF_DEFINED flag, which marks the expression 46# as "being interesting enough to be further processed". 47# 48.if empty(UNDEF:S,^$,value,W:Ufallback) 49. error 50.endif 51 52# And now to the surprising part. Applying the following :S modifier to the 53# undefined expression makes it non-empty, but the marker VEF_UNDEF is 54# preserved nevertheless. The :U modifier that follows only looks at the 55# VEF_UNDEF flag to decide whether the variable is defined or not. This kind 56# of makes sense since the :U modifier tests the _variable_, not the 57# _expression_. 58# 59# But since the variable was undefined to begin with, the fallback value from 60# the :U modifier is used in this expression. 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 empty variable named "" gets a fallback value of " ", which counts as 82# empty. 83# 84# Contrary to the other functions in conditionals, the trailing space is not 85# stripped off, as can be seen in the -dv debug log. If the space had been 86# stripped, it wouldn't make a difference in this case. 87# 88.if !empty(:U ) 89. error 90.endif 91 92# Now the variable named " " gets a non-empty value, which demonstrates that 93# neither leading nor trailing spaces are trimmed in the argument of the 94# function. If the spaces were trimmed, the variable name would be "" and 95# that variable is indeed undefined. Since ParseEmptyArg calls Var_Parse 96# without VARE_UNDEFERR, the value of the undefined variable is 97# returned as an empty string. 98${:U }= space 99.if empty( ) 100. error 101.endif 102 103# The value of the following expression is " word", which is not empty. 104.if empty(:U word) 105. error 106.endif 107 108# The :L modifier creates a variable expression that has the same value as 109# its name, which both are "VAR" in this case. The value is therefore not 110# empty. 111.if empty(VAR:L) 112. error 113.endif 114 115# The variable WORD has the value "word", which does not count as empty. 116.if empty(WORD) 117. error 118.endif 119 120# The expression ${} for a variable with the empty name always evaluates 121# to an empty string (see Var_Parse, varUndefined). 122.if !empty() 123. error 124.endif 125 126# Ensure that variable expressions that appear as part of the argument are 127# properly parsed. Typical use cases for this are .for loops, which are 128# expanded to exactly these ${:U} expressions. 129# 130# If everything goes well, the argument expands to "WORD", and that variable 131# is defined at the beginning of this file. The surrounding 'W' and 'D' 132# ensure that the parser in ParseEmptyArg has the correct position, both 133# before and after the call to Var_Parse. 134.if empty(W${:UOR}D) 135. error 136.endif 137 138# There may be spaces at the outside of the parentheses. 139# Spaces inside the parentheses are interpreted as part of the variable name. 140.if ! empty ( WORD ) 141. error 142.endif 143 144${:U WORD }= variable name with spaces 145 146# Now there is a variable named " WORD ", and it is not empty. 147.if empty ( WORD ) 148. error 149.endif 150 151# Parse error: missing closing parenthesis. 152.if empty(WORD 153. error 154.else 155. error 156.endif 157 158# Between 2020-06-28 and var.c 1.226 from 2020-07-02, this paragraph generated 159# a wrong error message "Variable VARNAME is recursive". 160# 161# The bug was that the !empty() condition was evaluated, even though this was 162# not necessary since the defined() condition already evaluated to false. 163# 164# When evaluating the !empty condition, the variable name was parsed as 165# "VARNAME${:U2}", but without expanding any nested variable expression, in 166# this case the ${:U2}. Therefore, the variable name came out as simply 167# "VARNAME". Since this variable name should have been discarded quickly after 168# parsing it, this unrealistic variable name should have done no harm. 169# 170# The variable expression was expanded though, and this was wrong. The 171# expansion was done without VARE_WANTRES (called VARF_WANTRES back 172# then) though. This had the effect that the ${:U1} from the value of VARNAME 173# expanded to an empty string. This in turn created the seemingly recursive 174# definition VARNAME=${VARNAME}, and that definition was never meant to be 175# expanded. 176# 177# This was fixed by expanding nested variable expressions in the variable name 178# only if the flag VARE_WANTRES is given. 179VARNAME= ${VARNAME${:U1}} 180.if defined(VARNAME${:U2}) && !empty(VARNAME${:U2}) 181.endif 182 183all: 184 @:; 185