zsh-workers
 help / color / mirror / code / Atom feed
* OPTIND set incorrectly by getopts for options without arg
@ 2015-01-13 20:38 Simon Chiang
  2015-01-13 21:34 ` Bart Schaefer
  0 siblings, 1 reply; 2+ messages in thread
From: Simon Chiang @ 2015-01-13 20:38 UTC (permalink / raw)
  To: zsh-workers

[-- Attachment #1: Type: text/plain, Size: 1637 bytes --]

Back in 2007 there was a question posted to the mailing list regarding
OPTIND and getopts (http://www.zsh.org/mla/users/2007/msg01188.html). To
quote, with some notes and one modifcation:

With zsh 4.3.4 the OPTIND incremental bebavior is inconsistent for options
with argument and without argument. For option with argument, OPTIND points
to next argument, while for option without argument it points to current
argument.

func() {
  OPTIND=1        # reset OPTIND each time in to prevent carryover
  getopts a:b optvar
  shift $(( OPTIND -1 ))
  echo "$OPTIND, $1"
}

func -a x y z
output: 3, y      # this is the correct output

func -b x y z
output: 1, -b     # this is the questionable output

Is this a bug? There is no consistent way to do "shift" as such.


Turns out according to the POSIX spec this is a bug (
http://pubs.opengroup.org/onlinepubs/000095399/utilities/getopts.html)

When the end of options is encountered, the getopts utility shall exit with
a return value greater than zero; the shell
variable OPTIND shall be set to the index of the first
non-option-argument.... Any of the following shall identify the end of
options: the special option "--", finding an argument that does not begin
with a '-', or encountering an error.


Unless I'm misreading that means that in the first example "y" indicates
the end of options so the correct output is "3, y".  In the second example
the "x" indicates the end of options so the correct output is "2, x".  For
what it's worth bash and dash set OPTIND in this way.

The original email was regarding zsh 4.3.4.  I can confirm this is still
the behavior at zsh 4.3.9.

Simon

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

* Re: OPTIND set incorrectly by getopts for options without arg
  2015-01-13 20:38 OPTIND set incorrectly by getopts for options without arg Simon Chiang
@ 2015-01-13 21:34 ` Bart Schaefer
  0 siblings, 0 replies; 2+ messages in thread
From: Bart Schaefer @ 2015-01-13 21:34 UTC (permalink / raw)
  To: Zsh hackers list

Quoting a bit more than I normally would to keep the POSIX text ...
jump to below.

On Tue, Jan 13, 2015 at 12:38 PM, Simon Chiang <simon.a.chiang@gmail.com> wrote:
>
> func() {
>   OPTIND=1        # reset OPTIND each time in to prevent carryover
>   getopts a:b optvar
>   shift $(( OPTIND -1 ))
>   echo "$OPTIND, $1"
> }
>
> func -a x y z
> output: 3, y      # this is the correct output
>
> func -b x y z
> output: 1, -b     # this is the questionable output
>
>
> Turns out according to the POSIX spec this is a bug (
> http://pubs.opengroup.org/onlinepubs/000095399/utilities/getopts.html)
>
> When the end of options is encountered, the getopts utility shall exit with
> a return value greater than zero; the shell
> variable OPTIND shall be set to the index of the first
> non-option-argument.... Any of the following shall identify the end of
> options: the special option "--", finding an argument that does not begin
> with a '-', or encountering an error.
>
>
> Unless I'm misreading that means that in the first example "y" indicates
> the end of options so the correct output is "3, y".  In the second example
> the "x" indicates the end of options so the correct output is "2, x".  For
> what it's worth bash and dash set OPTIND in this way.

If you add an "echo $?" after the call to getopts in the example
function, you will find that bash getopts has NOT "exit[ed] with a
return value greater than zero".  Neither has zsh getopts.

In zsh, if you add a SECOND call to getopts in the example function,
you will find that the second call DOES exit with a value of 1, and
that WHEN zsh getopts exits with a return value greater than zero,
THEN the value of OPTIND is set as POSIX specifies.

The distinction is the definition of "When the end of options is
encountered."  Zsh does not "encounter" the "end of options" until the
getopts call that actually attempts to "read past" the recognized
options.

You can see this better if you invoke the original example as "func -b
-a x y z".

Whether this is actually wrong or the spec is incomplete, I won't try
to argue here.


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

end of thread, other threads:[~2015-01-13 21:34 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-01-13 20:38 OPTIND set incorrectly by getopts for options without arg Simon Chiang
2015-01-13 21:34 ` Bart Schaefer

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