| # -*- coding: utf-8 -*- | 
 | #                     The LLVM Compiler Infrastructure | 
 | # | 
 | # This file is distributed under the University of Illinois Open Source | 
 | # License. See LICENSE.TXT for details. | 
 | """ This module implements basic shell escaping/unescaping methods. """ | 
 |  | 
 | import re | 
 | import shlex | 
 |  | 
 | __all__ = ['encode', 'decode'] | 
 |  | 
 |  | 
 | def encode(command): | 
 |     """ Takes a command as list and returns a string. """ | 
 |  | 
 |     def needs_quote(word): | 
 |         """ Returns true if arguments needs to be protected by quotes. | 
 |  | 
 |         Previous implementation was shlex.split method, but that's not good | 
 |         for this job. Currently is running through the string with a basic | 
 |         state checking. """ | 
 |  | 
 |         reserved = {' ', '$', '%', '&', '(', ')', '[', ']', '{', '}', '*', '|', | 
 |                     '<', '>', '@', '?', '!'} | 
 |         state = 0 | 
 |         for current in word: | 
 |             if state == 0 and current in reserved: | 
 |                 return True | 
 |             elif state == 0 and current == '\\': | 
 |                 state = 1 | 
 |             elif state == 1 and current in reserved | {'\\'}: | 
 |                 state = 0 | 
 |             elif state == 0 and current == '"': | 
 |                 state = 2 | 
 |             elif state == 2 and current == '"': | 
 |                 state = 0 | 
 |             elif state == 0 and current == "'": | 
 |                 state = 3 | 
 |             elif state == 3 and current == "'": | 
 |                 state = 0 | 
 |         return state != 0 | 
 |  | 
 |     def escape(word): | 
 |         """ Do protect argument if that's needed. """ | 
 |  | 
 |         table = {'\\': '\\\\', '"': '\\"'} | 
 |         escaped = ''.join([table.get(c, c) for c in word]) | 
 |  | 
 |         return '"' + escaped + '"' if needs_quote(word) else escaped | 
 |  | 
 |     return " ".join([escape(arg) for arg in command]) | 
 |  | 
 |  | 
 | def decode(string): | 
 |     """ Takes a command string and returns as a list. """ | 
 |  | 
 |     def unescape(arg): | 
 |         """ Gets rid of the escaping characters. """ | 
 |  | 
 |         if len(arg) >= 2 and arg[0] == arg[-1] and arg[0] == '"': | 
 |             arg = arg[1:-1] | 
 |             return re.sub(r'\\(["\\])', r'\1', arg) | 
 |         return re.sub(r'\\([\\ $%&\(\)\[\]\{\}\*|<>@?!])', r'\1', arg) | 
 |  | 
 |     return [unescape(arg) for arg in shlex.split(string)] |