char-005c-reverse-solidus.mk revision 1.2 1 # $NetBSD: char-005c-reverse-solidus.mk,v 1.2 2025/06/29 11:27:21 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 . error
61 .endif
62
63 # expect+1: Unclosed expression, expecting "}" for modifier "Mx\\}"
64 .if ${BACKSLASH:Mx\\}
65 . error
66 .else
67 . error
68 .endif
69
70 # expect+1: Unclosed expression, expecting "}" for modifier "Mx\\\\\\\\}"
71 .if ${BACKSLASH:Mx\\\\\\\\}
72 . error
73 .else
74 . error
75 .endif
76
77 # Adding more text after the backslash adds to the pattern, as the backslash
78 # serves to escape the ":" that is otherwise used to separate the modifiers.
79 # The result is a single ":M" modifier with the pattern "x:Nzzz".
80 .if ${BACKSLASH:Mx\:Nzzz} != ""
81 . error
82 .endif
83
84 # The pattern ends up as "x\:Nzzz". Only the sequence "\:" is unescaped, all
85 # others, including "\\", are left as-is.
86 .if ${BACKSLASH:Mx\\:Nzzz} != ""
87 . error
88 .endif
89
90 # The pattern for the ":M" modifier ends up as "x\\\\\\\:Nzzz". Only the
91 # sequence "\:" is unescaped, all others, including "\\", are left as-is.
92 .if ${BACKSLASH:Mx\\\\\\\\:Nzzz} != ""
93 . error
94 .endif
95
96 # The ":M" modifier is parsed differently than the other modifiers. To
97 # circumvent the peculiarities of that parser, the pattern can be passed via
98 # an expression. There, the usual escaping rules for modifiers apply.
99 # expect+1: Unfinished backslash at the end in pattern "\" of modifier ":M"
100 .if ${BACKSLASH:M${BACKSLASH}} != "\\"
101 . error
102 .else
103 . error
104 .endif
105
106 # Trying to bypass the parser by using a direct expression doesn't work, as
107 # the parser for the ":M" modifier does not parse the subexpression like in
108 # all other places, but instead counts the braces and tries to decode the
109 # escaping, which fails in this case.
110 # expect+1: Unclosed expression, expecting "}" for modifier "M${:U\\\\}} != "\\""
111 .if ${BACKSLASH:M${:U\\\\}} != "\\"
112 . error
113 .else
114 . error
115 .endif
116
117 # Matching a backslash with the pattern matching characters works.
118 .if ${BACKSLASH:M?} != "\\"
119 . error
120 .endif
121 .if ${BACKSLASH:M*} != "\\"
122 . error
123 .endif
124 .if ${BACKSLASH:M[Z-a]} != "\\"
125 . error
126 .endif
127 .if ${BACKSLASH:M[\\]} != "\\"
128 . error
129 .endif
130
131 # end https://gnats.netbsd.org/46139
132