I thought of making COMSUB pass a pointer to the struct op *t->left around

instead, but the parser for the so-called “backticks” (U+0060) still emits
plaintext COMSUB wdstrings, and the evaluation code emits plaintext if the
code is not run (‘-n’ option), so it’s not worth the effort and memory ma-
nagement issues, even though it _would_ optimise the most common case…

Bump version numbers, sync regression tests; add one testcase from the old
webpages too. Sync manpage, this now works, but keep the workaround in, as
“portability issue” with slightly changed wording.

Also, /bin/sleep must be used in one manpage example if sleep is built in.
This commit is contained in:
tg 2011-03-06 01:50:11 +00:00
parent 25905b91a7
commit c995f7ca98
3 changed files with 48 additions and 42 deletions

36
check.t
View File

@ -1,4 +1,4 @@
# $MirOS: src/bin/mksh/check.t,v 1.413 2011/02/27 19:41:17 tg Exp $ # $MirOS: src/bin/mksh/check.t,v 1.414 2011/03/06 01:50:08 tg Exp $
# $OpenBSD: bksl-nl.t,v 1.2 2001/01/28 23:04:56 niklas Exp $ # $OpenBSD: bksl-nl.t,v 1.2 2001/01/28 23:04:56 niklas Exp $
# $OpenBSD: history.t,v 1.5 2001/01/28 23:04:56 niklas Exp $ # $OpenBSD: history.t,v 1.5 2001/01/28 23:04:56 niklas Exp $
# $OpenBSD: read.t,v 1.3 2003/03/10 03:48:16 david Exp $ # $OpenBSD: read.t,v 1.3 2003/03/10 03:48:16 david Exp $
@ -25,7 +25,7 @@
# http://www.research.att.com/~gsf/public/ifs.sh # http://www.research.att.com/~gsf/public/ifs.sh
expected-stdout: expected-stdout:
@(#)MIRBSD KSH R39 2011/02/18 @(#)MIRBSD KSH R39 2011/03/05
description: description:
Check version of shell. Check version of shell.
stdin: stdin:
@ -6933,11 +6933,10 @@ expected-stdout:
--- ---
name: comsub-1 name: comsub-1
description: description:
COMSUB are currently parsed by hacking lex.c instead of COMSUB are now parsed recursively, so this works
recursively (see regression-6): matching parenthesēs bug see also regression-6: matching parenthesēs bug
Fails on: pdksh mksh bash2 bash3 zsh Fails on: pdksh bash2 bash3 zsh
Passes on: bash4 ksh93 Passes on: bash4 ksh93 mksh(20110305+)
expected-fail: yes
stdin: stdin:
echo $(case 1 in (1) echo yes;; (2) echo no;; esac) echo $(case 1 in (1) echo yes;; (2) echo no;; esac)
echo $(case 1 in 1) echo yes;; 2) echo no;; esac) echo $(case 1 in 1) echo yes;; 2) echo no;; esac)
@ -6949,10 +6948,9 @@ name: comsub-2
description: description:
RedHat BZ#496791 another case of missing recursion RedHat BZ#496791 another case of missing recursion
in parsing COMSUB expressions in parsing COMSUB expressions
Fails on: pdksh mksh bash2 bash3¹ bash4¹ zsh Fails on: pdksh bash2 bash3¹ bash4¹ zsh
Passes on: ksh93 Passes on: ksh93 mksh(20110305+)
bash[34] seem to choke on comment ending with backslash-newline bash[34] seem to choke on comment ending with backslash-newline
expected-fail: yes
stdin: stdin:
# a comment with " ' \ # a comment with " ' \
x=$( x=$(
@ -6963,6 +6961,24 @@ stdin:
expected-stdout: expected-stdout:
yes yes
--- ---
name: comsub-3
description:
Extended test for COMSUB explaining why a recursive parser
is a must (a non-recursive parser cannot pass all three of
these test cases, especially the # is difficult)
stdin:
echo $(typeset -i10 x=16#20; echo $x)
echo $(typeset -Uui16 x=16#$(id -u)
) .
echo $(c=1; d=1
typeset -Uui16 a=36#foo; c=2
typeset -Uui16 b=36 #foo; d=2
echo $a $b $c $d)
expected-stdout:
32
.
16#4F68 16#24 2 1
---
name: test-stnze-1 name: test-stnze-1
description: description:
Check that the short form [ $x ] works Check that the short form [ $x ] works

50
mksh.1
View File

@ -1,4 +1,4 @@
.\" $MirOS: src/bin/mksh/mksh.1,v 1.251 2011/02/18 22:26:11 tg Exp $ .\" $MirOS: src/bin/mksh/mksh.1,v 1.252 2011/03/06 01:50:09 tg Exp $
.\" $OpenBSD: ksh.1,v 1.138 2010/09/20 07:41:17 jmc Exp $ .\" $OpenBSD: ksh.1,v 1.138 2010/09/20 07:41:17 jmc Exp $
.\"- .\"-
.\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, .\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
@ -72,7 +72,7 @@
.\" with -mandoc, it might implement .Mx itself, but we want to .\" with -mandoc, it might implement .Mx itself, but we want to
.\" use our own definition. And .Dd must come *first*, always. .\" use our own definition. And .Dd must come *first*, always.
.\" .\"
.Dd $Mdocdate: February 18 2011 $ .Dd $Mdocdate: March 6 2011 $
.\" .\"
.\" Check which macro package we use .\" Check which macro package we use
.\" .\"
@ -1238,12 +1238,23 @@ Note that
has the same effect as has the same effect as
.Ic $(cat foo) . .Ic $(cat foo) .
.Pp .Pp
.Sy Note : Note that some shells do not use a recursive parser for command substitutions,
.Pf $( Ns Ar command Ns \&) leading to failure for certain constructs; to be portable, use as workaround
expressions are currently parsed by finding matching parentheses, .Ql x=$(cat) \*(Lt\*(Lt"EOF"
regardless of quoting; comments containing quote characters are (or the newline-keeping
not handled correctly. .Ql x=\*(Lt\*(Lt"EOF"
This should be fixed soon. extension) instead to merely slurp the string.
.St -p1003.1
recommends to use case statements of the form
.Ql "x=$(case $foo in (bar) echo $bar ;; (*) echo $baz ;; esac)"
instead, which would work but not serve as example for this portability issue.
.Bd -literal -offset indent
x=$(case $foo in bar) echo $bar ;; *) echo $baz ;; esac)
# above fails to parse on old shells; below is the workaround
x=$(eval $(cat)) \*(Lt\*(Lt"EOF"
case $foo in bar) echo $bar ;; *) echo $baz ;; esac
EOF
.Ed
.Pp .Pp
Arithmetic substitutions are replaced by the value of the specified expression. Arithmetic substitutions are replaced by the value of the specified expression.
For example, the command For example, the command
@ -6107,28 +6118,7 @@ the currently running part of the pipeline; in this example,
is immediately printed on suspension (but not later after an is immediately printed on suspension (but not later after an
.Ic fg ) . .Ic fg ) .
.Bd -literal -offset indent .Bd -literal -offset indent
$ sleep 666 && echo fubar $ /bin/sleep 666 && echo fubar
.Ed
.Pp
Some parts of the parser are not recursive; the following
code fails because of the parenthesis asymmetry
.Pq RedHat BZ#496791 .
A workaround exists; use
.Ql x=$(cat) \*(Lt\*(Lt"EOF"
or the newline-keeping
.Ql x=\*(Lt\*(Lt"EOF"
instead to merely slurp the string.
Of course, in this case, the form
.Ql x=$(case $foo in (bar) ...
actually recommended by
.St -p1003.1
would work as well, but we use it as an example of this parser bug.
.Bd -literal -offset indent
x=$(case $foo in bar) echo $bar ;; *) echo $baz ;; esac)
# above fails to parse; below is the workaround
x=$(eval $(cat)) \*(Lt\*(Lt"EOF"
case $foo in bar) echo $bar ;; *) echo $baz ;; esac
EOF
.Ed .Ed
.Pp .Pp
This document attempts to describe This document attempts to describe

4
sh.h
View File

@ -154,9 +154,9 @@
#endif #endif
#ifdef EXTERN #ifdef EXTERN
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.436 2011/03/06 01:25:33 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/sh.h,v 1.437 2011/03/06 01:50:11 tg Exp $");
#endif #endif
#define MKSH_VERSION "R39 2011/02/18" #define MKSH_VERSION "R39 2011/03/05"
#ifndef MKSH_INCLUDES_ONLY #ifndef MKSH_INCLUDES_ONLY