xref: /freebsd/contrib/bmake/unit-tests/varmod-defined.mk (revision d5e0a182cf153f8993a633b93d9220c99a89e760)
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