Backslash escapes shouldn't hide tokens.
authorBenjamin Smedberg <benjamin@smedbergs.us>
Fri, 20 Feb 2009 16:40:10 -0500
changeset 149 729f4f785446ea4aa669a96a5f89b4b4fca4535f
parent 148 0c338ff3d3d1b8fd0e31e5322e8bec02d50839f5
child 150 d3574d51916dce209529f41c7ae1a7f5c5210ca0
push id85
push userbsmedberg@mozilla.com
push dateFri, 20 Feb 2009 21:56:55 +0000
Backslash escapes shouldn't hide tokens.
pymake/parser.py
tests/func-refs.mk
--- a/pymake/parser.py
+++ b/pymake/parser.py
@@ -136,16 +136,17 @@ makefiletokensescaped = [r'\\\\#', r'\\#
 continuationtokensescaped = ['\\\\\n', r'\\.', '\n']
 
 class TokenList(object):
     """
     A list of tokens to search. Because these lists are static, we can perform
     optimizations (such as escaping and compiling regexes) on construction.
     """
     def __init__(self, tlist):
+        self.tlist = tlist
         self.emptylist = len(tlist) == 0
         escapedlist = [re.escape(t) for t in tlist]
         self.simplere = re.compile('|'.join(escapedlist))
         self.makefilere = re.compile('|'.join(escapedlist + makefiletokensescaped))
         self.continuationre = re.compile('|'.join(escapedlist + continuationtokensescaped))
 
         self.wslist = re.compile('(' + '|'.join(escapedlist) + ')' + r'(\s+|$)')
 
@@ -228,17 +229,20 @@ def itermakefilechars(d, offset, tokenli
             yield d.data[offset:start] + '\\ ', None, None, None
             d.readline()
             offset = d.skipwhitespace(end)
             continue
 
         if token == '\\#':
             yield d.data[offset:start] + '#', None, None, None
         elif token.startswith('\\'):
-            yield d.data[offset:end], None, None, None
+            if token[1:] in tokenlist.tlist:
+                yield d.data[offset:start + 1], token[1:], start + 1, end
+            else:
+                yield d.data[offset:end], None, None, None
         else:
             yield d.data[offset:start], token, start, end
 
         offset = end
 
 def itercommandchars(d, offset, tokenlist):
     s = tokenlist.continuationre
 
@@ -261,17 +265,20 @@ def itercommandchars(d, offset, tokenlis
             yield d.data[offset:end], None, None, None
             d.readline()
             offset = end
             if offset < len(d.data) and d.data[offset] == '\t':
                 offset += 1
             continue
         
         if token.startswith('\\'):
-            yield d.data[offset:end], None, None, None
+            if token[1:] in tokenlist.tlist:
+                yield d.data[offset:start + 1], token[1:], start + 1, end
+            else:
+                yield d.data[offset:end], None, None, None
         else:
             yield d.data[offset:start], token, start, end
 
         offset = end
 
 definestokenlist = TokenList.get(('define', 'endef'))
 
 def iterdefinechars(d, offset, tokenlist):
@@ -329,17 +336,20 @@ def iterdefinechars(d, offset, tokenlist
             d.readline()
             definecount += checkfortoken(end)
             if definecount == 0:
                 yield d.data[offset:start], None, None, None
                 return
 
             yield d.data[offset:end], None, None, None
         elif token.startswith('\\'):
-            yield d.data[offset:end], None, None, None
+            if token[1:] in tokenlist.tlist:
+                yield d.data[offset:start + 1], token[1:], start + 1, end
+            else:
+                yield d.data[offset:end], None, None, None
         else:
             yield d.data[offset:start], token, start, end
 
         offset = end
 
     # Unlike the other iterators, if you fall off this one there is an unterminated
     # define.
     raise SyntaxError("Unterminated define", d.getloc(startoffset))
--- a/tests/func-refs.mk
+++ b/tests/func-refs.mk
@@ -1,9 +1,10 @@
 unknown var = uval
 
 all:
 	test "$(subst a,b,value)" = "vblue"
 	test "${subst a,b,va)lue}" = "vb)lue"
+	test "$(subst /,\,ab/c)" = "ab\c"
 	test "$( subst a,b,value)" = ""
 	test "$(Subst a,b,value)" = ""
 	test "$(unknown var)" = "uval"
 	@echo TEST-PASS