From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 24409 invoked by alias); 1 Feb 2012 04:29:23 -0000 Mailing-List: contact zsh-workers-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Workers List List-Post: List-Help: X-Seq: 30176 Received: (qmail 7669 invoked from network); 1 Feb 2012 04:29:21 -0000 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.2 Received-SPF: none (ns1.primenet.com.au: domain at closedmail.com does not designate permitted sender hosts) From: Bart Schaefer Message-id: <120131202909.ZM6076@torch.brasslantern.com> Date: Tue, 31 Jan 2012 20:29:09 -0800 In-reply-to: <20120129183644.6d49d237@pws-pc.ntlworld.com> Comments: In reply to Peter Stephenson "Re: Bug with bash emulation regarding ':'" (Jan 29, 6:36pm) References: <20120129183644.6d49d237@pws-pc.ntlworld.com> X-Mailer: OpenZMail Classic (0.9.2 24April2005) To: zsh-workers@zsh.org Subject: Re: Bug with bash emulation regarding ':' MIME-version: 1.0 Content-type: text/plain; charset=us-ascii On Jan 29, 6:36pm, Peter Stephenson wrote: } } > _test () } > { } > array="one two three" } > for e in $array } > do } > echo "'$e'" } > done } > } } > } > l= } > : ${l:=$(_test)} } > echo "_${l}_" } >... } > _'one two three'_ } } presumably something is going on with quoting and/or tokenisation in or } close to multsub(), which is some of the hairier code in substitution, } when SH_WORD_SPLIT is in effect. Given that this sorta kinda worked back in 4.2.x ... I think the problem is explained by this comment (dates to 4.3.0-dev-4, which means this bug has gone unnoticed for almost exactly five years): 2619 case '-': 2620 if (vunset) { 2621 int ws = opts[SHWORDSPLIT]; 2622 val = dupstring(s); 2623 /* If word-splitting is enabled, we ask multsub() to split 2624 * the substituted string at unquoted whitespace. Then, we 2625 * turn off spbreak so that no further splitting occurs. 2626 * This allows a construct such as ${1+"$@"} to correctly 2627 * keep its array splits, and weird constructs such as 2628 * ${str+"one two" "3 2 1" foo "$str"} to only be split 2629 * at the unquoted spaces. */ 2630 opts[SHWORDSPLIT] = spbreak; 2631 multsub(&val, spbreak && !aspar, (aspar ? NULL : &aval), &isarr, NULL); 2632 opts[SHWORDSPLIT] = ws; 2633 copied = 1; 2634 spbreak = 0; The breakage in this specific example is at 2658 where SHWORDSPIT has been forced off, but there's probably another example where the above breaks too: 2648 case Equals: 2649 if (vunset) { 2650 int ws = opts[SHWORDSPLIT]; 2651 char sav = *idend; 2652 int l; 2653 2654 *idend = '\0'; 2655 val = dupstring(s); 2656 if (spsep || !arrasg) { 2657 opts[SHWORDSPLIT] = 0; 2658 multsub(&val, 0, NULL, &isarr, NULL); 2659 } else { 2660 opts[SHWORDSPLIT] = spbreak; 2661 multsub(&val, spbreak, &aval, &isarr, NULL); 2662 spbreak = 0; 2663 } 2664 opts[SHWORDSPLIT] = ws; The problem is that we want to suppress any further splitting in the current shell, but when we enter the subshell for $(...) it should revert to the original setting. I'm not sure how to pass that down the call stack appropriately.