Home | History | Annotate | Line # | Download | only in unit-tests
varmod-match-escape.mk revision 1.8
      1  1.8  rillig # $NetBSD: varmod-match-escape.mk,v 1.8 2023/06/01 20:56:35 rillig Exp $
      2  1.1  rillig #
      3  1.1  rillig # As of 2020-08-01, the :M and :N modifiers interpret backslashes differently,
      4  1.1  rillig # depending on whether there was a variable expression somewhere before the
      5  1.7  rillig # first backslash or not.  See ApplyModifier_Match, "copy = true".
      6  1.1  rillig #
      7  1.1  rillig # Apart from the different and possibly confusing debug output, there is no
      8  1.1  rillig # difference in behavior.  When parsing the modifier text, only \{, \} and \:
      9  1.1  rillig # are unescaped, and in the pattern matching these have the same meaning as
     10  1.1  rillig # their plain variants '{', '}' and ':'.  In the pattern matching from
     11  1.1  rillig # Str_Match, only \*, \? or \[ would make a noticeable difference.
     12  1.4  rillig 
     13  1.4  rillig .MAKEFLAGS: -dcv
     14  1.4  rillig 
     15  1.1  rillig SPECIALS=	\: : \\ * \*
     16  1.1  rillig .if ${SPECIALS:M${:U}\:} != ${SPECIALS:M\:${:U}}
     17  1.2  rillig .  warning unexpected
     18  1.1  rillig .endif
     19  1.4  rillig 
     20  1.4  rillig # And now both cases combined: A single modifier with both an escaped ':'
     21  1.4  rillig # as well as a variable expression that expands to a ':'.
     22  1.4  rillig #
     23  1.4  rillig # XXX: As of 2020-11-01, when an escaped ':' occurs before the variable
     24  1.4  rillig # expression, the whole modifier text is subject to unescaping '\:' to ':',
     25  1.4  rillig # before the variable expression is expanded.  This means that the '\:' in
     26  1.4  rillig # the variable expression is expanded as well, turning ${:U\:} into a simple
     27  1.4  rillig # ${:U:}, which silently expands to an empty string, instead of generating
     28  1.4  rillig # an error message.
     29  1.4  rillig #
     30  1.4  rillig # XXX: As of 2020-11-01, the modifier on the right-hand side of the
     31  1.4  rillig # comparison is parsed differently though.  First, the variable expression
     32  1.7  rillig # is parsed, resulting in ':' and needSubst=true.  After that, the escaped
     33  1.7  rillig # ':' is seen, and this time, copy=true is not executed but stays copy=false.
     34  1.4  rillig # Therefore the escaped ':' is kept as-is, and the final pattern becomes
     35  1.4  rillig # ':\:'.
     36  1.4  rillig #
     37  1.4  rillig # If ApplyModifier_Match had used the same parsing algorithm as Var_Subst,
     38  1.4  rillig # both patterns would end up as '::'.
     39  1.4  rillig #
     40  1.4  rillig VALUES=		: :: :\:
     41  1.4  rillig .if ${VALUES:M\:${:U\:}} != ${VALUES:M${:U\:}\:}
     42  1.8  rillig # expect+1: warning: XXX: Oops
     43  1.4  rillig .  warning XXX: Oops
     44  1.4  rillig .endif
     45  1.4  rillig 
     46  1.3  rillig .MAKEFLAGS: -d0
     47  1.1  rillig 
     48  1.5  rillig # XXX: As of 2020-11-01, unlike all other variable modifiers, a '$' in the
     49  1.5  rillig # :M and :N modifiers is written as '$$', not as '\$'.  This is confusing,
     50  1.5  rillig # undocumented and hopefully not used in practice.
     51  1.5  rillig .if ${:U\$:M$$} != "\$"
     52  1.5  rillig .  error
     53  1.5  rillig .endif
     54  1.5  rillig 
     55  1.5  rillig # XXX: As of 2020-11-01, unlike all other variable modifiers, '\$' is not
     56  1.5  rillig # parsed as an escaped '$'.  Instead, ApplyModifier_Match first scans for
     57  1.5  rillig # the ':' at the end of the modifier, which results in the pattern '\$'.
     58  1.5  rillig # No unescaping takes place since the pattern neither contained '\:' nor
     59  1.5  rillig # '\{' nor '\}'.  But the text is expanded, and a lonely '$' at the end
     60  1.5  rillig # is silently discarded.  The resulting expanded pattern is thus '\', that
     61  1.5  rillig # is a single backslash.
     62  1.5  rillig .if ${:U\$:M\$} != ""
     63  1.5  rillig .  error
     64  1.5  rillig .endif
     65  1.5  rillig 
     66  1.5  rillig # In lint mode, the case of a lonely '$' is covered with an error message.
     67  1.5  rillig .MAKEFLAGS: -dL
     68  1.8  rillig # expect+1: Dollar followed by nothing
     69  1.5  rillig .if ${:U\$:M\$} != ""
     70  1.5  rillig .  error
     71  1.5  rillig .endif
     72  1.5  rillig 
     73  1.6  rillig # The control flow of the pattern parser depends on the actual string that
     74  1.6  rillig # is being matched.  There needs to be either a test that shows a difference
     75  1.6  rillig # in behavior, or a proof that the behavior does not depend on the actual
     76  1.6  rillig # string.
     77  1.6  rillig #
     78  1.6  rillig # TODO: Str_Match("a-z]", "[a-z]")
     79  1.6  rillig # TODO: Str_Match("012", "[0-]]")
     80  1.6  rillig # TODO: Str_Match("0]", "[0-]]")
     81  1.6  rillig # TODO: Str_Match("1]", "[0-]]")
     82  1.6  rillig # TODO: Str_Match("[", "[[]")
     83  1.6  rillig # TODO: Str_Match("]", "[]")
     84  1.6  rillig # TODO: Str_Match("]", "[[-]]")
     85  1.6  rillig 
     86  1.6  rillig # In brackets, the backslash is just an ordinary character.
     87  1.6  rillig # Outside brackets, it is an escape character for a few special characters.
     88  1.6  rillig # TODO: Str_Match("\\", "[\\-]]")
     89  1.6  rillig # TODO: Str_Match("-]", "[\\-]]")
     90  1.6  rillig 
     91  1.1  rillig all:
     92  1.1  rillig 	@:;
     93