fix reentrancy of 'typeset -f' output in the face of aliases; also,

move alias handling for COMSUBs and friends to parse time by request
of Martijn Dekker (and for consistency with function definitions)
This commit is contained in:
tg 2017-04-06 01:59:58 +00:00
parent 094cce63c5
commit 3909a42540
9 changed files with 322 additions and 240 deletions

318
check.t
View File

@ -1,4 +1,4 @@
# $MirOS: src/bin/mksh/check.t,v 1.770 2017/04/06 00:41:38 tg Exp $ # $MirOS: src/bin/mksh/check.t,v 1.771 2017/04/06 01:59:51 tg Exp $
# -*- mode: sh -*- # -*- mode: sh -*-
#- #-
# Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, # Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
@ -30,7 +30,7 @@
# (2013/12/02 20:39:44) http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/regress/bin/ksh/?sortby=date # (2013/12/02 20:39:44) http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/regress/bin/ksh/?sortby=date
expected-stdout: expected-stdout:
@(#)MIRBSD KSH R54 2017/04/02 @(#)MIRBSD KSH R54 2017/04/05
description: description:
Check version of shell. Check version of shell.
stdin: stdin:
@ -39,7 +39,7 @@ name: KSH_VERSION
category: !shell:legacy-yes,!shell:textmode-yes category: !shell:legacy-yes,!shell:textmode-yes
--- ---
expected-stdout: expected-stdout:
@(#)LEGACY KSH R54 2017/04/02 @(#)LEGACY KSH R54 2017/04/05
description: description:
Check version of legacy shell. Check version of legacy shell.
stdin: stdin:
@ -48,7 +48,7 @@ name: KSH_VERSION-legacy
category: !shell:legacy-no,!shell:textmode-yes category: !shell:legacy-no,!shell:textmode-yes
--- ---
expected-stdout: expected-stdout:
@(#)MIRBSD KSH R54 2017/04/02 +TEXTMODE @(#)MIRBSD KSH R54 2017/04/05 +TEXTMODE
description: description:
Check version of shell. Check version of shell.
stdin: stdin:
@ -57,7 +57,7 @@ name: KSH_VERSION-textmode
category: !shell:legacy-yes,!shell:textmode-no category: !shell:legacy-yes,!shell:textmode-no
--- ---
expected-stdout: expected-stdout:
@(#)LEGACY KSH R54 2017/04/02 +TEXTMODE @(#)LEGACY KSH R54 2017/04/05 +TEXTMODE
description: description:
Check version of legacy shell. Check version of legacy shell.
stdin: stdin:
@ -298,6 +298,27 @@ expected-stdout:
bar - baz,z bar - baz,z
bar - baz,z bar - baz,z
--- ---
name: alias-12
description:
Something weird from Martijn Dekker
stdin:
alias echo=print
x() { echo a; (echo b); x=$(echo c); }
typeset -f x
alias OPEN='{' CLOSE='};'
{ OPEN echo hi1; CLOSE }
var=`{ OPEN echo hi2; CLOSE }` && echo "$var"
var=$({ OPEN echo hi3; CLOSE }) && echo "$var"
expected-stdout:
x() {
\print a
( \print b )
x=$(\print c )
}
hi1
hi2
hi3
---
name: arith-compound name: arith-compound
description: description:
Check that arithmetic expressions are compound constructs Check that arithmetic expressions are compound constructs
@ -2860,7 +2881,7 @@ stdin:
expected-stdout: expected-stdout:
0 0
bar() { bar() {
foo 4<<-a <<-b 5<<-c \foo 4<<-a <<-b 5<<-c
four four
a a
zero zero
@ -10903,10 +10924,10 @@ expected-stdout:
x() { x() {
case $1 in case $1 in
(u) (u)
echo x \echo x
;| ;|
(*) (*)
echo $1 \echo $1
;; ;;
esac esac
} }
@ -10914,6 +10935,7 @@ expected-stdout:
name: comsub-5 name: comsub-5
description: description:
Check COMSUB works with aliases (does not expand them twice) Check COMSUB works with aliases (does not expand them twice)
and reentrancy safety
stdin: stdin:
print '#!'"$__progname"'\nfor x in "$@"; do print -r -- "$x"; done' >pfn print '#!'"$__progname"'\nfor x in "$@"; do print -r -- "$x"; done' >pfn
chmod +x pfn chmod +x pfn
@ -10922,12 +10944,22 @@ stdin:
./pfn "$(echo foo)" ./pfn "$(echo foo)"
} }
./pfn "$(echo b)" ./pfn "$(echo b)"
typeset -f foo >x
cat x
foo
. ./x
typeset -f foo typeset -f foo
foo
expected-stdout: expected-stdout:
a b a b
foo() { foo() {
./pfn "$(echo foo )" ./pfn "$(\echo a foo )"
} }
a foo
foo() {
./pfn "$(\echo a foo )"
}
a foo
--- ---
name: comsub-torture name: comsub-torture
description: description:
@ -11038,56 +11070,56 @@ expected-stdout:
vara=1 varb='2 3' cmd arg1 $arg2 "$arg3 4" vara=1 varb='2 3' cmd arg1 $arg2 "$arg3 4"
} }
inline_TCOM() { inline_TCOM() {
vara=1 varb="2 3" cmd arg1 $arg2 "$arg3 4" vara=1 varb="2 3" \cmd arg1 $arg2 "$arg3 4"
} }
function comsub_TCOM { x=$( function comsub_TCOM { x=$(
vara=1 varb='2 3' cmd arg1 $arg2 "$arg3 4" vara=1 varb='2 3' cmd arg1 $arg2 "$arg3 4"
); } ); }
function comsub_TCOM { function comsub_TCOM {
x=$(vara=1 varb="2 3" cmd arg1 $arg2 "$arg3 4" ) x=$(vara=1 varb="2 3" \cmd arg1 $arg2 "$arg3 4" )
} }
function reread_TCOM { x=$(( function reread_TCOM { x=$((
vara=1 varb='2 3' cmd arg1 $arg2 "$arg3 4" vara=1 varb='2 3' cmd arg1 $arg2 "$arg3 4"
)|tr u x); } )|tr u x); }
function reread_TCOM { function reread_TCOM {
x=$(( vara=1 varb="2 3" cmd arg1 $arg2 "$arg3 4" ) | tr u x ) x=$(( vara=1 varb="2 3" \cmd arg1 $arg2 "$arg3 4" ) | \tr u x )
} }
inline_TPAREN_TPIPE_TLIST() { inline_TPAREN_TPIPE_TLIST() {
(echo $foo | tr -dc 0-9; echo) (echo $foo | tr -dc 0-9; echo)
} }
inline_TPAREN_TPIPE_TLIST() { inline_TPAREN_TPIPE_TLIST() {
( echo $foo | tr -dc 0-9 ( \echo $foo | \tr -dc 0-9
echo ) \echo )
} }
function comsub_TPAREN_TPIPE_TLIST { x=$( function comsub_TPAREN_TPIPE_TLIST { x=$(
(echo $foo | tr -dc 0-9; echo) (echo $foo | tr -dc 0-9; echo)
); } ); }
function comsub_TPAREN_TPIPE_TLIST { function comsub_TPAREN_TPIPE_TLIST {
x=$(( echo $foo | tr -dc 0-9 ; echo ) ) x=$(( \echo $foo | \tr -dc 0-9 ; \echo ) )
} }
function reread_TPAREN_TPIPE_TLIST { x=$(( function reread_TPAREN_TPIPE_TLIST { x=$((
(echo $foo | tr -dc 0-9; echo) (echo $foo | tr -dc 0-9; echo)
)|tr u x); } )|tr u x); }
function reread_TPAREN_TPIPE_TLIST { function reread_TPAREN_TPIPE_TLIST {
x=$(( ( echo $foo | tr -dc 0-9 ; echo ) ) | tr u x ) x=$(( ( \echo $foo | \tr -dc 0-9 ; \echo ) ) | \tr u x )
} }
inline_TAND_TOR() { inline_TAND_TOR() {
cmd && echo ja || echo nein cmd && echo ja || echo nein
} }
inline_TAND_TOR() { inline_TAND_TOR() {
cmd && echo ja || echo nein \cmd && \echo ja || \echo nein
} }
function comsub_TAND_TOR { x=$( function comsub_TAND_TOR { x=$(
cmd && echo ja || echo nein cmd && echo ja || echo nein
); } ); }
function comsub_TAND_TOR { function comsub_TAND_TOR {
x=$(cmd && echo ja || echo nein ) x=$(\cmd && \echo ja || \echo nein )
} }
function reread_TAND_TOR { x=$(( function reread_TAND_TOR { x=$((
cmd && echo ja || echo nein cmd && echo ja || echo nein
)|tr u x); } )|tr u x); }
function reread_TAND_TOR { function reread_TAND_TOR {
x=$(( cmd && echo ja || echo nein ) | tr u x ) x=$(( \cmd && \echo ja || \echo nein ) | \tr u x )
} }
inline_TSELECT() { inline_TSELECT() {
select file in *; do echo "<$file>" ; break ; done select file in *; do echo "<$file>" ; break ; done
@ -11095,21 +11127,21 @@ expected-stdout:
inline_TSELECT() { inline_TSELECT() {
select file in * select file in *
do do
echo "<$file>" \echo "<$file>"
break \break
done done
} }
function comsub_TSELECT { x=$( function comsub_TSELECT { x=$(
select file in *; do echo "<$file>" ; break ; done select file in *; do echo "<$file>" ; break ; done
); } ); }
function comsub_TSELECT { function comsub_TSELECT {
x=$(select file in * ; do echo "<$file>" ; break ; done ) x=$(select file in * ; do \echo "<$file>" ; \break ; done )
} }
function reread_TSELECT { x=$(( function reread_TSELECT { x=$((
select file in *; do echo "<$file>" ; break ; done select file in *; do echo "<$file>" ; break ; done
)|tr u x); } )|tr u x); }
function reread_TSELECT { function reread_TSELECT {
x=$(( select file in * ; do echo "<$file>" ; break ; done ) | tr u x ) x=$(( select file in * ; do \echo "<$file>" ; \break ; done ) | \tr u x )
} }
inline_TFOR_TTIME() { inline_TFOR_TTIME() {
time for i in {1,2,3} ; do echo $i ; done time for i in {1,2,3} ; do echo $i ; done
@ -11117,20 +11149,20 @@ expected-stdout:
inline_TFOR_TTIME() { inline_TFOR_TTIME() {
time for i in {1,2,3} time for i in {1,2,3}
do do
echo $i \echo $i
done done
} }
function comsub_TFOR_TTIME { x=$( function comsub_TFOR_TTIME { x=$(
time for i in {1,2,3} ; do echo $i ; done time for i in {1,2,3} ; do echo $i ; done
); } ); }
function comsub_TFOR_TTIME { function comsub_TFOR_TTIME {
x=$(time for i in {1,2,3} ; do echo $i ; done ) x=$(time for i in {1,2,3} ; do \echo $i ; done )
} }
function reread_TFOR_TTIME { x=$(( function reread_TFOR_TTIME { x=$((
time for i in {1,2,3} ; do echo $i ; done time for i in {1,2,3} ; do echo $i ; done
)|tr u x); } )|tr u x); }
function reread_TFOR_TTIME { function reread_TFOR_TTIME {
x=$(( time for i in {1,2,3} ; do echo $i ; done ) | tr u x ) x=$(( time for i in {1,2,3} ; do \echo $i ; done ) | \tr u x )
} }
inline_TCASE() { inline_TCASE() {
case $foo in 1) echo eins;& 2) echo zwei ;| *) echo kann net bis drei zählen;; esac case $foo in 1) echo eins;& 2) echo zwei ;| *) echo kann net bis drei zählen;; esac
@ -11138,13 +11170,13 @@ expected-stdout:
inline_TCASE() { inline_TCASE() {
case $foo in case $foo in
(1) (1)
echo eins \echo eins
;& ;&
(2) (2)
echo zwei \echo zwei
;| ;|
(*) (*)
echo kann net bis drei zählen \echo kann net bis drei zählen
;; ;;
esac esac
} }
@ -11152,13 +11184,13 @@ expected-stdout:
case $foo in 1) echo eins;& 2) echo zwei ;| *) echo kann net bis drei zählen;; esac case $foo in 1) echo eins;& 2) echo zwei ;| *) echo kann net bis drei zählen;; esac
); } ); }
function comsub_TCASE { function comsub_TCASE {
x=$(case $foo in (1) echo eins ;& (2) echo zwei ;| (*) echo kann net bis drei zählen ;; esac ) x=$(case $foo in (1) \echo eins ;& (2) \echo zwei ;| (*) \echo kann net bis drei zählen ;; esac )
} }
function reread_TCASE { x=$(( function reread_TCASE { x=$((
case $foo in 1) echo eins;& 2) echo zwei ;| *) echo kann net bis drei zählen;; esac case $foo in 1) echo eins;& 2) echo zwei ;| *) echo kann net bis drei zählen;; esac
)|tr u x); } )|tr u x); }
function reread_TCASE { function reread_TCASE {
x=$(( case $foo in (1) echo eins ;& (2) echo zwei ;| (*) echo kann net bis drei zählen ;; esac ) | tr u x ) x=$(( case $foo in (1) \echo eins ;& (2) \echo zwei ;| (*) \echo kann net bis drei zählen ;; esac ) | \tr u x )
} }
inline_TIF_TBANG_TDBRACKET_TELIF() { inline_TIF_TBANG_TDBRACKET_TELIF() {
if ! [[ 1 = 1 ]] ; then echo eins; elif [[ 1 = 2 ]]; then echo zwei ;else echo drei; fi if ! [[ 1 = 1 ]] ; then echo eins; elif [[ 1 = 2 ]]; then echo zwei ;else echo drei; fi
@ -11166,25 +11198,25 @@ expected-stdout:
inline_TIF_TBANG_TDBRACKET_TELIF() { inline_TIF_TBANG_TDBRACKET_TELIF() {
if ! [[ 1 = 1 ]] if ! [[ 1 = 1 ]]
then then
echo eins \echo eins
elif [[ 1 = 2 ]] elif [[ 1 = 2 ]]
then then
echo zwei \echo zwei
else else
echo drei \echo drei
fi fi
} }
function comsub_TIF_TBANG_TDBRACKET_TELIF { x=$( function comsub_TIF_TBANG_TDBRACKET_TELIF { x=$(
if ! [[ 1 = 1 ]] ; then echo eins; elif [[ 1 = 2 ]]; then echo zwei ;else echo drei; fi if ! [[ 1 = 1 ]] ; then echo eins; elif [[ 1 = 2 ]]; then echo zwei ;else echo drei; fi
); } ); }
function comsub_TIF_TBANG_TDBRACKET_TELIF { function comsub_TIF_TBANG_TDBRACKET_TELIF {
x=$(if ! [[ 1 = 1 ]] ; then echo eins ; elif [[ 1 = 2 ]] ; then echo zwei ; else echo drei ; fi ) x=$(if ! [[ 1 = 1 ]] ; then \echo eins ; elif [[ 1 = 2 ]] ; then \echo zwei ; else \echo drei ; fi )
} }
function reread_TIF_TBANG_TDBRACKET_TELIF { x=$(( function reread_TIF_TBANG_TDBRACKET_TELIF { x=$((
if ! [[ 1 = 1 ]] ; then echo eins; elif [[ 1 = 2 ]]; then echo zwei ;else echo drei; fi if ! [[ 1 = 1 ]] ; then echo eins; elif [[ 1 = 2 ]]; then echo zwei ;else echo drei; fi
)|tr u x); } )|tr u x); }
function reread_TIF_TBANG_TDBRACKET_TELIF { function reread_TIF_TBANG_TDBRACKET_TELIF {
x=$(( if ! [[ 1 = 1 ]] ; then echo eins ; elif [[ 1 = 2 ]] ; then echo zwei ; else echo drei ; fi ) | tr u x ) x=$(( if ! [[ 1 = 1 ]] ; then \echo eins ; elif [[ 1 = 2 ]] ; then \echo zwei ; else \echo drei ; fi ) | \tr u x )
} }
inline_TWHILE() { inline_TWHILE() {
i=1; while (( i < 10 )); do echo $i; let ++i; done i=1; while (( i < 10 )); do echo $i; let ++i; done
@ -11195,21 +11227,21 @@ expected-stdout:
\\builtin let " i < 10 " \\builtin let " i < 10 "
} }
do do
echo $i \echo $i
let ++i \let ++i
done done
} }
function comsub_TWHILE { x=$( function comsub_TWHILE { x=$(
i=1; while (( i < 10 )); do echo $i; let ++i; done i=1; while (( i < 10 )); do echo $i; let ++i; done
); } ); }
function comsub_TWHILE { function comsub_TWHILE {
x=$(i=1 ; while { \\builtin let " i < 10 " ; } ; do echo $i ; let ++i ; done ) x=$(i=1 ; while { \\builtin let " i < 10 " ; } ; do \echo $i ; \let ++i ; done )
} }
function reread_TWHILE { x=$(( function reread_TWHILE { x=$((
i=1; while (( i < 10 )); do echo $i; let ++i; done i=1; while (( i < 10 )); do echo $i; let ++i; done
)|tr u x); } )|tr u x); }
function reread_TWHILE { function reread_TWHILE {
x=$(( i=1 ; while { \\builtin let " i < 10 " ; } ; do echo $i ; let ++i ; done ) | tr u x ) x=$(( i=1 ; while { \\builtin let " i < 10 " ; } ; do \echo $i ; \let ++i ; done ) | \tr u x )
} }
inline_TUNTIL() { inline_TUNTIL() {
i=10; until (( !--i )) ; do echo $i; done i=10; until (( !--i )) ; do echo $i; done
@ -11220,39 +11252,39 @@ expected-stdout:
\\builtin let " !--i " \\builtin let " !--i "
} }
do do
echo $i \echo $i
done done
} }
function comsub_TUNTIL { x=$( function comsub_TUNTIL { x=$(
i=10; until (( !--i )) ; do echo $i; done i=10; until (( !--i )) ; do echo $i; done
); } ); }
function comsub_TUNTIL { function comsub_TUNTIL {
x=$(i=10 ; until { \\builtin let " !--i " ; } ; do echo $i ; done ) x=$(i=10 ; until { \\builtin let " !--i " ; } ; do \echo $i ; done )
} }
function reread_TUNTIL { x=$(( function reread_TUNTIL { x=$((
i=10; until (( !--i )) ; do echo $i; done i=10; until (( !--i )) ; do echo $i; done
)|tr u x); } )|tr u x); }
function reread_TUNTIL { function reread_TUNTIL {
x=$(( i=10 ; until { \\builtin let " !--i " ; } ; do echo $i ; done ) | tr u x ) x=$(( i=10 ; until { \\builtin let " !--i " ; } ; do \echo $i ; done ) | \tr u x )
} }
inline_TCOPROC() { inline_TCOPROC() {
cat * |& ls cat * |& ls
} }
inline_TCOPROC() { inline_TCOPROC() {
cat * |& \cat * |&
ls \ls
} }
function comsub_TCOPROC { x=$( function comsub_TCOPROC { x=$(
cat * |& ls cat * |& ls
); } ); }
function comsub_TCOPROC { function comsub_TCOPROC {
x=$(cat * |& ls ) x=$(\cat * |& \ls )
} }
function reread_TCOPROC { x=$(( function reread_TCOPROC { x=$((
cat * |& ls cat * |& ls
)|tr u x); } )|tr u x); }
function reread_TCOPROC { function reread_TCOPROC {
x=$(( cat * |& ls ) | tr u x ) x=$(( \cat * |& \ls ) | \tr u x )
} }
inline_TFUNCT_TBRACE_TASYNC() { inline_TFUNCT_TBRACE_TASYNC() {
function korn { echo eins; echo zwei ; } function korn { echo eins; echo zwei ; }
@ -11260,11 +11292,11 @@ expected-stdout:
} }
inline_TFUNCT_TBRACE_TASYNC() { inline_TFUNCT_TBRACE_TASYNC() {
function korn { function korn {
echo eins \echo eins
echo zwei \echo zwei
} }
bourne() { bourne() {
logger * & \logger * &
} }
} }
function comsub_TFUNCT_TBRACE_TASYNC { x=$( function comsub_TFUNCT_TBRACE_TASYNC { x=$(
@ -11272,32 +11304,32 @@ expected-stdout:
bourne () { logger * & } bourne () { logger * & }
); } ); }
function comsub_TFUNCT_TBRACE_TASYNC { function comsub_TFUNCT_TBRACE_TASYNC {
x=$(function korn { echo eins ; echo zwei ; } ; bourne() { logger * & } ) x=$(function korn { \echo eins ; \echo zwei ; } ; bourne() { \logger * & } )
} }
function reread_TFUNCT_TBRACE_TASYNC { x=$(( function reread_TFUNCT_TBRACE_TASYNC { x=$((
function korn { echo eins; echo zwei ; } function korn { echo eins; echo zwei ; }
bourne () { logger * & } bourne () { logger * & }
)|tr u x); } )|tr u x); }
function reread_TFUNCT_TBRACE_TASYNC { function reread_TFUNCT_TBRACE_TASYNC {
x=$(( function korn { echo eins ; echo zwei ; } ; bourne() { logger * & } ) | tr u x ) x=$(( function korn { \echo eins ; \echo zwei ; } ; bourne() { \logger * & } ) | \tr u x )
} }
inline_IOREAD_IOCAT() { inline_IOREAD_IOCAT() {
tr x u 0<foo >>bar tr x u 0<foo >>bar
} }
inline_IOREAD_IOCAT() { inline_IOREAD_IOCAT() {
tr x u <foo >>bar \tr x u <foo >>bar
} }
function comsub_IOREAD_IOCAT { x=$( function comsub_IOREAD_IOCAT { x=$(
tr x u 0<foo >>bar tr x u 0<foo >>bar
); } ); }
function comsub_IOREAD_IOCAT { function comsub_IOREAD_IOCAT {
x=$(tr x u <foo >>bar ) x=$(\tr x u <foo >>bar )
} }
function reread_IOREAD_IOCAT { x=$(( function reread_IOREAD_IOCAT { x=$((
tr x u 0<foo >>bar tr x u 0<foo >>bar
)|tr u x); } )|tr u x); }
function reread_IOREAD_IOCAT { function reread_IOREAD_IOCAT {
x=$(( tr x u <foo >>bar ) | tr u x ) x=$(( \tr x u <foo >>bar ) | \tr u x )
} }
inline_IOWRITE_IOCLOB_IOHERE_noIOSKIP() { inline_IOWRITE_IOCLOB_IOHERE_noIOSKIP() {
cat >|bar <<'EOFN' cat >|bar <<'EOFN'
@ -11305,7 +11337,7 @@ expected-stdout:
EOFN EOFN
} }
inline_IOWRITE_IOCLOB_IOHERE_noIOSKIP() { inline_IOWRITE_IOCLOB_IOHERE_noIOSKIP() {
cat >|bar <<"EOFN" \cat >|bar <<"EOFN"
foo foo
EOFN EOFN
@ -11316,7 +11348,7 @@ expected-stdout:
EOFN EOFN
); } ); }
function comsub_IOWRITE_IOCLOB_IOHERE_noIOSKIP { function comsub_IOWRITE_IOCLOB_IOHERE_noIOSKIP {
x=$(cat >|bar <<"EOFN" x=$(\cat >|bar <<"EOFN"
foo foo
EOFN EOFN
) )
@ -11327,10 +11359,10 @@ expected-stdout:
EOFN EOFN
)|tr u x); } )|tr u x); }
function reread_IOWRITE_IOCLOB_IOHERE_noIOSKIP { function reread_IOWRITE_IOCLOB_IOHERE_noIOSKIP {
x=$(( cat >|bar <<"EOFN" x=$(( \cat >|bar <<"EOFN"
foo foo
EOFN EOFN
) | tr u x ) ) | \tr u x )
} }
inline_IOWRITE_noIOCLOB_IOHERE_IOSKIP() { inline_IOWRITE_noIOCLOB_IOHERE_IOSKIP() {
cat 1>bar <<-EOFI cat 1>bar <<-EOFI
@ -11338,7 +11370,7 @@ expected-stdout:
EOFI EOFI
} }
inline_IOWRITE_noIOCLOB_IOHERE_IOSKIP() { inline_IOWRITE_noIOCLOB_IOHERE_IOSKIP() {
cat >bar <<-EOFI \cat >bar <<-EOFI
foo foo
EOFI EOFI
@ -11349,7 +11381,7 @@ expected-stdout:
EOFI EOFI
); } ); }
function comsub_IOWRITE_noIOCLOB_IOHERE_IOSKIP { function comsub_IOWRITE_noIOCLOB_IOHERE_IOSKIP {
x=$(cat >bar <<-EOFI x=$(\cat >bar <<-EOFI
foo foo
EOFI EOFI
) )
@ -11360,46 +11392,46 @@ expected-stdout:
EOFI EOFI
)|tr u x); } )|tr u x); }
function reread_IOWRITE_noIOCLOB_IOHERE_IOSKIP { function reread_IOWRITE_noIOCLOB_IOHERE_IOSKIP {
x=$(( cat >bar <<-EOFI x=$(( \cat >bar <<-EOFI
foo foo
EOFI EOFI
) | tr u x ) ) | \tr u x )
} }
inline_IORDWR_IODUP() { inline_IORDWR_IODUP() {
sh 1<>/dev/console 0<&1 2>&1 sh 1<>/dev/console 0<&1 2>&1
} }
inline_IORDWR_IODUP() { inline_IORDWR_IODUP() {
sh 1<>/dev/console <&1 2>&1 \sh 1<>/dev/console <&1 2>&1
} }
function comsub_IORDWR_IODUP { x=$( function comsub_IORDWR_IODUP { x=$(
sh 1<>/dev/console 0<&1 2>&1 sh 1<>/dev/console 0<&1 2>&1
); } ); }
function comsub_IORDWR_IODUP { function comsub_IORDWR_IODUP {
x=$(sh 1<>/dev/console <&1 2>&1 ) x=$(\sh 1<>/dev/console <&1 2>&1 )
} }
function reread_IORDWR_IODUP { x=$(( function reread_IORDWR_IODUP { x=$((
sh 1<>/dev/console 0<&1 2>&1 sh 1<>/dev/console 0<&1 2>&1
)|tr u x); } )|tr u x); }
function reread_IORDWR_IODUP { function reread_IORDWR_IODUP {
x=$(( sh 1<>/dev/console <&1 2>&1 ) | tr u x ) x=$(( \sh 1<>/dev/console <&1 2>&1 ) | \tr u x )
} }
inline_COMSUB_EXPRSUB_FUNSUB_VALSUB() { inline_COMSUB_EXPRSUB_FUNSUB_VALSUB() {
echo $(true) $((1+ 2)) ${ :;} ${| REPLY=x;} echo $(true) $((1+ 2)) ${ :;} ${| REPLY=x;}
} }
inline_COMSUB_EXPRSUB_FUNSUB_VALSUB() { inline_COMSUB_EXPRSUB_FUNSUB_VALSUB() {
echo $(true ) $((1+ 2)) ${ : ;} ${|REPLY=x ;} \echo $(\true ) $((1+ 2)) ${ : ;} ${|REPLY=x ;}
} }
function comsub_COMSUB_EXPRSUB_FUNSUB_VALSUB { x=$( function comsub_COMSUB_EXPRSUB_FUNSUB_VALSUB { x=$(
echo $(true) $((1+ 2)) ${ :;} ${| REPLY=x;} echo $(true) $((1+ 2)) ${ :;} ${| REPLY=x;}
); } ); }
function comsub_COMSUB_EXPRSUB_FUNSUB_VALSUB { function comsub_COMSUB_EXPRSUB_FUNSUB_VALSUB {
x=$(echo $(true ) $((1+ 2)) ${ : ;} ${|REPLY=x ;} ) x=$(\echo $(\true ) $((1+ 2)) ${ : ;} ${|REPLY=x ;} )
} }
function reread_COMSUB_EXPRSUB_FUNSUB_VALSUB { x=$(( function reread_COMSUB_EXPRSUB_FUNSUB_VALSUB { x=$((
echo $(true) $((1+ 2)) ${ :;} ${| REPLY=x;} echo $(true) $((1+ 2)) ${ :;} ${| REPLY=x;}
)|tr u x); } )|tr u x); }
function reread_COMSUB_EXPRSUB_FUNSUB_VALSUB { function reread_COMSUB_EXPRSUB_FUNSUB_VALSUB {
x=$(( echo $(true ) $((1+ 2)) ${ : ;} ${|REPLY=x ;} ) | tr u x ) x=$(( \echo $(\true ) $((1+ 2)) ${ : ;} ${|REPLY=x ;} ) | \tr u x )
} }
inline_QCHAR_OQUOTE_CQUOTE() { inline_QCHAR_OQUOTE_CQUOTE() {
echo fo\ob\"a\`r\'b\$az echo fo\ob\"a\`r\'b\$az
@ -11407,9 +11439,9 @@ expected-stdout:
echo 'fo\ob\"a\`r'\''b\$az' echo 'fo\ob\"a\`r'\''b\$az'
} }
inline_QCHAR_OQUOTE_CQUOTE() { inline_QCHAR_OQUOTE_CQUOTE() {
echo fo\ob\"a\`r\'b\$az \echo fo\ob\"a\`r\'b\$az
echo "fo\ob\"a\`r\'b\$az" \echo "fo\ob\"a\`r\'b\$az"
echo "fo\\ob\\\"a\\\`r"\'"b\\\$az" \echo "fo\\ob\\\"a\\\`r"\'"b\\\$az"
} }
function comsub_QCHAR_OQUOTE_CQUOTE { x=$( function comsub_QCHAR_OQUOTE_CQUOTE { x=$(
echo fo\ob\"a\`r\'b\$az echo fo\ob\"a\`r\'b\$az
@ -11417,7 +11449,7 @@ expected-stdout:
echo 'fo\ob\"a\`r'\''b\$az' echo 'fo\ob\"a\`r'\''b\$az'
); } ); }
function comsub_QCHAR_OQUOTE_CQUOTE { function comsub_QCHAR_OQUOTE_CQUOTE {
x=$(echo fo\ob\"a\`r\'b\$az ; echo "fo\ob\"a\`r\'b\$az" ; echo "fo\\ob\\\"a\\\`r"\'"b\\\$az" ) x=$(\echo fo\ob\"a\`r\'b\$az ; \echo "fo\ob\"a\`r\'b\$az" ; \echo "fo\\ob\\\"a\\\`r"\'"b\\\$az" )
} }
function reread_QCHAR_OQUOTE_CQUOTE { x=$(( function reread_QCHAR_OQUOTE_CQUOTE { x=$((
echo fo\ob\"a\`r\'b\$az echo fo\ob\"a\`r\'b\$az
@ -11425,7 +11457,7 @@ expected-stdout:
echo 'fo\ob\"a\`r'\''b\$az' echo 'fo\ob\"a\`r'\''b\$az'
)|tr u x); } )|tr u x); }
function reread_QCHAR_OQUOTE_CQUOTE { function reread_QCHAR_OQUOTE_CQUOTE {
x=$(( echo fo\ob\"a\`r\'b\$az ; echo "fo\ob\"a\`r\'b\$az" ; echo "fo\\ob\\\"a\\\`r"\'"b\\\$az" ) | tr u x ) x=$(( \echo fo\ob\"a\`r\'b\$az ; \echo "fo\ob\"a\`r\'b\$az" ; \echo "fo\\ob\\\"a\\\`r"\'"b\\\$az" ) | \tr u x )
} }
inline_OSUBST_CSUBST_OPAT_SPAT_CPAT() { inline_OSUBST_CSUBST_OPAT_SPAT_CPAT() {
[[ ${foo#bl\(u\)b} = @(bar|baz) ]] [[ ${foo#bl\(u\)b} = @(bar|baz) ]]
@ -11443,7 +11475,7 @@ expected-stdout:
[[ ${foo#bl\(u\)b} = @(bar|baz) ]] [[ ${foo#bl\(u\)b} = @(bar|baz) ]]
)|tr u x); } )|tr u x); }
function reread_OSUBST_CSUBST_OPAT_SPAT_CPAT { function reread_OSUBST_CSUBST_OPAT_SPAT_CPAT {
x=$(( [[ ${foo#bl\(u\)b} = @(bar|baz) ]] ) | tr u x ) x=$(( [[ ${foo#bl\(u\)b} = @(bar|baz) ]] ) | \tr u x )
} }
inline_heredoc_closed() { inline_heredoc_closed() {
x=$(cat <<EOFN x=$(cat <<EOFN
@ -11451,11 +11483,11 @@ expected-stdout:
EOFN); echo $x EOFN); echo $x
} }
inline_heredoc_closed() { inline_heredoc_closed() {
x=$(cat <<EOFN x=$(\cat <<EOFN
note there must be no space between EOFN and ) note there must be no space between EOFN and )
EOFN EOFN
) )
echo $x \echo $x
} }
function comsub_heredoc_closed { x=$( function comsub_heredoc_closed { x=$(
x=$(cat <<EOFN x=$(cat <<EOFN
@ -11463,10 +11495,10 @@ expected-stdout:
EOFN); echo $x EOFN); echo $x
); } ); }
function comsub_heredoc_closed { function comsub_heredoc_closed {
x=$(x=$(cat <<EOFN x=$(x=$(\cat <<EOFN
note there must be no space between EOFN and ) note there must be no space between EOFN and )
EOFN EOFN
) ; echo $x ) ) ; \echo $x )
} }
function reread_heredoc_closed { x=$(( function reread_heredoc_closed { x=$((
x=$(cat <<EOFN x=$(cat <<EOFN
@ -11474,10 +11506,10 @@ expected-stdout:
EOFN); echo $x EOFN); echo $x
)|tr u x); } )|tr u x); }
function reread_heredoc_closed { function reread_heredoc_closed {
x=$(( x=$(cat <<EOFN x=$(( x=$(\cat <<EOFN
note there must be no space between EOFN and ) note there must be no space between EOFN and )
EOFN EOFN
) ; echo $x ) | tr u x ) ) ; \echo $x ) | \tr u x )
} }
inline_heredoc_space() { inline_heredoc_space() {
x=$(cat <<EOFN\ x=$(cat <<EOFN\
@ -11485,11 +11517,11 @@ expected-stdout:
EOFN ); echo $x EOFN ); echo $x
} }
inline_heredoc_space() { inline_heredoc_space() {
x=$(cat <<EOFN\ x=$(\cat <<EOFN\
note the space between EOFN and ) is actually part of the here document marker note the space between EOFN and ) is actually part of the here document marker
EOFN EOFN
) )
echo $x \echo $x
} }
function comsub_heredoc_space { x=$( function comsub_heredoc_space { x=$(
x=$(cat <<EOFN\ x=$(cat <<EOFN\
@ -11497,10 +11529,10 @@ expected-stdout:
EOFN ); echo $x EOFN ); echo $x
); } ); }
function comsub_heredoc_space { function comsub_heredoc_space {
x=$(x=$(cat <<EOFN\ x=$(x=$(\cat <<EOFN\
note the space between EOFN and ) is actually part of the here document marker note the space between EOFN and ) is actually part of the here document marker
EOFN EOFN
) ; echo $x ) ) ; \echo $x )
} }
function reread_heredoc_space { x=$(( function reread_heredoc_space { x=$((
x=$(cat <<EOFN\ x=$(cat <<EOFN\
@ -11508,10 +11540,10 @@ expected-stdout:
EOFN ); echo $x EOFN ); echo $x
)|tr u x); } )|tr u x); }
function reread_heredoc_space { function reread_heredoc_space {
x=$(( x=$(cat <<EOFN\ x=$(( x=$(\cat <<EOFN\
note the space between EOFN and ) is actually part of the here document marker note the space between EOFN and ) is actually part of the here document marker
EOFN EOFN
) ; echo $x ) | tr u x ) ) ; \echo $x ) | \tr u x )
} }
inline_patch_motd() { inline_patch_motd() {
x=$(sysctl -n kern.version | sed 1q) x=$(sysctl -n kern.version | sed 1q)
@ -11530,8 +11562,8 @@ expected-stdout:
fi fi
} }
inline_patch_motd() { inline_patch_motd() {
x=$(sysctl -n kern.version | sed 1q ) x=$(\sysctl -n kern.version | \sed 1q )
[[ -s /etc/motd && "$([[ "$(head -1 /etc/motd )" != $x ]] && ed -s /etc/motd 2>&1 <<-EOF [[ -s /etc/motd && "$([[ "$(\head -1 /etc/motd )" != $x ]] && \ed -s /etc/motd 2>&1 <<-EOF
1,/^\$/d 1,/^\$/d
0a 0a
$x $x
@ -11539,11 +11571,11 @@ expected-stdout:
. .
wq wq
EOF EOF
)" = @(?) ]] && rm -f /etc/motd )" = @(?) ]] && \rm -f /etc/motd
if [[ ! -s /etc/motd ]] if [[ ! -s /etc/motd ]]
then then
install -c -o root -g wheel -m 664 /dev/null /etc/motd \install -c -o root -g wheel -m 664 /dev/null /etc/motd
print -- "$x\n" >/etc/motd \print -- "$x\n" >/etc/motd
fi fi
} }
function comsub_patch_motd { x=$( function comsub_patch_motd { x=$(
@ -11563,7 +11595,7 @@ expected-stdout:
fi fi
); } ); }
function comsub_patch_motd { function comsub_patch_motd {
x=$(x=$(sysctl -n kern.version | sed 1q ) ; [[ -s /etc/motd && "$([[ "$(head -1 /etc/motd )" != $x ]] && ed -s /etc/motd 2>&1 <<-EOF x=$(x=$(\sysctl -n kern.version | \sed 1q ) ; [[ -s /etc/motd && "$([[ "$(\head -1 /etc/motd )" != $x ]] && \ed -s /etc/motd 2>&1 <<-EOF
1,/^\$/d 1,/^\$/d
0a 0a
$x $x
@ -11571,7 +11603,7 @@ expected-stdout:
. .
wq wq
EOF EOF
)" = @(?) ]] && rm -f /etc/motd ; if [[ ! -s /etc/motd ]] ; then install -c -o root -g wheel -m 664 /dev/null /etc/motd ; print -- "$x\n" >/etc/motd ; fi ) )" = @(?) ]] && \rm -f /etc/motd ; if [[ ! -s /etc/motd ]] ; then \install -c -o root -g wheel -m 664 /dev/null /etc/motd ; \print -- "$x\n" >/etc/motd ; fi )
} }
function reread_patch_motd { x=$(( function reread_patch_motd { x=$((
x=$(sysctl -n kern.version | sed 1q) x=$(sysctl -n kern.version | sed 1q)
@ -11590,7 +11622,7 @@ expected-stdout:
fi fi
)|tr u x); } )|tr u x); }
function reread_patch_motd { function reread_patch_motd {
x=$(( x=$(sysctl -n kern.version | sed 1q ) ; [[ -s /etc/motd && "$([[ "$(head -1 /etc/motd )" != $x ]] && ed -s /etc/motd 2>&1 <<-EOF x=$(( x=$(\sysctl -n kern.version | \sed 1q ) ; [[ -s /etc/motd && "$([[ "$(\head -1 /etc/motd )" != $x ]] && \ed -s /etc/motd 2>&1 <<-EOF
1,/^\$/d 1,/^\$/d
0a 0a
$x $x
@ -11598,7 +11630,7 @@ expected-stdout:
. .
wq wq
EOF EOF
)" = @(?) ]] && rm -f /etc/motd ; if [[ ! -s /etc/motd ]] ; then install -c -o root -g wheel -m 664 /dev/null /etc/motd ; print -- "$x\n" >/etc/motd ; fi ) | tr u x ) )" = @(?) ]] && \rm -f /etc/motd ; if [[ ! -s /etc/motd ]] ; then \install -c -o root -g wheel -m 664 /dev/null /etc/motd ; \print -- "$x\n" >/etc/motd ; fi ) | \tr u x )
} }
inline_wdarrassign() { inline_wdarrassign() {
case x in case x in
@ -11627,7 +11659,7 @@ expected-stdout:
esac esac
)|tr u x); } )|tr u x); }
function reread_wdarrassign { function reread_wdarrassign {
x=$(( case x in (x) a+=b ; \\builtin set -A c+ -- d e ;; esac ) | tr u x ) x=$(( case x in (x) a+=b ; \\builtin set -A c+ -- d e ;; esac ) | \tr u x )
} }
--- ---
name: comsub-torture-io name: comsub-torture-io
@ -11694,56 +11726,56 @@ expected-stdout:
vara=1 varb='2 3' cmd arg1 $arg2 "$arg3 4" >&3 vara=1 varb='2 3' cmd arg1 $arg2 "$arg3 4" >&3
} }
inline_TCOM() { inline_TCOM() {
vara=1 varb="2 3" cmd arg1 $arg2 "$arg3 4" >&3 vara=1 varb="2 3" \cmd arg1 $arg2 "$arg3 4" >&3
} }
function comsub_TCOM { x=$( function comsub_TCOM { x=$(
vara=1 varb='2 3' cmd arg1 $arg2 "$arg3 4" >&3 vara=1 varb='2 3' cmd arg1 $arg2 "$arg3 4" >&3
); } ); }
function comsub_TCOM { function comsub_TCOM {
x=$(vara=1 varb="2 3" cmd arg1 $arg2 "$arg3 4" >&3 ) x=$(vara=1 varb="2 3" \cmd arg1 $arg2 "$arg3 4" >&3 )
} }
function reread_TCOM { x=$(( function reread_TCOM { x=$((
vara=1 varb='2 3' cmd arg1 $arg2 "$arg3 4" >&3 vara=1 varb='2 3' cmd arg1 $arg2 "$arg3 4" >&3
)|tr u x); } )|tr u x); }
function reread_TCOM { function reread_TCOM {
x=$(( vara=1 varb="2 3" cmd arg1 $arg2 "$arg3 4" >&3 ) | tr u x ) x=$(( vara=1 varb="2 3" \cmd arg1 $arg2 "$arg3 4" >&3 ) | \tr u x )
} }
inline_TPAREN_TPIPE_TLIST() { inline_TPAREN_TPIPE_TLIST() {
(echo $foo | tr -dc 0-9 >&3; echo >&3) >&3 (echo $foo | tr -dc 0-9 >&3; echo >&3) >&3
} }
inline_TPAREN_TPIPE_TLIST() { inline_TPAREN_TPIPE_TLIST() {
( echo $foo | tr -dc 0-9 >&3 ( \echo $foo | \tr -dc 0-9 >&3
echo >&3 ) >&3 \echo >&3 ) >&3
} }
function comsub_TPAREN_TPIPE_TLIST { x=$( function comsub_TPAREN_TPIPE_TLIST { x=$(
(echo $foo | tr -dc 0-9 >&3; echo >&3) >&3 (echo $foo | tr -dc 0-9 >&3; echo >&3) >&3
); } ); }
function comsub_TPAREN_TPIPE_TLIST { function comsub_TPAREN_TPIPE_TLIST {
x=$(( echo $foo | tr -dc 0-9 >&3 ; echo >&3 ) >&3 ) x=$(( \echo $foo | \tr -dc 0-9 >&3 ; \echo >&3 ) >&3 )
} }
function reread_TPAREN_TPIPE_TLIST { x=$(( function reread_TPAREN_TPIPE_TLIST { x=$((
(echo $foo | tr -dc 0-9 >&3; echo >&3) >&3 (echo $foo | tr -dc 0-9 >&3; echo >&3) >&3
)|tr u x); } )|tr u x); }
function reread_TPAREN_TPIPE_TLIST { function reread_TPAREN_TPIPE_TLIST {
x=$(( ( echo $foo | tr -dc 0-9 >&3 ; echo >&3 ) >&3 ) | tr u x ) x=$(( ( \echo $foo | \tr -dc 0-9 >&3 ; \echo >&3 ) >&3 ) | \tr u x )
} }
inline_TAND_TOR() { inline_TAND_TOR() {
cmd >&3 && >&3 echo ja || echo >&3 nein cmd >&3 && >&3 echo ja || echo >&3 nein
} }
inline_TAND_TOR() { inline_TAND_TOR() {
cmd >&3 && echo ja >&3 || echo nein >&3 \cmd >&3 && \echo ja >&3 || \echo nein >&3
} }
function comsub_TAND_TOR { x=$( function comsub_TAND_TOR { x=$(
cmd >&3 && >&3 echo ja || echo >&3 nein cmd >&3 && >&3 echo ja || echo >&3 nein
); } ); }
function comsub_TAND_TOR { function comsub_TAND_TOR {
x=$(cmd >&3 && echo ja >&3 || echo nein >&3 ) x=$(\cmd >&3 && \echo ja >&3 || \echo nein >&3 )
} }
function reread_TAND_TOR { x=$(( function reread_TAND_TOR { x=$((
cmd >&3 && >&3 echo ja || echo >&3 nein cmd >&3 && >&3 echo ja || echo >&3 nein
)|tr u x); } )|tr u x); }
function reread_TAND_TOR { function reread_TAND_TOR {
x=$(( cmd >&3 && echo ja >&3 || echo nein >&3 ) | tr u x ) x=$(( \cmd >&3 && \echo ja >&3 || \echo nein >&3 ) | \tr u x )
} }
inline_TSELECT() { inline_TSELECT() {
select file in *; do echo "<$file>" ; break >&3 ; done >&3 select file in *; do echo "<$file>" ; break >&3 ; done >&3
@ -11751,21 +11783,21 @@ expected-stdout:
inline_TSELECT() { inline_TSELECT() {
select file in * select file in *
do do
echo "<$file>" \echo "<$file>"
break >&3 \break >&3
done >&3 done >&3
} }
function comsub_TSELECT { x=$( function comsub_TSELECT { x=$(
select file in *; do echo "<$file>" ; break >&3 ; done >&3 select file in *; do echo "<$file>" ; break >&3 ; done >&3
); } ); }
function comsub_TSELECT { function comsub_TSELECT {
x=$(select file in * ; do echo "<$file>" ; break >&3 ; done >&3 ) x=$(select file in * ; do \echo "<$file>" ; \break >&3 ; done >&3 )
} }
function reread_TSELECT { x=$(( function reread_TSELECT { x=$((
select file in *; do echo "<$file>" ; break >&3 ; done >&3 select file in *; do echo "<$file>" ; break >&3 ; done >&3
)|tr u x); } )|tr u x); }
function reread_TSELECT { function reread_TSELECT {
x=$(( select file in * ; do echo "<$file>" ; break >&3 ; done >&3 ) | tr u x ) x=$(( select file in * ; do \echo "<$file>" ; \break >&3 ; done >&3 ) | \tr u x )
} }
inline_TFOR_TTIME() { inline_TFOR_TTIME() {
for i in {1,2,3} ; do time >&3 echo $i ; done >&3 for i in {1,2,3} ; do time >&3 echo $i ; done >&3
@ -11773,20 +11805,20 @@ expected-stdout:
inline_TFOR_TTIME() { inline_TFOR_TTIME() {
for i in {1,2,3} for i in {1,2,3}
do do
time echo $i >&3 time \echo $i >&3
done >&3 done >&3
} }
function comsub_TFOR_TTIME { x=$( function comsub_TFOR_TTIME { x=$(
for i in {1,2,3} ; do time >&3 echo $i ; done >&3 for i in {1,2,3} ; do time >&3 echo $i ; done >&3
); } ); }
function comsub_TFOR_TTIME { function comsub_TFOR_TTIME {
x=$(for i in {1,2,3} ; do time echo $i >&3 ; done >&3 ) x=$(for i in {1,2,3} ; do time \echo $i >&3 ; done >&3 )
} }
function reread_TFOR_TTIME { x=$(( function reread_TFOR_TTIME { x=$((
for i in {1,2,3} ; do time >&3 echo $i ; done >&3 for i in {1,2,3} ; do time >&3 echo $i ; done >&3
)|tr u x); } )|tr u x); }
function reread_TFOR_TTIME { function reread_TFOR_TTIME {
x=$(( for i in {1,2,3} ; do time echo $i >&3 ; done >&3 ) | tr u x ) x=$(( for i in {1,2,3} ; do time \echo $i >&3 ; done >&3 ) | \tr u x )
} }
inline_TCASE() { inline_TCASE() {
case $foo in 1) echo eins >&3;& 2) echo zwei >&3 ;| *) echo kann net bis drei zählen >&3;; esac >&3 case $foo in 1) echo eins >&3;& 2) echo zwei >&3 ;| *) echo kann net bis drei zählen >&3;; esac >&3
@ -11794,13 +11826,13 @@ expected-stdout:
inline_TCASE() { inline_TCASE() {
case $foo in case $foo in
(1) (1)
echo eins >&3 \echo eins >&3
;& ;&
(2) (2)
echo zwei >&3 \echo zwei >&3
;| ;|
(*) (*)
echo kann net bis drei zählen >&3 \echo kann net bis drei zählen >&3
;; ;;
esac >&3 esac >&3
} }
@ -11808,13 +11840,13 @@ expected-stdout:
case $foo in 1) echo eins >&3;& 2) echo zwei >&3 ;| *) echo kann net bis drei zählen >&3;; esac >&3 case $foo in 1) echo eins >&3;& 2) echo zwei >&3 ;| *) echo kann net bis drei zählen >&3;; esac >&3
); } ); }
function comsub_TCASE { function comsub_TCASE {
x=$(case $foo in (1) echo eins >&3 ;& (2) echo zwei >&3 ;| (*) echo kann net bis drei zählen >&3 ;; esac >&3 ) x=$(case $foo in (1) \echo eins >&3 ;& (2) \echo zwei >&3 ;| (*) \echo kann net bis drei zählen >&3 ;; esac >&3 )
} }
function reread_TCASE { x=$(( function reread_TCASE { x=$((
case $foo in 1) echo eins >&3;& 2) echo zwei >&3 ;| *) echo kann net bis drei zählen >&3;; esac >&3 case $foo in 1) echo eins >&3;& 2) echo zwei >&3 ;| *) echo kann net bis drei zählen >&3;; esac >&3
)|tr u x); } )|tr u x); }
function reread_TCASE { function reread_TCASE {
x=$(( case $foo in (1) echo eins >&3 ;& (2) echo zwei >&3 ;| (*) echo kann net bis drei zählen >&3 ;; esac >&3 ) | tr u x ) x=$(( case $foo in (1) \echo eins >&3 ;& (2) \echo zwei >&3 ;| (*) \echo kann net bis drei zählen >&3 ;; esac >&3 ) | \tr u x )
} }
inline_TIF_TBANG_TDBRACKET_TELIF() { inline_TIF_TBANG_TDBRACKET_TELIF() {
if ! [[ 1 = 1 ]] >&3 ; then echo eins; elif [[ 1 = 2 ]] >&3; then echo zwei ;else echo drei; fi >&3 if ! [[ 1 = 1 ]] >&3 ; then echo eins; elif [[ 1 = 2 ]] >&3; then echo zwei ;else echo drei; fi >&3
@ -11822,25 +11854,25 @@ expected-stdout:
inline_TIF_TBANG_TDBRACKET_TELIF() { inline_TIF_TBANG_TDBRACKET_TELIF() {
if ! [[ 1 = 1 ]] >&3 if ! [[ 1 = 1 ]] >&3
then then
echo eins \echo eins
elif [[ 1 = 2 ]] >&3 elif [[ 1 = 2 ]] >&3
then then
echo zwei \echo zwei
else else
echo drei \echo drei
fi >&3 fi >&3
} }
function comsub_TIF_TBANG_TDBRACKET_TELIF { x=$( function comsub_TIF_TBANG_TDBRACKET_TELIF { x=$(
if ! [[ 1 = 1 ]] >&3 ; then echo eins; elif [[ 1 = 2 ]] >&3; then echo zwei ;else echo drei; fi >&3 if ! [[ 1 = 1 ]] >&3 ; then echo eins; elif [[ 1 = 2 ]] >&3; then echo zwei ;else echo drei; fi >&3
); } ); }
function comsub_TIF_TBANG_TDBRACKET_TELIF { function comsub_TIF_TBANG_TDBRACKET_TELIF {
x=$(if ! [[ 1 = 1 ]] >&3 ; then echo eins ; elif [[ 1 = 2 ]] >&3 ; then echo zwei ; else echo drei ; fi >&3 ) x=$(if ! [[ 1 = 1 ]] >&3 ; then \echo eins ; elif [[ 1 = 2 ]] >&3 ; then \echo zwei ; else \echo drei ; fi >&3 )
} }
function reread_TIF_TBANG_TDBRACKET_TELIF { x=$(( function reread_TIF_TBANG_TDBRACKET_TELIF { x=$((
if ! [[ 1 = 1 ]] >&3 ; then echo eins; elif [[ 1 = 2 ]] >&3; then echo zwei ;else echo drei; fi >&3 if ! [[ 1 = 1 ]] >&3 ; then echo eins; elif [[ 1 = 2 ]] >&3; then echo zwei ;else echo drei; fi >&3
)|tr u x); } )|tr u x); }
function reread_TIF_TBANG_TDBRACKET_TELIF { function reread_TIF_TBANG_TDBRACKET_TELIF {
x=$(( if ! [[ 1 = 1 ]] >&3 ; then echo eins ; elif [[ 1 = 2 ]] >&3 ; then echo zwei ; else echo drei ; fi >&3 ) | tr u x ) x=$(( if ! [[ 1 = 1 ]] >&3 ; then \echo eins ; elif [[ 1 = 2 ]] >&3 ; then \echo zwei ; else \echo drei ; fi >&3 ) | \tr u x )
} }
inline_TWHILE() { inline_TWHILE() {
i=1; while (( i < 10 )) >&3; do echo $i; let ++i; done >&3 i=1; while (( i < 10 )) >&3; do echo $i; let ++i; done >&3
@ -11851,21 +11883,21 @@ expected-stdout:
\\builtin let " i < 10 " \\builtin let " i < 10 "
} >&3 } >&3
do do
echo $i \echo $i
let ++i \let ++i
done >&3 done >&3
} }
function comsub_TWHILE { x=$( function comsub_TWHILE { x=$(
i=1; while (( i < 10 )) >&3; do echo $i; let ++i; done >&3 i=1; while (( i < 10 )) >&3; do echo $i; let ++i; done >&3
); } ); }
function comsub_TWHILE { function comsub_TWHILE {
x=$(i=1 ; while { \\builtin let " i < 10 " ; } >&3 ; do echo $i ; let ++i ; done >&3 ) x=$(i=1 ; while { \\builtin let " i < 10 " ; } >&3 ; do \echo $i ; \let ++i ; done >&3 )
} }
function reread_TWHILE { x=$(( function reread_TWHILE { x=$((
i=1; while (( i < 10 )) >&3; do echo $i; let ++i; done >&3 i=1; while (( i < 10 )) >&3; do echo $i; let ++i; done >&3
)|tr u x); } )|tr u x); }
function reread_TWHILE { function reread_TWHILE {
x=$(( i=1 ; while { \\builtin let " i < 10 " ; } >&3 ; do echo $i ; let ++i ; done >&3 ) | tr u x ) x=$(( i=1 ; while { \\builtin let " i < 10 " ; } >&3 ; do \echo $i ; \let ++i ; done >&3 ) | \tr u x )
} }
inline_TUNTIL() { inline_TUNTIL() {
i=10; until (( !--i )) >&3 ; do echo $i; done >&3 i=10; until (( !--i )) >&3 ; do echo $i; done >&3
@ -11876,39 +11908,39 @@ expected-stdout:
\\builtin let " !--i " \\builtin let " !--i "
} >&3 } >&3
do do
echo $i \echo $i
done >&3 done >&3
} }
function comsub_TUNTIL { x=$( function comsub_TUNTIL { x=$(
i=10; until (( !--i )) >&3 ; do echo $i; done >&3 i=10; until (( !--i )) >&3 ; do echo $i; done >&3
); } ); }
function comsub_TUNTIL { function comsub_TUNTIL {
x=$(i=10 ; until { \\builtin let " !--i " ; } >&3 ; do echo $i ; done >&3 ) x=$(i=10 ; until { \\builtin let " !--i " ; } >&3 ; do \echo $i ; done >&3 )
} }
function reread_TUNTIL { x=$(( function reread_TUNTIL { x=$((
i=10; until (( !--i )) >&3 ; do echo $i; done >&3 i=10; until (( !--i )) >&3 ; do echo $i; done >&3
)|tr u x); } )|tr u x); }
function reread_TUNTIL { function reread_TUNTIL {
x=$(( i=10 ; until { \\builtin let " !--i " ; } >&3 ; do echo $i ; done >&3 ) | tr u x ) x=$(( i=10 ; until { \\builtin let " !--i " ; } >&3 ; do \echo $i ; done >&3 ) | \tr u x )
} }
inline_TCOPROC() { inline_TCOPROC() {
cat * >&3 |& >&3 ls cat * >&3 |& >&3 ls
} }
inline_TCOPROC() { inline_TCOPROC() {
cat * >&3 |& \cat * >&3 |&
ls >&3 \ls >&3
} }
function comsub_TCOPROC { x=$( function comsub_TCOPROC { x=$(
cat * >&3 |& >&3 ls cat * >&3 |& >&3 ls
); } ); }
function comsub_TCOPROC { function comsub_TCOPROC {
x=$(cat * >&3 |& ls >&3 ) x=$(\cat * >&3 |& \ls >&3 )
} }
function reread_TCOPROC { x=$(( function reread_TCOPROC { x=$((
cat * >&3 |& >&3 ls cat * >&3 |& >&3 ls
)|tr u x); } )|tr u x); }
function reread_TCOPROC { function reread_TCOPROC {
x=$(( cat * >&3 |& ls >&3 ) | tr u x ) x=$(( \cat * >&3 |& \ls >&3 ) | \tr u x )
} }
inline_TFUNCT_TBRACE_TASYNC() { inline_TFUNCT_TBRACE_TASYNC() {
function korn { echo eins; echo >&3 zwei ; } function korn { echo eins; echo >&3 zwei ; }
@ -11916,11 +11948,11 @@ expected-stdout:
} }
inline_TFUNCT_TBRACE_TASYNC() { inline_TFUNCT_TBRACE_TASYNC() {
function korn { function korn {
echo eins \echo eins
echo zwei >&3 \echo zwei >&3
} }
bourne() { bourne() {
logger * >&3 & \logger * >&3 &
} }
} }
function comsub_TFUNCT_TBRACE_TASYNC { x=$( function comsub_TFUNCT_TBRACE_TASYNC { x=$(
@ -11928,32 +11960,32 @@ expected-stdout:
bourne () { logger * >&3 & } bourne () { logger * >&3 & }
); } ); }
function comsub_TFUNCT_TBRACE_TASYNC { function comsub_TFUNCT_TBRACE_TASYNC {
x=$(function korn { echo eins ; echo zwei >&3 ; } ; bourne() { logger * >&3 & } ) x=$(function korn { \echo eins ; \echo zwei >&3 ; } ; bourne() { \logger * >&3 & } )
} }
function reread_TFUNCT_TBRACE_TASYNC { x=$(( function reread_TFUNCT_TBRACE_TASYNC { x=$((
function korn { echo eins; echo >&3 zwei ; } function korn { echo eins; echo >&3 zwei ; }
bourne () { logger * >&3 & } bourne () { logger * >&3 & }
)|tr u x); } )|tr u x); }
function reread_TFUNCT_TBRACE_TASYNC { function reread_TFUNCT_TBRACE_TASYNC {
x=$(( function korn { echo eins ; echo zwei >&3 ; } ; bourne() { logger * >&3 & } ) | tr u x ) x=$(( function korn { \echo eins ; \echo zwei >&3 ; } ; bourne() { \logger * >&3 & } ) | \tr u x )
} }
inline_COMSUB_EXPRSUB() { inline_COMSUB_EXPRSUB() {
echo $(true >&3) $((1+ 2)) echo $(true >&3) $((1+ 2))
} }
inline_COMSUB_EXPRSUB() { inline_COMSUB_EXPRSUB() {
echo $(true >&3 ) $((1+ 2)) \echo $(\true >&3 ) $((1+ 2))
} }
function comsub_COMSUB_EXPRSUB { x=$( function comsub_COMSUB_EXPRSUB { x=$(
echo $(true >&3) $((1+ 2)) echo $(true >&3) $((1+ 2))
); } ); }
function comsub_COMSUB_EXPRSUB { function comsub_COMSUB_EXPRSUB {
x=$(echo $(true >&3 ) $((1+ 2)) ) x=$(\echo $(\true >&3 ) $((1+ 2)) )
} }
function reread_COMSUB_EXPRSUB { x=$(( function reread_COMSUB_EXPRSUB { x=$((
echo $(true >&3) $((1+ 2)) echo $(true >&3) $((1+ 2))
)|tr u x); } )|tr u x); }
function reread_COMSUB_EXPRSUB { function reread_COMSUB_EXPRSUB {
x=$(( echo $(true >&3 ) $((1+ 2)) ) | tr u x ) x=$(( \echo $(\true >&3 ) $((1+ 2)) ) | \tr u x )
} }
--- ---
name: funsub-1 name: funsub-1

4
edit.c
View File

@ -28,7 +28,7 @@
#ifndef MKSH_NO_CMDLINE_EDITING #ifndef MKSH_NO_CMDLINE_EDITING
__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.317 2017/04/05 22:54:51 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/edit.c,v 1.318 2017/04/06 01:59:53 tg Exp $");
/* /*
* in later versions we might use libtermcap for this, but since external * in later versions we might use libtermcap for this, but since external
@ -5554,7 +5554,7 @@ x_eval_region_helper(const char *cmd, size_t len)
if (!kshsetjmp(e->jbuf)) { if (!kshsetjmp(e->jbuf)) {
char *wds = alloc(len + 3, ATEMP); char *wds = alloc(len + 3, ATEMP);
wds[0] = FUNSUB; wds[0] = FUNASUB;
memcpy(wds + 1, cmd, len); memcpy(wds + 1, cmd, len);
wds[len + 1] = '\0'; wds[len + 1] = '\0';
wds[len + 2] = EOS; wds[len + 2] = EOS;

42
eval.c
View File

@ -23,7 +23,7 @@
#include "sh.h" #include "sh.h"
__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.200 2017/04/02 15:00:41 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/eval.c,v 1.201 2017/04/06 01:59:54 tg Exp $");
/* /*
* string expansion * string expansion
@ -301,25 +301,36 @@ expand(
word = IFS_WORD; word = IFS_WORD;
quote = st->quotew; quote = st->quotew;
continue; continue;
case COMASUB:
case COMSUB: case COMSUB:
case FUNASUB:
case FUNSUB: case FUNSUB:
case VALSUB: case VALSUB:
tilde_ok = 0; tilde_ok = 0;
if (f & DONTRUNCOMMAND) { if (f & DONTRUNCOMMAND) {
word = IFS_WORD; word = IFS_WORD;
*dp++ = '$'; *dp++ = '$';
*dp++ = c == COMSUB ? '(' : '{'; switch (c) {
if (c != COMSUB) case COMASUB:
*dp++ = c == FUNSUB ? ' ' : '|'; case COMSUB:
*dp++ = '(';
c = ')';
break;
case FUNASUB:
case FUNSUB:
case VALSUB:
*dp++ = '{';
*dp++ = c == VALSUB ? '|' : ' ';
c = '}';
break;
}
while (*sp != '\0') { while (*sp != '\0') {
Xcheck(ds, dp); Xcheck(ds, dp);
*dp++ = *sp++; *dp++ = *sp++;
} }
if (c != COMSUB) { if (c == '}')
*dp++ = ';'; *dp++ = ';';
*dp++ = '}'; *dp++ = c;
} else
*dp++ = ')';
} else { } else {
type = comsub(&x, sp, c); type = comsub(&x, sp, c);
if (type != XBASE && (f & DOBLANK)) if (type != XBASE && (f & DOBLANK))
@ -1345,17 +1356,28 @@ varsub(Expand *xp, const char *sp, const char *word,
* Run the command in $(...) and read its output. * Run the command in $(...) and read its output.
*/ */
static int static int
comsub(Expand *xp, const char *cp, int fn MKSH_A_UNUSED) comsub(Expand *xp, const char *cp, int fn)
{ {
Source *s, *sold; Source *s, *sold;
struct op *t; struct op *t;
struct shf *shf; struct shf *shf;
bool doalias = false;
uint8_t old_utfmode = UTFMODE; uint8_t old_utfmode = UTFMODE;
switch (fn) {
case COMASUB:
fn = COMSUB;
if (0)
/* FALLTHROUGH */
case FUNASUB:
fn = FUNSUB;
doalias = true;
}
s = pushs(SSTRING, ATEMP); s = pushs(SSTRING, ATEMP);
s->start = s->str = cp; s->start = s->str = cp;
sold = source; sold = source;
t = compile(s, true); t = compile(s, true, doalias);
afree(s, ATEMP); afree(s, ATEMP);
source = sold; source = sold;

26
funcs.c
View File

@ -38,7 +38,7 @@
#endif #endif
#endif #endif
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.335 2017/04/06 00:53:33 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.336 2017/04/06 01:59:55 tg Exp $");
#if HAVE_KILLPG #if HAVE_KILLPG
/* /*
@ -741,6 +741,17 @@ do_whence(const char **wp, int fcflags, bool vflag, bool iscommand)
return (rv); return (rv);
} }
bool
valid_alias_name(const char *cp)
{
while (*cp)
if (!ksh_isalias(*cp))
return (false);
else
++cp;
return (true);
}
int int
c_alias(const char **wp) c_alias(const char **wp)
{ {
@ -839,14 +850,11 @@ c_alias(const char **wp)
strndupx(xalias, alias, val++ - alias, ATEMP); strndupx(xalias, alias, val++ - alias, ATEMP);
alias = xalias; alias = xalias;
} }
newval = alias; if (!valid_alias_name(alias)) {
while (*newval) bi_errorf(Tinvname, alias, Talias);
if (!ksh_isalias(*newval)) { afree(xalias, ATEMP);
bi_errorf(Tinvname, alias, Talias); return (1);
afree(xalias, ATEMP); }
return (1);
} else
++newval;
h = hash(alias); h = hash(alias);
if (val == NULL && !tflag && !xflag) { if (val == NULL && !tflag && !xflag) {
ap = ktsearch(t, alias, h); ap = ktsearch(t, alias, h);

4
lex.c
View File

@ -23,7 +23,7 @@
#include "sh.h" #include "sh.h"
__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.233 2017/04/06 00:41:41 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/lex.c,v 1.234 2017/04/06 01:59:55 tg Exp $");
/* /*
* states while lexing word * states while lexing word
@ -532,7 +532,7 @@ yylex(int cf)
case '`': case '`':
subst_gravis: subst_gravis:
PUSH_STATE(SBQUOTE); PUSH_STATE(SBQUOTE);
*wp++ = COMSUB; *wp++ = COMASUB;
/* /*
* We need to know whether we are within double * We need to know whether we are within double
* quotes in order to translate \" to " within * quotes in order to translate \" to " within

4
main.c
View File

@ -34,7 +34,7 @@
#include <locale.h> #include <locale.h>
#endif #endif
__RCSID("$MirOS: src/bin/mksh/main.c,v 1.329 2017/04/02 15:00:43 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/main.c,v 1.330 2017/04/06 01:59:56 tg Exp $");
extern char **environ; extern char **environ;
@ -827,7 +827,7 @@ shell(Source * volatile s, volatile bool toplevel)
j_notify(); j_notify();
set_prompt(PS1, s); set_prompt(PS1, s);
} }
t = compile(s, sfirst); t = compile(s, sfirst, true);
if (interactive) if (interactive)
histsave(&s->line, NULL, HIST_FLUSH, true); histsave(&s->line, NULL, HIST_FLUSH, true);
sfirst = false; sfirst = false;

9
sh.h
View File

@ -175,9 +175,9 @@
#endif #endif
#ifdef EXTERN #ifdef EXTERN
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.804 2017/04/06 00:53:35 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/sh.h,v 1.805 2017/04/06 01:59:56 tg Exp $");
#endif #endif
#define MKSH_VERSION "R54 2017/04/02" #define MKSH_VERSION "R54 2017/04/05"
/* arithmetic types: C implementation */ /* arithmetic types: C implementation */
#if !HAVE_CAN_INTTYPES #if !HAVE_CAN_INTTYPES
@ -1690,6 +1690,8 @@ struct op {
#define ADELIM 12 /* arbitrary delimiter: ${foo:2:3} ${foo/bar/baz} */ #define ADELIM 12 /* arbitrary delimiter: ${foo:2:3} ${foo/bar/baz} */
#define FUNSUB 14 /* ${ foo;} substitution (NUL terminated) */ #define FUNSUB 14 /* ${ foo;} substitution (NUL terminated) */
#define VALSUB 15 /* ${|foo;} substitution (NUL terminated) */ #define VALSUB 15 /* ${|foo;} substitution (NUL terminated) */
#define COMASUB 16 /* `…` substitution (COMSUB but expand aliases) */
#define FUNASUB 17 /* function substitution but expand aliases */
/* /*
* IO redirection * IO redirection
@ -2076,6 +2078,7 @@ int c_printf(const char **);
int c_whence(const char **); int c_whence(const char **);
int c_command(const char **); int c_command(const char **);
int c_typeset(const char **); int c_typeset(const char **);
bool valid_alias_name(const char *);
int c_alias(const char **); int c_alias(const char **);
int c_unalias(const char **); int c_unalias(const char **);
int c_let(const char **); int c_let(const char **);
@ -2321,7 +2324,7 @@ ssize_t shf_vfprintf(struct shf *, const char *, va_list)
MKSH_A_FORMAT(__printf__, 2, 0); MKSH_A_FORMAT(__printf__, 2, 0);
/* syn.c */ /* syn.c */
void initkeywords(void); void initkeywords(void);
struct op *compile(Source *, bool); struct op *compile(Source *, bool, bool);
bool parse_usec(const char *, struct timeval *); bool parse_usec(const char *, struct timeval *);
char *yyrecursive(int); char *yyrecursive(int);
void yyrecursive_pop(bool); void yyrecursive_pop(bool);

126
syn.c
View File

@ -23,7 +23,7 @@
#include "sh.h" #include "sh.h"
__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.119 2017/04/06 00:41:42 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/syn.c,v 1.120 2017/04/06 01:59:57 tg Exp $");
struct nesting_state { struct nesting_state {
int start_token; /* token than began nesting (eg, FOR) */ int start_token; /* token than began nesting (eg, FOR) */
@ -35,25 +35,24 @@ struct yyrecursive_state {
struct yyrecursive_state *next; struct yyrecursive_state *next;
struct ioword **old_herep; struct ioword **old_herep;
int old_symbol; int old_symbol;
int old_salias;
int old_nesting_type; int old_nesting_type;
bool old_reject; bool old_reject;
}; };
static void yyparse(void); static void yyparse(bool);
static struct op *pipeline(int); static struct op *pipeline(int, int);
static struct op *andor(void); static struct op *andor(int);
static struct op *c_list(bool); static struct op *c_list(int, bool);
static struct ioword *synio(int); static struct ioword *synio(int);
static struct op *nested(int, int, int); static struct op *nested(int, int, int, int);
static struct op *get_command(int); static struct op *get_command(int, int);
static struct op *dogroup(void); static struct op *dogroup(int);
static struct op *thenpart(void); static struct op *thenpart(int);
static struct op *elsepart(void); static struct op *elsepart(int);
static struct op *caselist(void); static struct op *caselist(int);
static struct op *casepart(int); static struct op *casepart(int, int);
static struct op *function_body(char *, bool); static struct op *function_body(char *, int, bool);
static char **wordlist(void); static char **wordlist(int);
static struct op *block(int, struct op *, struct op *); static struct op *block(int, struct op *, struct op *);
static struct op *newtp(int); static struct op *newtp(int);
static void syntaxerr(const char *) MKSH_A_NORETURN; static void syntaxerr(const char *) MKSH_A_NORETURN;
@ -71,7 +70,6 @@ static struct nesting_state nesting; /* \n changed to ; */
static bool reject; /* token(cf) gets symbol again */ static bool reject; /* token(cf) gets symbol again */
static int symbol; /* yylex value */ static int symbol; /* yylex value */
static int sALIAS = ALIAS; /* 0 in yyrecursive */
#define REJECT (reject = true) #define REJECT (reject = true)
#define ACCEPT (reject = false) #define ACCEPT (reject = false)
@ -83,13 +81,13 @@ static const char Tcbrace[] = "}";
static const char Tesac[] = "esac"; static const char Tesac[] = "esac";
static void static void
yyparse(void) yyparse(bool doalias)
{ {
int c; int c;
ACCEPT; ACCEPT;
outtree = c_list(source->type == SSTRING); outtree = c_list(doalias ? ALIAS : 0, source->type == SSTRING);
c = tpeek(0); c = tpeek(0);
if (c == 0 && !outtree) if (c == 0 && !outtree)
outtree = newtp(TEOF); outtree = newtp(TEOF);
@ -98,14 +96,14 @@ yyparse(void)
} }
static struct op * static struct op *
pipeline(int cf) pipeline(int cf, int sALIAS)
{ {
struct op *t, *p, *tl = NULL; struct op *t, *p, *tl = NULL;
t = get_command(cf); t = get_command(cf, sALIAS);
if (t != NULL) { if (t != NULL) {
while (token(0) == '|') { while (token(0) == '|') {
if ((p = get_command(CONTIN)) == NULL) if ((p = get_command(CONTIN, sALIAS)) == NULL)
syntaxerr(NULL); syntaxerr(NULL);
if (tl == NULL) if (tl == NULL)
t = tl = block(TPIPE, t, p); t = tl = block(TPIPE, t, p);
@ -118,15 +116,15 @@ pipeline(int cf)
} }
static struct op * static struct op *
andor(void) andor(int sALIAS)
{ {
struct op *t, *p; struct op *t, *p;
int c; int c;
t = pipeline(0); t = pipeline(0, sALIAS);
if (t != NULL) { if (t != NULL) {
while ((c = token(0)) == LOGAND || c == LOGOR) { while ((c = token(0)) == LOGAND || c == LOGOR) {
if ((p = pipeline(CONTIN)) == NULL) if ((p = pipeline(CONTIN, sALIAS)) == NULL)
syntaxerr(NULL); syntaxerr(NULL);
t = block(c == LOGAND? TAND: TOR, t, p); t = block(c == LOGAND? TAND: TOR, t, p);
} }
@ -136,14 +134,14 @@ andor(void)
} }
static struct op * static struct op *
c_list(bool multi) c_list(int sALIAS, bool multi)
{ {
struct op *t = NULL, *p, *tl = NULL; struct op *t = NULL, *p, *tl = NULL;
int c; int c;
bool have_sep; bool have_sep;
while (/* CONSTCOND */ 1) { while (/* CONSTCOND */ 1) {
p = andor(); p = andor(sALIAS);
/* /*
* Token has always been read/rejected at this point, so * Token has always been read/rejected at this point, so
* we don't worry about what flags to pass token() * we don't worry about what flags to pass token()
@ -232,13 +230,13 @@ synio(int cf)
} }
static struct op * static struct op *
nested(int type, int smark, int emark) nested(int type, int smark, int emark, int sALIAS)
{ {
struct op *t; struct op *t;
struct nesting_state old_nesting; struct nesting_state old_nesting;
nesting_push(&old_nesting, smark); nesting_push(&old_nesting, smark);
t = c_list(true); t = c_list(sALIAS, true);
musthave(emark, KEYWORD|sALIAS); musthave(emark, KEYWORD|sALIAS);
nesting_pop(&old_nesting); nesting_pop(&old_nesting);
return (block(type, t, NULL)); return (block(type, t, NULL));
@ -262,7 +260,7 @@ static const char setA_cmd2[] = {
}; };
static struct op * static struct op *
get_command(int cf) get_command(int cf, int sALIAS)
{ {
struct op *t; struct op *t;
int c, iopn = 0, syniocf, lno; int c, iopn = 0, syniocf, lno;
@ -376,7 +374,8 @@ get_command(int cf)
syntaxerr(NULL); syntaxerr(NULL);
ACCEPT; ACCEPT;
musthave(/*(*/')', 0); musthave(/*(*/')', 0);
t = function_body(XPptrv(args)[0], false); t = function_body(XPptrv(args)[0],
sALIAS, false);
} }
goto Leave; goto Leave;
@ -392,13 +391,13 @@ get_command(int cf)
Subshell: Subshell:
subshell_nesting_type_saved = subshell_nesting_type; subshell_nesting_type_saved = subshell_nesting_type;
subshell_nesting_type = ')'; subshell_nesting_type = ')';
t = nested(TPAREN, '(', ')'); t = nested(TPAREN, '(', ')', sALIAS);
subshell_nesting_type = subshell_nesting_type_saved; subshell_nesting_type = subshell_nesting_type_saved;
break; break;
} }
case '{': /*}*/ case '{': /*}*/
t = nested(TBRACE, '{', '}'); t = nested(TBRACE, '{', '}', sALIAS);
break; break;
case MDPAREN: case MDPAREN:
@ -448,8 +447,8 @@ get_command(int cf)
c == FOR ? "for" : Tselect); c == FOR ? "for" : Tselect);
strdupx(t->str, ident, ATEMP); strdupx(t->str, ident, ATEMP);
nesting_push(&old_nesting, c); nesting_push(&old_nesting, c);
t->vars = wordlist(); t->vars = wordlist(sALIAS);
t->left = dogroup(); t->left = dogroup(sALIAS);
nesting_pop(&old_nesting); nesting_pop(&old_nesting);
break; break;
@ -457,8 +456,8 @@ get_command(int cf)
case UNTIL: case UNTIL:
nesting_push(&old_nesting, c); nesting_push(&old_nesting, c);
t = newtp((c == WHILE) ? TWHILE : TUNTIL); t = newtp((c == WHILE) ? TWHILE : TUNTIL);
t->left = c_list(true); t->left = c_list(sALIAS, true);
t->right = dogroup(); t->right = dogroup(sALIAS);
nesting_pop(&old_nesting); nesting_pop(&old_nesting);
break; break;
@ -467,22 +466,22 @@ get_command(int cf)
musthave(LWORD, 0); musthave(LWORD, 0);
t->str = yylval.cp; t->str = yylval.cp;
nesting_push(&old_nesting, c); nesting_push(&old_nesting, c);
t->left = caselist(); t->left = caselist(sALIAS);
nesting_pop(&old_nesting); nesting_pop(&old_nesting);
break; break;
case IF: case IF:
nesting_push(&old_nesting, c); nesting_push(&old_nesting, c);
t = newtp(TIF); t = newtp(TIF);
t->left = c_list(true); t->left = c_list(sALIAS, true);
t->right = thenpart(); t->right = thenpart(sALIAS);
musthave(FI, KEYWORD|sALIAS); musthave(FI, KEYWORD|sALIAS);
nesting_pop(&old_nesting); nesting_pop(&old_nesting);
break; break;
case BANG: case BANG:
syniocf &= ~(KEYWORD|sALIAS); syniocf &= ~(KEYWORD|sALIAS);
t = pipeline(0); t = pipeline(0, sALIAS);
if (t == NULL) if (t == NULL)
syntaxerr(NULL); syntaxerr(NULL);
t = block(TBANG, NULL, t); t = block(TBANG, NULL, t);
@ -490,7 +489,7 @@ get_command(int cf)
case TIME: case TIME:
syniocf &= ~(KEYWORD|sALIAS); syniocf &= ~(KEYWORD|sALIAS);
t = pipeline(0); t = pipeline(0, sALIAS);
if (t && t->type == TCOM) { if (t && t->type == TCOM) {
t->str = alloc(2, ATEMP); t->str = alloc(2, ATEMP);
/* TF_* flags */ /* TF_* flags */
@ -502,7 +501,7 @@ get_command(int cf)
case FUNCTION: case FUNCTION:
musthave(LWORD, 0); musthave(LWORD, 0);
t = function_body(yylval.cp, true); t = function_body(yylval.cp, sALIAS, true);
break; break;
} }
@ -541,7 +540,7 @@ get_command(int cf)
} }
static struct op * static struct op *
dogroup(void) dogroup(int sALIAS)
{ {
int c; int c;
struct op *list; struct op *list;
@ -559,40 +558,40 @@ dogroup(void)
c = '}'; c = '}';
else else
syntaxerr(NULL); syntaxerr(NULL);
list = c_list(true); list = c_list(sALIAS, true);
musthave(c, KEYWORD|sALIAS); musthave(c, KEYWORD|sALIAS);
return (list); return (list);
} }
static struct op * static struct op *
thenpart(void) thenpart(int sALIAS)
{ {
struct op *t; struct op *t;
musthave(THEN, KEYWORD|sALIAS); musthave(THEN, KEYWORD|sALIAS);
t = newtp(0); t = newtp(0);
t->left = c_list(true); t->left = c_list(sALIAS, true);
if (t->left == NULL) if (t->left == NULL)
syntaxerr(NULL); syntaxerr(NULL);
t->right = elsepart(); t->right = elsepart(sALIAS);
return (t); return (t);
} }
static struct op * static struct op *
elsepart(void) elsepart(int sALIAS)
{ {
struct op *t; struct op *t;
switch (token(KEYWORD|sALIAS|CMDASN)) { switch (token(KEYWORD|sALIAS|CMDASN)) {
case ELSE: case ELSE:
if ((t = c_list(true)) == NULL) if ((t = c_list(sALIAS, true)) == NULL)
syntaxerr(NULL); syntaxerr(NULL);
return (t); return (t);
case ELIF: case ELIF:
t = newtp(TELIF); t = newtp(TELIF);
t->left = c_list(true); t->left = c_list(sALIAS, true);
t->right = thenpart(); t->right = thenpart(sALIAS);
return (t); return (t);
default: default:
@ -602,7 +601,7 @@ elsepart(void)
} }
static struct op * static struct op *
caselist(void) caselist(int sALIAS)
{ {
struct op *t, *tl; struct op *t, *tl;
int c; int c;
@ -618,7 +617,7 @@ caselist(void)
t = tl = NULL; t = tl = NULL;
/* no ALIAS here */ /* no ALIAS here */
while ((tpeek(CONTIN|KEYWORD|ESACONLY)) != c) { while ((tpeek(CONTIN|KEYWORD|ESACONLY)) != c) {
struct op *tc = casepart(c); struct op *tc = casepart(c, sALIAS);
if (tl == NULL) if (tl == NULL)
t = tl = tc, tl->right = NULL; t = tl = tc, tl->right = NULL;
else else
@ -629,7 +628,7 @@ caselist(void)
} }
static struct op * static struct op *
casepart(int endtok) casepart(int endtok, int sALIAS)
{ {
struct op *t; struct op *t;
XPtrV ptns; XPtrV ptns;
@ -661,7 +660,7 @@ casepart(int endtok)
t->vars = (char **)XPclose(ptns); t->vars = (char **)XPclose(ptns);
musthave(')', 0); musthave(')', 0);
t->left = c_list(true); t->left = c_list(sALIAS, true);
/* initialise to default for ;; or omitted */ /* initialise to default for ;; or omitted */
t->u.charflag = ';'; t->u.charflag = ';';
@ -685,7 +684,7 @@ casepart(int endtok)
} }
static struct op * static struct op *
function_body(char *name, function_body(char *name, int sALIAS,
/* function foo { ... } vs foo() { .. } */ /* function foo { ... } vs foo() { .. } */
bool ksh_func) bool ksh_func)
{ {
@ -727,7 +726,7 @@ function_body(char *name,
t->u.ksh_func = tobool(ksh_func); t->u.ksh_func = tobool(ksh_func);
t->lineno = source->line; t->lineno = source->line;
if ((t->left = get_command(CONTIN)) == NULL) { if ((t->left = get_command(CONTIN, sALIAS)) == NULL) {
char *tv; char *tv;
/* /*
* Probably something like foo() followed by EOF or ';'. * Probably something like foo() followed by EOF or ';'.
@ -752,7 +751,7 @@ function_body(char *name,
} }
static char ** static char **
wordlist(void) wordlist(int sALIAS)
{ {
int c; int c;
XPtrV args; XPtrV args;
@ -930,7 +929,7 @@ newtp(int type)
} }
struct op * struct op *
compile(Source *s, bool skiputf8bom) compile(Source *s, bool skiputf8bom, bool doalias)
{ {
nesting.start_token = 0; nesting.start_token = 0;
nesting.start_line = 0; nesting.start_line = 0;
@ -938,7 +937,7 @@ compile(Source *s, bool skiputf8bom)
source = s; source = s;
if (skiputf8bom) if (skiputf8bom)
yyskiputf8bom(); yyskiputf8bom();
yyparse(); yyparse(doalias);
return (outtree); return (outtree);
} }
@ -1126,7 +1125,7 @@ parse_usec(const char *s, struct timeval *tv)
* a COMSUB recursively using the main shell parser and lexer * a COMSUB recursively using the main shell parser and lexer
*/ */
char * char *
yyrecursive(int subtype MKSH_A_UNUSED) yyrecursive(int subtype)
{ {
struct op *t; struct op *t;
char *cp; char *cp;
@ -1154,12 +1153,10 @@ yyrecursive(int subtype MKSH_A_UNUSED)
memcpy(ys->old_heres, heres, sizeof(heres)); memcpy(ys->old_heres, heres, sizeof(heres));
ys->old_herep = herep; ys->old_herep = herep;
herep = heres; herep = heres;
ys->old_salias = sALIAS;
sALIAS = 0;
ys->next = e->yyrecursive_statep; ys->next = e->yyrecursive_statep;
e->yyrecursive_statep = ys; e->yyrecursive_statep = ys;
/* we use TPAREN as a helper container here */ /* we use TPAREN as a helper container here */
t = nested(TPAREN, stok, etok); t = nested(TPAREN, stok, etok, ALIAS);
yyrecursive_pop(false); yyrecursive_pop(false);
/* t->left because nested(TPAREN, ...) hides our goodies there */ /* t->left because nested(TPAREN, ...) hides our goodies there */
@ -1179,7 +1176,6 @@ yyrecursive_pop(bool popall)
return; return;
e->yyrecursive_statep = ys->next; e->yyrecursive_statep = ys->next;
sALIAS = ys->old_salias;
memcpy(heres, ys->old_heres, sizeof(heres)); memcpy(heres, ys->old_heres, sizeof(heres));
herep = ys->old_herep; herep = ys->old_herep;
reject = ys->old_reject; reject = ys->old_reject;

29
tree.c
View File

@ -2,7 +2,7 @@
/*- /*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
* 2011, 2012, 2013, 2015, 2016 * 2011, 2012, 2013, 2015, 2016, 2017
* mirabilos <m@mirbsd.org> * mirabilos <m@mirbsd.org>
* *
* Provided that these terms and disclaimer and all copyright notices * Provided that these terms and disclaimer and all copyright notices
@ -23,7 +23,7 @@
#include "sh.h" #include "sh.h"
__RCSID("$MirOS: src/bin/mksh/tree.c,v 1.86 2016/07/25 00:04:48 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/tree.c,v 1.87 2017/04/06 01:59:58 tg Exp $");
#define INDENT 8 #define INDENT 8
@ -86,6 +86,15 @@ ptree(struct op *t, int indent, struct shf *shf)
shf_puts("#no-vars# ", shf); shf_puts("#no-vars# ", shf);
if (t->args) { if (t->args) {
w = t->args; w = t->args;
if (*w && **w == CHAR) {
char *cp = wdstrip(*w++, WDS_TPUTS);
if (valid_alias_name(cp))
shf_putc('\\', shf);
shf_puts(cp, shf);
shf_putc(' ', shf);
afree(cp, ATEMP);
}
while (*w) while (*w)
fptreef(shf, indent, Tf_S_, *w++); fptreef(shf, indent, Tf_S_, *w++);
} else } else
@ -352,6 +361,7 @@ wdvarput(struct shf *shf, const char *wp, int quotelevel, int opmode)
} }
shf_putc(c, shf); shf_putc(c, shf);
break; break;
case COMASUB:
case COMSUB: case COMSUB:
shf_puts("$(", shf); shf_puts("$(", shf);
cs = ")"; cs = ")";
@ -360,6 +370,7 @@ wdvarput(struct shf *shf, const char *wp, int quotelevel, int opmode)
shf_putc(c, shf); shf_putc(c, shf);
shf_puts(cs, shf); shf_puts(cs, shf);
break; break;
case FUNASUB:
case FUNSUB: case FUNSUB:
c = ' '; c = ' ';
if (0) if (0)
@ -409,8 +420,9 @@ wdvarput(struct shf *shf, const char *wp, int quotelevel, int opmode)
case SPAT: case SPAT:
c = '|'; c = '|';
if (0) if (0)
/* FALLTHROUGH */
case CPAT: case CPAT:
c = /*(*/ ')'; c = /*(*/ ')';
shf_putc(c, shf); shf_putc(c, shf);
break; break;
} }
@ -606,7 +618,9 @@ wdscan(const char *wp, int c)
case QCHAR: case QCHAR:
wp++; wp++;
break; break;
case COMASUB:
case COMSUB: case COMSUB:
case FUNASUB:
case FUNSUB: case FUNSUB:
case VALSUB: case VALSUB:
case EXPRSUB: case EXPRSUB:
@ -832,8 +846,9 @@ dumpwdvar_i(struct shf *shf, const char *wp, int quotelevel)
} }
shf_puts("ADELIM=", shf); shf_puts("ADELIM=", shf);
if (0) if (0)
/* FALLTHROUGH */
case CHAR: case CHAR:
shf_puts("CHAR=", shf); shf_puts("CHAR=", shf);
dumpchar(shf, *wp++); dumpchar(shf, *wp++);
break; break;
case QCHAR: case QCHAR:
@ -844,6 +859,9 @@ dumpwdvar_i(struct shf *shf, const char *wp, int quotelevel)
shf_putc('\\', shf); shf_putc('\\', shf);
dumpchar(shf, c); dumpchar(shf, c);
goto closeandout; goto closeandout;
case COMASUB:
shf_puts("COMASUB<", shf);
goto dumpsub;
case COMSUB: case COMSUB:
shf_puts("COMSUB<", shf); shf_puts("COMSUB<", shf);
dumpsub: dumpsub:
@ -852,6 +870,9 @@ dumpwdvar_i(struct shf *shf, const char *wp, int quotelevel)
closeandout: closeandout:
shf_putc('>', shf); shf_putc('>', shf);
break; break;
case FUNASUB:
shf_puts("FUNASUB<", shf);
goto dumpsub;
case FUNSUB: case FUNSUB:
shf_puts("FUNSUB<", shf); shf_puts("FUNSUB<", shf);
goto dumpsub; goto dumpsub;