Date: Sun, 30 May 2010 14:11:27 +0000 (UTC) From: Jilles Tjoelker <jilles@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r208655 - in head: bin/sh tools/regression/bin/sh/parser Message-ID: <201005301411.o4UEBRYc065260@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: jilles Date: Sun May 30 14:11:27 2010 New Revision: 208655 URL: http://svn.freebsd.org/changeset/base/208655 Log: sh: Change interaction of command substitution and here documents. If a command substitution contains a newline token, this no longer starts here documents of outer commands. This way, we follow POSIX's idea of the command substitution being a separate script more closely. It also matches other shells better and is consistent with newline characters in quotes not starting here documents. The extension tested in parser/heredoc3.0 ($(cat <<EOF)\ntext\nEOF\n) continues to be supported. In particular, this change allows things like cat <<EOF && echo `pwd` (a `` command substitution after a here document) which formerly silently used an empty file as the here document, because the EOF of the inner command "pwd" also forced an empty here document. Added: head/tools/regression/bin/sh/parser/heredoc4.0 (contents, props changed) head/tools/regression/bin/sh/parser/heredoc5.0 (contents, props changed) Modified: head/bin/sh/parser.c Modified: head/bin/sh/parser.c ============================================================================== --- head/bin/sh/parser.c Sun May 30 13:32:39 2010 (r208654) +++ head/bin/sh/parser.c Sun May 30 14:11:27 2010 (r208655) @@ -973,6 +973,8 @@ parsebackq(char *out, struct nodelist ** const int bq_startlinno = plinno; char *volatile ostr = NULL; struct parsefile *const savetopfile = getcurrentfile(); + struct heredoc *const saveheredoclist = heredoclist; + struct heredoc *here; str = NULL; if (setjmp(jmploc.loc)) { @@ -981,6 +983,7 @@ parsebackq(char *out, struct nodelist ** ckfree(str); if (ostr) ckfree(ostr); + heredoclist = saveheredoclist; handler = savehandler; if (exception == EXERROR) { startlinno = bq_startlinno; @@ -995,6 +998,7 @@ parsebackq(char *out, struct nodelist ** memcpy(str, stackblock(), savelen); } handler = &jmploc; + heredoclist = NULL; INTON; if (oldstyle) { /* We must read until the closing backquote, giving special @@ -1091,21 +1095,26 @@ done: while (stackblocksize() <= savelen) growstackblock(); STARTSTACKSTR(out); + INTOFF; if (str) { memcpy(out, str, savelen); STADJUST(savelen, out); - INTOFF; ckfree(str); str = NULL; - INTON; } if (ostr) { - INTOFF; ckfree(ostr); ostr = NULL; - INTON; + } + here = saveheredoclist; + if (here != NULL) { + while (here->next != NULL) + here = here->next; + here->next = heredoclist; + heredoclist = saveheredoclist; } handler = savehandler; + INTON; if (quoted) USTPUTC(CTLBACKQ | CTLQUOTE, out); else Added: head/tools/regression/bin/sh/parser/heredoc4.0 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/tools/regression/bin/sh/parser/heredoc4.0 Sun May 30 14:11:27 2010 (r208655) @@ -0,0 +1,44 @@ +# $FreeBSD$ + +failures=0 + +check() { + if ! eval "[ $* ]"; then + echo "Failed: $*" + : $((failures += 1)) + fi +} + +f() { + cat <<EOF && echo `echo bar` +foo +EOF +} +check '"`f`" = "foo +bar"' + +f() { + cat <<EOF && echo $(echo bar) +foo +EOF +} +check '"$(f)" = "foo +bar"' + +f() { + echo `echo bar` && cat <<EOF +foo +EOF +} +check '"`f`" = "bar +foo"' + +f() { + echo $(echo bar) && cat <<EOF +foo +EOF +} +check '"$(f)" = "bar +foo"' + +exit $((failures != 0)) Added: head/tools/regression/bin/sh/parser/heredoc5.0 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/tools/regression/bin/sh/parser/heredoc5.0 Sun May 30 14:11:27 2010 (r208655) @@ -0,0 +1,56 @@ +# $FreeBSD$ + +failures=0 + +check() { + if ! eval "[ $* ]"; then + echo "Failed: $*" + : $((failures += 1)) + fi +} + +f() { + cat <<EOF && echo `cat <<EOF +bar +EOF +` +foo +EOF +} +check '"`f`" = "foo +bar"' + +f() { + cat <<EOF && echo $(cat <<EOF +bar +EOF +) +foo +EOF +} +check '"$(f)" = "foo +bar"' + +f() { + echo `cat <<EOF +bar +EOF +` && cat <<EOF +foo +EOF +} +check '"`f`" = "bar +foo"' + +f() { + echo $(cat <<EOF +bar +EOF +) && cat <<EOF +foo +EOF +} +check '"$(f)" = "bar +foo"' + +exit $((failures != 0))
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201005301411.o4UEBRYc065260>