aboutsummaryrefslogtreecommitdiff
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 06df07d06..e4349ccad 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -8632,37 +8632,50 @@ static
8632#endif 8632#endif
8633int evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__)); 8633int evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
8634 8634
8635static int skiploop(void)
8636{
8637 int skip = evalskip;
8638
8639 switch (skip) {
8640 case 0:
8641 break;
8642 case SKIPBREAK:
8643 case SKIPCONT:
8644 if (--skipcount <= 0) {
8645 evalskip = 0;
8646 break;
8647 }
8648 skip = SKIPBREAK;
8649 break;
8650 }
8651 return skip;
8652}
8653
8635static int 8654static int
8636evalloop(union node *n, int flags) 8655evalloop(union node *n, int flags)
8637{ 8656{
8657 int skip;
8638 int status; 8658 int status;
8639 8659
8640 loopnest++; 8660 loopnest++;
8641 status = 0; 8661 status = 0;
8642 flags &= EV_TESTED; 8662 flags &= EV_TESTED;
8643 for (;;) { 8663 do {
8644 int i; 8664 int i;
8645 8665
8646 i = evaltree(n->nbinary.ch1, EV_TESTED); 8666 i = evaltree(n->nbinary.ch1, EV_TESTED);
8647 if (evalskip) { 8667 skip = skiploop();
8648 skipping: 8668 if (skip == SKIPFUNC)
8649 if (evalskip == SKIPCONT && --skipcount <= 0) { 8669 status = i;
8650 evalskip = 0; 8670 if (skip)
8651 continue; 8671 continue;
8652 }
8653 if (evalskip == SKIPBREAK && --skipcount <= 0)
8654 evalskip = 0;
8655 break;
8656 }
8657 if (n->type != NWHILE) 8672 if (n->type != NWHILE)
8658 i = !i; 8673 i = !i;
8659 if (i != 0) 8674 if (i != 0)
8660 break; 8675 break;
8661 status = evaltree(n->nbinary.ch2, flags); 8676 status = evaltree(n->nbinary.ch2, flags);
8662 if (evalskip) 8677 skip = skiploop();
8663 goto skipping; 8678 } while (!(skip & ~SKIPCONT));
8664 }
8665 exitstatus = status;
8666 loopnest--; 8679 loopnest--;
8667 8680
8668 return status; 8681 return status;
@@ -8682,9 +8695,6 @@ evalfor(union node *n, int flags)
8682 arglist.lastp = &arglist.list; 8695 arglist.lastp = &arglist.list;
8683 for (argp = n->nfor.args; argp; argp = argp->narg.next) { 8696 for (argp = n->nfor.args; argp; argp = argp->narg.next) {
8684 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE); 8697 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8685 /* XXX */
8686 if (evalskip)
8687 goto out;
8688 } 8698 }
8689 *arglist.lastp = NULL; 8699 *arglist.lastp = NULL;
8690 8700
@@ -8693,18 +8703,10 @@ evalfor(union node *n, int flags)
8693 for (sp = arglist.list; sp; sp = sp->next) { 8703 for (sp = arglist.list; sp; sp = sp->next) {
8694 setvar0(n->nfor.var, sp->text); 8704 setvar0(n->nfor.var, sp->text);
8695 status = evaltree(n->nfor.body, flags); 8705 status = evaltree(n->nfor.body, flags);
8696 if (evalskip) { 8706 if (skiploop() & ~SKIPCONT)
8697 if (evalskip == SKIPCONT && --skipcount <= 0) {
8698 evalskip = 0;
8699 continue;
8700 }
8701 if (evalskip == SKIPBREAK && --skipcount <= 0)
8702 evalskip = 0;
8703 break; 8707 break;
8704 }
8705 } 8708 }
8706 loopnest--; 8709 loopnest--;
8707 out:
8708 popstackmark(&smark); 8710 popstackmark(&smark);
8709 8711
8710 return status; 8712 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 000000000..0ebd8e5a3
--- /dev/null
+++ b/shell/ash_test/ash-misc/func6.right
@@ -0,0 +1,2 @@
1Two:2
2Two:2
diff --git a/shell/ash_test/ash-misc/func6.tests b/shell/ash_test/ash-misc/func6.tests
new file mode 100755
index 000000000..029c3e85e
--- /dev/null
+++ b/shell/ash_test/ash-misc/func6.tests
@@ -0,0 +1,11 @@
1f1() {
2 while return 2; do :; done
3}
4f1
5echo Two:$?
6
7f2() {
8 while :; do return 2; done
9}
10f2
11echo Two:$?