summaryrefslogtreecommitdiffstats
path: root/eshtrans
diff options
context:
space:
mode:
authorP. J. McDermott <pj@pehjota.net>2016-02-21 12:12:20 (EST)
committer P. J. McDermott <pj@pehjota.net>2016-02-21 12:14:23 (EST)
commit506a0723291b4abc4b707a6353a840ef51f95ee8 (patch)
tree4babbc574fd99607d9cb39d5b999d79ff21e9ecd /eshtrans
parent37a60f8da15bcf6ef93c9173e3a5c6cecf9693cc (diff)
downloadeggshell-506a0723291b4abc4b707a6353a840ef51f95ee8.zip
eggshell-506a0723291b4abc4b707a6353a840ef51f95ee8.tar.gz
eggshell-506a0723291b4abc4b707a6353a840ef51f95ee8.tar.bz2
eshtrans/frontend: Fix handling of words beginning with "\"
Diffstat (limited to 'eshtrans')
-rw-r--r--eshtrans/frontend/lexer.esh48
-rw-r--r--eshtrans/main.esh8
2 files changed, 42 insertions, 14 deletions
diff --git a/eshtrans/frontend/lexer.esh b/eshtrans/frontend/lexer.esh
index 0991239..d904aa0 100644
--- a/eshtrans/frontend/lexer.esh
+++ b/eshtrans/frontend/lexer.esh
@@ -361,14 +361,14 @@ next_word()
local res=
local word=
- if ! res="$(scan_word false)"; then
+ if ! res="$(scan_word false "${prev_c}")"; then
exit 1
fi
ln_off=${res%%${RS}*}
res="${res#*${RS}}"
c="${res%%${RS}*}"
res="${res#*${RS}}"
- word="${prev_c}${res%%${RS}*}"
+ word="${res%%${RS}*}"
# We must advance lineno because scan_word() was run in a subshell.
lineno=$((${lineno} + ${ln_off}))
@@ -396,16 +396,28 @@ next_word()
scan_word()
{
local in_param="${1}"
- shift 1
- local res=
+ local prev_c="${2}"
+ shift 2
+ local lines=
local word=
local quoted=
- local lines=
+ local tmp_c=
+ local res=
local wordexp=
+ lines=0
word=''
quoted=false
- lines=0
+
+ # Sort of a localized ungetc().
+ case "${prev_c}" in
+ '') ;;
+ *)
+ tmp_c="${c}"
+ c="${prev_c}"
+ ;;
+ esac
+
while :; do
dbg "parsing word char '$c' at lineno $lineno"
case "${c}" in
@@ -436,7 +448,10 @@ scan_word()
'delimiters'
fi
esac
- lgetc
+ case "${prev_c}" in
+ '') lgetc;;
+ *) c="${tmp_c}"; prev_c='';;
+ esac
if ! res=$(scan_wordexp); then
exit 1
fi
@@ -460,8 +475,13 @@ scan_word()
break
;;
\\)
+ dbg 'first backslash in word'
word="${word}${c}"
- lgetc
+ case "${prev_c}" in
+ '') lgetc;;
+ *) c="${tmp_c}"; prev_c='';;
+ esac
+ dbg "next char: '$c'"
case "${c}" in '')
# Bash, ksh93, mksh, and zsh ignore a
# backslash at the end of a file, but
@@ -479,7 +499,10 @@ scan_word()
\')
word="${word}${c}"
while :; do
- lgetc
+ case "${prev_c}" in
+ '') lgetc;;
+ *) c="${tmp_c}"; prev_c='';;
+ esac
word="${word}${c}"
case "${c}" in
'')
@@ -511,7 +534,10 @@ scan_word()
word="${word}${c}"
;;
esac
- lgetc
+ case "${prev_c}" in
+ '') lgetc;;
+ *) c="${tmp_c}"; prev_c='';;
+ esac
done
if ${quoted}; then
@@ -673,7 +699,7 @@ scan_wordexp_param_brace()
# If a modification was found
if ${mod}; then
# Get word.
- if ! res="$(scan_word true)"; then
+ if ! res="$(scan_word true '')"; then
exit 1
fi
ln_off=${res%%${RS}*}
diff --git a/eshtrans/main.esh b/eshtrans/main.esh
index 1cd6e07..46edd26 100644
--- a/eshtrans/main.esh
+++ b/eshtrans/main.esh
@@ -98,7 +98,9 @@ main()
#try 'v=foo'
#try 'if &&'
#try 'if true; do'
-try 'foo' '#bar'
-try '# foo' 'bar'
-try '' 'foo'
+#try 'foo' '#bar'
+#try '# foo' 'bar'
+#try '' 'foo'
+dbg=true
+try '\\ foo'
}