zsh-workers
 help / color / mirror / code / Atom feed
* Bug with "return" from inside "if"
@ 2016-11-05 20:25 Bart Schaefer
  2016-11-05 21:00 ` Bart Schaefer
  0 siblings, 1 reply; 4+ messages in thread
From: Bart Schaefer @ 2016-11-05 20:25 UTC (permalink / raw)
  To: zsh-workers

% () { if return 1; then echo yes; else echo no; fi } && echo $?
0

This goes back at least as far as zsh 4.2.

diff --git a/Src/loop.c b/Src/loop.c
index b791a89..f65c72b 100644
--- a/Src/loop.c
+++ b/Src/loop.c
@@ -570,7 +570,8 @@ execif(Estate state, int do_exec)
 	cmdpop();
     } else {
 	noerrexit = olderrexit;
-	lastval = 0;
+	if (!retflag)
+	    lastval = 0;
     }
     state->pc = end;
 


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Bug with "return" from inside "if"
  2016-11-05 20:25 Bug with "return" from inside "if" Bart Schaefer
@ 2016-11-05 21:00 ` Bart Schaefer
  2016-11-05 22:16   ` Bug (?) with "return" from inside "while" Bart Schaefer
  0 siblings, 1 reply; 4+ messages in thread
From: Bart Schaefer @ 2016-11-05 21:00 UTC (permalink / raw)
  To: zsh-workers

On Nov 5,  1:25pm, Bart Schaefer wrote:
} Subject: Bug with "return" from inside "if"
}
} % () { if return 1; then echo yes; else echo no; fi } && echo $?
} 0

Incidentally:

whatsupwithwhile () {
   while return 1
   do ;
   done
}

Both dash and zsh return an exit status of zero from whatsupwithwhile;
bash returns 1.

The change for this, if desirable, is less obvious than with execif(),
so I haven't dug into it yet.


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Bug (?) with "return" from inside "while"
  2016-11-05 21:00 ` Bart Schaefer
@ 2016-11-05 22:16   ` Bart Schaefer
  2016-11-07  9:38     ` Peter Stephenson
  0 siblings, 1 reply; 4+ messages in thread
From: Bart Schaefer @ 2016-11-05 22:16 UTC (permalink / raw)
  To: zsh-workers

On Nov 5,  2:00pm, Bart Schaefer wrote:
}
} The change for [execwhile()] is less obvious than with execif(),

As best I can tell, the exit value of a "while" loop is supposed to
be the exit value of the last executed statement in the loop-body,
but the value of $? on entry to the loop body is supposed to be the
value of the last executed statement in the condition.

Thus

    i=0
    while (( i++ < 1 )); do echo $?; (return 27); done
    echo $?

should echo

    0
    27

And

    i=0
    until (( i++ == 1 )); do echo $?; (return 27); done
    echo $?

should echo

    1
    27

The question is what the exit status should be if the conditional
includes an explicit "return N".  dash and zsh up to this point
return the exit status of the loop body, or zero if the loop body
has never executed.  Bash returns N, which seems more correct.

A related question is what happens if the loop is interrupted with
^C.  The most recent changes to execwhile() are all about handling
that (plus making the interrupt possible if the condition or body
or both are empty).  Is an interrupted condition the same as one
that returned false (or true in the case of until)?  This somewhat
obscures what is intended in the case where there is no interrupt.

There's also the question of what $? should be upon entry to the
condition.  On the first loop it's unchanged from the previous
command, but on successive loops it's the value from the loop body.
On the other hand the value of $? on entry to the loop body is the
value from the condition (always 0 for while, nonzero for until).
(Patch below doesn't address this at all.)

I think the following is the minimum sensible change but there may
be corner cases that it's not covering.

diff --git a/Src/loop.c b/Src/loop.c
index f65c72b..367c0df 100644
--- a/Src/loop.c
+++ b/Src/loop.c
@@ -439,13 +439,12 @@ execwhile(Estate state, UNUSED(int do_exec))
             if (!((lastval == 0) ^ isuntil)) {
                 if (breaks)
                     breaks--;
-                lastval = oldval;
+		if (!retflag)
+		    lastval = oldval;
                 break;
             }
-            if (retflag) {
-                lastval = oldval;
+            if (retflag)
                 break;
-            }
 
 	    /* In case the loop body is also a functional no-op,
 	     * make sure signal handlers recognize ^C as above. */


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Bug (?) with "return" from inside "while"
  2016-11-05 22:16   ` Bug (?) with "return" from inside "while" Bart Schaefer
@ 2016-11-07  9:38     ` Peter Stephenson
  0 siblings, 0 replies; 4+ messages in thread
From: Peter Stephenson @ 2016-11-07  9:38 UTC (permalink / raw)
  To: zsh-workers

On Sat, 5 Nov 2016 15:16:09 -0700
Bart Schaefer <schaefer@brasslantern.com> wrote:
> As best I can tell, the exit value of a "while" loop is supposed to
> be the exit value of the last executed statement in the loop-body,
> but the value of $? on entry to the loop body is supposed to be the
> value of the last executed statement in the condition.

Yes, that just got fixed for certain constructs.

> The question is what the exit status should be if the conditional
> includes an explicit "return N".  dash and zsh up to this point
> return the exit status of the loop body, or zero if the loop body
> has never executed.  Bash returns N, which seems more correct.

You'd think so.

> A related question is what happens if the loop is interrupted with
> ^C.  The most recent changes to execwhile() are all about handling
> that (plus making the interrupt possible if the condition or body
> or both are empty).  Is an interrupted condition the same as one
> that returned false (or true in the case of until)?  This somewhat
> obscures what is intended in the case where there is no interrupt.

If it's interrupted, any stack of callers should be interrupted, too.
The status should only be significant when you get back to the top
level, or exit the shell, and this should happen if errflag is et.  Then
it should fix up a suitable status at that opint.  So the key thing
internally is making sure it does get interrupted.

> There's also the question of what $? should be upon entry to the
> condition.  On the first loop it's unchanged from the previous
> command, but on successive loops it's the value from the loop body.
> On the other hand the value of $? on entry to the loop body is the
> value from the condition (always 0 for while, nonzero for until).
> (Patch below doesn't address this at all.)

That's not obviously stupid.  Those are the last commands to have been
executed.  Recently found problems were due to clearing it when it
shouldn't be, rather than leaving it do the last value.

pws


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2016-11-07  9:39 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-11-05 20:25 Bug with "return" from inside "if" Bart Schaefer
2016-11-05 21:00 ` Bart Schaefer
2016-11-05 22:16   ` Bug (?) with "return" from inside "while" Bart Schaefer
2016-11-07  9:38     ` Peter Stephenson

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).