1# $NetBSD: varmod.mk,v 1.11 2024/04/20 10:18:56 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# These tests assume
60.MAKE.SAVE_DOLLARS = yes
61
62DOLLAR1=	$$
63DOLLAR2=	${:U\$}
64
65# To get a single '$' sign in the value of an expression, it has to
66# be written as '$$' in a literal variable value.
67#
68# See Var_Parse, where it calls Var_Subst.
69.if ${DOLLAR1} != "\$"
70.  error
71.endif
72
73# Another way to get a single '$' sign is to use the :U modifier.  In the
74# argument of that modifier, a '$' is escaped using the backslash instead.
75#
76# See Var_Parse, where it calls Var_Subst.
77.if ${DOLLAR2} != "\$"
78.  error
79.endif
80
81# It is also possible to use the :U modifier directly in the expression.
82#
83# See Var_Parse, where it calls Var_Subst.
84.if ${:U\$} != "\$"
85.  error
86.endif
87
88# XXX: As of 2020-09-13, it is not possible to use '$$' in a variable name
89# to mean a single '$'.  This contradicts the manual page, which says that
90# '$' can be escaped as '$$'.
91.if ${$$:L} != ""
92.  error
93.endif
94
95# In lint mode, make prints helpful error messages.
96# For compatibility, make does not print these error messages in normal mode.
97# Should it?
98.MAKEFLAGS: -dL
99# expect+2: To escape a dollar, use \$, not $$, at "$$:L} != """
100# expect+1: Invalid variable name ':', at "$:L} != """
101.if ${$$:L} != ""
102.  error
103.endif
104
105# A '$' followed by nothing is an error as well.
106# expect+1: while evaluating "${:Uword:@word@${word}$@} != "word"": Dollar followed by nothing
107.if ${:Uword:@word@${word}$@} != "word"
108.  error
109.endif
110
111# The variable modifier :P does not fall back to the SysV modifier.
112# Therefore the modifier :P=RE generates a parse error.
113# XXX: The .error should not be reached since the expression is
114# malformed, and this error should be propagated up to Cond_EvalLine.
115VAR=	STOP
116# expect+1: while evaluating variable "VAR": Missing delimiter ':' after modifier "P"
117.if ${VAR:P=RE} != "STORE"
118# expect+1: Missing argument for ".error"
119.  error
120.endif
121
122all: # nothing
123