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