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 -*-
#-
# 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
expected-stdout:
@(#)MIRBSD KSH R54 2017/04/02
@(#)MIRBSD KSH R54 2017/04/05
description:
Check version of shell.
stdin:
@ -39,7 +39,7 @@ name: KSH_VERSION
category: !shell:legacy-yes,!shell:textmode-yes
---
expected-stdout:
@(#)LEGACY KSH R54 2017/04/02
@(#)LEGACY KSH R54 2017/04/05
description:
Check version of legacy shell.
stdin:
@ -48,7 +48,7 @@ name: KSH_VERSION-legacy
category: !shell:legacy-no,!shell:textmode-yes
---
expected-stdout:
@(#)MIRBSD KSH R54 2017/04/02 +TEXTMODE
@(#)MIRBSD KSH R54 2017/04/05 +TEXTMODE
description:
Check version of shell.
stdin:
@ -57,7 +57,7 @@ name: KSH_VERSION-textmode
category: !shell:legacy-yes,!shell:textmode-no
---
expected-stdout:
@(#)LEGACY KSH R54 2017/04/02 +TEXTMODE
@(#)LEGACY KSH R54 2017/04/05 +TEXTMODE
description:
Check version of legacy shell.
stdin:
@ -298,6 +298,27 @@ expected-stdout:
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
description:
Check that arithmetic expressions are compound constructs
@ -2860,7 +2881,7 @@ stdin:
expected-stdout:
0
bar() {
foo 4<<-a <<-b 5<<-c
\foo 4<<-a <<-b 5<<-c
four
a
zero
@ -10903,10 +10924,10 @@ expected-stdout:
x() {
case $1 in
(u)
echo x
\echo x
;|
(*)
echo $1
\echo $1
;;
esac
}
@ -10914,6 +10935,7 @@ expected-stdout:
name: comsub-5
description:
Check COMSUB works with aliases (does not expand them twice)
and reentrancy safety
stdin:
print '#!'"$__progname"'\nfor x in "$@"; do print -r -- "$x"; done' >pfn
chmod +x pfn
@ -10922,12 +10944,22 @@ stdin:
./pfn "$(echo foo)"
}
./pfn "$(echo b)"
typeset -f foo >x
cat x
foo
. ./x
typeset -f foo
foo
expected-stdout:
a b
foo() {
./pfn "$(echo foo )"
./pfn "$(\echo a foo )"
}
a foo
foo() {
./pfn "$(\echo a foo )"
}
a foo
---
name: comsub-torture
description:
@ -11038,56 +11070,56 @@ expected-stdout:
vara=1 varb='2 3' cmd arg1 $arg2 "$arg3 4"
}
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=$(
vara=1 varb='2 3' cmd arg1 $arg2 "$arg3 4"
); }
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=$((
vara=1 varb='2 3' cmd arg1 $arg2 "$arg3 4"
)|tr u x); }
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() {
(echo $foo | tr -dc 0-9; echo)
}
inline_TPAREN_TPIPE_TLIST() {
( echo $foo | tr -dc 0-9
echo )
( \echo $foo | \tr -dc 0-9
\echo )
}
function comsub_TPAREN_TPIPE_TLIST { x=$(
(echo $foo | tr -dc 0-9; echo)
); }
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=$((
(echo $foo | tr -dc 0-9; echo)
)|tr u x); }
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() {
cmd && echo ja || echo nein
}
inline_TAND_TOR() {
cmd && echo ja || echo nein
\cmd && \echo ja || \echo nein
}
function comsub_TAND_TOR { x=$(
cmd && echo ja || echo nein
); }
function comsub_TAND_TOR {
x=$(cmd && echo ja || echo nein )
x=$(\cmd && \echo ja || \echo nein )
}
function reread_TAND_TOR { x=$((
cmd && echo ja || echo nein
)|tr u x); }
function reread_TAND_TOR {
x=$(( cmd && echo ja || echo nein ) | tr u x )
x=$(( \cmd && \echo ja || \echo nein ) | \tr u x )
}
inline_TSELECT() {
select file in *; do echo "<$file>" ; break ; done
@ -11095,21 +11127,21 @@ expected-stdout:
inline_TSELECT() {
select file in *
do
echo "<$file>"
break
\echo "<$file>"
\break
done
}
function comsub_TSELECT { x=$(
select file in *; do echo "<$file>" ; break ; done
); }
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=$((
select file in *; do echo "<$file>" ; break ; done
)|tr u x); }
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() {
time for i in {1,2,3} ; do echo $i ; done
@ -11117,20 +11149,20 @@ expected-stdout:
inline_TFOR_TTIME() {
time for i in {1,2,3}
do
echo $i
\echo $i
done
}
function comsub_TFOR_TTIME { x=$(
time for i in {1,2,3} ; do echo $i ; done
); }
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=$((
time for i in {1,2,3} ; do echo $i ; done
)|tr u x); }
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() {
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() {
case $foo in
(1)
echo eins
\echo eins
;&
(2)
echo zwei
\echo zwei
;|
(*)
echo kann net bis drei zählen
\echo kann net bis drei zählen
;;
esac
}
@ -11152,13 +11184,13 @@ expected-stdout:
case $foo in 1) echo eins;& 2) echo zwei ;| *) echo kann net bis drei zählen;; esac
); }
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=$((
case $foo in 1) echo eins;& 2) echo zwei ;| *) echo kann net bis drei zählen;; esac
)|tr u x); }
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() {
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() {
if ! [[ 1 = 1 ]]
then
echo eins
\echo eins
elif [[ 1 = 2 ]]
then
echo zwei
\echo zwei
else
echo drei
\echo drei
fi
}
function comsub_TIF_TBANG_TDBRACKET_TELIF { x=$(
if ! [[ 1 = 1 ]] ; then echo eins; elif [[ 1 = 2 ]]; then echo zwei ;else echo drei; fi
); }
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=$((
if ! [[ 1 = 1 ]] ; then echo eins; elif [[ 1 = 2 ]]; then echo zwei ;else echo drei; fi
)|tr u x); }
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() {
i=1; while (( i < 10 )); do echo $i; let ++i; done
@ -11195,21 +11227,21 @@ expected-stdout:
\\builtin let " i < 10 "
}
do
echo $i
let ++i
\echo $i
\let ++i
done
}
function comsub_TWHILE { x=$(
i=1; while (( i < 10 )); do echo $i; let ++i; done
); }
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=$((
i=1; while (( i < 10 )); do echo $i; let ++i; done
)|tr u x); }
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() {
i=10; until (( !--i )) ; do echo $i; done
@ -11220,39 +11252,39 @@ expected-stdout:
\\builtin let " !--i "
}
do
echo $i
\echo $i
done
}
function comsub_TUNTIL { x=$(
i=10; until (( !--i )) ; do echo $i; done
); }
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=$((
i=10; until (( !--i )) ; do echo $i; done
)|tr u x); }
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() {
cat * |& ls
}
inline_TCOPROC() {
cat * |&
ls
\cat * |&
\ls
}
function comsub_TCOPROC { x=$(
cat * |& ls
); }
function comsub_TCOPROC {
x=$(cat * |& ls )
x=$(\cat * |& \ls )
}
function reread_TCOPROC { x=$((
cat * |& ls
)|tr u x); }
function reread_TCOPROC {
x=$(( cat * |& ls ) | tr u x )
x=$(( \cat * |& \ls ) | \tr u x )
}
inline_TFUNCT_TBRACE_TASYNC() {
function korn { echo eins; echo zwei ; }
@ -11260,11 +11292,11 @@ expected-stdout:
}
inline_TFUNCT_TBRACE_TASYNC() {
function korn {
echo eins
echo zwei
\echo eins
\echo zwei
}
bourne() {
logger * &
\logger * &
}
}
function comsub_TFUNCT_TBRACE_TASYNC { x=$(
@ -11272,32 +11304,32 @@ expected-stdout:
bourne () { logger * & }
); }
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 korn { echo eins; echo zwei ; }
bourne () { logger * & }
)|tr u x); }
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() {
tr x u 0<foo >>bar
}
inline_IOREAD_IOCAT() {
tr x u <foo >>bar
\tr x u <foo >>bar
}
function comsub_IOREAD_IOCAT { x=$(
tr x u 0<foo >>bar
); }
function comsub_IOREAD_IOCAT {
x=$(tr x u <foo >>bar )
x=$(\tr x u <foo >>bar )
}
function reread_IOREAD_IOCAT { x=$((
tr x u 0<foo >>bar
)|tr u x); }
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() {
cat >|bar <<'EOFN'
@ -11305,7 +11337,7 @@ expected-stdout:
EOFN
}
inline_IOWRITE_IOCLOB_IOHERE_noIOSKIP() {
cat >|bar <<"EOFN"
\cat >|bar <<"EOFN"
foo
EOFN
@ -11316,7 +11348,7 @@ expected-stdout:
EOFN
); }
function comsub_IOWRITE_IOCLOB_IOHERE_noIOSKIP {
x=$(cat >|bar <<"EOFN"
x=$(\cat >|bar <<"EOFN"
foo
EOFN
)
@ -11327,10 +11359,10 @@ expected-stdout:
EOFN
)|tr u x); }
function reread_IOWRITE_IOCLOB_IOHERE_noIOSKIP {
x=$(( cat >|bar <<"EOFN"
x=$(( \cat >|bar <<"EOFN"
foo
EOFN
) | tr u x )
) | \tr u x )
}
inline_IOWRITE_noIOCLOB_IOHERE_IOSKIP() {
cat 1>bar <<-EOFI
@ -11338,7 +11370,7 @@ expected-stdout:
EOFI
}
inline_IOWRITE_noIOCLOB_IOHERE_IOSKIP() {
cat >bar <<-EOFI
\cat >bar <<-EOFI
foo
EOFI
@ -11349,7 +11381,7 @@ expected-stdout:
EOFI
); }
function comsub_IOWRITE_noIOCLOB_IOHERE_IOSKIP {
x=$(cat >bar <<-EOFI
x=$(\cat >bar <<-EOFI
foo
EOFI
)
@ -11360,46 +11392,46 @@ expected-stdout:
EOFI
)|tr u x); }
function reread_IOWRITE_noIOCLOB_IOHERE_IOSKIP {
x=$(( cat >bar <<-EOFI
x=$(( \cat >bar <<-EOFI
foo
EOFI
) | tr u x )
) | \tr u x )
}
inline_IORDWR_IODUP() {
sh 1<>/dev/console 0<&1 2>&1
}
inline_IORDWR_IODUP() {
sh 1<>/dev/console <&1 2>&1
\sh 1<>/dev/console <&1 2>&1
}
function comsub_IORDWR_IODUP { x=$(
sh 1<>/dev/console 0<&1 2>&1
); }
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=$((
sh 1<>/dev/console 0<&1 2>&1
)|tr u x); }
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() {
echo $(true) $((1+ 2)) ${ :;} ${| REPLY=x;}
}
inline_COMSUB_EXPRSUB_FUNSUB_VALSUB() {
echo $(true ) $((1+ 2)) ${ : ;} ${|REPLY=x ;}
\echo $(\true ) $((1+ 2)) ${ : ;} ${|REPLY=x ;}
}
function comsub_COMSUB_EXPRSUB_FUNSUB_VALSUB { x=$(
echo $(true) $((1+ 2)) ${ :;} ${| REPLY=x;}
); }
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=$((
echo $(true) $((1+ 2)) ${ :;} ${| REPLY=x;}
)|tr u x); }
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() {
echo fo\ob\"a\`r\'b\$az
@ -11407,9 +11439,9 @@ expected-stdout:
echo 'fo\ob\"a\`r'\''b\$az'
}
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=$(
echo fo\ob\"a\`r\'b\$az
@ -11417,7 +11449,7 @@ expected-stdout:
echo 'fo\ob\"a\`r'\''b\$az'
); }
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=$((
echo fo\ob\"a\`r\'b\$az
@ -11425,7 +11457,7 @@ expected-stdout:
echo 'fo\ob\"a\`r'\''b\$az'
)|tr u x); }
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() {
[[ ${foo#bl\(u\)b} = @(bar|baz) ]]
@ -11443,7 +11475,7 @@ expected-stdout:
[[ ${foo#bl\(u\)b} = @(bar|baz) ]]
)|tr u x); }
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() {
x=$(cat <<EOFN
@ -11451,11 +11483,11 @@ expected-stdout:
EOFN); echo $x
}
inline_heredoc_closed() {
x=$(cat <<EOFN
x=$(\cat <<EOFN
note there must be no space between EOFN and )
EOFN
)
echo $x
\echo $x
}
function comsub_heredoc_closed { x=$(
x=$(cat <<EOFN
@ -11463,10 +11495,10 @@ expected-stdout:
EOFN); echo $x
); }
function comsub_heredoc_closed {
x=$(x=$(cat <<EOFN
x=$(x=$(\cat <<EOFN
note there must be no space between EOFN and )
EOFN
) ; echo $x )
) ; \echo $x )
}
function reread_heredoc_closed { x=$((
x=$(cat <<EOFN
@ -11474,10 +11506,10 @@ expected-stdout:
EOFN); echo $x
)|tr u x); }
function reread_heredoc_closed {
x=$(( x=$(cat <<EOFN
x=$(( x=$(\cat <<EOFN
note there must be no space between EOFN and )
EOFN
) ; echo $x ) | tr u x )
) ; \echo $x ) | \tr u x )
}
inline_heredoc_space() {
x=$(cat <<EOFN\
@ -11485,11 +11517,11 @@ expected-stdout:
EOFN ); echo $x
}
inline_heredoc_space() {
x=$(cat <<EOFN\
x=$(\cat <<EOFN\
note the space between EOFN and ) is actually part of the here document marker
EOFN
)
echo $x
\echo $x
}
function comsub_heredoc_space { x=$(
x=$(cat <<EOFN\
@ -11497,10 +11529,10 @@ expected-stdout:
EOFN ); echo $x
); }
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
EOFN
) ; echo $x )
) ; \echo $x )
}
function reread_heredoc_space { x=$((
x=$(cat <<EOFN\
@ -11508,10 +11540,10 @@ expected-stdout:
EOFN ); echo $x
)|tr u x); }
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
EOFN
) ; echo $x ) | tr u x )
) ; \echo $x ) | \tr u x )
}
inline_patch_motd() {
x=$(sysctl -n kern.version | sed 1q)
@ -11530,8 +11562,8 @@ expected-stdout:
fi
}
inline_patch_motd() {
x=$(sysctl -n kern.version | sed 1q )
[[ -s /etc/motd && "$([[ "$(head -1 /etc/motd )" != $x ]] && ed -s /etc/motd 2>&1 <<-EOF
x=$(\sysctl -n kern.version | \sed 1q )
[[ -s /etc/motd && "$([[ "$(\head -1 /etc/motd )" != $x ]] && \ed -s /etc/motd 2>&1 <<-EOF
1,/^\$/d
0a
$x
@ -11539,11 +11571,11 @@ expected-stdout:
.
wq
EOF
)" = @(?) ]] && rm -f /etc/motd
)" = @(?) ]] && \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
\install -c -o root -g wheel -m 664 /dev/null /etc/motd
\print -- "$x\n" >/etc/motd
fi
}
function comsub_patch_motd { x=$(
@ -11563,7 +11595,7 @@ expected-stdout:
fi
); }
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
0a
$x
@ -11571,7 +11603,7 @@ expected-stdout:
.
wq
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=$((
x=$(sysctl -n kern.version | sed 1q)
@ -11590,7 +11622,7 @@ expected-stdout:
fi
)|tr u x); }
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
0a
$x
@ -11598,7 +11630,7 @@ expected-stdout:
.
wq
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() {
case x in
@ -11627,7 +11659,7 @@ expected-stdout:
esac
)|tr u x); }
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
@ -11694,56 +11726,56 @@ expected-stdout:
vara=1 varb='2 3' cmd arg1 $arg2 "$arg3 4" >&3
}
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=$(
vara=1 varb='2 3' cmd arg1 $arg2 "$arg3 4" >&3
); }
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=$((
vara=1 varb='2 3' cmd arg1 $arg2 "$arg3 4" >&3
)|tr u x); }
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() {
(echo $foo | tr -dc 0-9 >&3; echo >&3) >&3
}
inline_TPAREN_TPIPE_TLIST() {
( 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 { x=$(
(echo $foo | tr -dc 0-9 >&3; echo >&3) >&3
); }
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=$((
(echo $foo | tr -dc 0-9 >&3; echo >&3) >&3
)|tr u x); }
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() {
cmd >&3 && >&3 echo ja || echo >&3 nein
}
inline_TAND_TOR() {
cmd >&3 && echo ja >&3 || echo nein >&3
\cmd >&3 && \echo ja >&3 || \echo nein >&3
}
function comsub_TAND_TOR { x=$(
cmd >&3 && >&3 echo ja || echo >&3 nein
); }
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=$((
cmd >&3 && >&3 echo ja || echo >&3 nein
)|tr u x); }
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() {
select file in *; do echo "<$file>" ; break >&3 ; done >&3
@ -11751,21 +11783,21 @@ expected-stdout:
inline_TSELECT() {
select file in *
do
echo "<$file>"
break >&3
\echo "<$file>"
\break >&3
done >&3
}
function comsub_TSELECT { x=$(
select file in *; do echo "<$file>" ; break >&3 ; done >&3
); }
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=$((
select file in *; do echo "<$file>" ; break >&3 ; done >&3
)|tr u x); }
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() {
for i in {1,2,3} ; do time >&3 echo $i ; done >&3
@ -11773,20 +11805,20 @@ expected-stdout:
inline_TFOR_TTIME() {
for i in {1,2,3}
do
time echo $i >&3
time \echo $i >&3
done >&3
}
function comsub_TFOR_TTIME { x=$(
for i in {1,2,3} ; do time >&3 echo $i ; done >&3
); }
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=$((
for i in {1,2,3} ; do time >&3 echo $i ; done >&3
)|tr u x); }
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() {
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() {
case $foo in
(1)
echo eins >&3
\echo eins >&3
;&
(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
}
@ -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
); }
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=$((
case $foo in 1) echo eins >&3;& 2) echo zwei >&3 ;| *) echo kann net bis drei zählen >&3;; esac >&3
)|tr u 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 ) | 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() {
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() {
if ! [[ 1 = 1 ]] >&3
then
echo eins
\echo eins
elif [[ 1 = 2 ]] >&3
then
echo zwei
\echo zwei
else
echo drei
\echo drei
fi >&3
}
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
); }
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=$((
if ! [[ 1 = 1 ]] >&3 ; then echo eins; elif [[ 1 = 2 ]] >&3; then echo zwei ;else echo drei; fi >&3
)|tr u 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 ) | 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() {
i=1; while (( i < 10 )) >&3; do echo $i; let ++i; done >&3
@ -11851,21 +11883,21 @@ expected-stdout:
\\builtin let " i < 10 "
} >&3
do
echo $i
let ++i
\echo $i
\let ++i
done >&3
}
function comsub_TWHILE { x=$(
i=1; while (( i < 10 )) >&3; do echo $i; let ++i; done >&3
); }
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=$((
i=1; while (( i < 10 )) >&3; do echo $i; let ++i; done >&3
)|tr u x); }
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() {
i=10; until (( !--i )) >&3 ; do echo $i; done >&3
@ -11876,39 +11908,39 @@ expected-stdout:
\\builtin let " !--i "
} >&3
do
echo $i
\echo $i
done >&3
}
function comsub_TUNTIL { x=$(
i=10; until (( !--i )) >&3 ; do echo $i; done >&3
); }
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=$((
i=10; until (( !--i )) >&3 ; do echo $i; done >&3
)|tr u x); }
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() {
cat * >&3 |& >&3 ls
}
inline_TCOPROC() {
cat * >&3 |&
ls >&3
\cat * >&3 |&
\ls >&3
}
function comsub_TCOPROC { x=$(
cat * >&3 |& >&3 ls
); }
function comsub_TCOPROC {
x=$(cat * >&3 |& ls >&3 )
x=$(\cat * >&3 |& \ls >&3 )
}
function reread_TCOPROC { x=$((
cat * >&3 |& >&3 ls
)|tr u x); }
function reread_TCOPROC {
x=$(( cat * >&3 |& ls >&3 ) | tr u x )
x=$(( \cat * >&3 |& \ls >&3 ) | \tr u x )
}
inline_TFUNCT_TBRACE_TASYNC() {
function korn { echo eins; echo >&3 zwei ; }
@ -11916,11 +11948,11 @@ expected-stdout:
}
inline_TFUNCT_TBRACE_TASYNC() {
function korn {
echo eins
echo zwei >&3
\echo eins
\echo zwei >&3
}
bourne() {
logger * >&3 &
\logger * >&3 &
}
}
function comsub_TFUNCT_TBRACE_TASYNC { x=$(
@ -11928,32 +11960,32 @@ expected-stdout:
bourne () { logger * >&3 & }
); }
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 korn { echo eins; echo >&3 zwei ; }
bourne () { logger * >&3 & }
)|tr u x); }
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() {
echo $(true >&3) $((1+ 2))
}
inline_COMSUB_EXPRSUB() {
echo $(true >&3 ) $((1+ 2))
\echo $(\true >&3 ) $((1+ 2))
}
function comsub_COMSUB_EXPRSUB { x=$(
echo $(true >&3) $((1+ 2))
); }
function comsub_COMSUB_EXPRSUB {
x=$(echo $(true >&3 ) $((1+ 2)) )
x=$(\echo $(\true >&3 ) $((1+ 2)) )
}
function reread_COMSUB_EXPRSUB { x=$((
echo $(true >&3) $((1+ 2))
)|tr u x); }
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

4
edit.c
View File

@ -28,7 +28,7 @@
#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
@ -5554,7 +5554,7 @@ x_eval_region_helper(const char *cmd, size_t len)
if (!kshsetjmp(e->jbuf)) {
char *wds = alloc(len + 3, ATEMP);
wds[0] = FUNSUB;
wds[0] = FUNASUB;
memcpy(wds + 1, cmd, len);
wds[len + 1] = '\0';
wds[len + 2] = EOS;

42
eval.c
View File

@ -23,7 +23,7 @@
#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
@ -301,25 +301,36 @@ expand(
word = IFS_WORD;
quote = st->quotew;
continue;
case COMASUB:
case COMSUB:
case FUNASUB:
case FUNSUB:
case VALSUB:
tilde_ok = 0;
if (f & DONTRUNCOMMAND) {
word = IFS_WORD;
*dp++ = '$';
*dp++ = c == COMSUB ? '(' : '{';
if (c != COMSUB)
*dp++ = c == FUNSUB ? ' ' : '|';
switch (c) {
case COMASUB:
case COMSUB:
*dp++ = '(';
c = ')';
break;
case FUNASUB:
case FUNSUB:
case VALSUB:
*dp++ = '{';
*dp++ = c == VALSUB ? '|' : ' ';
c = '}';
break;
}
while (*sp != '\0') {
Xcheck(ds, dp);
*dp++ = *sp++;
}
if (c != COMSUB) {
if (c == '}')
*dp++ = ';';
*dp++ = '}';
} else
*dp++ = ')';
*dp++ = c;
} else {
type = comsub(&x, sp, c);
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.
*/
static int
comsub(Expand *xp, const char *cp, int fn MKSH_A_UNUSED)
comsub(Expand *xp, const char *cp, int fn)
{
Source *s, *sold;
struct op *t;
struct shf *shf;
bool doalias = false;
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->start = s->str = cp;
sold = source;
t = compile(s, true);
t = compile(s, true, doalias);
afree(s, ATEMP);
source = sold;

26
funcs.c
View File

@ -38,7 +38,7 @@
#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
/*
@ -741,6 +741,17 @@ do_whence(const char **wp, int fcflags, bool vflag, bool iscommand)
return (rv);
}
bool
valid_alias_name(const char *cp)
{
while (*cp)
if (!ksh_isalias(*cp))
return (false);
else
++cp;
return (true);
}
int
c_alias(const char **wp)
{
@ -839,14 +850,11 @@ c_alias(const char **wp)
strndupx(xalias, alias, val++ - alias, ATEMP);
alias = xalias;
}
newval = alias;
while (*newval)
if (!ksh_isalias(*newval)) {
bi_errorf(Tinvname, alias, Talias);
afree(xalias, ATEMP);
return (1);
} else
++newval;
if (!valid_alias_name(alias)) {
bi_errorf(Tinvname, alias, Talias);
afree(xalias, ATEMP);
return (1);
}
h = hash(alias);
if (val == NULL && !tflag && !xflag) {
ap = ktsearch(t, alias, h);

4
lex.c
View File

@ -23,7 +23,7 @@
#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
@ -532,7 +532,7 @@ yylex(int cf)
case '`':
subst_gravis:
PUSH_STATE(SBQUOTE);
*wp++ = COMSUB;
*wp++ = COMASUB;
/*
* We need to know whether we are within double
* quotes in order to translate \" to " within

4
main.c
View File

@ -34,7 +34,7 @@
#include <locale.h>
#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;
@ -827,7 +827,7 @@ shell(Source * volatile s, volatile bool toplevel)
j_notify();
set_prompt(PS1, s);
}
t = compile(s, sfirst);
t = compile(s, sfirst, true);
if (interactive)
histsave(&s->line, NULL, HIST_FLUSH, true);
sfirst = false;

9
sh.h
View File

@ -175,9 +175,9 @@
#endif
#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
#define MKSH_VERSION "R54 2017/04/02"
#define MKSH_VERSION "R54 2017/04/05"
/* arithmetic types: C implementation */
#if !HAVE_CAN_INTTYPES
@ -1690,6 +1690,8 @@ struct op {
#define ADELIM 12 /* arbitrary delimiter: ${foo:2:3} ${foo/bar/baz} */
#define FUNSUB 14 /* ${ 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
@ -2076,6 +2078,7 @@ int c_printf(const char **);
int c_whence(const char **);
int c_command(const char **);
int c_typeset(const char **);
bool valid_alias_name(const char *);
int c_alias(const char **);
int c_unalias(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);
/* syn.c */
void initkeywords(void);
struct op *compile(Source *, bool);
struct op *compile(Source *, bool, bool);
bool parse_usec(const char *, struct timeval *);
char *yyrecursive(int);
void yyrecursive_pop(bool);

126
syn.c
View File

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

29
tree.c
View File

@ -2,7 +2,7 @@
/*-
* 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>
*
* Provided that these terms and disclaimer and all copyright notices
@ -23,7 +23,7 @@
#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
@ -86,6 +86,15 @@ ptree(struct op *t, int indent, struct shf *shf)
shf_puts("#no-vars# ", shf);
if (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)
fptreef(shf, indent, Tf_S_, *w++);
} else
@ -352,6 +361,7 @@ wdvarput(struct shf *shf, const char *wp, int quotelevel, int opmode)
}
shf_putc(c, shf);
break;
case COMASUB:
case COMSUB:
shf_puts("$(", shf);
cs = ")";
@ -360,6 +370,7 @@ wdvarput(struct shf *shf, const char *wp, int quotelevel, int opmode)
shf_putc(c, shf);
shf_puts(cs, shf);
break;
case FUNASUB:
case FUNSUB:
c = ' ';
if (0)
@ -409,8 +420,9 @@ wdvarput(struct shf *shf, const char *wp, int quotelevel, int opmode)
case SPAT:
c = '|';
if (0)
/* FALLTHROUGH */
case CPAT:
c = /*(*/ ')';
c = /*(*/ ')';
shf_putc(c, shf);
break;
}
@ -606,7 +618,9 @@ wdscan(const char *wp, int c)
case QCHAR:
wp++;
break;
case COMASUB:
case COMSUB:
case FUNASUB:
case FUNSUB:
case VALSUB:
case EXPRSUB:
@ -832,8 +846,9 @@ dumpwdvar_i(struct shf *shf, const char *wp, int quotelevel)
}
shf_puts("ADELIM=", shf);
if (0)
/* FALLTHROUGH */
case CHAR:
shf_puts("CHAR=", shf);
shf_puts("CHAR=", shf);
dumpchar(shf, *wp++);
break;
case QCHAR:
@ -844,6 +859,9 @@ dumpwdvar_i(struct shf *shf, const char *wp, int quotelevel)
shf_putc('\\', shf);
dumpchar(shf, c);
goto closeandout;
case COMASUB:
shf_puts("COMASUB<", shf);
goto dumpsub;
case COMSUB:
shf_puts("COMSUB<", shf);
dumpsub:
@ -852,6 +870,9 @@ dumpwdvar_i(struct shf *shf, const char *wp, int quotelevel)
closeandout:
shf_putc('>', shf);
break;
case FUNASUB:
shf_puts("FUNASUB<", shf);
goto dumpsub;
case FUNSUB:
shf_puts("FUNSUB<", shf);
goto dumpsub;