diff options
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | Doc/Zsh/options.yo | 23 | ||||
-rw-r--r-- | Src/exec.c | 17 | ||||
-rw-r--r-- | Src/options.c | 1 | ||||
-rw-r--r-- | Src/zsh.h | 1 | ||||
-rw-r--r-- | Test/E01options.ztst | 44 | ||||
-rwxr-xr-x | Test/ztst.zsh | 6 |
7 files changed, 90 insertions, 8 deletions
diff --git a/ChangeLog b/ChangeLog index 2b689b71d..6c4355e2f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2014-06-13 Peter Stephenson <p.w.stephenson@ntlworld.com> + * 32768, with further modifications: Doc/Zsh/options.yo, + Src/exec.c, Src/options.c, Src/zsh.h, Test/E01options.ztst, + Test/ztst.zsh: LOCAL_LOOPS option to restrict effect of + continue and break in function scope. + * 32666: Doc/Zsh/compat.yo: shell emulation based on executable name incompletely documented. @@ -18,6 +23,7 @@ * Jun T: 32755: Doc/Zsh/grammar.yo: move line that was in the wrong place. + 2014-06-07 Barton E. Schaefer <schaefer@zsh.org> * Nikolas Garofil: 32737: Src/utils.c: properly ifdef declarations diff --git a/Doc/Zsh/options.yo b/Doc/Zsh/options.yo index 7788cd755..9cb385e49 100644 --- a/Doc/Zsh/options.yo +++ b/Doc/Zsh/options.yo @@ -1631,6 +1631,21 @@ 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 the option is set in a calling function, a +tt(break) or a tt(continue) that is not caught within a called function +(regardless of the setting of the option within that function) +produces a warning and the effect is cancelled. +) pindex(LOCAL_OPTIONS) pindex(NO_LOCAL_OPTIONS) pindex(LOCALOPTIONS) @@ -1639,10 +1654,10 @@ item(tt(LOCAL_OPTIONS) <K>)( If this option is set at the point of return from a shell function, most options (including this one) which were in force upon entry to the function are restored; options that are not restored are -tt(PRIVILEGED) and tt(RESTRICTED). Otherwise, only this option and the -tt(XTRACE) and tt(PRINT_EXIT_VALUE) options are restored. Hence -if this is explicitly unset by a shell function the other options in -force at the point of return will remain so. +tt(PRIVILEGED) and tt(RESTRICTED). Otherwise, only this option, +and the tt(LOCAL_LOOPS), tt(XTRACE) and tt(PRINT_EXIT_VALUE) options are +restored. Hence if this is explicitly unset by a shell function the +other options in force at the point of return will remain so. A shell function can also guarantee itself a known shell configuration with a formulation like `tt(emulate -L zsh)'; the tt(-L) activates tt(LOCAL_OPTIONS). diff --git a/Src/exec.c b/Src/exec.c index 8249deff2..5ad957f98 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -4614,7 +4614,7 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval) char *name = shfunc->node.nam; int flags = shfunc->node.flags, ooflags; char *fname = dupstring(name); - int obreaks, saveemulation, restore_sticky; + int obreaks, ocontflag, oloops, saveemulation, restore_sticky; Eprog prog; struct funcstack fstack; static int oflags; @@ -4626,7 +4626,9 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval) pushheap(); oargv0 = NULL; - obreaks = breaks;; + obreaks = breaks; + ocontflag = contflag; + oloops = loops; if (trap_state == TRAP_STATE_PRIMED) trap_return--; oldlastval = lastval; @@ -4814,6 +4816,17 @@ 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"); + breaks = obreaks; + contflag = ocontflag; + loops = oloops; } endtrapscope(); diff --git a/Src/options.c b/Src/options.c index 2163bff4d..6e4e7b911 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 05d582cda..fa7396112 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 d9f219115..46b183776 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 745a13cff..74111f6cc 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[*]}) |