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