Skip to content

Commit

Permalink
[osh2oil] Fix crash bug translating empty string.
Browse files Browse the repository at this point in the history
case $1 in '') caused a problem because we weren't returning the span_id
of the left single quote.

Also, notes about osh2oil translation:

- (( )) translates to sh-expr
- The different RHS styles
  • Loading branch information
Andy Chu committed Aug 29, 2018
1 parent afee5d5 commit ed1c953
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 14 deletions.
11 changes: 2 additions & 9 deletions core/word.py
Expand Up @@ -120,17 +120,10 @@ def LeftMostSpanForPart(part):
return part.token.span_id

elif part.tag == word_part_e.SingleQuotedPart:
if part.tokens:
return part.tokens[0].span_id
else:
return const.NO_INTEGER
return part.spids[0] # single quote location

elif part.tag == word_part_e.DoubleQuotedPart:
if part.parts:
return LeftMostSpanForPart(part.parts[0])
else:
# We need the double quote location
return const.NO_INTEGER
return part.spids[0] # double quote location

elif part.tag == word_part_e.SimpleVarSub:
return part.token.span_id
Expand Down
22 changes: 22 additions & 0 deletions test/osh2oil.sh
Expand Up @@ -398,6 +398,22 @@ setglobal g = ''
setglobal g = 'x'
OIL
cat >/dev/null <<TODO_ENABLE
# empty quoted words
osh0-oil3 << 'OSH' 3<< 'OIL'
dq=""
OSH
setglobal dq = ""
OIL
# empty quoted words
osh0-oil3 << 'OSH' 3<< 'OIL'
sq=''
OSH
setglobal sq = ''
OIL
TODO_ENABLE
# Local variable
osh0-oil3 << 'OSH' 3<< 'OIL'
f() {
Expand Down Expand Up @@ -821,6 +837,9 @@ case $var in
foo|bar)
[ -f foo ] && echo file
;;
'')
echo empty
;;
*)
echo default
;;
Expand All @@ -830,6 +849,9 @@ match $var {
with foo|bar
test -f foo && echo file
with ''
echo empty
with *
echo default
Expand Down
47 changes: 42 additions & 5 deletions tools/osh2oil.py
Expand Up @@ -123,6 +123,36 @@ def PrintAsOil(arena, node, debug_spans):
# ${x:-default} -> @-(x or 'default')

def _GetRhsStyle(w):
"""
Determine what style an assignment should use. '' or "", or an expression.
SQ foo= setglobal foo = ''
SQ foo='' setglobal foo = ''
DQ foo="" setglobal foo = "" # Or we could normalize it if no subs?
DQ foo="" setglobal foo = "" # Or we could normalize it if no subs?
# Need these too.
# Or honestly should C strings be the default? And then raw strings are
# optional? Because most usages of \n and \0 can turn into Oil?
# Yeah I want the default to be statically parseable, so we subvert the \t
# and \n of command line tools?
# As long as we are fully analyzing the strings, we might as well go all the
# way!
# I think I need a PartialStaticEval() to paper over this.
#
# The main issue is regex and globs, because they use escape for a different
# purpose. I think just do
# grep r'foo\tbar' or something.
C_SQ foo=$'\n' setglobal foo = C'\n'
C_DQ foo=$'\n'"$bar" setglobal foo = C"\n$(bar)"
Expr path=${1:-} setglobal path = $1 or ''
Expr host=${2:-$(hostname)} setglobal host = $2 or $[hostname]
What's the difference between Expr and Unquoted? I think they're the same/
"""

# NOTE: Pattern matching style would be a lot nicer for this...

# Arith and command sub both retain $() and $[], so they are not pure
Expand Down Expand Up @@ -636,13 +666,14 @@ def DoCommand(self, node, local_symbols, at_top_level=False):
self.f.write('}')

elif node.tag == command_e.DParen:
# Just change (( )) to ( )
# Test it with while loop

# TODO: (( a == 0 )) is sh-expr ' a == 0 '
#
# NOTE: I have a (( n++ )) in one script. That can be 'set n++' or
# 'set n += 1'.

#self.DoArithExpr(node.child, local_symbols)
#
# Auto-translation is:
#
# sh-expr 'n++'
raise NotImplementedError('DParen')

elif node.tag == command_e.DBracket:
Expand Down Expand Up @@ -847,6 +878,7 @@ def DoCommand(self, node, local_symbols, at_top_level=False):
raise AssertionError(node.__class__.__name__)

def DoWordAsExpr(self, node, local_symbols):
# TODO: This is wrong!
style = _GetRhsStyle(node)
if style == word_style_e.SQ:
self.f.write("'")
Expand All @@ -856,6 +888,11 @@ def DoWordAsExpr(self, node, local_symbols):
self.f.write('"')
self.DoWordInCommand(node, local_symbols)
self.f.write('"')
# TODO: Put these back
#elif style == word_style_e.Expr:
# pass
#elif style == word_style_e.Unquoted:
# pass
else:
# "${foo:-default}" -> foo or 'default'
# ${foo:-default} -> @split(foo or 'default')
Expand Down

0 comments on commit ed1c953

Please sign in to comment.