Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Re: break/continue vs. try-always
On Sun, 08 Jun 2014 19:11:15 -0700
Bart Schaefer <schaefer@xxxxxxxxxxxxxxxx> 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 <schaefer@xxxxxxxxxxxxxxxx> 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 <p.w.stephenson@xxxxxxxxxxxx>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/
Messages sorted by:
Reverse Date,
Date,
Thread,
Author