--- src/bin/sh/eval.c 2004/03/19 18:39:41 1.4 +++ src/bin/sh/eval.c 2006/07/20 17:01:21 1.4.4.1 @@ -91,8 +91,8 @@ int exitstatus; /* exit status of last int oexitstatus; /* saved exit status */ -STATIC void evalloop(union node *); -STATIC void evalfor(union node *); +STATIC void evalloop(union node *, int); +STATIC void evalfor(union node *, int); STATIC void evalcase(union node *, int); STATIC void evalsubshell(union node *, int); STATIC void expredir(union node *); @@ -183,6 +183,9 @@ evalstring(char *s) void evaltree(union node *n, int flags) { + int do_etest; + + do_etest = 0; if (n == NULL) { TRACE(("evaltree(NULL) called\n")); exitstatus = 0; @@ -194,7 +197,7 @@ evaltree(union node *n, int flags) TRACE(("evaltree(0x%lx: %d) called\n", (long)n, n->type)); switch (n->type) { case NSEMI: - evaltree(n->nbinary.ch1, 0); + evaltree(n->nbinary.ch1, flags & ~EV_EXIT); if (evalskip) goto out; evaltree(n->nbinary.ch2, flags); @@ -202,7 +205,6 @@ evaltree(union node *n, int flags) case NAND: evaltree(n->nbinary.ch1, EV_TESTED); if (evalskip || exitstatus != 0) { - flags |= EV_TESTED; goto out; } evaltree(n->nbinary.ch2, flags); @@ -221,6 +223,7 @@ evaltree(union node *n, int flags) break; case NSUBSHELL: evalsubshell(n, flags); + do_etest = !(flags & EV_TESTED); break; case NBACKGND: evalsubshell(n, flags); @@ -239,29 +242,13 @@ evaltree(union node *n, int flags) } case NWHILE: case NUNTIL: - evalloop(n); + evalloop(n, flags & ~EV_EXIT); break; case NFOR: - evalfor(n); - /* - * The 'for' command does not set exitstatus, so the value - * now in exitstatus is from the last command executed in - * the 'for' loop. That exit value had been tested (wrt - * 'sh -e' checking) while processing that command, and - * it should not be re-tested here. - */ - flags |= EV_TESTED; + evalfor(n, flags & ~EV_EXIT); break; case NCASE: evalcase(n, flags); - /* - * The 'case' command does not set exitstatus, so the value - * now in exitstatus is from the last command executed in - * the 'case' block. That exit value had been tested (wrt - * 'sh -e' checking) while processing that command, and - * it should not be re-tested here. - */ - flags |= EV_TESTED; break; case NDEFUN: defun(n->narg.text, n->narg.next); @@ -274,9 +261,11 @@ evaltree(union node *n, int flags) case NPIPE: evalpipe(n); + do_etest = !(flags & EV_TESTED); break; case NCMD: evalcommand(n, flags, (struct backcmd *)NULL); + do_etest = !(flags & EV_TESTED); break; default: out1fmt("Node type = %d\n", n->type); @@ -286,20 +275,13 @@ evaltree(union node *n, int flags) out: if (pendingsigs) dotrap(); - /* - * XXX - Like "!(n->type == NSEMI)", more types will probably - * need to be excluded from this test. It's probably better - * to set or unset EV_TESTED in the loop above than to bloat - * the conditional here. - */ - if ((flags & EV_EXIT) || (eflag && exitstatus - && !(flags & EV_TESTED) && !(n->type == NSEMI))) + if ((flags & EV_EXIT) || (eflag && exitstatus != 0 && do_etest)) exitshell(exitstatus); } STATIC void -evalloop(union node *n) +evalloop(union node *n, int flags) { int status; @@ -323,7 +305,7 @@ skipping: if (evalskip == SKIPCONT && if (exitstatus == 0) break; } - evaltree(n->nbinary.ch2, 0); + evaltree(n->nbinary.ch2, flags); status = exitstatus; if (evalskip) goto skipping; @@ -335,7 +317,7 @@ skipping: if (evalskip == SKIPCONT && STATIC void -evalfor(union node *n) +evalfor(union node *n, int flags) { struct arglist arglist; union node *argp; @@ -356,7 +338,7 @@ evalfor(union node *n) loopnest++; for (sp = arglist.list ; sp ; sp = sp->next) { setvar(n->nfor.var, sp->text, 0); - evaltree(n->nfor.body, 0); + evaltree(n->nfor.body, flags); if (evalskip) { if (evalskip == SKIPCONT && --skipcount <= 0) { evalskip = 0;