View
@@ -1,2 +1,3 @@
osh/osh.asdl osh/osh.asdl
osh/types.asdl osh/types.asdl
core/runtime.asdl core/runtime.asdl
View
@@ -300,6 +300,14 @@ def __init__(self, ifs_whitespace, ifs_other):
self.ifs_other = ifs_other
def Split(self, s, allow_escape):
"""
Args:
s: string to split
allow_escape: False for read -r, this means \ doesn't do anything.
TODO: This should be (frag, do_split) pairs, to avoid IFS='\'
double-escaping issue.
"""
ws_chars = self.ifs_whitespace
other_chars = self.ifs_other
View
@@ -0,0 +1,57 @@
#!/bin/bash
#
# Demo of word evaluation.
#
# Usage:
# ./hard.sh <function name>
#
# Bug with the current algorithm: IFS=\\
set -- 'a*b' 'c d'
typeset -a myarray
myarray=('w x' 'y*z', 'bin')
space=' '
glob='*h b*' # anything that ends with h, then anything that begins with b
spec/bin/argv.py -"$@"-$space-"$space-${myarray[@]}"/$glob
# ['-a b', 'c d-', '- -w x', 'y z,', 'bin/opypy-osh', 'bin/osh', 'bin/sh', 'benchmarks', 'bin', 'build']
# I have a single word.
# I evaluate all the parts:
#
# "$@" -> ArrayPartValue
# $space -> StringPartValue
# "$space" -> StringPartValue
# $myarray -> ArrayPartValue
# $glob -> StringPartValue
#
# Then I _MakeWordFrames. Each frame is (frag, list)
# (frag, do_split_elide)
#
# [ ('-a b', False) ]
# [ ('c d', False), ('-', False), (' ', True), ('-', False), (' ', False),
# ('-', False), ('w x', False) ]
# [ ('y z', False) ]
# [ ('bin', False), ('*h b*', True) ]
# Then for each frame, do _EvalWordFrame. Respect the boolean, and do
# glob.GlobEscape or self.splitter.Escape(frag)
# '-a b'
# -> Glob escape
# '-a b'
# -> Split EScape
# '-a\ b'
# 'c\ d-'
# '-'
# Possible fix to IFS='\' problem: do globbing and splitting in two completely
# separate steps. The Split() function should respect [(frag, bool do_split) ...]
#
# If not splitting, then it's easy to emit the span.
View
@@ -153,7 +153,7 @@ argv.py 1${undefined:-"2_3"x_x"4_5"}6
### IFS empty doesn't do splitting
IFS=''
x=$(echo -e ' a b\tc\n')
argv $x
argv.py $x
## STDOUT:
[' a b\tc']
## END
@@ -165,14 +165,50 @@ argv $x
### IFS unset behaves like $' \t\n'
unset IFS
x=$(echo -e ' a b\tc\n')
argv $x
argv.py $x
## STDOUT:
['a', 'b', 'c']
## END
## N-I dash STDOUT:
['-e', 'a', 'b', 'c']
## END
### IFS='\'
# NOTE: OSH fails this because of double backslash escaping issue!
IFS='\'
s='a\b'
argv.py $s
## STDOUT:
['a', 'b']
## END
### IFS='\ '
# NOTE: OSH fails this because of double backslash escaping issue!
# When IFS is \, then you're no longer using backslash escaping.
IFS='\ '
s='a\b \\ c d\'
argv.py $s
## STDOUT:
['a', 'b', '', 'c', 'd']
## END
### IFS characters are glob metacharacters
IFS='* '
s='a*b c'
argv.py $s
IFS='?'
s='?x?y?z?'
argv.py $s
IFS='['
s='[x[y[z['
argv.py $s
## STDOUT:
['a', 'b', 'c']
['', 'x', 'y', 'z']
['', 'x', 'y', 'z']
## END
# TODO:
# - unquoted args of whitespace are not elided (when IFS = null)
View
@@ -95,6 +95,7 @@ strip-op-char-class() { _compare gold/strip-op-char-class.sh; }
# Similar tests for backslash escaping.
echo-e() { _compare gold/echo-e.sh; }
dollar-sq() { _compare gold/dollar-sq.sh; }
word-eval() { _compare gold/word-eval.sh; }
abuild() {
_compare gold/abuild.sh is_function is_function
@@ -121,6 +122,11 @@ readonly -a PASSING=(
glob
no-op
complex-here-docs
echo-e
dollar-sq
word-eval
strip-op-char-class
abuild
View
@@ -209,7 +209,7 @@ comments() {
}
word-split() {
sh-spec spec/word-split.test.sh \
sh-spec spec/word-split.test.sh --osh-failures-allowed 2 \
${REF_SHELLS[@]} $OSH "$@"
}