Home | History | Annotate | Line # | Download | only in unit-tests
var-op-sunsh.mk revision 1.9
      1  1.9  rillig # $NetBSD: var-op-sunsh.mk,v 1.9 2022/01/16 09:38:04 rillig Exp $
      2  1.1  rillig #
      3  1.1  rillig # Tests for the :sh= variable assignment operator, which runs its right-hand
      4  1.1  rillig # side through the shell.  It is a seldom-used alternative to the !=
      5  1.9  rillig # assignment operator, adopted from SUN make.
      6  1.1  rillig 
      7  1.1  rillig .MAKEFLAGS: -dL			# Enable sane error messages
      8  1.1  rillig 
      9  1.1  rillig # This is the idiomatic form of the Sun shell assignment operator.
     10  1.1  rillig # The assignment operator is directly preceded by the ':sh'.
     11  1.1  rillig VAR:sh=		echo colon-sh
     12  1.1  rillig .if ${VAR} != "colon-sh"
     13  1.1  rillig .  error
     14  1.1  rillig .endif
     15  1.1  rillig 
     16  1.2  rillig # It is also possible to have whitespace around the :sh assignment
     17  1.2  rillig # operator modifier.
     18  1.2  rillig VAR :sh =	echo colon-sh-spaced
     19  1.2  rillig .if ${VAR} != "colon-sh-spaced"
     20  1.2  rillig .  error
     21  1.2  rillig .endif
     22  1.2  rillig 
     23  1.2  rillig # Until 2020-10-04, the ':sh' could even be followed by other characters.
     24  1.2  rillig # This was neither documented by NetBSD make nor by Solaris make and was
     25  1.2  rillig # an implementation error.
     26  1.2  rillig #
     27  1.9  rillig # Since 2020-10-04, this is a normal variable assignment to the variable named
     28  1.9  rillig # 'VAR:shell', using the '=' assignment operator.
     29  1.1  rillig VAR:shell=	echo colon-shell
     30  1.9  rillig # The variable name needs to be generated using a ${:U...} expression because
     31  1.9  rillig # it is not possible to express the ':' as part of a literal variable name,
     32  1.9  rillig # see ParseVarname.
     33  1.2  rillig .if ${${:UVAR\:shell}} != "echo colon-shell"
     34  1.1  rillig .  error
     35  1.1  rillig .endif
     36  1.1  rillig 
     37  1.2  rillig # Several colons can syntactically appear in a variable name.
     38  1.2  rillig # Until 2020-10-04, the last of them was interpreted as the ':sh'
     39  1.2  rillig # assignment operator.
     40  1.2  rillig #
     41  1.2  rillig # Since 2020-10-04, the colons are part of the variable name.
     42  1.1  rillig VAR:shoe:shore=	echo two-colons
     43  1.2  rillig .if ${${:UVAR\:shoe\:shore}} != "echo two-colons"
     44  1.1  rillig .  error
     45  1.1  rillig .endif
     46  1.1  rillig 
     47  1.2  rillig # Until 2020-10-04, the following expression was wrongly marked as
     48  1.2  rillig # a parse error.  This was because the parser for variable assignments
     49  1.2  rillig # just looked for the previous ":sh", without taking any contextual
     50  1.2  rillig # information into account.
     51  1.1  rillig #
     52  1.1  rillig # There are two different syntactical elements that look exactly the same:
     53  1.1  rillig # The variable modifier ':sh' and the assignment operator modifier ':sh'.
     54  1.2  rillig # Intuitively this variable name contains the variable modifier, but until
     55  1.2  rillig # 2020-10-04, the parser regarded it as an assignment operator modifier, in
     56  1.8  rillig # Parse_Var.
     57  1.2  rillig VAR.${:Uecho 123:sh}=	ok-123
     58  1.2  rillig .if ${VAR.123} != "ok-123"
     59  1.1  rillig .  error
     60  1.1  rillig .endif
     61  1.1  rillig 
     62  1.2  rillig # Same pattern here. Until 2020-10-04, the ':sh' inside the nested expression
     63  1.2  rillig # was taken for the :sh assignment operator modifier, even though it was
     64  1.2  rillig # escaped by a backslash.
     65  1.2  rillig VAR.${:U echo\:shell}=	ok-shell
     66  1.2  rillig .if ${VAR.${:U echo\:shell}} != "ok-shell"
     67  1.1  rillig .  error
     68  1.1  rillig .endif
     69  1.1  rillig 
     70  1.2  rillig # Until 2020-10-04, the word 'shift' was also affected since it starts with
     71  1.2  rillig # ':sh'.
     72  1.2  rillig VAR.key:shift=		Shift
     73  1.2  rillig .if ${${:UVAR.key\:shift}} != "Shift"
     74  1.1  rillig .  error
     75  1.1  rillig .endif
     76  1.1  rillig 
     77  1.3  rillig # Just for fun: The code in Parse_IsVar allows for multiple appearances of
     78  1.3  rillig # the ':sh' assignment operator modifier.  Let's see what happens ...
     79  1.3  rillig #
     80  1.3  rillig # Well, the end result is correct but the way until there is rather
     81  1.7  rillig # adventurous.  This only works because the parser replaces each and every
     82  1.8  rillig # whitespace character that is not nested with '\0' (see Parse_Var).
     83  1.3  rillig # The variable name therefore ends before the first ':sh', and the last
     84  1.3  rillig # ':sh' turns the assignment operator into the shell command evaluation.
     85  1.8  rillig # Parse_Var completely trusts Parse_IsVar to properly verify the syntax.
     86  1.3  rillig #
     87  1.3  rillig # The ':sh' is the only word that may occur between the variable name and
     88  1.5  rillig # the assignment operator at nesting level 0.  All other words would lead
     89  1.5  rillig # to a parse error since the left-hand side of an assignment must be
     90  1.5  rillig # exactly one word.
     91  1.3  rillig VAR :sh :sh :sh :sh=	echo multiple
     92  1.3  rillig .if ${VAR} != "multiple"
     93  1.3  rillig .  error
     94  1.3  rillig .endif
     95  1.3  rillig 
     96  1.4  rillig # The word ':sh' is not the only thing that can occur after a variable name.
     97  1.4  rillig # Since the parser just counts braces and parentheses instead of properly
     98  1.4  rillig # expanding nested expressions, the token ' :sh' can be used to add arbitrary
     99  1.4  rillig # text between the variable name and the assignment operator, it just has to
    100  1.4  rillig # be enclosed in braces or parentheses.
    101  1.9  rillig #
    102  1.9  rillig # Since the text to the left of the assignment operator '=' does not end with
    103  1.9  rillig # ':sh', the effective assignment operator becomes '=', not '!='.
    104  1.4  rillig VAR :sh(Put a comment here)=	comment in parentheses
    105  1.4  rillig .if ${VAR} != "comment in parentheses"
    106  1.4  rillig .  error
    107  1.4  rillig .endif
    108  1.4  rillig 
    109  1.4  rillig # The unintended comment can include multiple levels of nested braces and
    110  1.9  rillig # parentheses.  Braces and parentheses are interchangeable, that is, a '(' can
    111  1.9  rillig # be closed by either ')' or '}'.  These braces and parentheses are only
    112  1.9  rillig # counted by Parse_IsVar, in particular Parse_Var doesn't see them.
    113  1.4  rillig VAR :sh{Put}((((a}{comment}}}}{here}=	comment in braces
    114  1.4  rillig .if ${VAR} != "comment in braces"
    115  1.4  rillig .  error
    116  1.4  rillig .endif
    117  1.4  rillig 
    118  1.9  rillig # The assignment modifier ':sh' can be combined with the assignment operator
    119  1.9  rillig # '+='.  In such a case the ':sh' is silently ignored, and the effective
    120  1.9  rillig # assignment operator is '+='.
    121  1.5  rillig #
    122  1.9  rillig # XXX: This combination should not be allowed at all, as it is confusing.
    123  1.5  rillig VAR=		one
    124  1.5  rillig VAR :sh +=	echo two
    125  1.5  rillig .if ${VAR} != "one echo two"
    126  1.5  rillig .  error ${VAR}
    127  1.5  rillig .endif
    128  1.5  rillig 
    129  1.9  rillig # The assignment modifier ':sh' can be combined with the assignment operator
    130  1.9  rillig # '!='.  In such a case the ':sh' is silently ignored, and the effective
    131  1.9  rillig # assignment operator is '!=', just like with '+=' or the other compound
    132  1.9  rillig # assignment operators.
    133  1.9  rillig #
    134  1.9  rillig # XXX: This combination should not be allowed at all, as it is confusing.
    135  1.9  rillig VAR :sh !=	echo echo echo echo spaces-around
    136  1.9  rillig .if ${VAR} != "echo echo echo spaces-around"
    137  1.9  rillig .  error ${VAR}
    138  1.9  rillig .endif
    139  1.9  rillig 
    140  1.9  rillig # If there is no space between the variable name and the assignment modifier
    141  1.9  rillig # ':sh', the ':sh' becomes part of the variable name, as the parser only
    142  1.9  rillig # expects a single assignment modifier to the left of the '=', which in this
    143  1.9  rillig # case is the '!'.
    144  1.9  rillig VAR:sh !=	echo echo echo echo space-after
    145  1.9  rillig .if ${${:UVAR\:sh}} != "echo echo echo space-after"
    146  1.9  rillig .  error ${${:UVAR\:sh}}
    147  1.9  rillig .endif
    148  1.6  rillig 
    149  1.9  rillig all: .PHONY
    150