yash icon indicating copy to clipboard operation
yash copied to clipboard

for loop wrong exit status

Open oguz-ismail opened this issue 1 year ago • 5 comments

The following shell script should print 1 according to POSIX:

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

But it prints 0 on yash.

oguz-ismail avatar Feb 13 '24 17:02 oguz-ismail

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.

magicant avatar Feb 14 '24 03:02 magicant

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.

oguz-ismail avatar Feb 14 '24 06:02 oguz-ismail

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.

magicant avatar Feb 14 '24 14:02 magicant

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?

oguz-ismail avatar Feb 14 '24 15:02 oguz-ismail

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

magicant avatar Feb 14 '24 16:02 magicant