|
|
@@ -8,6 +8,7 @@ |
|
|
|
|
|
from core import braces
|
|
|
from core import expr_eval
|
|
|
from core import legacy
|
|
|
from core import glob_
|
|
|
from core.id_kind import Id, Kind, LookupKind
|
|
|
from core import runtime
|
|
|
@@ -42,20 +43,6 @@ def _ValueToPartValue(val, quoted): |
|
|
raise AssertionError
|
|
|
|
|
|
|
|
|
def _GetIfs(mem):
|
|
|
"""
|
|
|
Used for splitting words in Splitter.
|
|
|
"""
|
|
|
val = mem.GetVar('IFS')
|
|
|
if val.tag == value_e.Undef:
|
|
|
return ''
|
|
|
elif val.tag == value_e.Str:
|
|
|
return val.s
|
|
|
else:
|
|
|
# TODO: Raise proper error
|
|
|
raise AssertionError("IFS shouldn't be an array")
|
|
|
|
|
|
|
|
|
def _GetJoinChar(mem):
|
|
|
"""
|
|
|
For decaying arrays by joining, eg. "$@" -> $@.
|
|
|
@@ -79,84 +66,6 @@ def _GetJoinChar(mem): |
|
|
raise AssertionError("IFS shouldn't be an array")
|
|
|
|
|
|
|
|
|
def _Split(s, ifs):
|
|
|
"""Helper function for IFS split."""
|
|
|
parts = ['']
|
|
|
for c in s:
|
|
|
if c in ifs:
|
|
|
parts.append('')
|
|
|
else:
|
|
|
parts[-1] += c
|
|
|
return parts
|
|
|
|
|
|
|
|
|
def _IfsSplit(s, ifs):
|
|
|
"""
|
|
|
http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05
|
|
|
https://www.gnu.org/software/bash/manual/bashref.html#Word-Splitting
|
|
|
|
|
|
Summary:
|
|
|
1. ' \t\n' is special. Whitespace is trimmed off the front and back.
|
|
|
2. if IFS is '', no field splitting is performed.
|
|
|
3. Otherwise, suppose IFS = ' ,\t'. Then IFS whitespace is space or comma.
|
|
|
a. IFS whitespace isgnored at beginning and end.
|
|
|
b. any other IFS char delimits the field, along with adjacent IFS
|
|
|
whitespace.
|
|
|
c. IFS whitespace shall delimit a field.
|
|
|
|
|
|
# Can we do this be regex or something? Use regex match?
|
|
|
"""
|
|
|
assert isinstance(ifs, str), ifs
|
|
|
if not ifs:
|
|
|
return [s] # no splitting
|
|
|
|
|
|
# print("IFS SPLIT %r %r" % (s, ifs))
|
|
|
# TODO: This detect if it's ALL whitespace? If ifs_other is empty?
|
|
|
if ifs == ' \t\n':
|
|
|
return _Split(s, ifs)
|
|
|
|
|
|
# Detect IFS whitespace
|
|
|
ifs_whitespace = ''
|
|
|
ifs_other = ''
|
|
|
for c in ifs:
|
|
|
if c in ' \t\n':
|
|
|
ifs_whitespace += c
|
|
|
else:
|
|
|
ifs_other += c
|
|
|
|
|
|
# TODO: Rule 3a. Ignore leading and trailing IFS whitespace?
|
|
|
|
|
|
# hack to make an RE
|
|
|
|
|
|
# Hm this escapes \t as \\\t? I guess that works.
|
|
|
ws_re = re.escape(ifs_whitespace)
|
|
|
|
|
|
other_re = re.escape(ifs_other)
|
|
|
#print('chars', repr(ifs_whitespace), repr(ifs_other))
|
|
|
#print('RE', repr(ws_re), repr(other_re))
|
|
|
|
|
|
# BUG: re.split() is the wrong model. It works with the 'delimiting' model.
|
|
|
# Forward iteration. TODO: grep for IFS in dash/mksh/bash/ash.
|
|
|
|
|
|
# ifs_ws | ifs_ws* non_ws_ifs ifs_ws*
|
|
|
if ifs_whitespace and ifs_other:
|
|
|
# first alternative is rule 3c.
|
|
|
# BUG: It matches the whitespace first?
|
|
|
pat = '[%s]+|[%s]*[%s][%s]*' % (ws_re, ws_re, other_re, ws_re)
|
|
|
elif ifs_whitespace:
|
|
|
pat = '[%s]+' % ws_re
|
|
|
elif ifs_other:
|
|
|
pat = '[%s]' % other_re
|
|
|
else:
|
|
|
raise AssertionError
|
|
|
|
|
|
#print('PAT', repr(pat))
|
|
|
regex = re.compile(pat)
|
|
|
frags = regex.split(s)
|
|
|
#log('split %r by %r -> frags %s', s, pat, frags)
|
|
|
return frags
|
|
|
|
|
|
|
|
|
def _SplitPartsIntoFragments(part_vals, ifs):
|
|
|
"""
|
|
|
part_value[] -> part_value[]
|
|
|
@@ -168,7 +77,7 @@ def _SplitPartsIntoFragments(part_vals, ifs): |
|
|
if p.tag == part_value_e.StringPartValue:
|
|
|
#log("SPLITTING %s with ifs %r", p, ifs)
|
|
|
if p.do_split_elide:
|
|
|
frags = _IfsSplit(p.s, ifs)
|
|
|
frags = legacy.IfsSplit(p.s, ifs)
|
|
|
res = [runtime.fragment(f, True, p.do_glob) for f in frags]
|
|
|
#log("RES %s", res)
|
|
|
else:
|
|
|
@@ -1074,7 +983,7 @@ def _EvalWordAndReframe(self, word): |
|
|
"""
|
|
|
part_vals = self._EvalParts(word)
|
|
|
#log('part_vals after _EvalParts %s', part_vals)
|
|
|
ifs = _GetIfs(self.mem)
|
|
|
ifs = legacy.GetIfs(self.mem)
|
|
|
frag_arrays = _SplitPartsIntoFragments(part_vals, ifs)
|
|
|
#log('Fragments after split: %s', frag_arrays)
|
|
|
frag_arrays = _Reframe(frag_arrays)
|
|
|
|