The 'getopt-gnu' module is one of the most heavily used modules
of Gnulib (more than 50 packages use it) and it, together with
'xalloc' and 'regex', one of the first three modules a package
typically uses.
So, I thought, I can use it in my packages, without expecting problems.
Today, I wrote this code:
--------------------------------------------------------------------
/* Long options. */
static const struct option long_options[] =
{
{ "context", required_argument, NULL, 'c' },
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'V' },
{ NULL, 0, NULL, 0 }
};
int optchar;
while ((optchar = getopt_long (argc, argv, "+chV", long_options, NULL))
!= EOF)
switch (optchar)
{
case '\0': /* Long option. */
break;
case 'c':
context = optarg;
break;
case 'h':
do_help = true;
break;
case 'V':
do_version = true;
break;
default:
usage (EXIT_FAILURE);
}
}
--------------------------------------------------------------------
Can you spot what is wrong with this code?
When I invoke the program as "./program -c foo bar", the value of
'optind' is 2, whereas I expected it to be 3 (since I specified that
'--context' takes a required argument and '-c' is the equivalent of
'--context').
Can you spot it now?
The problem is that the properties of an option have to be specified
in *two* places: in the long_options array *and* in the 3rd argument
to getopt_long().
I propose to add to getopt_long() — in Gnulib — code that verifies
the consistency between the two places, when a certain environment
variable (say, GETOPT_DEBUG) is set. And produces output on stderr
such as:
getopt_long: warning: option '--context' requires an argument but option '-c'
takes no argument.
Then, at least, a developer could debug the problem by building their
package with
$ gl_cv_func_getopt_posix=no gl_cv_func_getopt_gnu=no ./configure
Opinions? Objections?
Bruno