From b3fa5c528c79b27986a77c92a48b7f70e7f9e7d3 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Fri, 13 Oct 2017 18:17:09 +0100 Subject: 41877: Separate out SH_FILE_EXPANSION loop from parameter substitution. Parameter substitution can add nodes that need to be rescanned by it, but not by file expansion, so the two don't play well together. --- ChangeLog | 8 ++++++++ Src/subst.c | 39 +++++++++++++++++++++++---------------- Test/E01options.ztst | 10 ++++++++++ 3 files changed, 41 insertions(+), 16 deletions(-) diff --git a/ChangeLog b/ChangeLog index 06f3ba89c..d89e92f95 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2017-10-13 Peter Stephenson + + * 41877: Src/subst·c, Test/E01options.ztst: Separate out + SH_FILE_EXPANSION loop from parameter substitution as the latter + can add nodes: SH_FILE_EXPANSION should see following nodes + only, but on the next loop parameter substitution needs to see + added nodes for further expansion. + 2017-10-11 Daniel Shahaf * 41825/0002: Completion/Zsh/Command/_stat: Complete -x options diff --git a/Src/subst.c b/Src/subst.c index 8c290cccf..d027e3d83 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -108,7 +108,6 @@ prefork(LinkList list, int flags, int *ret_flags) queue_signals(); node = firstnode(list); while (node) { - LinkNode nextnode = 0; if ((flags & (PREFORK_SINGLE|PREFORK_ASSIGN)) == PREFORK_ASSIGN && (insnode = keyvalpairelement(list, node))) { node = insnode; @@ -137,23 +136,31 @@ prefork(LinkList list, int flags, int *ret_flags) * testing if cptr changed... */ setdata(node, cptr); - /* - * Advance now because we must not expand filenames again - * after string substitution (which may insert new nodes). - */ - nextnode = node; - incnode(nextnode); - } - if (!(node = stringsubst(list, node, - flags & ~(PREFORK_TYPESET|PREFORK_ASSIGN), - ret_flags, asssub))) { - unqueue_signals(); - return; } - if (isset(SHFILEEXPANSION)) - node = nextnode; else - incnode(node); + { + if (!(node = stringsubst(list, node, + flags & ~(PREFORK_TYPESET|PREFORK_ASSIGN), + ret_flags, asssub))) { + unqueue_signals(); + return; + } + } + incnode(node); + } + if (isset(SHFILEEXPANSION)) { + /* + * stringsubst() may insert new nodes, so doesn't work + * well in the same loop as file expansion. + */ + for (node = firstnode(list); node; incnode(node)) { + if (!(node = stringsubst(list, node, + flags & ~(PREFORK_TYPESET|PREFORK_ASSIGN), + ret_flags, asssub))) { + unqueue_signals(); + return; + } + } } for (node = firstnode(list); node; incnode(node)) { if (node == stop) diff --git a/Test/E01options.ztst b/Test/E01options.ztst index 6929f5140..0f6bb3455 100644 --- a/Test/E01options.ztst +++ b/Test/E01options.ztst @@ -1038,6 +1038,16 @@ F:Regression test for workers/41811 >~/one >~/two + ( + setopt shfileexpansion + set -- also appearing + print -l $*$* + ) +0:SH_FILE_EXPANSION interaction with inserting nodes from parameters +>also +>appearingalso +>appearing + testpat() { if [[ $1 = ${~2} ]]; then print $1 $2 yes; else print $1 $2 no; fi } -- cgit 1.4.1