fixed #449964: sre.sub raises an exception if the template contains a
\g<x> group reference followed by a character escape

(also restructured a few things on the way to fixing #449000)
diff --git a/Lib/sre.py b/Lib/sre.py
index a87870e..7a640f9 100644
--- a/Lib/sre.py
+++ b/Lib/sre.py
@@ -251,11 +251,13 @@
     else:
         template = _compile_repl(template, pattern)
         literals = template[1]
-        sub = 0 # temporarly disabled, see bug #449000
-        if (sub and not count and pattern._isliteral() and
-            len(literals) == 1 and literals[0]):
-            # shortcut: both pattern and string are literals
-            return string.replace(text, pattern.pattern, literals[0]), 0
+        if sub and not count:
+            literal = pattern._getliteral()
+            if literal and "\\" in literal:
+                literal = None # may contain untranslated escapes
+            if literal is not None and len(literals) == 1 and literals[0]:
+                # shortcut: both pattern and string are literals
+                return string.replace(text, pattern.pattern, literals[0]), 0
         def filter(match, template=template):
             return sre_parse.expand_template(template, match)
     n = i = 0
diff --git a/Lib/sre_parse.py b/Lib/sre_parse.py
index af1edbf..7d9b889 100644
--- a/Lib/sre_parse.py
+++ b/Lib/sre_parse.py
@@ -647,9 +647,9 @@
             p.append((LITERAL, literal))
     sep = source[:0]
     if type(sep) is type(""):
-        char = chr
+        makechar = chr
     else:
-        char = unichr
+        makechar = unichr
     while 1:
         this = s.get()
         if this is None:
@@ -693,14 +693,14 @@
                         break
                 if not code:
                     this = this[1:]
-                    code = LITERAL, char(atoi(this[-6:], 8) & 0xff)
+                    code = LITERAL, makechar(atoi(this[-6:], 8) & 0xff)
                 if code[0] is LITERAL:
                     literal(code[1])
                 else:
                     a(code)
             else:
                 try:
-                    this = char(ESCAPES[this][1])
+                    this = makechar(ESCAPES[this][1])
                 except KeyError:
                     pass
                 literal(this)
diff --git a/Lib/test/test_sre.py b/Lib/test/test_sre.py
index 49fe4c6..4a71447 100644
--- a/Lib/test/test_sre.py
+++ b/Lib/test/test_sre.py
@@ -104,6 +104,9 @@
 test(r"""sre.sub(r'(?P<unk>x)', '\g<unk>\g<unk>', 'xx')""", 'xxxx')
 test(r"""sre.sub(r'(?P<unk>x)', '\g<1>\g<1>', 'xx')""", 'xxxx')
 
+# bug 449964: fails for group followed by other escape
+test(r"""sre.sub(r'(?P<unk>x)', '\g<1>\g<1>\\b', 'xx')""", 'xx\bxx\b')
+
 test(r"""sre.sub(r'a', r'\t\n\v\r\f\a\b\B\Z\a\A\w\W\s\S\d\D', 'a')""", '\t\n\v\r\f\a\b\\B\\Z\a\\A\\w\\W\\s\\S\\d\\D')
 test(r"""sre.sub(r'a', '\t\n\v\r\f\a', 'a')""", '\t\n\v\r\f\a')
 test(r"""sre.sub(r'a', '\t\n\v\r\f\a', 'a')""", (chr(9)+chr(10)+chr(11)+chr(13)+chr(12)+chr(7)))