From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 5788 invoked by alias); 12 Jun 2014 20:22:59 -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: 32768 Received: (qmail 16334 invoked from network); 12 Jun 2014 20:22:52 -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 X-Originating-IP: [86.6.157.246] X-Spam: 0 X-Authority: v=2.1 cv=R7aNGLhX c=1 sm=1 tr=0 a=BvYiZ/UW0Fmn8Wufq9dPrg==:117 a=BvYiZ/UW0Fmn8Wufq9dPrg==:17 a=NLZqzBF-AAAA:8 a=LGXc4NIGxrIA:10 a=uObrxnre4hsA:10 a=kj9zAlcOel0A:10 a=q2GGsy2AAAAA:8 a=Fl4RO6Ht0vV6opSMR9AA:9 a=CjuIK1q_8ugA:10 a=I6wTmPyJxzYA:10 a=_dQi-Dcv4p4A:10 Date: Thu, 12 Jun 2014 20:35:25 +0100 From: Peter Stephenson To: zsh-workers@zsh.org Subject: Re: break/continue vs. try-always Message-ID: <20140612203525.4c8e66d4@pws-pc.ntlworld.com> In-Reply-To: <140608191115.ZM20627@torch.brasslantern.com> References: <140603191227.ZM28198@torch.brasslantern.com> <140604223723.ZM22960@torch.brasslantern.com> <140605085319.ZM4272@torch.brasslantern.com> <20140606215853.0c6ecae9@pws-pc.ntlworld.com> <20140606224523.09d5f22c@pws-pc.ntlworld.com> <140606232250.ZM23057@torch.brasslantern.com> <20140608185401.35bed78f@pws-pc.ntlworld.com> <140608114123.ZM20229@torch.brasslantern.com> <20140608204358.4ec607b8@pws-pc.ntlworld.com> <140608140146.ZM20431@torch.brasslantern.com> <20140608225035.078a86a8@pws-pc.ntlworld.com> <140608191115.ZM20627@torch.brasslantern.com> X-Mailer: Claws Mail 3.8.0 (GTK+ 2.24.7; x86_64-redhat-linux-gnu) Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit On Sun, 08 Jun 2014 19:11:15 -0700 Bart Schaefer wrote: > On Jun 8, 10:50pm, Peter Stephenson wrote: > } Subject: Re: break/continue vs. try-always > } > } On Sun, 08 Jun 2014 14:01:46 -0700 > } Bart Schaefer wrote: > } > } neater way to handle this would be to add an option to force break and > } > } continue to respect function scope. > } > > } > The problem with that solution is that it propagates downward > } > } This is why I pointed out you could do > } > } setopt localoptions localloops > } () { > } setopt nolocalloops # or emulation or whatever > } # call user code > } } > } # localloops is restored on return here and used to cancel breaks / > } # contflag before resuming user code at this point. > > Ah, you didn't have the "setopt nolocalloops" in the anonymous scope > the last time. OK, this is fine, and it sets up up well in the event > that the austin-group decides to impose this semantics for Issue 8 > (though it looks like they're going to make it unspecified instead). This makes a break or continue at the end of a function produce a warning. It didn't seem worth a hard error, but presumably a break or continue is usually intended to do something so it should be reported if it doesn't. diff --git a/Doc/Zsh/options.yo b/Doc/Zsh/options.yo index 7788cd7..31247f5 100644 --- a/Doc/Zsh/options.yo +++ b/Doc/Zsh/options.yo @@ -1631,6 +1631,19 @@ tt(FUNCTION_ARGZERO) from on to off (or off to on) does not change the current value of tt($0). Only the state upon entry to the function or script has an effect. Compare tt(POSIX_ARGZERO). ) +pindex(LOCAL_LOOPS) +pindex(NO_LOCAL_LOOPS) +pindex(LOCALLOOPS) +pindex(NOLOCALLOOPS) +cindex(break, inside function) +cindex(continue, inside function) +cinde(function, scope of break and continue) +item(tt(LOCAL_LOOPS))( +When this option is not set, the effect of tt(break) and tt(continue) +commands may propagate outside function scope, affecting loops in +calling functions. When this option is not set, a tt(break) or +a tt(continue) that is not caught within a function produces a warning. +) pindex(LOCAL_OPTIONS) pindex(NO_LOCAL_OPTIONS) pindex(LOCALOPTIONS) diff --git a/Src/exec.c b/Src/exec.c index 8249def..a5982a7 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -4814,6 +4814,15 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval) opts[XTRACE] = saveopts[XTRACE]; opts[PRINTEXITVALUE] = saveopts[PRINTEXITVALUE]; opts[LOCALOPTIONS] = saveopts[LOCALOPTIONS]; + opts[LOCALLOOPS] = saveopts[LOCALLOOPS]; + } + + if (opts[LOCALLOOPS]) { + if (contflag) + zwarn("`continue' active at end of function scope"); + if (breaks) + zwarn("`break' active at end of function scope"); + contflag = breaks = 0; } endtrapscope(); diff --git a/Src/options.c b/Src/options.c index 2163bff..6e4e7b9 100644 --- a/Src/options.c +++ b/Src/options.c @@ -180,6 +180,7 @@ static struct optname optns[] = { {{NULL, "listrowsfirst", 0}, LISTROWSFIRST}, {{NULL, "listtypes", OPT_ALL}, LISTTYPES}, {{NULL, "localoptions", OPT_EMULATE|OPT_KSH}, LOCALOPTIONS}, +{{NULL, "localloops", OPT_EMULATE}, LOCALLOOPS}, {{NULL, "localpatterns", OPT_EMULATE}, LOCALPATTERNS}, {{NULL, "localtraps", OPT_EMULATE|OPT_KSH}, LOCALTRAPS}, {{NULL, "login", OPT_SPECIAL}, LOGINSHELL}, diff --git a/Src/zsh.h b/Src/zsh.h index 05d582c..fa73961 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -2129,6 +2129,7 @@ enum { LISTPACKED, LISTROWSFIRST, LISTTYPES, + LOCALLOOPS, LOCALOPTIONS, LOCALPATTERNS, LOCALTRAPS, diff --git a/Test/E01options.ztst b/Test/E01options.ztst index d9f2191..46b1837 100644 --- a/Test/E01options.ztst +++ b/Test/E01options.ztst @@ -430,7 +430,7 @@ foo unfunction foo 0:FUNCTION_ARGZERO option ->My name is ZTST_execchunk +>My name is (anon) >My name is foo setopt _NO_glob_ @@ -1114,3 +1114,45 @@ >1 >1 >2 + + for (( i = 0; i < 10; i++ )); do + () { + print $i + break + } + done +0:NO_LOCAL_LOOPS +>0 + + () { + emulate -L zsh + setopt localloops + for (( i = 0; i < 10; i++ )); do + () { + setopt nolocalloops # ignored in parent + print $i + break + } + done + } +0:LOCAL_LOOPS +>0 +>1 +>2 +>3 +>4 +>5 +>6 +>7 +>8 +>9 +?(anon):4: `break' active at end of function scope +?(anon):4: `break' active at end of function scope +?(anon):4: `break' active at end of function scope +?(anon):4: `break' active at end of function scope +?(anon):4: `break' active at end of function scope +?(anon):4: `break' active at end of function scope +?(anon):4: `break' active at end of function scope +?(anon):4: `break' active at end of function scope +?(anon):4: `break' active at end of function scope +?(anon):4: `break' active at end of function scope diff --git a/Test/ztst.zsh b/Test/ztst.zsh index 745a13c..74111f6 100755 --- a/Test/ztst.zsh +++ b/Test/ztst.zsh @@ -260,8 +260,12 @@ $ZTST_redir" # Execute an indented chunk. Redirections will already have # been set up, but we need to handle the options. ZTST_execchunk() { + setopt localloops # don't let continue & break propagate out options=($ZTST_testopts) - eval "$ZTST_code" + () { + unsetopt localloops + eval "$ZTST_code" + } ZTST_status=$? # careful... ksh_arrays may be in effect. ZTST_testopts=(${(kv)options[*]}) -- Peter Stephenson Web page now at http://homepage.ntlworld.com/p.w.stephenson/