Permalink
Browse files

Fix the evaluation of "${empty:-}".

Bug reported/reproduced by lheckemann in
ec7ca9d.

We treat it like "${empty:-''}", i.e. by inserting a dummy
SingleQuotedPart.

This is analogous to how

empty=

is equivalent to

empty=''

All spec tests pass.
  • Loading branch information...
Andy Chu
Andy Chu committed Sep 23, 2017
1 parent ec7ca9d commit 8da6ccb98bed9354aa7c8c4d389818d67fa905f2
Showing with 18 additions and 6 deletions.
  1. +3 −2 core/word.py
  2. +1 −1 core/word_eval.py
  3. +12 −1 osh/word_parse.py
  4. +2 −2 spec/var-sub-quote.test.sh
View
@@ -408,8 +408,9 @@ def LooksLikeAssignment(w):
rhs = ast.CompoundWord()
if len(w.parts) == 1:
# NOTE: This is necesssary so that EmptyUnquoted elision isn't
# applied. EMPTY= is like EMPTY=''.
# This fake SingleQuotedPart is necesssary so that EmptyUnquoted elision
# isn't applied. EMPTY= is like EMPTY=''.
# TODO: This part doesn't have spids, so it might break some invariants.
rhs.parts.append(ast.SingleQuotedPart())
else:
for p in w.parts[1:]:
View
@@ -991,7 +991,7 @@ def EvalWordToAny(self, word, glob_escape=False):
return runtime.StrArray(strs)
part_vals = self._EvalParts(word)
#log('part_vals %s', part_vals)
#log('EvalWordToAny part_vals %s', part_vals)
# Instead of splitting, do a trivial transformation to frag array.
# Example:
View
@@ -23,6 +23,7 @@
word_e = ast.word_e
p_die = util.p_die
log = util.log
# Substitutions can be nested, but which inner subs are allowed depends on the
# outer sub. See _ReadLeftParts vs. _ReadDoubleQuotedLeftParts.
@@ -140,8 +141,18 @@ def _ReadVarOpArg(self, arg_lex_mode, eof_type=Id.Undefined_Tok,
# valid, even when unquoted.
self._Next(arg_lex_mode)
self._Peek()
return self._ReadCompoundWord(
w = self._ReadCompoundWord(
lex_mode=arg_lex_mode, eof_type=eof_type, empty_ok=empty_ok)
# This is for "${s:-}", ${s/a//}, etc. It is analogous to
# LooksLikeAssignment where we turn x= into x=''. It has the same
# potential problem of not having spids.
#
# NOTE: empty_ok is False only for the PatSub pattern, which means we'll
# return a CompoundWord(parts=[]), which fails later.
if not w.parts and empty_ok:
w.parts.append(ast.SingleQuotedPart())
return w
def _ReadSliceArg(self):
"""Read an arithmetic expression for either part of ${a : i+1 : i+2}."""
@@ -15,8 +15,8 @@
# makes sense I guess. Vim's syntax highlighting is throwing me off.
### :- with empty alternative
foo=
argv.py "${foo:-}"
empty=
argv.py "${empty:-}"
# stdout: ['']
### :-

0 comments on commit 8da6ccb

Please sign in to comment.