Permalink
Browse files

Categorize bad backslashes, and make \" -> " because other shells do it.

  • Loading branch information...
Andy Chu
Andy Chu committed Jan 9, 2018
1 parent c632dc3 commit 7ce594a3d53bca0e6b653804c41fbf83baf0c6ab
Showing with 25 additions and 12 deletions.
  1. +2 −1 core/id_kind.py
  2. +8 −4 core/word_compile.py
  3. +9 −7 osh/lex.py
  4. +6 −0 spec/quote.test.sh
View
@@ -402,7 +402,8 @@ def _AddKinds(spec):
'OneChar', 'Stop', 'Hex',
# Two variants of Octal: \377, and \0377.
'Octal3', 'Octal4',
'Unicode4', 'Unicode8', 'Literals'
'Unicode4', 'Unicode8', 'Literals',
'BadBackslash', # \D or trailing \
])
View
@@ -20,6 +20,8 @@
't': '\t',
'v': '\v',
'\\': '\\',
"'": "'", # for $'' only, not echo -e
'"': '"', # not sure why this is escaped within $''
}
# TODO: Strict mode syntax errors:
@@ -34,8 +36,13 @@ def EvalCStringToken(id_, value):
$'' could use it at compile time, much like brace expansion in braces.py.
"""
if id_ == Id.Char_Literals:
return value
elif id_ == Id.Char_BadBackslash: # TODO: error in strict mode
return value
if id_ == Id.Char_OneChar:
elif id_ == Id.Char_OneChar:
c = value[1]
return _ONE_CHAR[c]
@@ -70,9 +77,6 @@ def EvalCStringToken(id_, value):
i = int(s, 16)
return unichr(i)
elif id_ == Id.Char_Literals:
return value
else:
raise AssertionError
View
@@ -406,9 +406,9 @@ def IsKeyword(name):
# Backslash that ends a line. Note '.' doesn't match a newline character.
C('\\\n', Id.Char_Literals),
# e.g. \A is not an escape, and \x doesn't match a hex escape. This could be
# an error.
C('\\', Id.Char_Literals),
# e.g. \A is not an escape, and \x doesn't match a hex escape. We allow it,
# but a lint tool could warn about it.
C('\\', Id.Char_BadBackslash),
]
# Used by ECHO_LEXER in core/builtin.py.
@@ -419,8 +419,9 @@ def IsKeyword(name):
C(r'\c', Id.Char_Stop),
# Backslash that ends the string.
R(r'\\$', Id.Char_Literals),
# Bad Backslash should not end the string. We allow it, but a lint tool
# should warn about it.
R(r'\\$', Id.Char_BadBackslash),
# e.g. 'foo', anything that's not a backslash escape
R(r'[^\\]+', Id.Char_Literals),
@@ -434,8 +435,9 @@ def IsKeyword(name):
# with no leading 0.
R(r'\\[0-7]{1,3}', Id.Char_Octal3),
# \' is escaped in $'' mode, but not echo -e
C(r'\'', Id.Char_OneChar),
# ' is escaped in $'' mode, but not echo -e. Ditto fr ", not sure why.
C(r"\'", Id.Char_OneChar),
C(r'\"', Id.Char_OneChar),
# e.g. 'foo', anything that's not a backslash escape. Need to exclude ' as
# well.
View
@@ -139,6 +139,12 @@ echo $'foo'
# stdout: foo
# N-I dash stdout: $foo
### $'' with quotes
echo $'single \' double \"'
# stdout: single ' double "
# N-I dash stdout-json: ""
# N-I dash status: 2
### $'' with newlines
echo $'col1\ncol2\ncol3'
# stdout-json: "col1\ncol2\ncol3\n"

0 comments on commit 7ce594a

Please sign in to comment.