1*d5e0a182SSimon J. Gerraty# $NetBSD: var-op-assign.mk,v 1.11 2023/11/19 21:47:52 rillig Exp $
22c3632d1SSimon J. Gerraty#
32c3632d1SSimon J. Gerraty# Tests for the = variable assignment operator, which overwrites an existing
42c3632d1SSimon J. Gerraty# variable or creates it.
52c3632d1SSimon J. Gerraty
62c3632d1SSimon J. Gerraty# This is a simple variable assignment.
72c3632d1SSimon J. Gerraty# To the left of the assignment operator '=' there is the variable name,
8e2eeea75SSimon J. Gerraty# and to the right is the variable value.  The variable value is stored as-is,
9e2eeea75SSimon J. Gerraty# it is not expanded in any way.
102c3632d1SSimon J. Gerraty#
112c3632d1SSimon J. GerratyVAR=	value
122c3632d1SSimon J. Gerraty
132c3632d1SSimon J. Gerraty# This condition demonstrates that whitespace around the assignment operator
142c3632d1SSimon J. Gerraty# is discarded.  Otherwise the value would start with a single tab.
152c3632d1SSimon J. Gerraty#
162c3632d1SSimon J. Gerraty.if ${VAR} != "value"
172c3632d1SSimon J. Gerraty.  error
182c3632d1SSimon J. Gerraty.endif
192c3632d1SSimon J. Gerraty
202c3632d1SSimon J. Gerraty# Whitespace to the left of the assignment operator is ignored as well.
212c3632d1SSimon J. Gerraty# The variable value can contain arbitrary characters.
222c3632d1SSimon J. Gerraty#
232c3632d1SSimon J. Gerraty# The '#' needs to be escaped with a backslash, this happens in a very
242c3632d1SSimon J. Gerraty# early stage of parsing and applies to all line types, except for the
252c3632d1SSimon J. Gerraty# commands, which are indented with a tab.
262c3632d1SSimon J. Gerraty#
272c3632d1SSimon J. Gerraty# The '$' needs to be escaped with another '$', otherwise it would refer to
282c3632d1SSimon J. Gerraty# another variable.
292c3632d1SSimon J. Gerraty#
302c3632d1SSimon J. GerratyVAR=	new value and \# some $$ special characters	# comment
312c3632d1SSimon J. Gerraty
322c3632d1SSimon J. Gerraty# When a string literal appears in a condition, the escaping rules are
332c3632d1SSimon J. Gerraty# different.  Run make with the -dc option to see the details.
342c3632d1SSimon J. Gerraty.if ${VAR} != "new value and \# some \$ special characters"
352c3632d1SSimon J. Gerraty.  error ${VAR}
362c3632d1SSimon J. Gerraty.endif
372c3632d1SSimon J. Gerraty
382c3632d1SSimon J. Gerraty# The variable value may contain references to other variables.
392c3632d1SSimon J. Gerraty# In this example, the reference is to the variable with the empty name,
40e2eeea75SSimon J. Gerraty# which is never defined.
41e2eeea75SSimon J. Gerraty#
42e2eeea75SSimon J. Gerraty# This alone would not produce any side-effects, therefore the variable has
43e2eeea75SSimon J. Gerraty# a :!...! modifier that executes a shell command.  The :!...! modifier turns
44e2eeea75SSimon J. Gerraty# an undefined expression into a defined one, see ApplyModifier_ShellCommand,
45b0c40a00SSimon J. Gerraty# the call to Expr_Define.
46e2eeea75SSimon J. Gerraty#
47e2eeea75SSimon J. Gerraty# Since the right-hand side of a '=' assignment is not expanded at the time
48e2eeea75SSimon J. Gerraty# when the variable is defined, the first command is not run at all.
492c3632d1SSimon J. GerratyVAR=	${:! echo 'not yet evaluated' 1>&2 !}
502c3632d1SSimon J. GerratyVAR=	${:! echo 'this will be evaluated later' 1>&2 !}
512c3632d1SSimon J. Gerraty
522c3632d1SSimon J. Gerraty# Now force the variable to be evaluated.
532c3632d1SSimon J. Gerraty# This outputs the line to stderr.
542c3632d1SSimon J. Gerraty.if ${VAR}
552c3632d1SSimon J. Gerraty.endif
562c3632d1SSimon J. Gerraty
572c3632d1SSimon J. Gerraty# In a variable assignment, the variable name must consist of a single word.
58e2eeea75SSimon J. Gerraty# The following line therefore generates a parse error.
5998875883SSimon J. Gerraty# expect+1: Invalid line 'VARIABLE NAME=	variable value'
602c3632d1SSimon J. GerratyVARIABLE NAME=	variable value
612c3632d1SSimon J. Gerraty
622c3632d1SSimon J. Gerraty# But if the whitespace appears inside parentheses or braces, everything is
632c3632d1SSimon J. Gerraty# fine.
642c3632d1SSimon J. Gerraty#
652c3632d1SSimon J. Gerraty# XXX: This was not an intentional decision, as variable names typically
662c3632d1SSimon J. Gerraty# neither contain parentheses nor braces.  This is only a side-effect from
672c3632d1SSimon J. Gerraty# the implementation of the parser, which cheats when parsing a variable
682c3632d1SSimon J. Gerraty# name.  It only counts parentheses and braces instead of properly parsing
69*d5e0a182SSimon J. Gerraty# nested expressions such as VAR.${param}.
702c3632d1SSimon J. Gerraty#
712c3632d1SSimon J. GerratyVAR(spaces in parentheses)=	()
722c3632d1SSimon J. GerratyVAR{spaces in braces}=		{}
732c3632d1SSimon J. Gerraty
742c3632d1SSimon J. Gerraty# Be careful and use indirect variable names here, to prevent accidentally
752c3632d1SSimon J. Gerraty# accepting the test in case the parser just uses "VAR" as the variable name,
762c3632d1SSimon J. Gerraty# ignoring all the rest.
772c3632d1SSimon J. Gerraty#
782c3632d1SSimon J. GerratyVARNAME_PAREN=	VAR(spaces in parentheses)
792c3632d1SSimon J. GerratyVARNAME_BRACES=	VAR{spaces in braces}
802c3632d1SSimon J. Gerraty
812c3632d1SSimon J. Gerraty.if ${${VARNAME_PAREN}} != "()"
822c3632d1SSimon J. Gerraty.  error
832c3632d1SSimon J. Gerraty.endif
842c3632d1SSimon J. Gerraty
852c3632d1SSimon J. Gerraty.if ${${VARNAME_BRACES}} != "{}"
862c3632d1SSimon J. Gerraty.  error
872c3632d1SSimon J. Gerraty.endif
882c3632d1SSimon J. Gerraty
892c3632d1SSimon J. Gerraty# In safe mode, parsing would stop immediately after the "VARIABLE NAME="
902c3632d1SSimon J. Gerraty# line, since any commands run after that are probably working with
912c3632d1SSimon J. Gerraty# unexpected variable values.
922c3632d1SSimon J. Gerraty#
932c3632d1SSimon J. Gerraty# Therefore, just output an info message.
94148ee845SSimon J. Gerraty# expect+1: Parsing still continues until here.
952c3632d1SSimon J. Gerraty.info Parsing still continues until here.
962c3632d1SSimon J. Gerraty
972c3632d1SSimon J. Gerratyall:
982c3632d1SSimon J. Gerraty	@:;
99