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