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