varmod.mk revision 1.13 1 1.13 rillig # $NetBSD: varmod.mk,v 1.13 2024/06/02 11:25:03 rillig Exp $
2 1.1 rillig #
3 1.2 rillig # Tests for variable modifiers, such as :Q, :S,from,to or :Ufallback.
4 1.7 rillig #
5 1.7 rillig # See also:
6 1.7 rillig # varparse-errors.mk
7 1.1 rillig
8 1.6 rillig # As of 2022-08-06, the possible behaviors during parsing are:
9 1.6 rillig #
10 1.6 rillig # * `strict`: the parsing style used by most modifiers:
11 1.6 rillig # * either uses `ParseModifierPart` or parses the modifier literal
12 1.6 rillig # * other modifiers may follow, separated by a ':'
13 1.6 rillig #
14 1.6 rillig # * `greedy`: calls `ParseModifierPart` with `ch->endc`; this means
15 1.6 rillig # that no further modifiers are parsed in that expression.
16 1.6 rillig #
17 1.6 rillig # * `no-colon`: after parsing this modifier, the following modifier
18 1.6 rillig # does not need to be separated by a colon.
19 1.6 rillig # Omitting this colon is bad style.
20 1.6 rillig #
21 1.6 rillig # * `individual`: parsing this modifier does not follow the common
22 1.6 rillig # pattern of calling `ParseModifierPart`.
23 1.6 rillig #
24 1.6 rillig # The SysV column says whether a parse error in the modifier falls back
25 1.6 rillig # trying the `:from=to` System V modifier.
26 1.6 rillig #
27 1.6 rillig # | **Operator** | **Behavior** | **Remarks** | **SysV** |
28 1.6 rillig # |--------------|--------------|--------------------|----------|
29 1.6 rillig # | `!` | no-colon | | no |
30 1.6 rillig # | `:=` | greedy | | yes |
31 1.6 rillig # | `?:` | greedy | | no |
32 1.6 rillig # | `@` | no-colon | | no |
33 1.6 rillig # | `C` | no-colon | | no |
34 1.6 rillig # | `D` | individual | custom parser | N/A |
35 1.6 rillig # | `E` | strict | | yes |
36 1.6 rillig # | `H` | strict | | yes |
37 1.6 rillig # | `L` | no-colon | | N/A |
38 1.6 rillig # | `M` | individual | custom parser | N/A |
39 1.6 rillig # | `N` | individual | custom parser | N/A |
40 1.6 rillig # | `O` | strict | only literal value | no |
41 1.6 rillig # | `P` | no-colon | | N/A |
42 1.6 rillig # | `Q` | strict | | yes |
43 1.6 rillig # | `R` | strict | | yes |
44 1.6 rillig # | `S` | no-colon | | N/A |
45 1.6 rillig # | `T` | strict | | N/A |
46 1.6 rillig # | `U` | individual | custom parser | N/A |
47 1.6 rillig # | `[` | strict | | no |
48 1.6 rillig # | `_` | individual | strcspn | yes |
49 1.6 rillig # | `gmtime` | strict | only literal value | yes |
50 1.6 rillig # | `hash` | strict | | N/A |
51 1.6 rillig # | `localtime` | strict | only literal value | yes |
52 1.6 rillig # | `q` | strict | | yes |
53 1.6 rillig # | `range` | strict | | N/A |
54 1.6 rillig # | `sh` | strict | | N/A |
55 1.6 rillig # | `t` | strict | | no |
56 1.6 rillig # | `u` | strict | | yes |
57 1.6 rillig # | `from=to` | greedy | SysV, fallback | N/A |
58 1.6 rillig
59 1.10 sjg # These tests assume
60 1.10 sjg .MAKE.SAVE_DOLLARS = yes
61 1.10 sjg
62 1.3 rillig DOLLAR1= $$
63 1.3 rillig DOLLAR2= ${:U\$}
64 1.1 rillig
65 1.9 rillig # To get a single '$' sign in the value of an expression, it has to
66 1.3 rillig # be written as '$$' in a literal variable value.
67 1.3 rillig #
68 1.3 rillig # See Var_Parse, where it calls Var_Subst.
69 1.3 rillig .if ${DOLLAR1} != "\$"
70 1.3 rillig . error
71 1.3 rillig .endif
72 1.3 rillig
73 1.3 rillig # Another way to get a single '$' sign is to use the :U modifier. In the
74 1.3 rillig # argument of that modifier, a '$' is escaped using the backslash instead.
75 1.3 rillig #
76 1.3 rillig # See Var_Parse, where it calls Var_Subst.
77 1.3 rillig .if ${DOLLAR2} != "\$"
78 1.3 rillig . error
79 1.3 rillig .endif
80 1.3 rillig
81 1.3 rillig # It is also possible to use the :U modifier directly in the expression.
82 1.3 rillig #
83 1.3 rillig # See Var_Parse, where it calls Var_Subst.
84 1.3 rillig .if ${:U\$} != "\$"
85 1.3 rillig . error
86 1.3 rillig .endif
87 1.3 rillig
88 1.3 rillig # XXX: As of 2020-09-13, it is not possible to use '$$' in a variable name
89 1.3 rillig # to mean a single '$'. This contradicts the manual page, which says that
90 1.3 rillig # '$' can be escaped as '$$'.
91 1.3 rillig .if ${$$:L} != ""
92 1.3 rillig . error
93 1.3 rillig .endif
94 1.3 rillig
95 1.3 rillig # In lint mode, make prints helpful error messages.
96 1.3 rillig # For compatibility, make does not print these error messages in normal mode.
97 1.3 rillig # Should it?
98 1.3 rillig .MAKEFLAGS: -dL
99 1.8 rillig # expect+2: To escape a dollar, use \$, not $$, at "$$:L} != """
100 1.8 rillig # expect+1: Invalid variable name ':', at "$:L} != """
101 1.3 rillig .if ${$$:L} != ""
102 1.3 rillig . error
103 1.3 rillig .endif
104 1.3 rillig
105 1.3 rillig # A '$' followed by nothing is an error as well.
106 1.11 rillig # expect+1: while evaluating "${:Uword:@word@${word}$@} != "word"": Dollar followed by nothing
107 1.3 rillig .if ${:Uword:@word@${word}$@} != "word"
108 1.3 rillig . error
109 1.3 rillig .endif
110 1.3 rillig
111 1.4 rillig # The variable modifier :P does not fall back to the SysV modifier.
112 1.4 rillig # Therefore the modifier :P=RE generates a parse error.
113 1.9 rillig # XXX: The .error should not be reached since the expression is
114 1.5 rillig # malformed, and this error should be propagated up to Cond_EvalLine.
115 1.4 rillig VAR= STOP
116 1.11 rillig # expect+1: while evaluating variable "VAR": Missing delimiter ':' after modifier "P"
117 1.4 rillig .if ${VAR:P=RE} != "STORE"
118 1.8 rillig # expect+1: Missing argument for ".error"
119 1.4 rillig . error
120 1.4 rillig .endif
121 1.4 rillig
122 1.12 rillig # Test the word selection modifier ':[n]' with a very large number that is
123 1.12 rillig # larger than ULONG_MAX for any supported platform.
124 1.12 rillig # expect+1: Malformed conditional (${word:L:[99333000222000111000]})
125 1.12 rillig .if ${word:L:[99333000222000111000]}
126 1.12 rillig .endif
127 1.12 rillig # expect+1: Malformed conditional (${word:L:[2147483648]})
128 1.12 rillig .if ${word:L:[2147483648]}
129 1.12 rillig .endif
130 1.12 rillig
131 1.12 rillig # Test the range generation modifier ':range=n' with a very large number that
132 1.12 rillig # is larger than SIZE_MAX for any supported platform.
133 1.12 rillig # expect+2: Malformed conditional (${word:L:range=99333000222000111000})
134 1.12 rillig # expect+1: while evaluating variable "word": Invalid number "99333000222000111000}" for ':range' modifier
135 1.12 rillig .if ${word:L:range=99333000222000111000}
136 1.12 rillig .endif
137 1.13 rillig
138 1.13 rillig # In an indirect modifier, the delimiter is '\0', which at the same time marks
139 1.13 rillig # the end of the string. The sequence '\\' '\0' is not an escaped delimiter,
140 1.13 rillig # as it would be wrong to skip past the end of the string.
141 1.13 rillig # expect+2: while evaluating "${:${:Ugmtime=\\}}": Invalid time value "\"
142 1.13 rillig # expect+1: Malformed conditional (${:${:Ugmtime=\\}})
143 1.13 rillig .if ${:${:Ugmtime=\\}}
144 1.13 rillig . error
145 1.13 rillig .endif
146