summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--shell/ash.c56
-rw-r--r--shell/ash_test/ash-misc/func6.right2
-rwxr-xr-xshell/ash_test/ash-misc/func6.tests11
3 files changed, 42 insertions, 27 deletions
diff --git a/shell/ash.c b/shell/ash.c
index 06df07d..e4349cc 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -8632,37 +8632,50 @@ static
#endif
int evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
+static int skiploop(void)
+{
+ int skip = evalskip;
+
+ switch (skip) {
+ case 0:
+ break;
+ case SKIPBREAK:
+ case SKIPCONT:
+ if (--skipcount <= 0) {
+ evalskip = 0;
+ break;
+ }
+ skip = SKIPBREAK;
+ break;
+ }
+ return skip;
+}
+
static int
evalloop(union node *n, int flags)
{
+ int skip;
int status;
loopnest++;
status = 0;
flags &= EV_TESTED;
- for (;;) {
+ do {
int i;
i = evaltree(n->nbinary.ch1, EV_TESTED);
- if (evalskip) {
- skipping:
- if (evalskip == SKIPCONT && --skipcount <= 0) {
- evalskip = 0;
- continue;
- }
- if (evalskip == SKIPBREAK && --skipcount <= 0)
- evalskip = 0;
- break;
- }
+ skip = skiploop();
+ if (skip == SKIPFUNC)
+ status = i;
+ if (skip)
+ continue;
if (n->type != NWHILE)
i = !i;
if (i != 0)
break;
status = evaltree(n->nbinary.ch2, flags);
- if (evalskip)
- goto skipping;
- }
- exitstatus = status;
+ skip = skiploop();
+ } while (!(skip & ~SKIPCONT));
loopnest--;
return status;
@@ -8682,9 +8695,6 @@ evalfor(union node *n, int flags)
arglist.lastp = &arglist.list;
for (argp = n->nfor.args; argp; argp = argp->narg.next) {
expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
- /* XXX */
- if (evalskip)
- goto out;
}
*arglist.lastp = NULL;
@@ -8693,18 +8703,10 @@ evalfor(union node *n, int flags)
for (sp = arglist.list; sp; sp = sp->next) {
setvar0(n->nfor.var, sp->text);
status = evaltree(n->nfor.body, flags);
- if (evalskip) {
- if (evalskip == SKIPCONT && --skipcount <= 0) {
- evalskip = 0;
- continue;
- }
- if (evalskip == SKIPBREAK && --skipcount <= 0)
- evalskip = 0;
+ if (skiploop() & ~SKIPCONT)
break;
- }
}
loopnest--;
- out:
popstackmark(&smark);
return status;
diff --git a/shell/ash_test/ash-misc/func6.right b/shell/ash_test/ash-misc/func6.right
new file mode 100644
index 0000000..0ebd8e5
--- /dev/null
+++ b/shell/ash_test/ash-misc/func6.right
@@ -0,0 +1,2 @@
+Two:2
+Two:2
diff --git a/shell/ash_test/ash-misc/func6.tests b/shell/ash_test/ash-misc/func6.tests
new file mode 100755
index 0000000..029c3e8
--- /dev/null
+++ b/shell/ash_test/ash-misc/func6.tests
@@ -0,0 +1,11 @@
+f1() {
+ while return 2; do :; done
+}
+f1
+echo Two:$?
+
+f2() {
+ while :; do return 2; done
+}
+f2
+echo Two:$?