varname-empty.mk revision 1.7
11.7Srillig# $NetBSD: varname-empty.mk,v 1.7 2020/10/23 17:53:01 rillig Exp $
21.1Srillig#
31.1Srillig# Tests for the special variable with the empty name.
41.1Srillig#
51.6Srillig# There is no variable named "" at all, and this fact is used a lot in
61.6Srillig# variable expressions of the form ${:Ufallback}.  These expressions are
71.6Srillig# based on the variable named "" and use the :U modifier to assign a
81.6Srillig# fallback value to the expression (but not to the variable).
91.6Srillig#
101.6Srillig# This form of expressions is used to implement value substitution in the
111.6Srillig# .for loops.  Another use case is in a variable assignment of the form
121.6Srillig# ${:Uvarname}=value, which allows for characters in the variable name that
131.6Srillig# would otherwise be interpreted by the parser, such as whitespace, ':',
141.6Srillig# '=', '$', backslash.
151.6Srillig#
161.6Srillig# The only places where a variable is assigned a value are Var_Set and
171.6Srillig# Var_Append, and these places protect the variable named "" from being
181.6Srillig# defined.  This is different from read-only variables, as that flag can
191.7Srillig# only apply to variables that are defined.  The variable named "" must
201.7Srillig# never be defined though.
211.6Srillig#
221.7Srillig# See also:
231.7Srillig#	The special variables @F or ^D, in var-class-local.mk
241.1Srillig
251.2Srillig# Until 2020-08-22 it was possible to assign a value to the variable with
261.7Srillig# the empty name, leading to all kinds of unexpected effects in .for loops
271.7Srillig# and other places that assume that ${:Ufallback} expands to "fallback".
281.7Srillig# The bug in Var_Set was that only expanded variables had been checked for
291.7Srillig# the empty name, but not the direct assignments with an empty name.
301.3Srillig?=	default
311.4Srillig=	assigned	# undefined behavior until 2020-08-22
321.3Srillig+=	appended
331.3Srillig:=	subst
341.5Srillig!=	echo 'shell-output'
351.7Srillig.if ${:Ufallback} != "fallback"
361.7Srillig.  error
371.7Srillig.endif
381.7Srillig
391.7Srillig${:U}=	assigned indirectly
401.7Srillig.if ${:Ufallback} != "fallback"
411.7Srillig.  error
421.7Srillig.endif
431.7Srillig
441.7Srillig# Before 2020-08-22, the simple assignment operator '=' after an empty
451.7Srillig# variable name had an off-by-one bug in Parse_DoVar.  The code that was
461.7Srillig# supposed to "skip to operator character" started its search _after_ the
471.7Srillig# assignment operator, assuming that the variable name would be at least
481.7Srillig# one character long.  It then looked for the next occurrence of a '=', which
491.7Srillig# could be several lines away or not occur at all.  While looking for the
501.7Srillig# '=', some whitespace was nulled out, leading to out-of-bounds write.
511.7Srillig=	assigned	# undefined behavior until 2020-08-22
521.1Srillig
531.1Srillig# The .for loop expands the expression ${i} to ${:U1}, ${:U2} and so on.
541.1Srillig# This only works if the variable with the empty name is guaranteed to
551.1Srillig# be undefined.
561.1Srillig.for i in 1 2 3
571.1SrilligNUMBERS+=	${i}
581.1Srillig.endfor
591.1Srillig
601.1Srilligall:
611.5Srillig	@echo out: ${:Ufallback}
621.5Srillig	@echo out: ${NUMBERS}
63