[lit] Speculatively fix PR24554 by manually closing the process handle
[oota-llvm.git] / utils / lit / lit / ShUtil.py
index c4bbb3d3731d53dacb835ca1b12e3c5064b658c0..1945ba723bcd63b215d60b33b21b9a3c7157823c 100644 (file)
@@ -1,7 +1,8 @@
+from __future__ import absolute_import
 import itertools
 
-import Util
-from ShCommands import Command, Pipeline, Seq
+import lit.util
+from lit.ShCommands import Command, Pipeline, Seq
 
 class ShLexer:
     def __init__(self, data, win32Escapes = False):
@@ -35,7 +36,7 @@ class ShLexer:
         if ('|' in chunk or '&' in chunk or 
             '<' in chunk or '>' in chunk or
             "'" in chunk or '"' in chunk or
-            '\\' in chunk):
+            ';' in chunk or '\\' in chunk):
             return None
         
         self.pos = self.pos - 1 + len(chunk)
@@ -48,7 +49,7 @@ class ShLexer:
             str = c
         while self.pos != self.end:
             c = self.look()
-            if c.isspace() or c in "|&":
+            if c.isspace() or c in "|&;":
                 break
             elif c in '><':
                 # This is an annoying case; we treat '2>' as a single token so
@@ -66,13 +67,16 @@ class ShLexer:
                 return (tok[0], num)                    
             elif c == '"':
                 self.eat()
-                str += self.lex_arg_quoted('"')\r
+                str += self.lex_arg_quoted('"')
+            elif c == "'":
+                self.eat()
+                str += self.lex_arg_quoted("'")
             elif not self.win32Escapes and c == '\\':
                 # Outside of a string, '\\' escapes everything.
                 self.eat()
                 if self.pos == self.end:
-                    Util.warning("escape at end of quoted argument in: %r" % 
-                                 self.data)
+                    lit.util.warning(
+                        "escape at end of quoted argument in: %r" % self.data)
                     return str
                 str += self.eat()
             else:
@@ -89,8 +93,8 @@ class ShLexer:
                 # Inside a '"' quoted string, '\\' only escapes the quote
                 # character and backslash, otherwise it is preserved.
                 if self.pos == self.end:
-                    Util.warning("escape at end of quoted argument in: %r" % 
-                                 self.data)
+                    lit.util.warning(
+                        "escape at end of quoted argument in: %r" % self.data)
                     return str
                 c = self.eat()
                 if c == '"': # 
@@ -101,7 +105,7 @@ class ShLexer:
                     str += '\\' + c
             else:
                 str += c
-        Util.warning("missing quote character in %r" % self.data)
+        lit.util.warning("missing quote character in %r" % self.data)
         return str
     
     def lex_arg_checked(self, c):
@@ -113,9 +117,11 @@ class ShLexer:
         reference = self.lex_arg_slow(c)
         if res is not None:
             if res != reference:
-                raise ValueError,"Fast path failure: %r != %r" % (res, reference)
+                raise ValueError("Fast path failure: %r != %r" % (
+                        res, reference))
             if self.pos != end:
-                raise ValueError,"Fast path failure: %r != %r" % (self.pos, end)
+                raise ValueError("Fast path failure: %r != %r" % (
+                        self.pos, end))
         return reference
         
     def lex_arg(self, c):
@@ -126,7 +132,7 @@ class ShLexer:
         lex_one_token - Lex a single 'sh' token. """
 
         c = self.eat()
-        if c in ';!':
+        if c == ';':
             return (c,)
         if c == '|':
             if self.maybe_eat('|'):
@@ -163,28 +169,28 @@ class ShLexer:
 ###
  
 class ShParser:
-    def __init__(self, data, win32Escapes = False):
+    def __init__(self, data, win32Escapes = False, pipefail = False):
         self.data = data
+        self.pipefail = pipefail
         self.tokens = ShLexer(data, win32Escapes = win32Escapes).lex()
     
     def lex(self):
-        try:
-            return self.tokens.next()
-        except StopIteration:
-            return None
+        for item in self.tokens:
+            return item
+        return None
     
     def look(self):
-        next = self.lex()
-        if next is not None:
-            self.tokens = itertools.chain([next], self.tokens)
-        return next
+        token = self.lex()
+        if token is not None:
+            self.tokens = itertools.chain([token], self.tokens)
+        return token
     
     def parse_command(self):
         tok = self.lex()
         if not tok:
-            raise ValueError,"empty command!"
+            raise ValueError("empty command!")
         if isinstance(tok, tuple):
-            raise ValueError,"syntax error near unexpected token %r" % tok[0]
+            raise ValueError("syntax error near unexpected token %r" % tok[0])
         
         args = [tok]
         redirects = []
@@ -209,22 +215,19 @@ class ShParser:
             op = self.lex()
             arg = self.lex()
             if not arg:
-                raise ValueError,"syntax error near token %r" % op[0]
+                raise ValueError("syntax error near token %r" % op[0])
             redirects.append((op, arg))
 
         return Command(args, redirects)
 
     def parse_pipeline(self):
         negate = False
-        if self.look() == ('!',):
-            self.lex()
-            negate = True
 
         commands = [self.parse_command()]
         while self.look() == ('|',):
             self.lex()
             commands.append(self.parse_command())
-        return Pipeline(commands, negate)
+        return Pipeline(commands, negate, self.pipefail)
             
     def parse(self):
         lhs = self.parse_pipeline()
@@ -234,7 +237,8 @@ class ShParser:
             assert isinstance(operator, tuple) and len(operator) == 1
 
             if not self.look():
-                raise ValueError, "missing argument to operator %r" % operator[0]
+                raise ValueError(
+                    "missing argument to operator %r" % operator[0])
             
             # FIXME: Operator precedence!!
             lhs = Seq(lhs, operator[0], self.parse_pipeline())
@@ -250,9 +254,9 @@ class TestShLexer(unittest.TestCase):
         return list(ShLexer(str, *args, **kwargs).lex())
 
     def test_basic(self):
-        self.assertEqual(self.lex('a|b>c&d<e'),
+        self.assertEqual(self.lex('a|b>c&d<e;f'),
                          ['a', ('|',), 'b', ('>',), 'c', ('&',), 'd', 
-                          ('<',), 'e'])
+                          ('<',), 'e', (';',), 'f'])
 
     def test_redirection_tokens(self):
         self.assertEqual(self.lex('a2>c'),
@@ -287,6 +291,10 @@ class TestShParse(unittest.TestCase):
                          Pipeline([Command(['echo', 'hello'], [])], False))
         self.assertEqual(self.parse('echo ""'),
                          Pipeline([Command(['echo', ''], [])], False))
+        self.assertEqual(self.parse("""echo -DFOO='a'"""),
+                         Pipeline([Command(['echo', '-DFOO=a'], [])], False))
+        self.assertEqual(self.parse('echo -DFOO="a"'),
+                         Pipeline([Command(['echo', '-DFOO=a'], [])], False))
 
     def test_redirection(self):
         self.assertEqual(self.parse('echo hello > c'),
@@ -310,10 +318,6 @@ class TestShParse(unittest.TestCase):
                                    Command(['c'], [])],
                                   False))
 
-        self.assertEqual(self.parse('! a'),
-                         Pipeline([Command(['a'], [])],
-                                  True))
-
     def test_list(self):        
         self.assertEqual(self.parse('a ; b'),
                          Seq(Pipeline([Command(['a'], [])], False),
@@ -342,5 +346,10 @@ class TestShParse(unittest.TestCase):
                              '||',
                              Pipeline([Command(['c'], [])], False)))
 
+        self.assertEqual(self.parse('a; b'),
+                         Seq(Pipeline([Command(['a'], [])], False),
+                             ';',
+                             Pipeline([Command(['b'], [])], False)))
+
 if __name__ == '__main__':
     unittest.main()