sh: Make return return from the closest function or dot script.

Formerly, return always returned from a function if it was called from a
function, even if there was a closer dot script. This was for compatibility
with the Bourne shell which only allowed returning from functions.

Other modern shells and POSIX return from the function or the dot script,
whichever is closest.

Git 1.8.4's rebase --continue depends on the POSIX behaviour.

Reported by:	Christoph Mallon, avg
This commit is contained in:
Jilles Tjoelker 2013-09-04 22:10:16 +00:00
parent dbbd7a968b
commit 2935c4cc5e
5 changed files with 23 additions and 15 deletions

View File

@ -324,7 +324,7 @@ skipping: if (evalskip == SKIPCONT && --skipcount <= 0) {
}
if (evalskip == SKIPBREAK && --skipcount <= 0)
evalskip = 0;
if (evalskip == SKIPFUNC || evalskip == SKIPFILE)
if (evalskip == SKIPRETURN)
status = exitstatus;
break;
}
@ -1068,7 +1068,7 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
funcnest--;
popredir();
INTON;
if (evalskip == SKIPFUNC) {
if (evalskip == SKIPRETURN) {
evalskip = 0;
skipcount = 0;
}
@ -1305,14 +1305,8 @@ returncmd(int argc, char **argv)
{
int ret = argc > 1 ? number(argv[1]) : oexitstatus;
if (funcnest) {
evalskip = SKIPFUNC;
skipcount = 1;
} else {
/* skip the rest of the file */
evalskip = SKIPFILE;
skipcount = 1;
}
evalskip = SKIPRETURN;
skipcount = 1;
return ret;
}

View File

@ -67,5 +67,4 @@ extern int skipcount;
/* reasons for skipping commands (see comment on breakcmd routine) */
#define SKIPBREAK 1
#define SKIPCONT 2
#define SKIPFUNC 3
#define SKIPFILE 4
#define SKIPRETURN 3

View File

@ -231,7 +231,7 @@ cmdloop(int top)
popstackmark(&smark);
setstackmark(&smark);
if (evalskip != 0) {
if (evalskip == SKIPFILE)
if (evalskip == SKIPRETURN)
evalskip = 0;
break;
}

View File

@ -1145,8 +1145,10 @@ command is
.Pp
.D1 Ic return Op Ar exitstatus
.Pp
It terminates the current executional scope, returning from the previous
nested function, sourced script, or shell instance, in that order.
It terminates the current executional scope, returning from the closest
nested function or sourced script;
if no function or sourced script is being executed,
it exits the shell instance.
The
.Ic return
command is implemented as a special built-in command.

View File

@ -0,0 +1,13 @@
# $FreeBSD$
if [ "$1" = nested ]; then
return 17
fi
f() {
set -- nested
. "$0"
return $(($? ^ 1))
}
f
exit $(($? ^ 16))