getopt_long ¶LSB specification:
https://refspecs.linuxbase.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/baselib-getopt-long-3.html
Documentation:
Portability problems fixed by Gnulib:
getopt_long does not obey the combination of
‘+’ and ‘:’ flags in the options string on some platforms:
glibc 2.11.
-W foo to behave synonymously with --foo:
glibc 2.11.
getopt_long does not support the ‘+’ flag in
the options string on some platforms:
macOS 14, AIX 5.2, Solaris 10.
optind after a missing required argument is wrong
on some platforms:
macOS 14.
getopt_long does not obey the ‘-’ flag in the
options string when POSIXLY_CORRECT is set on some platforms:
Cygwin 1.7.0.
POSIXLY_CORRECT, when optind is set to ‘0’:
NetBSD, Cygwin 1.7.0.
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.
W; but
there are no long options, on some platforms:
glibc 2.14.
Portability problems not fixed by Gnulib:
Gnulib provides also a module options, that
fixes the following shortcomings of the getopt_long API.
These shortcomings are best illustrated with an 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);
}
option[] array for the long option
and in the string argument for the short option.
It is too easy to forget to
add the ":" or "::" part in the string argument
and thus get inconsistent behaviour
between the long option and the short option.
| In the array | In the string |
|---|---|
no_argument | "" |
required_argument | ":" |
optional_argument | "::" |
int-typed variable to a value,
you can specify this action in the options[] array,
and thus omit the handling in the 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 switch statement.
Here again, there is the opportunity for
inconsistent behaviour between the long option and the short option.
val field in a struct option has different meanings,
depending on another field:
If the flag field is non-NULL,
val is a value to be stored in a variable.
If the flag field is NULL,
val is a key to be returned from getopt_long
and subject to the switch statement.
enum type, or a flags word.
opterr.
struct option is a misnomer:
It cannot encode short options.
Therefore, it would have better been called struct long_option.
getopt_long function is expected to
receive the same arguments in each call, in the while loop.
The effects are undefined if you don’t follow this (unwritten!) constraint.
getopt_long, indexptr, is redundant, because
when the flag is non-NULL,
the switch statement does not need to handle the option,
and when the flag is NULL,
getopt_long returns the value of val,
as a way to identify which option was seen.