magicant / yash

Yet another shell
http://magicant.github.io/yash/
GNU General Public License v2.0
301 stars 28 forks source link

for loop wrong exit status #41

Open oguz-ismail opened 5 months ago

oguz-ismail commented 5 months ago

The following shell script should print 1 according to POSIX:

for x in y; do
  ! continue
done
echo $?

But it prints 0 on yash.

magicant commented 5 months ago

Can you pinpoint the statements that require that behavior in POSIX?

Note that the current behavior is the intended consequence of ba43abb7d95b656ce7470b11b91a21995fd2b525. See https://osdn.net/projects/yash/ticket/46224.

oguz-ismail commented 5 months ago

Can you pinpoint the statements that require that behavior in POSIX?

XCU 2.15 Special Built-in Utilities/continue/EXIT STATUS

0 Successful completion.

XCU 2.9.2 Pipelines/Exit Status

If the pipeline does not begin with the ! reserved word, the exit status shall be the exit status of the last command specified in the pipeline. Otherwise, the exit status shall be the logical NOT of the exit status of the last command. That is, if the last command returns zero, the exit status shall be 1; if the last command returns greater than zero, the exit status shall be zero.

XCU 2.9.4 Compound Commands/The for Loop/Exit Status

The exit status of a for command shall be the exit status of the last command that executes. If there are no items, the exit status shall be zero.

Note that the current behavior is the intended consequence of ba43abb. See https://osdn.net/projects/yash/ticket/46224.

That ticket is about return only. See XCU 2.15 Special Built-in Utilities/return/EXIT STATUS

The value of the special parameter '?' shall be set to n, an unsigned decimal integer, or to the exit status of the last command executed if n is not specified.

magicant commented 5 months ago

Thanks, but I don't think your quotes conclude that your script should print 1 rather than 0.

The point is that the negated pipeline does not finish at all, either successfully or unsuccessfully. It just gets aborted without producing any exit status. The situation can be made clearer by rewriting with more compound commands:

for x in y; do
  if continue; then
    false
  else
    true
  fi
done
echo $?

The false or true command is never executed, so the if command never runs till the end. The echo shows the exit status of continue, not that of if.

for x in y; do
  ! {
    continue

    # This `echo` is never executed as it follows `continue`.
    echo oops
    # ... which means the end of the `{ ... }` command is never reached.
  }
  # ... which means the end of the enclosing `! ...` command is never reached.
done
echo $?

Since the end of the ! command is not reached, you'll never see the exit status of the ! command.

oguz-ismail commented 5 months ago

The point is that the negated pipeline does not finish at all, either successfully or unsuccessfully. It just gets aborted without producing any exit status.

Is this what POSIX says or what yash does?

magicant commented 5 months ago

That's my interpretation of POSIX, and what yash does.