char-005c-reverse-solidus.mk revision 1.1 1 # $NetBSD: char-005c-reverse-solidus.mk,v 1.1 2025/06/29 09:40:13 rillig Exp $
2 #
3 # Tests for the character U+005C "REVERSE SOLIDUS".
4 #
5 # See also:
6 # TODO
7 # TODO
8 # TODO
9
10 # TODO: Where is this character used normally?
11 # TODO: What are the edge cases?
12
13 # TODO: escape '#' in lines
14 # TODO: escape '#' in comments
15 # TODO: escape ':' in modifiers
16 # TODO: escape any character in condition strings
17
18 # begin https://gnats.netbsd.org/46139
19
20 # Too see the details of parsing, uncomment the following line.
21 #.MAKEFLAGS: -dcpv
22
23 # This backslash is treated as a line continuation.
24 # It does not end up in the variable value.
25 LINE_CONTINUATION=foo\
26 # This line is still part of the variable assignment
27 .if ${LINE_CONTINUATION:C,[^a-z],<>,gW} != "foo"
28 . error
29 .endif
30
31 # The variable value contains two backslashes.
32 TWO_BACKSLASHES_AT_EOL=foo\\
33 .if ${TWO_BACKSLASHES_AT_EOL:C,[^a-z],<>,gW} != "foo<><>"
34 . error
35 .endif
36
37 TRAILING_WHITESPACE=foo\ # trailing space
38 .if ${TRAILING_WHITESPACE:C,[^a-z],<>,gW} != "foo<><>"
39 . error
40 .endif
41
42 # The simplest was to produce a single backslash is the :U modifier.
43 BACKSLASH= ${:U\\}
44 .if ${BACKSLASH} != "\\"
45 . error
46 .endif
47 BACKSLASH_C= ${:U1:C,.,\\,}
48 .if ${BACKSLASH_C} != "\\"
49 . error
50 .endif
51
52 # expect+5: Unclosed expression, expecting "}" for modifier "Mx\}"
53 # At the point where the unclosed expression is detected, the ":M" modifier
54 # has been applied to the expression. Its pattern is "x}", which doesn't
55 # match the single backslash.
56 # expect: while evaluating variable "BACKSLASH" with value ""
57 .if ${BACKSLASH:Mx\}
58 . error
59 .else
60 # FIXME: After an error in the condition, both branches must be skipped.
61 # expect+1: Missing argument for ".error"
62 . error
63 .endif
64
65 # expect+1: Unclosed expression, expecting "}" for modifier "Mx\\}"
66 .if ${BACKSLASH:Mx\\}
67 . error
68 .else
69 # FIXME: After an error in the condition, both branches must be skipped.
70 # expect+1: Missing argument for ".error"
71 . error
72 .endif
73
74 # expect+1: Unclosed expression, expecting "}" for modifier "Mx\\\\\\\\}"
75 .if ${BACKSLASH:Mx\\\\\\\\}
76 . error
77 .else
78 # FIXME: After an error in the condition, both branches must be skipped.
79 # expect+1: Missing argument for ".error"
80 . error
81 .endif
82
83 # Adding more text after the backslash adds to the pattern, as the backslash
84 # serves to escape the ":" that is otherwise used to separate the modifiers.
85 # The result is a single ":M" modifier with the pattern "x:Nzzz".
86 .if ${BACKSLASH:Mx\:Nzzz} != ""
87 . error
88 .endif
89
90 # The pattern ends up as "x\:Nzzz". Only the sequence "\:" is unescaped, all
91 # others, including "\\", are left as-is.
92 .if ${BACKSLASH:Mx\\:Nzzz} != ""
93 . error
94 .endif
95
96 # The pattern for the ":M" modifier ends up as "x\\\\\\\:Nzzz". Only the
97 # sequence "\:" is unescaped, all others, including "\\", are left as-is.
98 .if ${BACKSLASH:Mx\\\\\\\\:Nzzz} != ""
99 . error
100 .endif
101
102 # The ":M" modifier is parsed differently than the other modifiers. To
103 # circumvent the peculiarities of that parser, the pattern can be passed via
104 # an expression. There, the usual escaping rules for modifiers apply.
105 # expect+1: Unfinished backslash at the end in pattern "\" of modifier ":M"
106 .if ${BACKSLASH:M${BACKSLASH}} != "\\"
107 # FIXME: After an error in the condition, both branches must be skipped.
108 # expect+1: Missing argument for ".error"
109 . error
110 .else
111 . error
112 .endif
113
114 # Trying to bypass the parser by using a direct expression doesn't work, as
115 # the parser for the ":M" modifier does not parse the subexpression like in
116 # all other places, but instead counts the braces and tries to decode the
117 # escaping, which fails in this case.
118 # expect+1: Unclosed expression, expecting "}" for modifier "M${:U\\\\}} != "\\""
119 .if ${BACKSLASH:M${:U\\\\}} != "\\"
120 . error
121 .else
122 # expect+1: Missing argument for ".error"
123 . error
124 .endif
125
126 # Matching a backslash with the pattern matching characters works.
127 .if ${BACKSLASH:M?} != "\\"
128 . error
129 .endif
130 .if ${BACKSLASH:M*} != "\\"
131 . error
132 .endif
133 .if ${BACKSLASH:M[Z-a]} != "\\"
134 . error
135 .endif
136 .if ${BACKSLASH:M[\\]} != "\\"
137 . error
138 .endif
139
140 # end https://gnats.netbsd.org/46139
141