1*d5e0a182SSimon J. Gerraty# $NetBSD: varmod-defined.mk,v 1.16 2023/11/19 21:47:52 rillig Exp $ 22c3632d1SSimon J. Gerraty# 32c3632d1SSimon J. Gerraty# Tests for the :D variable modifier, which returns the given string 42c3632d1SSimon J. Gerraty# if the variable is defined. It is closely related to the :U modifier. 52c3632d1SSimon J. Gerraty 612904384SSimon J. Gerraty# Force the test results to be independent of the default value of this 712904384SSimon J. Gerraty# setting, which is 'yes' for NetBSD's usr.bin/make but 'no' for the bmake 812904384SSimon J. Gerraty# distribution and pkgsrc/devel/bmake. 9e2eeea75SSimon J. Gerraty.MAKE.SAVE_DOLLARS= yes 10e2eeea75SSimon J. Gerraty 112c3632d1SSimon J. GerratyDEF= defined 122c3632d1SSimon J. Gerraty.undef UNDEF 132c3632d1SSimon J. Gerraty 142c3632d1SSimon J. Gerraty# Since DEF is defined, the value of the expression is "value", not 152c3632d1SSimon J. Gerraty# "defined". 162c3632d1SSimon J. Gerraty# 172c3632d1SSimon J. Gerraty.if ${DEF:Dvalue} != "value" 182c3632d1SSimon J. Gerraty. error 192c3632d1SSimon J. Gerraty.endif 202c3632d1SSimon J. Gerraty 212c3632d1SSimon J. Gerraty# Since UNDEF is not defined, the "value" is ignored. Instead of leaving the 222c3632d1SSimon J. Gerraty# expression undefined, it is set to "", exactly to allow the expression to 232c3632d1SSimon J. Gerraty# be used in .if conditions. In this place, other undefined expressions 242c3632d1SSimon J. Gerraty# would generate an error message. 252c3632d1SSimon J. Gerraty# XXX: Ideally the error message would be "undefined variable", but as of 262c3632d1SSimon J. Gerraty# 2020-08-25 it is "Malformed conditional". 272c3632d1SSimon J. Gerraty# 282c3632d1SSimon J. Gerraty.if ${UNDEF:Dvalue} != "" 292c3632d1SSimon J. Gerraty. error 302c3632d1SSimon J. Gerraty.endif 312c3632d1SSimon J. Gerraty 32956e45f6SSimon J. Gerraty# The modifier text may contain plain text as well as expressions. 33956e45f6SSimon J. Gerraty# 34956e45f6SSimon J. Gerraty.if ${DEF:D<${DEF}>} != "<defined>" 35956e45f6SSimon J. Gerraty. error 36956e45f6SSimon J. Gerraty.endif 37956e45f6SSimon J. Gerraty 38956e45f6SSimon J. Gerraty# Special characters that would be interpreted differently can be escaped. 39956e45f6SSimon J. Gerraty# These are '}' (the closing character of the expression), ':', '$' and '\'. 40956e45f6SSimon J. Gerraty# Any other backslash sequences are preserved. 41956e45f6SSimon J. Gerraty# 42956e45f6SSimon J. Gerraty# The escaping rules for string literals in conditions are completely 43956e45f6SSimon J. Gerraty# different though. There, any character may be escaped using a backslash. 44956e45f6SSimon J. Gerraty# 45956e45f6SSimon J. Gerraty.if ${DEF:D \} \: \$ \\ \) \n } != " } : \$ \\ \\) \\n " 46956e45f6SSimon J. Gerraty. error 47956e45f6SSimon J. Gerraty.endif 48956e45f6SSimon J. Gerraty 49*d5e0a182SSimon J. Gerraty# Like in several other places in expressions, when 50956e45f6SSimon J. Gerraty# ApplyModifier_Defined calls Var_Parse, double dollars lead to a parse 51956e45f6SSimon J. Gerraty# error that is silently ignored. This makes all dollar signs disappear, 52*d5e0a182SSimon J. Gerraty# except for the last, which is a well-formed expression. 53956e45f6SSimon J. Gerraty# 54956e45f6SSimon J. Gerraty.if ${DEF:D$$$$$${DEF}} != "defined" 55956e45f6SSimon J. Gerraty. error 56956e45f6SSimon J. Gerraty.endif 57956e45f6SSimon J. Gerraty 58956e45f6SSimon J. Gerraty# Any other text is written without any further escaping. In contrast 59956e45f6SSimon J. Gerraty# to the :M modifier, parentheses and braces do not need to be nested. 60956e45f6SSimon J. Gerraty# Instead, the :D modifier is implemented sanely by parsing nested 61*d5e0a182SSimon J. Gerraty# expressions as such, without trying any shortcuts. See ParseModifier_Match 62956e45f6SSimon J. Gerraty# for an inferior variant. 63956e45f6SSimon J. Gerraty# 64956e45f6SSimon J. Gerraty.if ${DEF:D!&((((} != "!&((((" 65956e45f6SSimon J. Gerraty. error 66956e45f6SSimon J. Gerraty.endif 67956e45f6SSimon J. Gerraty 68956e45f6SSimon J. Gerraty# The :D modifier is often used in combination with the :U modifier. 69956e45f6SSimon J. Gerraty# It does not matter in which order the :D and :U modifiers appear. 70956e45f6SSimon J. Gerraty.if ${UNDEF:Dyes:Uno} != no 71956e45f6SSimon J. Gerraty. error 72956e45f6SSimon J. Gerraty.endif 73956e45f6SSimon J. Gerraty.if ${UNDEF:Uno:Dyes} != no 74956e45f6SSimon J. Gerraty. error 75956e45f6SSimon J. Gerraty.endif 76956e45f6SSimon J. Gerraty.if ${DEF:Dyes:Uno} != yes 77956e45f6SSimon J. Gerraty. error 78956e45f6SSimon J. Gerraty.endif 79956e45f6SSimon J. Gerraty.if ${DEF:Uno:Dyes} != yes 80956e45f6SSimon J. Gerraty. error 81956e45f6SSimon J. Gerraty.endif 82956e45f6SSimon J. Gerraty 83956e45f6SSimon J. Gerraty# Since the variable with the empty name is never defined, the :D modifier 84956e45f6SSimon J. Gerraty# can be used to add comments in the middle of an expression. That 85956e45f6SSimon J. Gerraty# expression always evaluates to an empty string. 86956e45f6SSimon J. Gerraty.if ${:D This is a comment. } != "" 87956e45f6SSimon J. Gerraty. error 88956e45f6SSimon J. Gerraty.endif 89956e45f6SSimon J. Gerraty 90956e45f6SSimon J. Gerraty# TODO: Add more tests for parsing the plain text part, to cover each branch 91956e45f6SSimon J. Gerraty# of ApplyModifier_Defined. 92956e45f6SSimon J. Gerraty 93e2eeea75SSimon J. Gerraty# The :D and :U modifiers behave differently from the :@var@ modifier in 94e2eeea75SSimon J. Gerraty# that they preserve dollars in a ':=' assignment. This is because 95b0c40a00SSimon J. Gerraty# ApplyModifier_Defined passes the emode unmodified to Var_Parse, unlike 96e2eeea75SSimon J. Gerraty# ApplyModifier_Loop, which uses ParseModifierPart, which in turn removes 97b0c40a00SSimon J. Gerraty# the keepDollar flag from emode. 98e2eeea75SSimon J. Gerraty# 99e2eeea75SSimon J. Gerraty# XXX: This inconsistency is documented nowhere. 100e2eeea75SSimon J. Gerraty.MAKEFLAGS: -dv 101e2eeea75SSimon J. Gerraty8_DOLLARS= $$$$$$$$ 102e2eeea75SSimon J. GerratyVAR:= ${8_DOLLARS} 103e2eeea75SSimon J. GerratyVAR:= ${VAR:D${8_DOLLARS}} 104e2eeea75SSimon J. GerratyVAR:= ${VAR:@var@${8_DOLLARS}@} 105e2eeea75SSimon J. Gerraty.MAKEFLAGS: -d0 106e2eeea75SSimon J. Gerraty 1074fde40d9SSimon J. Gerraty 1084fde40d9SSimon J. Gerraty# Before var.c 1.1030 from 2022-08-24, the following expression caused an 109*d5e0a182SSimon J. Gerraty# out-of-bounds read when parsing the indirect ':U' modifier. 1104fde40d9SSimon J. GerratyM_U_backslash:= ${:UU\\} 1114fde40d9SSimon J. Gerraty.if ${:${M_U_backslash}} != "\\" 1124fde40d9SSimon J. Gerraty. error 1134fde40d9SSimon J. Gerraty.endif 1144fde40d9SSimon J. Gerraty 1154fde40d9SSimon J. Gerraty 1164fde40d9SSimon J. Gerratyall: .PHONY 117