zsh-workers
 help / color / mirror / code / Atom feed
* 'case' zeroes "$?"
@ 2016-10-09 21:01 ` Martijn Dekker
  2016-10-09 21:34   ` Martijn Dekker
  2016-10-10  8:55   ` Peter Stephenson
  0 siblings, 2 replies; 4+ messages in thread
From: Martijn Dekker @ 2016-10-09 21:01 UTC (permalink / raw)
  To: Zsh hackers list

Unlike on other shells, 'case' on zsh zeroes "$?" before executing a
command within 'case', making it more inconvenient to test exit status.

Example:

(exit 37) || case $? in 37) echo "$?";; esac

All shells except zsh and Busybox ash output 37; zsh outputs 0.
(dash recently fixed this: 0.5.8 outputs 0, 0.5.9.1 outputs 37.)

Thanks,

- Martijn


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

* Re: 'case' zeroes "$?"
  2016-10-09 21:01 ` 'case' zeroes "$?" Martijn Dekker
@ 2016-10-09 21:34   ` Martijn Dekker
  2016-10-10  8:55   ` Peter Stephenson
  1 sibling, 0 replies; 4+ messages in thread
From: Martijn Dekker @ 2016-10-09 21:34 UTC (permalink / raw)
  To: Zsh hackers list

Op 09-10-16 om 23:01 schreef Martijn Dekker:
> Example:
> 
> (exit 37) || case $? in 37) echo "$?";; esac
> 
> All shells except zsh and Busybox ash output 37; zsh outputs 0.

Actually, busybox ash just fixed this as well, see:
https://bugs.busybox.net/show_bug.cgi?id=9311
https://git.kernel.org/cgit/utils/dash/dash.git/commit/?id=da534b740e628512e8e0e62729d6a2ef521e5096

FreeBSD sh, another Almquist derivative, also outputs 37.

Thanks,

- M.


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

* Re: 'case' zeroes "$?"
  2016-10-09 21:01 ` 'case' zeroes "$?" Martijn Dekker
  2016-10-09 21:34   ` Martijn Dekker
@ 2016-10-10  8:55   ` Peter Stephenson
  2016-10-13  9:30     ` Martijn Dekker
  1 sibling, 1 reply; 4+ messages in thread
From: Peter Stephenson @ 2016-10-10  8:55 UTC (permalink / raw)
  To: Zsh hackers list

On Sun, 9 Oct 2016 23:01:35 +0200
Martijn Dekker <martijn@inlv.org> wrote:
> Unlike on other shells, 'case' on zsh zeroes "$?" before executing a
> command within 'case', making it more inconvenient to test exit status.
> 
> Example:
> 
> (exit 37) || case $? in 37) echo "$?";; esac

This looks straightforward.  The first $? in the case pattern is expanded
as a command line argument, before the case is executed, so missed this.

diff --git a/Src/loop.c b/Src/loop.c
index 3b9d021..94b61b7 100644
--- a/Src/loop.c
+++ b/Src/loop.c
@@ -592,7 +592,6 @@ execcase(Estate state, int do_exec)
     word = ecgetstr(state, EC_DUP, NULL);
     singsub(&word);
     untokenize(word);
-    lastval = 0;
 
     cmdpush(CS_CASE);
     while (state->pc < end) {
diff --git a/Test/A01grammar.ztst b/Test/A01grammar.ztst
index 0b1085c..0e77f3e 100644
--- a/Test/A01grammar.ztst
+++ b/Test/A01grammar.ztst
@@ -757,6 +757,14 @@
 >}
 >Stuff here
 
+  (exit 37)
+  case $? in
+    (37) echo $?
+    ;;
+  esac
+0:case retains exit status for execution of cases
+>37
+
   x=1
   x=2 | echo $x
   echo $x


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

* Re: 'case' zeroes "$?"
  2016-10-10  8:55   ` Peter Stephenson
@ 2016-10-13  9:30     ` Martijn Dekker
  0 siblings, 0 replies; 4+ messages in thread
From: Martijn Dekker @ 2016-10-13  9:30 UTC (permalink / raw)
  To: Zsh hackers list

Op 10-10-16 om 10:55 schreef Peter Stephenson:
> On Sun, 9 Oct 2016 23:01:35 +0200
> Martijn Dekker <martijn@inlv.org> wrote:
>> > Unlike on other shells, 'case' on zsh zeroes "$?" before executing a
>> > command within 'case', making it more inconvenient to test exit status.
>> > 
>> > Example:
>> > 
>> > (exit 37) || case $? in 37) echo "$?";; esac
> This looks straightforward.

Perhaps not quite. The patch has introduced a new bug: instead of
prematurely resetting the exit status, it's now not reset at all.

Test script:

false
case stuff in (nomatch) foo ;; esac
echo $?

Expected output: 0
Actual output: 1

Reference:
http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_09_04_05
"The exit status of case shall be zero if no patterns are matched.
Otherwise, the exit status shall be the exit status of the last command
executed in the compound-list."

So we need a flag to remember if any patterns are matched. Let me try my
hand at a patch for this:

diff --git a/Src/loop.c b/Src/loop.c
index 94b61b7..0b9ab15 100644
--- a/Src/loop.c
+++ b/Src/loop.c
@@ -584,7 +584,7 @@ execcase(Estate state, int do_exec)
     Wordcode end, next;
     wordcode code = state->pc[-1];
     char *word, *pat;
-    int npat, save, nalts, ialt, patok;
+    int npat, save, nalts, ialt, patok, anypatok;
     Patprog *spprog, pprog;

     end = state->pc + WC_CASE_SKIP(code);
@@ -592,6 +592,7 @@ execcase(Estate state, int do_exec)
     word = ecgetstr(state, EC_DUP, NULL);
     singsub(&word);
     untokenize(word);
+    anypatok = 0;

     cmdpush(CS_CASE);
     while (state->pc < end) {
@@ -648,7 +649,7 @@ execcase(Estate state, int do_exec)
 		    *spprog = pprog;
 	    }
 	    if (pprog && pattry(pprog, word))
-		patok = 1;
+		patok = anypatok = 1;
 	    state->pc += 2;
 	    nalts--;
 	}
@@ -679,6 +680,9 @@ execcase(Estate state, int do_exec)

     state->pc = end;

+    if (!anypatok)
+	lastval = 0;
+
     return lastval;
 }

diff --git a/Test/A01grammar.ztst b/Test/A01grammar.ztst
index 0e77f3e..e4b6870 100644
--- a/Test/A01grammar.ztst
+++ b/Test/A01grammar.ztst
@@ -765,6 +765,23 @@
 0:case retains exit status for execution of cases
 >37

+  false
+  case stuff in
+    (nomatch) foo
+    ;;
+  esac
+  echo $?
+0:case sets exit status to zero if no patterns are matched
+>0
+
+  case match in
+    (match) true; false; (exit 37)
+    ;;
+  esac
+  echo $?
+0:case keeps exit status of last command executed in compound-list
+>37
+
   x=1
   x=2 | echo $x
   echo $x


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

end of thread, other threads:[~2016-10-13  9:30 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <CGME20161009210214eucas1p21d253eca777c6b4e9f6e243aa18da25e@eucas1p2.samsung.com>
2016-10-09 21:01 ` 'case' zeroes "$?" Martijn Dekker
2016-10-09 21:34   ` Martijn Dekker
2016-10-10  8:55   ` Peter Stephenson
2016-10-13  9:30     ` Martijn Dekker

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).