]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/bmake/unit-tests/var-op-sunsh.mk
Merge bmake-20201117
[FreeBSD/FreeBSD.git] / contrib / bmake / unit-tests / var-op-sunsh.mk
1 # $NetBSD: var-op-sunsh.mk,v 1.6 2020/11/15 20:20:58 rillig Exp $
2 #
3 # Tests for the :sh= variable assignment operator, which runs its right-hand
4 # side through the shell.  It is a seldom-used alternative to the !=
5 # assignment operator, adopted from Sun make.
6
7 .MAKEFLAGS: -dL                 # Enable sane error messages
8
9 # This is the idiomatic form of the Sun shell assignment operator.
10 # The assignment operator is directly preceded by the ':sh'.
11 VAR:sh=         echo colon-sh
12 .if ${VAR} != "colon-sh"
13 .  error
14 .endif
15
16 # It is also possible to have whitespace around the :sh assignment
17 # operator modifier.
18 VAR :sh =       echo colon-sh-spaced
19 .if ${VAR} != "colon-sh-spaced"
20 .  error
21 .endif
22
23 # Until 2020-10-04, the ':sh' could even be followed by other characters.
24 # This was neither documented by NetBSD make nor by Solaris make and was
25 # an implementation error.
26 #
27 # Since 2020-10-04, this is a normal variable assignment using the '='
28 # assignment operator.
29 VAR:shell=      echo colon-shell
30 .if ${${:UVAR\:shell}} != "echo colon-shell"
31 .  error
32 .endif
33
34 # Several colons can syntactically appear in a variable name.
35 # Until 2020-10-04, the last of them was interpreted as the ':sh'
36 # assignment operator.
37 #
38 # Since 2020-10-04, the colons are part of the variable name.
39 VAR:shoe:shore= echo two-colons
40 .if ${${:UVAR\:shoe\:shore}} != "echo two-colons"
41 .  error
42 .endif
43
44 # Until 2020-10-04, the following expression was wrongly marked as
45 # a parse error.  This was because the parser for variable assignments
46 # just looked for the previous ":sh", without taking any contextual
47 # information into account.
48 #
49 # There are two different syntactical elements that look exactly the same:
50 # The variable modifier ':sh' and the assignment operator modifier ':sh'.
51 # Intuitively this variable name contains the variable modifier, but until
52 # 2020-10-04, the parser regarded it as an assignment operator modifier, in
53 # Parse_DoVar.
54 VAR.${:Uecho 123:sh}=   ok-123
55 .if ${VAR.123} != "ok-123"
56 .  error
57 .endif
58
59 # Same pattern here. Until 2020-10-04, the ':sh' inside the nested expression
60 # was taken for the :sh assignment operator modifier, even though it was
61 # escaped by a backslash.
62 VAR.${:U echo\:shell}=  ok-shell
63 .if ${VAR.${:U echo\:shell}} != "ok-shell"
64 .  error
65 .endif
66
67 # Until 2020-10-04, the word 'shift' was also affected since it starts with
68 # ':sh'.
69 VAR.key:shift=          Shift
70 .if ${${:UVAR.key\:shift}} != "Shift"
71 .  error
72 .endif
73
74 # Just for fun: The code in Parse_IsVar allows for multiple appearances of
75 # the ':sh' assignment operator modifier.  Let's see what happens ...
76 #
77 # Well, the end result is correct but the way until there is rather
78 # adventurous.  This only works because the parser replaces each an every
79 # whitespace character that is not nested with '\0' (see Parse_DoVar).
80 # The variable name therefore ends before the first ':sh', and the last
81 # ':sh' turns the assignment operator into the shell command evaluation.
82 # Parse_DoVar completely trusts Parse_IsVar to properly verify the syntax.
83 #
84 # The ':sh' is the only word that may occur between the variable name and
85 # the assignment operator at nesting level 0.  All other words would lead
86 # to a parse error since the left-hand side of an assignment must be
87 # exactly one word.
88 VAR :sh :sh :sh :sh=    echo multiple
89 .if ${VAR} != "multiple"
90 .  error
91 .endif
92
93 # The word ':sh' is not the only thing that can occur after a variable name.
94 # Since the parser just counts braces and parentheses instead of properly
95 # expanding nested expressions, the token ' :sh' can be used to add arbitrary
96 # text between the variable name and the assignment operator, it just has to
97 # be enclosed in braces or parentheses.
98 VAR :sh(Put a comment here)=    comment in parentheses
99 .if ${VAR} != "comment in parentheses"
100 .  error
101 .endif
102
103 # The unintended comment can include multiple levels of nested braces and
104 # parentheses, they don't even need to be balanced since they are only
105 # counted by Parse_IsVar and ignored by Parse_DoVar.
106 VAR :sh{Put}((((a}{comment}}}}{here}=   comment in braces
107 .if ${VAR} != "comment in braces"
108 .  error
109 .endif
110
111 # Syntactically, the ':sh' modifier can be combined with the '+=' assignment
112 # operator.  In such a case the ':sh' modifier is silently ignored.
113 #
114 # XXX: This combination should not be allowed at all.
115 VAR=            one
116 VAR :sh +=      echo two
117 .if ${VAR} != "one echo two"
118 .  error ${VAR}
119 .endif
120
121 # TODO: test VAR:sh!=command
122
123 all:
124         @:;