| @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 |