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