1# $NetBSD: varname.mk,v 1.18 2025/06/28 22:39:29 rillig Exp $ 2# 3# Tests for variable names. 4 5.MAKEFLAGS: -dv 6 7# In a variable assignment, braces are allowed in the variable name, but they 8# must be balanced. Parentheses and braces may be mixed. 9VAR{{{}}}= 3 braces 10.if "${VAR{{{}}}}" != "3 braces" 11. error 12.endif 13 14# In expressions, the parser works differently. It doesn't treat 15# braces and parentheses equally, therefore the first closing brace already 16# marks the end of the variable name. 17VARNAME= VAR((( 18${VARNAME}= 3 open parentheses 19.if "${VAR(((}}}}" != "3 open parentheses}}}" 20. error 21.endif 22 23# In the above test, the variable name is constructed indirectly. Neither 24# of the following expressions produces the intended effect. 25# 26# This is not a variable assignment since the parentheses and braces are not 27# balanced. At the end of the line, there are still 3 levels open, which 28# means the variable name is not finished. 29# expect+2: Missing ")" in archive specification 30# expect+1: Error in archive specification: "VAR" 31${:UVAR(((}= try1 32# On the left-hand side of a variable assignments, the backslash is not parsed 33# as an escape character, therefore the parentheses still count to the nesting 34# level, which at the end of the line is still 3. Therefore this is not a 35# variable assignment as well. 36# expect+1: Invalid line "${:UVAR\(\(\(}= try2", expanded to "VAR\(\(\(= try2" 37${:UVAR\(\(\(}= try2 38# To assign to a variable with an arbitrary name, the variable name has to 39# come from an external source, not the text that is parsed in the assignment 40# itself. This is exactly the reason why further above, the indirect 41# ${VARNAME} works, while all other attempts fail. 42${VARNAME}= try3 43 44.MAKEFLAGS: -d0 45 46# All variable names of a scope are stored in the same hash table, using a 47# simple hash function. Ensure that HashTable_Find handles collisions 48# correctly and that the correct variable is looked up. The strings "0x" and 49# "1Y" have the same hash code, as 31 * '0' + 'x' == 31 * '1' + 'Y'. 50V.0x= 0x 51V.1Y= 1Y 52.if ${V.0x} != "0x" || ${V.1Y} != "1Y" 53. error 54.endif 55 56# The string "ASDZguv", when used as a prefix of a variable name, keeps the 57# hash code unchanged, its own hash code is 0. 58ASDZguvV.0x= 0x 59ASDZguvV.1Y= 1Y 60.if ${ASDZguvV.0x} != "0x" 61. error 62.elif ${ASDZguvV.1Y} != "1Y" 63. error 64.endif 65 66# Ensure that variables with the same hash code whose name is a prefix of the 67# other can be accessed. In this case, the shorter variable name is defined 68# first to make it appear later in the bucket of the hash table. 69ASDZguv= once 70ASDZguvASDZguv= twice 71.if ${ASDZguv} != "once" 72. error 73.elif ${ASDZguvASDZguv} != "twice" 74. error 75.endif 76 77# Ensure that variables with the same hash code whose name is a prefix of the 78# other can be accessed. In this case, the longer variable name is defined 79# first to make it appear later in the bucket of the hash table. 80ASDZguvASDZguv.param= twice 81ASDZguv.param= once 82.if ${ASDZguv.param} != "once" 83. error 84.elif ${ASDZguvASDZguv.param} != "twice" 85. error 86.endif 87 88 89# Warn about expressions in the style of GNU make, as these would silently 90# expand to an empty string instead. 91# 92# https://pubs.opengroup.org/onlinepubs/9799919799/utilities/make.html says: 93# a macro name shall not contain an <equals-sign>, <blank>, or control 94# character. 95# 96GNU_MAKE_IF= $(if ${HAVE_STRLEN},yes,no) 97# expect+1: warning: Invalid character " " in variable name "if ,yes,no" 98.if ${GNU_MAKE_IF} != "" 99. error 100.endif 101# 102# This requirement needs to be ignored for expressions with a ":L" or ":?:" 103# modifier, as these modifiers rely on arbitrary characters in the expression 104# name. 105.if ${"left" == "right":?equal:unequal} != "unequal" 106. error 107.endif 108# 109# In fact, this requirement is ignored for any expression that has a modifier. 110# In this indirect case, though, the expression with the space in the name is 111# a nested expression, so the ":U" modifier doesn't affect the warning. 112# expect+1: warning: Invalid character " " in variable name "if ,yes,no" 113.if ${GNU_MAKE_IF:Ufallback} != "" 114. error 115.endif 116# 117# A modifier in a nested expression does not affect the warning. 118GNU_MAKE_IF_EXPR= $(if ${HAVE_STRLEN},${HEADERS:.h=.c},) 119# expect+1: warning: Invalid character " " in variable name "if ,," 120.if ${GNU_MAKE_IF_EXPR} != "" 121. error 122.endif 123# 124# When the GNU make expression contains a colon, chances are good that the 125# colon is interpreted as an unknown modifier. 126GNU_MAKE_IF_MODIFIER= $(if ${HAVE_STRLEN},answer:yes,answer:no) 127# expect+1: Unknown modifier ":yes,answer" 128.if ${GNU_MAKE_IF_MODIFIER} != "no)" 129. error 130.endif 131# 132# If the variable name contains a non-printable character, the warning 133# contains the numeric character value instead, to prevent control sequences 134# in the output. 135CONTROL_CHARACTER= ${:U a b:ts\t} 136# expect+2: warning: Invalid character "\x09" in variable name "a b" 137# expect+1: Variable "a b" is undefined 138.if ${${CONTROL_CHARACTER}} != "" 139.endif 140# 141# For now, only whitespace generates a warning, non-ASCII characters don't. 142UMLAUT= ÄÖÜ 143# expect+1: Variable "ÄÖÜ" is undefined 144.if ${${UMLAUT}} != "" 145.endif 146