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