@node getopt_long
@subsection @code{getopt_long}
@findex getopt_long

LSB specification:@* @url{https://refspecs.linuxbase.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/baselib-getopt-long-3.html}

Documentation:
@itemize
@item
@ifinfo
@ref{Getopt Long Options,,Parsing Long Options with getopt_long,libc},
@end ifinfo
@ifnotinfo
@url{https://www.gnu.org/software/libc/manual/html_node/Getopt-Long-Options.html},
@end ifnotinfo
@item
@uref{https://www.kernel.org/doc/man-pages/online/pages/man3/getopt_long.3.html,,man getopt_long}.
@end itemize

Gnulib module: getopt-gnu
@mindex getopt-gnu

Portability problems fixed by Gnulib:
@itemize
@item
This function is missing on some platforms:
AIX 5.1, HP-UX 11, MSVC 14.
@item
The function @code{getopt_long} does not obey the combination of
@samp{+} and @samp{:} flags in the options string on some platforms:
glibc 2.11.
@item
The use of @samp{W;} in the optstring argument to does not always
allow @code{-W foo} to behave synonymously with @code{--foo}:
glibc 2.11.
@item
The function @code{getopt_long} does not support the @samp{+} flag in
the options string on some platforms:
macOS 14, AIX 5.2, Solaris 10.
@item
The value of @code{optind} after a missing required argument is wrong
on some platforms:
macOS 14.
@item
The function @code{getopt_long} does not obey the @samp{-} flag in the
options string when @env{POSIXLY_CORRECT} is set on some platforms:
Cygwin 1.7.0.
@item
Some implementations fail to reset state, including re-checking
@env{POSIXLY_CORRECT}, when @code{optind} is set to @samp{0}:
NetBSD, Cygwin 1.7.0.
@item
The function @code{getopt_long} does not support options with optional
arguments on some platforms:
macOS 14, OpenBSD 4.0, AIX 5.2, Solaris 11 2010-11, Cygwin 1.5.x.
@item
This function crashes if the option string includes @code{W;} but
there are no long options, on some platforms:
glibc 2.14.
@end itemize

Portability problems not fixed by Gnulib:
@itemize
@end itemize

@mindex options
Gnulib provides also a module @code{options}, that
fixes the following shortcomings of the @code{getopt_long} API.

These shortcomings are best illustrated with an example:

@example
static struct option const long_options[] =
@{
  @{ "width", required_argument, NULL, 'w' @},
  @{ "help", no_argument, &show_help, 1 @},
  @{ "version", no_argument, &show_version, 1 @},
  @{ NULL, 0, NULL, 0 @}
@};

while ((optchar = getopt_long (argc, argv, "w:xhV", long_options, NULL))
       != -1)
  switch (optchar)
    @{
    case '\0':           /* Long option with flag != NULL.  */
      break;
    case 'w':
      set_width (optarg);
      break;
    case 'x':
      do_x = true;
      break;
    case 'h':
      show_help = 1;     /* Action code duplication!  */
      break;
    case 'V':
      show_version = 1;  /* Action code duplication!  */
      break;
    default:
      usage (EXIT_FAILURE);
    @}
@end example

@itemize
@item
The information whether an option takes a required vs.@: optional argument
needs to be specified twice:
in the @code{option[]} array for the long option
and in the string argument for the short option.
It is too easy to forget to
add the @code{":"} or @code{"::"} part in the string argument
and thus get inconsistent behaviour
between the long option and the short option.
@item
This information needs to be specified twice, but in different ways:
@multitable @columnfractions .3 .3
@headitem In the array @tab In the string
@item @code{no_argument} @tab @code{""}
@item @code{required_argument} @tab @code{":"}
@item @code{optional_argument} @tab @code{"::"}
@end multitable
@item
For an action that merely sets an @code{int}-typed variable to a value,
you can specify this action in the @code{options[]} array,
and thus omit the handling in the @code{switch} statement.
But this works only for options that are
long options without a corresponding short option.
As soon as the option has a corresponding short option,
you do need to handle it in the @code{switch} statement.
Here again, there is the opportunity for
inconsistent behaviour between the long option and the short option.
@item
The @code{val} field in a @code{struct option} has different meanings,
depending on another field:
If the @code{flag} field is non-NULL,
@code{val} is a value to be stored in a variable.
If the @code{flag} field is NULL,
@code{val} is a key to be returned from @code{getopt_long}
and subject to the @code{switch} statement.
@item
The handling of non-option arguments is specified by
prepending a certain character (@samp{+} or @samp{-}) to the string argument.
This is not one of the usual ways to specify things in an API.
The conventional way in an API is
an argument of @code{enum} type, or a flags word.
@item
The handling of errors consists of two independent flags,
and each of the flags has to be specified in a different way:
one flag is specified by
prepending a certain character (@samp{:}) to the string argument;
the other flag is specified through the global variable @code{opterr}.
@item
The @code{struct option} is a misnomer:
It cannot encode short options.
Therefore, it would have better been called @code{struct long_option}.
@item
The @code{getopt_long} function is expected to
receive the same arguments in each call, in the @code{while} loop.
The effects are undefined if you don't follow this (unwritten!) constraint.
@item
The fifth argument to @code{getopt_long}, @var{indexptr}, is redundant, because
when the @code{flag} is non-NULL,
the @code{switch} statement does not need to handle the option,
and when the @code{flag} is NULL,
@code{getopt_long} returns the value of @code{val},
as a way to identify which option was seen.
@end itemize
