1# $NetBSD: varmod-defined.mk,v 1.13 2022/08/24 20:22:10 rillig Exp $ 2# 3# Tests for the :D variable modifier, which returns the given string 4# if the variable is defined. It is closely related to the :U modifier. 5 6# Force the test results to be independent of the default value of this 7# setting, which is 'yes' for NetBSD's usr.bin/make but 'no' for the bmake 8# distribution and pkgsrc/devel/bmake. 9.MAKE.SAVE_DOLLARS= yes 10 11DEF= defined 12.undef UNDEF 13 14# Since DEF is defined, the value of the expression is "value", not 15# "defined". 16# 17.if ${DEF:Dvalue} != "value" 18. error 19.endif 20 21# Since UNDEF is not defined, the "value" is ignored. Instead of leaving the 22# expression undefined, it is set to "", exactly to allow the expression to 23# be used in .if conditions. In this place, other undefined expressions 24# would generate an error message. 25# XXX: Ideally the error message would be "undefined variable", but as of 26# 2020-08-25 it is "Malformed conditional". 27# 28.if ${UNDEF:Dvalue} != "" 29. error 30.endif 31 32# The modifier text may contain plain text as well as expressions. 33# 34.if ${DEF:D<${DEF}>} != "<defined>" 35. error 36.endif 37 38# Special characters that would be interpreted differently can be escaped. 39# These are '}' (the closing character of the expression), ':', '$' and '\'. 40# Any other backslash sequences are preserved. 41# 42# The escaping rules for string literals in conditions are completely 43# different though. There, any character may be escaped using a backslash. 44# 45.if ${DEF:D \} \: \$ \\ \) \n } != " } : \$ \\ \\) \\n " 46. error 47.endif 48 49# Like in several other places in variable expressions, when 50# ApplyModifier_Defined calls Var_Parse, double dollars lead to a parse 51# error that is silently ignored. This makes all dollar signs disappear, 52# except for the last, which is a well-formed variable expression. 53# 54.if ${DEF:D$$$$$${DEF}} != "defined" 55. error 56.endif 57 58# Any other text is written without any further escaping. In contrast 59# to the :M modifier, parentheses and braces do not need to be nested. 60# Instead, the :D modifier is implemented sanely by parsing nested 61# expressions as such, without trying any shortcuts. See ApplyModifier_Match 62# for an inferior variant. 63# 64.if ${DEF:D!&((((} != "!&((((" 65. error 66.endif 67 68# The :D modifier is often used in combination with the :U modifier. 69# It does not matter in which order the :D and :U modifiers appear. 70.if ${UNDEF:Dyes:Uno} != no 71. error 72.endif 73.if ${UNDEF:Uno:Dyes} != no 74. error 75.endif 76.if ${DEF:Dyes:Uno} != yes 77. error 78.endif 79.if ${DEF:Uno:Dyes} != yes 80. error 81.endif 82 83# Since the variable with the empty name is never defined, the :D modifier 84# can be used to add comments in the middle of an expression. That 85# expression always evaluates to an empty string. 86.if ${:D This is a comment. } != "" 87. error 88.endif 89 90# TODO: Add more tests for parsing the plain text part, to cover each branch 91# of ApplyModifier_Defined. 92 93# The :D and :U modifiers behave differently from the :@var@ modifier in 94# that they preserve dollars in a ':=' assignment. This is because 95# ApplyModifier_Defined passes the emode unmodified to Var_Parse, unlike 96# ApplyModifier_Loop, which uses ParseModifierPart, which in turn removes 97# the keepDollar flag from emode. 98# 99# XXX: This inconsistency is documented nowhere. 100.MAKEFLAGS: -dv 1018_DOLLARS= $$$$$$$$ 102VAR:= ${8_DOLLARS} 103VAR:= ${VAR:D${8_DOLLARS}} 104VAR:= ${VAR:@var@${8_DOLLARS}@} 105.MAKEFLAGS: -d0 106 107 108# Before var.c 1.1030 from 2022-08-24, the following expression caused an 109# out-of-bounds read when parsing the indirect ':D' modifier. 110M_U_backslash:= ${:UU\\} 111.if ${:${M_U_backslash}} != "\\" 112. error 113.endif 114 115 116all: .PHONY 117