Date: Mon, 23 Aug 2010 23:58:50 +0200 From: Jilles Tjoelker <jilles@stack.nl> To: Brian Somers <brian@FreeBSD.org> Cc: svn-src-head@FreeBSD.org, svn-src-all@FreeBSD.org, src-committers@FreeBSD.org Subject: Re: svn commit: r211609 - head/tools/regression/bin/sh/builtins Message-ID: <20100823215850.GC67671@stack.nl> In-Reply-To: <20100823003314.57d41b94@dev.lan.Awfulhak.org> References: <201008221104.o7MB4Ung001538@svn.freebsd.org> <20100823003314.57d41b94@dev.lan.Awfulhak.org>
next in thread | previous in thread | raw e-mail | index | archive | help
On Mon, Aug 23, 2010 at 12:33:14AM -0700, Brian Somers wrote: > On Sun, 22 Aug 2010 11:04:30 +0000 (UTC) Jilles Tjoelker <jilles@FreeBSD.org> wrote: > > Author: jilles > > Date: Sun Aug 22 11:04:30 2010 > > New Revision: 211609 > > URL: http://svn.freebsd.org/changeset/base/211609 > > Log: > > sh: Add a test for breaking from a loop outside the current function. > > It is unwise to rely on this but I'd like to know if this would break. > > Added: > > head/tools/regression/bin/sh/builtins/break3.0 (contents, props changed) > > Added: head/tools/regression/bin/sh/builtins/break3.0 > > ============================================================================== > > --- /dev/null 00:00:00 1970 (empty, because file is newly added) > > +++ head/tools/regression/bin/sh/builtins/break3.0 Sun Aug 22 11:04:30 2010 (r211609) > > @@ -0,0 +1,15 @@ > > +# $FreeBSD$ > > + > > +# We accept this and people might rely on it. > > +# However, various other shells do not accept it. > > + > > +f() { > > + break > > + echo bad1 > > +} > > + > > +while :; do > > + f > > + echo bad2 > > + exit 2 > > +done > This feature should be counted as a bug IMHO. How can f() possibly > know whether there's a surrounding context to break from? If you replace f by its definition, there is an obvious meaning. And how about a script like: while :; do f() { ...; break; ...; } ... f ... done I will admit that there are various other shells that do not implement this. > Having said that, this behaviour is the same in bash except that bash > will complain if it's asked to break when the context is wrong, > perhaps we should complain too? > $ bash -c 'f() { break; echo no break; }; for f in good bad; do echo $f; f; done' > good > $ sh -c 'f() { break; echo no break; }; for f in good bad; do echo $f; f; done' > good > $ bash -c 'f() { break; echo no break; }; f' > bash: line 0: break: only meaningful in a `for', `while', or `until' loop > no break > $ bash -c 'f() { break 2>/dev/null; echo no break; }; f' > no break > $ sh -c 'f() { break; echo no break; }; f' > no break The System V sh and ksh93 behave the same way with break and continue builtins outside loops. I don't think this is very broken, and there is a limit on how many incompatible changes I'm willing to make. This doesn't make the cut. Warning messages to stderr mostly get lost in the noise, I don't really like them. I do not expect people to test for failure of break and continue, and bash even sets $? to 0 despite printing a warning. If this error is so important as to need an error message I think should abort the shell as well (via error(), so that "command break" will avoid aborting). Furthermore note that bash disables these warnings in POSIX mode. As an aside, if breaking out of a function were to be disallowed, a stronger approach seems possible: special builtins cannot be overridden by functions or PATH (we currently do not implement this), so if the parser (after alias expansion) sees a command "break" or "continue", it must be the special builtin and a parse error could result if it is not in a loop, or possibly a ksh93-like parse warning with -n. -- Jilles Tjoelker
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20100823215850.GC67671>