mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-27 11:43:34 +08:00
aeacb9f912
In one place, glibc's getopt uses alloca to construct a linked list of possibilities for an "ambiguous" long option. In gnulib, malloc should be used instead. Providing for both cases complicates things a fair bit. Instead of merging straight across, therefore, I have chosen to rewrite it using a boolean vector instead of a linked list. There is then only one allocation that might need freeing; in glibc it can honor __libc_use_alloca as usual, and in gnulib we define __libc_use_alloca to always be false, so we don't need ifdefs in the middle of the function. This should also be slightly more efficient in the normal case of long options being fully spelled out -- I think most people aren't even aware they _can_ sometimes abbreviate long options. One interesting consequence is that the list of possibilities is now printed in exactly the order they appear in the list of long options, instead of the first possibility being shuffled to the end. This shouldn't be a big deal but it did break one test that relied on the exact text of this error message. (The reason the previous patch was "in aid of" merging from gnulib is I didn't want to have to make this change in two places.) (The patch looks bigger than it really is because there's a fair bit of reindentation and code rearrangement.) * posix/getopt.c: When used standalone, define __libc_use_alloca as always false and alloca to abort if called. (process_long_option): Rewrite handling of ambiguous long options to use a single boolean vector, not a linked list; use __libc_use_alloca to decide whether to allocate this using alloca. * posix/tst-getopt_long1.c: Adjust text of expected error message.
63 lines
1.3 KiB
C
63 lines
1.3 KiB
C
static void do_prepare (void);
|
|
#define PREPARE(argc, argv) do_prepare ()
|
|
static int do_test (void);
|
|
#define TEST_FUNCTION do_test ()
|
|
#include "../test-skeleton.c"
|
|
|
|
|
|
static char *fname;
|
|
|
|
|
|
static void
|
|
do_prepare (void)
|
|
{
|
|
if (create_temp_file ("tst-getopt_long1", &fname) < 0)
|
|
{
|
|
printf ("cannot create temp file: %m\n");
|
|
exit (1);
|
|
}
|
|
}
|
|
|
|
|
|
static const struct option opts[] =
|
|
{
|
|
{ "one", no_argument, NULL, '1' },
|
|
{ "two", no_argument, NULL, '2' },
|
|
{ "one-one", no_argument, NULL, '3' },
|
|
{ "four", no_argument, NULL, '4' },
|
|
{ "onto", no_argument, NULL, '5' },
|
|
{ NULL, 0, NULL, 0 }
|
|
};
|
|
|
|
|
|
static int
|
|
do_test (void)
|
|
{
|
|
if (freopen (fname, "w+", stderr) == NULL)
|
|
{
|
|
printf ("freopen failed: %m\n");
|
|
return 1;
|
|
}
|
|
|
|
char *argv[] = { (char *) "program", (char *) "--on" };
|
|
int argc = 2;
|
|
|
|
int c = getopt_long (argc, argv, "12345", opts, NULL);
|
|
printf ("return value: %c\n", c);
|
|
|
|
rewind (stderr);
|
|
char *line = NULL;
|
|
size_t len = 0;
|
|
if (getline (&line, &len, stderr) < 0)
|
|
{
|
|
printf ("cannot read stderr redirect: %m\n");
|
|
return 1;
|
|
}
|
|
printf ("message = \"%s\"\n", line);
|
|
|
|
static const char expected[] = "\
|
|
program: option '--on' is ambiguous; possibilities: '--one' '--one-one' '--onto'\n";
|
|
|
|
return c != '?' || strcmp (line, expected) != 0;
|
|
}
|