Home | History | Annotate | Line # | Download | only in unit-tests
cond-token-plain.mk revision 1.14
      1  1.14  rillig # $NetBSD: cond-token-plain.mk,v 1.14 2021/12/12 09:36:00 rillig Exp $
      2   1.1  rillig #
      3   1.2  rillig # Tests for plain tokens (that is, string literals without quotes)
      4  1.14  rillig # in .if conditions.  These are also called bare words.
      5   1.1  rillig 
      6   1.3  rillig .MAKEFLAGS: -dc
      7   1.3  rillig 
      8  1.14  rillig # The word 'value' after the '!=' is a bare word.
      9   1.3  rillig .if ${:Uvalue} != value
     10   1.3  rillig .  error
     11   1.3  rillig .endif
     12   1.3  rillig 
     13  1.14  rillig # Using a '#' in a string literal in a condition leads to a malformed
     14  1.14  rillig # condition since comment parsing is done in an early phase and removes the
     15  1.14  rillig # '#' and everything after it long before the condition parser gets to see it.
     16   1.3  rillig #
     17   1.3  rillig # XXX: The error message is missing for this malformed condition.
     18   1.6  rillig # The right-hand side of the comparison is just a '"', before unescaping.
     19   1.3  rillig .if ${:U} != "#hash"
     20   1.3  rillig .  error
     21   1.3  rillig .endif
     22   1.3  rillig 
     23   1.3  rillig # To get a '#' into a condition, it has to be escaped using a backslash.
     24   1.3  rillig # This prevents the comment parser from removing it, and in turn, it becomes
     25   1.3  rillig # visible to CondParser_String.
     26   1.3  rillig .if ${:U\#hash} != "\#hash"
     27   1.3  rillig .  error
     28   1.3  rillig .endif
     29   1.3  rillig 
     30   1.3  rillig # Since 2002-12-30, and still as of 2020-09-11, CondParser_Token handles
     31   1.3  rillig # the '#' specially, even though at this point, there should be no need for
     32   1.3  rillig # comment handling anymore.  The comments are supposed to be stripped off
     33   1.3  rillig # in a very early parsing phase.
     34   1.3  rillig #
     35   1.5  rillig # See https://gnats.netbsd.org/19596 for example makefiles demonstrating the
     36  1.14  rillig # original problems.  At that time, the parser didn't recognize the comment in
     37  1.14  rillig # the line '.else # comment3'.  This workaround is not needed anymore since
     38  1.14  rillig # comments are stripped in an earlier phase.  See "case '#'" in
     39  1.14  rillig # CondParser_Token.
     40   1.5  rillig #
     41   1.3  rillig # XXX: Missing error message for the malformed condition. The right-hand
     42   1.6  rillig # side before unescaping is double-quotes, backslash, backslash.
     43   1.3  rillig .if ${:U\\} != "\\#hash"
     44   1.3  rillig .  error
     45   1.3  rillig .endif
     46   1.3  rillig 
     47   1.3  rillig # The right-hand side of a comparison is not parsed as a token, therefore
     48   1.3  rillig # the code from CondParser_Token does not apply to it.
     49   1.6  rillig # TODO: Explain the consequences.
     50   1.6  rillig # TODO: Does this mean that more syntactic variants are allowed here?
     51   1.3  rillig .if ${:U\#hash} != \#hash
     52   1.3  rillig .  error
     53   1.3  rillig .endif
     54   1.3  rillig 
     55   1.3  rillig # XXX: What is the purpose of treating an escaped '#' in the following
     56   1.3  rillig # condition as a comment?  And why only at the beginning of a token,
     57   1.3  rillig # just as in the shell?
     58   1.3  rillig .if 0 \# This is treated as a comment, but why?
     59   1.3  rillig .  error
     60   1.3  rillig .endif
     61   1.3  rillig 
     62   1.3  rillig # Ah, ok, this can be used to add an end-of-condition comment.  But does
     63   1.3  rillig # anybody really use this?  This is neither documented nor obvious since
     64   1.3  rillig # the '#' is escaped.  It's much clearer to write a comment in the line
     65   1.3  rillig # above the condition.
     66   1.3  rillig .if ${0 \# comment :?yes:no} != no
     67   1.3  rillig .  error
     68   1.3  rillig .endif
     69   1.3  rillig .if ${1 \# comment :?yes:no} != yes
     70   1.3  rillig .  error
     71   1.3  rillig .endif
     72   1.1  rillig 
     73   1.4  rillig # Usually there is whitespace around the comparison operator, but this is
     74   1.4  rillig # not required.
     75   1.4  rillig .if ${UNDEF:Uundefined}!=undefined
     76   1.4  rillig .  error
     77   1.4  rillig .endif
     78   1.4  rillig .if ${UNDEF:U12345}>12345
     79   1.4  rillig .  error
     80   1.4  rillig .endif
     81   1.4  rillig .if ${UNDEF:U12345}<12345
     82   1.4  rillig .  error
     83   1.4  rillig .endif
     84   1.4  rillig .if (${UNDEF:U0})||0
     85   1.4  rillig .  error
     86   1.4  rillig .endif
     87   1.4  rillig 
     88   1.4  rillig # Only the comparison operator terminates the comparison operand, and it's
     89   1.4  rillig # a coincidence that the '!' is both used in the '!=' comparison operator
     90   1.4  rillig # as well as for negating a comparison result.
     91   1.4  rillig #
     92   1.4  rillig # The boolean operators '&' and '|' don't terminate a comparison operand.
     93   1.4  rillig .if ${:Uvar}&&name != "var&&name"
     94   1.4  rillig .  error
     95   1.4  rillig .endif
     96   1.4  rillig .if ${:Uvar}||name != "var||name"
     97   1.4  rillig .  error
     98   1.4  rillig .endif
     99   1.4  rillig 
    100   1.7  rillig # A bare word may appear alone in a condition, without any comparison
    101   1.7  rillig # operator.  It is implicitly converted into defined(bare).
    102   1.7  rillig .if bare
    103   1.7  rillig .  error
    104   1.7  rillig .else
    105   1.7  rillig .  info A bare word is treated like defined(...), and the variable $\
    106   1.7  rillig 	'bare' is not defined.
    107   1.7  rillig .endif
    108   1.7  rillig 
    109   1.7  rillig VAR=	defined
    110   1.7  rillig .if VAR
    111   1.7  rillig .  info A bare word is treated like defined(...).
    112   1.7  rillig .else
    113   1.7  rillig .  error
    114   1.7  rillig .endif
    115   1.7  rillig 
    116   1.7  rillig # Bare words may be intermixed with variable expressions.
    117   1.7  rillig .if V${:UA}R
    118   1.7  rillig .  info ok
    119   1.7  rillig .else
    120   1.7  rillig .  error
    121   1.7  rillig .endif
    122   1.7  rillig 
    123   1.7  rillig # In bare words, even undefined variables are allowed.  Without the bare
    124   1.7  rillig # words, undefined variables are not allowed.  That feels inconsistent.
    125   1.7  rillig .if V${UNDEF}AR
    126   1.7  rillig .  info Undefined variables in bare words expand to an empty string.
    127   1.7  rillig .else
    128   1.7  rillig .  error
    129   1.7  rillig .endif
    130   1.7  rillig 
    131   1.7  rillig .if 0${:Ux00}
    132   1.7  rillig .  error
    133   1.7  rillig .else
    134   1.7  rillig .  info Numbers can be composed from literals and variable expressions.
    135   1.7  rillig .endif
    136   1.7  rillig 
    137   1.7  rillig .if 0${:Ux01}
    138   1.7  rillig .  info Numbers can be composed from literals and variable expressions.
    139   1.7  rillig .else
    140   1.7  rillig .  error
    141   1.7  rillig .endif
    142   1.7  rillig 
    143   1.8  rillig # If the right-hand side is missing, it's a parse error.
    144   1.8  rillig .if "" ==
    145   1.8  rillig .  error
    146   1.8  rillig .else
    147   1.8  rillig .  error
    148   1.8  rillig .endif
    149   1.8  rillig 
    150   1.8  rillig # If the left-hand side is missing, it's a parse error as well, but without
    151   1.8  rillig # a specific error message.
    152   1.8  rillig .if == ""
    153   1.8  rillig .  error
    154   1.8  rillig .else
    155   1.8  rillig .  error
    156   1.8  rillig .endif
    157   1.8  rillig 
    158   1.8  rillig # The '\\' is not a line continuation.  Neither is it an unquoted string
    159  1.13  rillig # literal.  Instead, it is parsed as a bare word (ParseWord),
    160   1.8  rillig # and in that context, the backslash is just an ordinary character. The
    161   1.8  rillig # function argument thus stays '\\' (2 backslashes).  This string is passed
    162   1.8  rillig # to FuncDefined, and since there is no variable named '\\', the condition
    163   1.8  rillig # evaluates to false.
    164   1.8  rillig .if \\
    165   1.8  rillig .  error
    166   1.8  rillig .else
    167   1.8  rillig .  info The variable '\\' is not defined.
    168   1.8  rillig .endif
    169   1.8  rillig 
    170   1.8  rillig ${:U\\\\}=	backslash
    171   1.8  rillig .if \\
    172   1.8  rillig .  info Now the variable '\\' is defined.
    173   1.8  rillig .else
    174   1.8  rillig .  error
    175   1.8  rillig .endif
    176   1.8  rillig 
    177   1.9  rillig # Anything that doesn't start with a double quote is considered a "bare word".
    178   1.9  rillig # Strangely, a bare word may contain double quotes inside.  Nobody should ever
    179   1.9  rillig # depend on this since it may well be unintended.  See CondParser_String.
    180   1.9  rillig .if "unquoted\"quoted" != unquoted"quoted
    181   1.9  rillig .  error
    182   1.9  rillig .endif
    183   1.9  rillig 
    184  1.10  rillig # FIXME: In CondParser_String, Var_Parse returns var_Error without a
    185  1.10  rillig # corresponding error message.
    186  1.10  rillig .if $$$$$$$$ != ""
    187  1.10  rillig .  error
    188  1.10  rillig .else
    189  1.10  rillig .  error
    190  1.10  rillig .endif
    191  1.10  rillig 
    192  1.11  rillig # In a condition in an .if directive, the left-hand side must not be an
    193  1.11  rillig # unquoted string literal.
    194  1.11  rillig # expect+1: Malformed conditional (left == right)
    195  1.11  rillig .if left == right
    196  1.11  rillig .endif
    197  1.11  rillig # Before cond.c 1.276 from 2021-09-21, a variable expression containing the
    198  1.11  rillig # modifier ':?:' allowed unquoted string literals for the rest of the
    199  1.11  rillig # condition.  This was an unintended implementation mistake.
    200  1.12  rillig # expect+1: Malformed conditional (${0:?:} || left == right)
    201  1.11  rillig .if ${0:?:} || left == right
    202  1.11  rillig .endif
    203  1.11  rillig # This affected only the comparisons after the expression, so the following
    204  1.11  rillig # was still a syntax error.
    205  1.11  rillig # expect+1: Malformed conditional (left == right || ${0:?:})
    206  1.11  rillig .if left == right || ${0:?:}
    207  1.11  rillig .endif
    208  1.11  rillig 
    209   1.7  rillig # See cond-token-string.mk for similar tests where the condition is enclosed
    210   1.7  rillig # in "quotes".
    211   1.7  rillig 
    212   1.1  rillig all:
    213   1.1  rillig 	@:;
    214