xref: /freebsd/contrib/bmake/unit-tests/var-op-assign.mk (revision 783d3ff6d7fae619db8a7990b8a6387de0c677b5)
1# $NetBSD: var-op-assign.mk,v 1.11 2023/11/19 21:47:52 rillig Exp $
2#
3# Tests for the = variable assignment operator, which overwrites an existing
4# variable or creates it.
5
6# This is a simple variable assignment.
7# To the left of the assignment operator '=' there is the variable name,
8# and to the right is the variable value.  The variable value is stored as-is,
9# it is not expanded in any way.
10#
11VAR=	value
12
13# This condition demonstrates that whitespace around the assignment operator
14# is discarded.  Otherwise the value would start with a single tab.
15#
16.if ${VAR} != "value"
17.  error
18.endif
19
20# Whitespace to the left of the assignment operator is ignored as well.
21# The variable value can contain arbitrary characters.
22#
23# The '#' needs to be escaped with a backslash, this happens in a very
24# early stage of parsing and applies to all line types, except for the
25# commands, which are indented with a tab.
26#
27# The '$' needs to be escaped with another '$', otherwise it would refer to
28# another variable.
29#
30VAR=	new value and \# some $$ special characters	# comment
31
32# When a string literal appears in a condition, the escaping rules are
33# different.  Run make with the -dc option to see the details.
34.if ${VAR} != "new value and \# some \$ special characters"
35.  error ${VAR}
36.endif
37
38# The variable value may contain references to other variables.
39# In this example, the reference is to the variable with the empty name,
40# which is never defined.
41#
42# This alone would not produce any side-effects, therefore the variable has
43# a :!...! modifier that executes a shell command.  The :!...! modifier turns
44# an undefined expression into a defined one, see ApplyModifier_ShellCommand,
45# the call to Expr_Define.
46#
47# Since the right-hand side of a '=' assignment is not expanded at the time
48# when the variable is defined, the first command is not run at all.
49VAR=	${:! echo 'not yet evaluated' 1>&2 !}
50VAR=	${:! echo 'this will be evaluated later' 1>&2 !}
51
52# Now force the variable to be evaluated.
53# This outputs the line to stderr.
54.if ${VAR}
55.endif
56
57# In a variable assignment, the variable name must consist of a single word.
58# The following line therefore generates a parse error.
59# expect+1: Invalid line 'VARIABLE NAME=	variable value'
60VARIABLE NAME=	variable value
61
62# But if the whitespace appears inside parentheses or braces, everything is
63# fine.
64#
65# XXX: This was not an intentional decision, as variable names typically
66# neither contain parentheses nor braces.  This is only a side-effect from
67# the implementation of the parser, which cheats when parsing a variable
68# name.  It only counts parentheses and braces instead of properly parsing
69# nested expressions such as VAR.${param}.
70#
71VAR(spaces in parentheses)=	()
72VAR{spaces in braces}=		{}
73
74# Be careful and use indirect variable names here, to prevent accidentally
75# accepting the test in case the parser just uses "VAR" as the variable name,
76# ignoring all the rest.
77#
78VARNAME_PAREN=	VAR(spaces in parentheses)
79VARNAME_BRACES=	VAR{spaces in braces}
80
81.if ${${VARNAME_PAREN}} != "()"
82.  error
83.endif
84
85.if ${${VARNAME_BRACES}} != "{}"
86.  error
87.endif
88
89# In safe mode, parsing would stop immediately after the "VARIABLE NAME="
90# line, since any commands run after that are probably working with
91# unexpected variable values.
92#
93# Therefore, just output an info message.
94# expect+1: Parsing still continues until here.
95.info Parsing still continues until here.
96
97all:
98	@:;
99