Re: 'continue' does not work in files sourced with dotcmd

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, Jul 08, 2011 at 04:09:36PM +0800, Herbert Xu wrote:
> On Thu, Jul 07, 2011 at 09:18:12AM -0600, Eric Blake wrote:
> > Meanwhile, I still have to wonder about dash behavior - if dash is _not_
> > treating continue as a syntax error, then why is it aborting the dot
> > script?  Compare:

> This is a consequence of the way continue/break/return is implemented
> in dash.

> As this construct cannot be used portably anyway, I'm not inclined to
> make any changes unless you can do it without increasing the code
> size.

It is not a hard consequence, the behaviour can be fixed fairly easily.

I noticed a similar problem in FreeBSD sh and fixed it in head in August
2010, Subversion r211349.

A testcase is (note that this must be saved to a named file because it
sources itself):
####
# $FreeBSD: head/tools/regression/bin/sh/builtins/break1.0 211349 2010-08-15 21:06:53Z jilles $

if [ "$1" != nested ]; then
	while :; do
		set -- nested
		. "$0"
		echo bad2
		exit 2
	done
	exit 0
fi
# To trigger the bug, the following commands must be at the top level,
# with newlines in between.
break
echo bad1
exit 1
####

Given that quite a few shells pass this test, I consider it prudent to
make it work. It is not unlikely that someone somewhere has written a
script that depends on it, and treating the break or continue as a
return is rather surprising in a negative way. (Similar for break or
continue in eval or trap, though I think those work in dash.)

A fix for dash is below. The dash code is broken in a different way than
the FreeBSD sh code was, but the patched code is pretty much the same.
This makes the above test work and does not change the outcome of any
other tests in the FreeBSD sh testsuite.

diff --git a/src/main.c b/src/main.c
index af987c6..cdd91e2 100644
--- a/src/main.c
+++ b/src/main.c
@@ -242,7 +242,8 @@ cmdloop(int top)
 
 		skip = evalskip;
 		if (skip) {
-			evalskip = 0;
+			if (skip == SKIPFILE)
+				evalskip = 0;
 			break;
 		}
 	}

Using
	evalskip &= ~SKIPFILE;
instead of
	if (skip == SKIPFILE)
		evalskip = 0;
should also work and might generate shorter code.

-- 
Jilles Tjoelker
--
To unsubscribe from this list: send the line "unsubscribe dash" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [LARTC]     [Bugtraq]     [Yosemite Forum]     [Photo]

  Powered by Linux