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