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