517
518
trace.mutter('Unable to set hidden attribute on %r: %s', path, e)
520
_whitespace_match = re.compile(u'\s', re.UNICODE).match
523
class _PushbackSequence(object):
524
def __init__(self, orig):
525
self._iter = iter(orig)
526
self._pushback_buffer = []
529
if len(self._pushback_buffer) > 0:
530
return self._pushback_buffer.pop()
532
return self._iter.next()
534
def pushback(self, char):
535
self._pushback_buffer.append(char)
541
class _Whitespace(object):
542
def process(self, next_char, seq, context):
543
if _whitespace_match(next_char):
544
if len(context.token) > 0:
548
elif (next_char == u'"'
549
or (context.single_quotes_allowed and next_char == u"'")):
550
context.quoted = True
551
return _Quotes(next_char, self)
552
elif next_char == u'\\':
553
return _Backslash(self)
555
context.token.append(next_char)
559
class _Quotes(object):
560
def __init__(self, quote_char, exit_state):
561
self.quote_char = quote_char
562
self.exit_state = exit_state
564
def process(self, next_char, seq, context):
565
if next_char == u'\\':
566
return _Backslash(self)
567
elif next_char == self.quote_char:
568
return self.exit_state
570
context.token.append(next_char)
574
class _Backslash(object):
575
# See http://msdn.microsoft.com/en-us/library/bb776391(VS.85).aspx
576
def __init__(self, exit_state):
577
self.exit_state = exit_state
580
def process(self, next_char, seq, context):
581
if next_char == u'\\':
584
elif next_char == u'"':
585
# 2N backslashes followed by '"' are N backslashes
586
context.token.append(u'\\' * (self.count/2))
587
# 2N+1 backslashes follwed by '"' are N backslashes followed by '"'
588
# which should not be processed as the start or end of quoted arg
589
if self.count % 2 == 1:
590
context.token.append(next_char) # odd number of '\' escapes the '"'
592
seq.pushback(next_char) # let exit_state handle next_char
594
return self.exit_state
596
# N backslashes not followed by '"' are just N backslashes
598
context.token.append(u'\\' * self.count)
600
seq.pushback(next_char) # let exit_state handle next_char
601
return self.exit_state
603
def finish(self, context):
605
context.token.append(u'\\' * self.count)
609
def process(self, next_char, seq, context):
610
if _whitespace_match(next_char):
612
elif (next_char == u'"'
613
or (context.single_quotes_allowed and next_char == u"'")):
614
return _Quotes(next_char, self)
615
elif next_char == u'\\':
616
return _Backslash(self)
618
context.token.append(next_char)
622
class UnicodeShlex(object):
623
def __init__(self, command_line, single_quotes_allowed=False):
624
self._seq = _PushbackSequence(command_line)
625
self.single_quotes_allowed = single_quotes_allowed
631
quoted, token = self._get_token()
636
def _get_token(self):
639
state = _Whitespace()
640
for next_char in self._seq:
641
state = state.process(next_char, self._seq, self)
644
if not state is None and not getattr(state, 'finish', None) is None:
646
result = u''.join(self.token)
647
if not self.quoted and result == '':
649
return self.quoted, result
652
521
def command_line_to_argv(command_line, wildcard_expansion=True,
653
522
single_quotes_allowed=False):
654
523
"""Convert a Unicode command line into a list of argv arguments.