doc: use ASCII in .texi files where UTF-8 isn't needed
[gnulib.git] / tests / test-getopt_long.h
index 63cc5c7..07ea4a2 100644 (file)
@@ -1,5 +1,5 @@
 /* Test of command line argument processing.
-   Copyright (C) 2009 Free Software Foundation, Inc.
+   Copyright (C) 2009-2014 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 
 static int a_seen;
 static int b_seen;
+static int q_seen;
 
 static const struct option long_options_required[] =
   {
     { "alpha",    no_argument,       NULL, 'a' },
     { "beta",     no_argument,       &b_seen, 1 },
     { "prune",    required_argument, NULL, 'p' },
-    { "quetsche", required_argument, NULL, 'q' },
+    { "quetsche", required_argument, &q_seen, 1 },
+    { "xtremely-",no_argument,       NULL, 1003 },
     { "xtra",     no_argument,       NULL, 1001 },
     { "xtreme",   no_argument,       NULL, 1002 },
     { "xtremely", no_argument,       NULL, 1003 },
@@ -36,54 +38,63 @@ static const struct option long_options_optional[] =
     { "alpha",    no_argument,       NULL, 'a' },
     { "beta",     no_argument,       &b_seen, 1 },
     { "prune",    optional_argument, NULL, 'p' },
-    { "quetsche", optional_argument, NULL, 'q' },
+    { "quetsche", optional_argument, &q_seen, 1 },
     { NULL,       0,                 NULL, 0 }
   };
 
 static void
 getopt_long_loop (int argc, const char **argv,
-                 const char *options, const struct option *long_options,
-                 const char **p_value, const char **q_value,
-                 int *non_options_count, const char **non_options,
-                 int *unrecognized)
+                  const char *options, const struct option *long_options,
+                  const char **p_value, const char **q_value,
+                  int *non_options_count, const char **non_options,
+                  int *unrecognized)
 {
-  int option_index;
+  int option_index = -1;
   int c;
 
   opterr = 0;
+  q_seen = 0;
   while ((c = getopt_long (argc, (char **) argv, options, long_options,
-                          &option_index))
-        != -1)
+                           &option_index))
+         != -1)
     {
       switch (c)
-       {
-       case 0:
-         /* An option with a non-NULL flag pointer was processed.  */
-         break;
-       case 'a':
-         a_seen++;
-         break;
-       case 'b':
-         b_seen = 1;
-         break;
-       case 'p':
-         *p_value = optarg;
-         break;
-       case 'q':
-         *q_value = optarg;
-         break;
-       case '\1':
-         /* Must only happen with option '-' at the beginning.  */
-         ASSERT (options[0] == '-');
-         non_options[(*non_options_count)++] = optarg;
-         break;
-       case '?':
-         *unrecognized = optopt;
-         break;
-       default:
-         *unrecognized = c;
-         break;
-       }
+        {
+        case 0:
+          /* An option with a non-NULL flag pointer was processed.  */
+          if (q_seen)
+            *q_value = optarg;
+          break;
+        case 'a':
+          a_seen++;
+          break;
+        case 'b':
+          b_seen = 1;
+          break;
+        case 'p':
+          *p_value = optarg;
+          break;
+        case 'q':
+          *q_value = optarg;
+          break;
+        case '\1':
+          /* Must only happen with option '-' at the beginning.  */
+          ASSERT (options[0] == '-');
+          non_options[(*non_options_count)++] = optarg;
+          break;
+        case ':':
+          /* Must only happen with option ':' at the beginning.  */
+          ASSERT (options[0] == ':'
+                  || ((options[0] == '-' || options[0] == '+')
+                      && options[1] == ':'));
+          /* fall through */
+        case '?':
+          *unrecognized = optopt;
+          break;
+        default:
+          *unrecognized = c;
+          break;
+        }
     }
 }
 
@@ -235,8 +246,95 @@ test_getopt_long (void)
     ASSERT (c == 1003);
   }
 
-  /* Test processing of boolean options.  */
-  for (start = OPTIND_MIN; start <= 1; start++)
+  /* Check that -W handles unknown options.  */
+  {
+    int argc = 0;
+    const char *argv[10];
+    int option_index;
+    int c;
+
+    argv[argc++] = "program";
+    argv[argc++] = "-W";
+    argv[argc] = NULL;
+    optind = 1;
+    opterr = 0;
+    c = do_getopt_long (argc, argv, "W;", long_options_required, &option_index);
+    ASSERT (c == '?');
+    ASSERT (optopt == 'W');
+  }
+  {
+    int argc = 0;
+    const char *argv[10];
+    int option_index;
+    int c;
+
+    argv[argc++] = "program";
+    argv[argc++] = "-Wunknown";
+    argv[argc] = NULL;
+    optind = 1;
+    opterr = 0;
+    c = do_getopt_long (argc, argv, "W;", long_options_required, &option_index);
+    /* glibc and BSD behave differently here, but for now, we allow
+       both behaviors since W support is not frequently used.  */
+    if (c == '?')
+      {
+        ASSERT (optopt == 0);
+        ASSERT (optarg == NULL);
+      }
+    else
+      {
+        ASSERT (c == 'W');
+        ASSERT (strcmp (optarg, "unknown") == 0);
+      }
+  }
+  {
+    int argc = 0;
+    const char *argv[10];
+    int option_index;
+    int c;
+
+    argv[argc++] = "program";
+    argv[argc++] = "-W";
+    argv[argc++] = "unknown";
+    argv[argc] = NULL;
+    optind = 1;
+    opterr = 0;
+    c = do_getopt_long (argc, argv, "W;", long_options_required, &option_index);
+    /* glibc and BSD behave differently here, but for now, we allow
+       both behaviors since W support is not frequently used.  */
+    if (c == '?')
+      {
+        ASSERT (optopt == 0);
+        ASSERT (optarg == NULL);
+      }
+    else
+      {
+        ASSERT (c == 'W');
+        ASSERT (strcmp (optarg, "unknown") == 0);
+      }
+  }
+
+  /* Test that 'W' does not dump core:
+     http://sourceware.org/bugzilla/show_bug.cgi?id=12922  */
+  {
+    int argc = 0;
+    const char *argv[10];
+    int option_index;
+    int c;
+
+    argv[argc++] = "program";
+    argv[argc++] = "-W";
+    argv[argc++] = "dummy";
+    argv[argc] = NULL;
+    optind = 1;
+    opterr = 0;
+    c = do_getopt_long (argc, argv, "W;", NULL, &option_index);
+    ASSERT (c == 'W');
+    ASSERT (optind == 2);
+  }
+
+  /* Test processing of boolean short options.  */
+  for (start = 0; start <= 1; start++)
     {
       const char *p_value = NULL;
       const char *q_value = NULL;
@@ -255,8 +353,8 @@ test_getopt_long (void)
       argv[argc] = NULL;
       optind = start;
       getopt_long_loop (argc, argv, "ab", long_options_required,
-                       &p_value, &q_value,
-                       &non_options_count, non_options, &unrecognized);
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
       ASSERT (a_seen == 1);
       ASSERT (b_seen == 0);
       ASSERT (p_value == NULL);
@@ -265,7 +363,7 @@ test_getopt_long (void)
       ASSERT (unrecognized == 0);
       ASSERT (optind == 2);
     }
-  for (start = OPTIND_MIN; start <= 1; start++)
+  for (start = 0; start <= 1; start++)
     {
       const char *p_value = NULL;
       const char *q_value = NULL;
@@ -285,8 +383,8 @@ test_getopt_long (void)
       argv[argc] = NULL;
       optind = start;
       getopt_long_loop (argc, argv, "ab", long_options_required,
-                       &p_value, &q_value,
-                       &non_options_count, non_options, &unrecognized);
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
       ASSERT (a_seen == 1);
       ASSERT (b_seen == 1);
       ASSERT (p_value == NULL);
@@ -295,7 +393,7 @@ test_getopt_long (void)
       ASSERT (unrecognized == 0);
       ASSERT (optind == 3);
     }
-  for (start = OPTIND_MIN; start <= 1; start++)
+  for (start = 0; start <= 1; start++)
     {
       const char *p_value = NULL;
       const char *q_value = NULL;
@@ -314,8 +412,8 @@ test_getopt_long (void)
       argv[argc] = NULL;
       optind = start;
       getopt_long_loop (argc, argv, "ab", long_options_required,
-                       &p_value, &q_value,
-                       &non_options_count, non_options, &unrecognized);
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
       ASSERT (a_seen == 1);
       ASSERT (b_seen == 1);
       ASSERT (p_value == NULL);
@@ -324,7 +422,7 @@ test_getopt_long (void)
       ASSERT (unrecognized == 0);
       ASSERT (optind == 2);
     }
-  for (start = OPTIND_MIN; start <= 1; start++)
+  for (start = 0; start <= 1; start++)
     {
       const char *p_value = NULL;
       const char *q_value = NULL;
@@ -344,8 +442,8 @@ test_getopt_long (void)
       argv[argc] = NULL;
       optind = start;
       getopt_long_loop (argc, argv, "ab", long_options_required,
-                       &p_value, &q_value,
-                       &non_options_count, non_options, &unrecognized);
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
       ASSERT (a_seen == 2);
       ASSERT (b_seen == 1);
       ASSERT (p_value == NULL);
@@ -355,8 +453,196 @@ test_getopt_long (void)
       ASSERT (optind == 3);
     }
 
-  /* Test processing of options with arguments.  */
-  for (start = OPTIND_MIN; start <= 1; start++)
+  /* Test processing of boolean long options.  */
+  for (start = 0; start <= 1; start++)
+    {
+      const char *p_value = NULL;
+      const char *q_value = NULL;
+      int non_options_count = 0;
+      const char *non_options[10];
+      int unrecognized = 0;
+      int argc = 0;
+      const char *argv[10];
+      a_seen = 0;
+      b_seen = 0;
+
+      argv[argc++] = "program";
+      argv[argc++] = "--alpha";
+      argv[argc++] = "foo";
+      argv[argc++] = "bar";
+      argv[argc] = NULL;
+      optind = start;
+      getopt_long_loop (argc, argv, "ab", long_options_required,
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
+      ASSERT (a_seen == 1);
+      ASSERT (b_seen == 0);
+      ASSERT (p_value == NULL);
+      ASSERT (q_value == NULL);
+      ASSERT (non_options_count == 0);
+      ASSERT (unrecognized == 0);
+      ASSERT (optind == 2);
+    }
+  for (start = 0; start <= 1; start++)
+    {
+      const char *p_value = NULL;
+      const char *q_value = NULL;
+      int non_options_count = 0;
+      const char *non_options[10];
+      int unrecognized = 0;
+      int argc = 0;
+      const char *argv[10];
+      a_seen = 0;
+      b_seen = 0;
+
+      argv[argc++] = "program";
+      argv[argc++] = "--beta";
+      argv[argc++] = "--alpha";
+      argv[argc++] = "foo";
+      argv[argc++] = "bar";
+      argv[argc] = NULL;
+      optind = start;
+      getopt_long_loop (argc, argv, "ab", long_options_required,
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
+      ASSERT (a_seen == 1);
+      ASSERT (b_seen == 1);
+      ASSERT (p_value == NULL);
+      ASSERT (q_value == NULL);
+      ASSERT (non_options_count == 0);
+      ASSERT (unrecognized == 0);
+      ASSERT (optind == 3);
+    }
+  for (start = 0; start <= 1; start++)
+    {
+      const char *p_value = NULL;
+      const char *q_value = NULL;
+      int non_options_count = 0;
+      const char *non_options[10];
+      int unrecognized = 0;
+      int argc = 0;
+      const char *argv[10];
+      a_seen = 0;
+      b_seen = 0;
+
+      argv[argc++] = "program";
+      argv[argc++] = "--alpha";
+      argv[argc++] = "--beta";
+      argv[argc++] = "--alpha";
+      argv[argc++] = "--beta";
+      argv[argc++] = "foo";
+      argv[argc++] = "bar";
+      argv[argc] = NULL;
+      optind = start;
+      getopt_long_loop (argc, argv, "ab", long_options_required,
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
+      ASSERT (a_seen == 2);
+      ASSERT (b_seen == 1);
+      ASSERT (p_value == NULL);
+      ASSERT (q_value == NULL);
+      ASSERT (non_options_count == 0);
+      ASSERT (unrecognized == 0);
+      ASSERT (optind == 5);
+    }
+
+  /* Test processing of boolean long options via -W.  */
+  for (start = 0; start <= 1; start++)
+    {
+      const char *p_value = NULL;
+      const char *q_value = NULL;
+      int non_options_count = 0;
+      const char *non_options[10];
+      int unrecognized = 0;
+      int argc = 0;
+      const char *argv[10];
+      a_seen = 0;
+      b_seen = 0;
+
+      argv[argc++] = "program";
+      argv[argc++] = "-Walpha";
+      argv[argc++] = "foo";
+      argv[argc++] = "bar";
+      argv[argc] = NULL;
+      optind = start;
+      getopt_long_loop (argc, argv, "abW;", long_options_required,
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
+      ASSERT (a_seen == 1);
+      ASSERT (b_seen == 0);
+      ASSERT (p_value == NULL);
+      ASSERT (q_value == NULL);
+      ASSERT (non_options_count == 0);
+      ASSERT (unrecognized == 0);
+      ASSERT (optind == 2);
+    }
+  for (start = 0; start <= 1; start++)
+    {
+      const char *p_value = NULL;
+      const char *q_value = NULL;
+      int non_options_count = 0;
+      const char *non_options[10];
+      int unrecognized = 0;
+      int argc = 0;
+      const char *argv[10];
+      a_seen = 0;
+      b_seen = 0;
+
+      argv[argc++] = "program";
+      argv[argc++] = "-W";
+      argv[argc++] = "beta";
+      argv[argc++] = "-W";
+      argv[argc++] = "alpha";
+      argv[argc++] = "foo";
+      argv[argc++] = "bar";
+      argv[argc] = NULL;
+      optind = start;
+      getopt_long_loop (argc, argv, "aW;b", long_options_required,
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
+      ASSERT (a_seen == 1);
+      ASSERT (b_seen == 1);
+      ASSERT (p_value == NULL);
+      ASSERT (q_value == NULL);
+      ASSERT (non_options_count == 0);
+      ASSERT (unrecognized == 0);
+      ASSERT (optind == 5);
+    }
+  for (start = 0; start <= 1; start++)
+    {
+      const char *p_value = NULL;
+      const char *q_value = NULL;
+      int non_options_count = 0;
+      const char *non_options[10];
+      int unrecognized = 0;
+      int argc = 0;
+      const char *argv[10];
+      a_seen = 0;
+      b_seen = 0;
+
+      argv[argc++] = "program";
+      argv[argc++] = "-Walpha";
+      argv[argc++] = "-Wbeta";
+      argv[argc++] = "-Walpha";
+      argv[argc++] = "-Wbeta";
+      argv[argc++] = "foo";
+      argv[argc++] = "bar";
+      argv[argc] = NULL;
+      optind = start;
+      getopt_long_loop (argc, argv, "W;ab", long_options_required,
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
+      ASSERT (a_seen == 2);
+      ASSERT (b_seen == 1);
+      ASSERT (p_value == NULL);
+      ASSERT (q_value == NULL);
+      ASSERT (non_options_count == 0);
+      ASSERT (unrecognized == 0);
+      ASSERT (optind == 5);
+    }
+
+  /* Test processing of short options with arguments.  */
+  for (start = 0; start <= 1; start++)
     {
       const char *p_value = NULL;
       const char *q_value = NULL;
@@ -373,18 +659,553 @@ test_getopt_long (void)
       argv[argc++] = "bar";
       argv[argc] = NULL;
       optind = start;
-      getopt_long_loop (argc, argv, "p:q:", long_options_required,
-                       &p_value, &q_value,
-                       &non_options_count, non_options, &unrecognized);
+      getopt_long_loop (argc, argv, "p:q:", long_options_required,
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
+      ASSERT (a_seen == 0);
+      ASSERT (b_seen == 0);
+      ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0);
+      ASSERT (q_value == NULL);
+      ASSERT (non_options_count == 0);
+      ASSERT (unrecognized == 0);
+      ASSERT (optind == 2);
+    }
+  for (start = 0; start <= 1; start++)
+    {
+      const char *p_value = NULL;
+      const char *q_value = NULL;
+      int non_options_count = 0;
+      const char *non_options[10];
+      int unrecognized = 0;
+      int argc = 0;
+      const char *argv[10];
+      a_seen = 0;
+      b_seen = 0;
+
+      argv[argc++] = "program";
+      argv[argc++] = "-p";
+      argv[argc++] = "foo";
+      argv[argc++] = "bar";
+      argv[argc] = NULL;
+      optind = start;
+      getopt_long_loop (argc, argv, "p:q:", long_options_required,
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
+      ASSERT (a_seen == 0);
+      ASSERT (b_seen == 0);
+      ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0);
+      ASSERT (q_value == NULL);
+      ASSERT (non_options_count == 0);
+      ASSERT (unrecognized == 0);
+      ASSERT (optind == 3);
+    }
+  for (start = 0; start <= 1; start++)
+    {
+      const char *p_value = NULL;
+      const char *q_value = NULL;
+      int non_options_count = 0;
+      const char *non_options[10];
+      int unrecognized = 0;
+      int argc = 0;
+      const char *argv[10];
+      a_seen = 0;
+      b_seen = 0;
+
+      argv[argc++] = "program";
+      argv[argc++] = "-ab";
+      argv[argc++] = "-q";
+      argv[argc++] = "baz";
+      argv[argc++] = "-pfoo";
+      argv[argc++] = "bar";
+      argv[argc] = NULL;
+      optind = start;
+      getopt_long_loop (argc, argv, "abp:q:", long_options_required,
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
+      ASSERT (a_seen == 1);
+      ASSERT (b_seen == 1);
+      ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0);
+      ASSERT (q_value != NULL && strcmp (q_value, "baz") == 0);
+      ASSERT (non_options_count == 0);
+      ASSERT (unrecognized == 0);
+      ASSERT (optind == 5);
+    }
+
+  /* Test processing of long options with arguments.  */
+  for (start = 0; start <= 1; start++)
+    {
+      const char *p_value = NULL;
+      const char *q_value = NULL;
+      int non_options_count = 0;
+      const char *non_options[10];
+      int unrecognized = 0;
+      int argc = 0;
+      const char *argv[10];
+      a_seen = 0;
+      b_seen = 0;
+
+      argv[argc++] = "program";
+      argv[argc++] = "--p=foo";
+      argv[argc++] = "bar";
+      argv[argc] = NULL;
+      optind = start;
+      getopt_long_loop (argc, argv, "p:q:", long_options_required,
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
+      ASSERT (a_seen == 0);
+      ASSERT (b_seen == 0);
+      ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0);
+      ASSERT (q_value == NULL);
+      ASSERT (non_options_count == 0);
+      ASSERT (unrecognized == 0);
+      ASSERT (optind == 2);
+    }
+  for (start = 0; start <= 1; start++)
+    {
+      const char *p_value = NULL;
+      const char *q_value = NULL;
+      int non_options_count = 0;
+      const char *non_options[10];
+      int unrecognized = 0;
+      int argc = 0;
+      const char *argv[10];
+      a_seen = 0;
+      b_seen = 0;
+
+      argv[argc++] = "program";
+      argv[argc++] = "--p";
+      argv[argc++] = "foo";
+      argv[argc++] = "bar";
+      argv[argc] = NULL;
+      optind = start;
+      getopt_long_loop (argc, argv, "p:q:", long_options_required,
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
+      ASSERT (a_seen == 0);
+      ASSERT (b_seen == 0);
+      ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0);
+      ASSERT (q_value == NULL);
+      ASSERT (non_options_count == 0);
+      ASSERT (unrecognized == 0);
+      ASSERT (optind == 3);
+    }
+  for (start = 0; start <= 1; start++)
+    {
+      const char *p_value = NULL;
+      const char *q_value = NULL;
+      int non_options_count = 0;
+      const char *non_options[10];
+      int unrecognized = 0;
+      int argc = 0;
+      const char *argv[10];
+      a_seen = 0;
+      b_seen = 0;
+
+      argv[argc++] = "program";
+      argv[argc++] = "-ab";
+      argv[argc++] = "--q";
+      argv[argc++] = "baz";
+      argv[argc++] = "--p=foo";
+      argv[argc++] = "bar";
+      argv[argc] = NULL;
+      optind = start;
+      getopt_long_loop (argc, argv, "abp:q:", long_options_required,
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
+      ASSERT (a_seen == 1);
+      ASSERT (b_seen == 1);
+      ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0);
+      ASSERT (q_value != NULL && strcmp (q_value, "baz") == 0);
+      ASSERT (non_options_count == 0);
+      ASSERT (unrecognized == 0);
+      ASSERT (optind == 5);
+    }
+
+  /* Test processing of long options with arguments via -W.  */
+  for (start = 0; start <= 1; start++)
+    {
+      const char *p_value = NULL;
+      const char *q_value = NULL;
+      int non_options_count = 0;
+      const char *non_options[10];
+      int unrecognized = 0;
+      int argc = 0;
+      const char *argv[10];
+      a_seen = 0;
+      b_seen = 0;
+
+      argv[argc++] = "program";
+      argv[argc++] = "-Wp=foo";
+      argv[argc++] = "bar";
+      argv[argc] = NULL;
+      optind = start;
+      getopt_long_loop (argc, argv, "p:q:W;", long_options_required,
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
+      ASSERT (a_seen == 0);
+      ASSERT (b_seen == 0);
+      ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0);
+      ASSERT (q_value == NULL);
+      ASSERT (non_options_count == 0);
+      ASSERT (unrecognized == 0);
+      ASSERT (optind == 2);
+    }
+  for (start = 0; start <= 1; start++)
+    {
+      const char *p_value = NULL;
+      const char *q_value = NULL;
+      int non_options_count = 0;
+      const char *non_options[10];
+      int unrecognized = 0;
+      int argc = 0;
+      const char *argv[10];
+      a_seen = 0;
+      b_seen = 0;
+
+      argv[argc++] = "program";
+      argv[argc++] = "-W";
+      argv[argc++] = "p";
+      argv[argc++] = "foo";
+      argv[argc++] = "bar";
+      argv[argc] = NULL;
+      optind = start;
+      getopt_long_loop (argc, argv, "p:W;q:", long_options_required,
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
+      ASSERT (a_seen == 0);
+      ASSERT (b_seen == 0);
+      ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0);
+      ASSERT (q_value == NULL);
+      ASSERT (non_options_count == 0);
+      ASSERT (unrecognized == 0);
+      ASSERT (optind == 4);
+    }
+  for (start = 0; start <= 1; start++)
+    {
+      const char *p_value = NULL;
+      const char *q_value = NULL;
+      int non_options_count = 0;
+      const char *non_options[10];
+      int unrecognized = 0;
+      int argc = 0;
+      const char *argv[10];
+      a_seen = 0;
+      b_seen = 0;
+
+      argv[argc++] = "program";
+      argv[argc++] = "-ab";
+      argv[argc++] = "-Wq";
+      argv[argc++] = "baz";
+      argv[argc++] = "-W";
+      argv[argc++] = "p=foo";
+      argv[argc++] = "bar";
+      argv[argc] = NULL;
+      optind = start;
+      getopt_long_loop (argc, argv, "W;abp:q:", long_options_required,
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
+      ASSERT (a_seen == 1);
+      ASSERT (b_seen == 1);
+      ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0);
+      ASSERT (q_value != NULL && strcmp (q_value, "baz") == 0);
+      ASSERT (non_options_count == 0);
+      ASSERT (unrecognized == 0);
+      ASSERT (optind == 6);
+    }
+
+  /* Test processing of short options with optional arguments.  */
+  for (start = 0; start <= 1; start++)
+    {
+      const char *p_value = NULL;
+      const char *q_value = NULL;
+      int non_options_count = 0;
+      const char *non_options[10];
+      int unrecognized = 0;
+      int argc = 0;
+      const char *argv[10];
+      a_seen = 0;
+      b_seen = 0;
+
+      argv[argc++] = "program";
+      argv[argc++] = "-pfoo";
+      argv[argc++] = "bar";
+      argv[argc] = NULL;
+      optind = start;
+      getopt_long_loop (argc, argv, "p::q::", long_options_optional,
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
+      ASSERT (a_seen == 0);
+      ASSERT (b_seen == 0);
+      ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0);
+      ASSERT (q_value == NULL);
+      ASSERT (non_options_count == 0);
+      ASSERT (unrecognized == 0);
+      ASSERT (optind == 2);
+    }
+  for (start = 0; start <= 1; start++)
+    {
+      const char *p_value = NULL;
+      const char *q_value = NULL;
+      int non_options_count = 0;
+      const char *non_options[10];
+      int unrecognized = 0;
+      int argc = 0;
+      const char *argv[10];
+      a_seen = 0;
+      b_seen = 0;
+
+      argv[argc++] = "program";
+      argv[argc++] = "-p";
+      argv[argc++] = "foo";
+      argv[argc++] = "bar";
+      argv[argc] = NULL;
+      optind = start;
+      getopt_long_loop (argc, argv, "p::q::", long_options_optional,
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
+      ASSERT (a_seen == 0);
+      ASSERT (b_seen == 0);
+      ASSERT (p_value == NULL);
+      ASSERT (q_value == NULL);
+      ASSERT (non_options_count == 0);
+      ASSERT (unrecognized == 0);
+      ASSERT (optind == 2);
+    }
+  for (start = 0; start <= 1; start++)
+    {
+      const char *p_value = NULL;
+      const char *q_value = NULL;
+      int non_options_count = 0;
+      const char *non_options[10];
+      int unrecognized = 0;
+      int argc = 0;
+      const char *argv[10];
+      a_seen = 0;
+      b_seen = 0;
+
+      argv[argc++] = "program";
+      argv[argc++] = "-p";
+      argv[argc++] = "-a";
+      argv[argc++] = "bar";
+      argv[argc] = NULL;
+      optind = start;
+      getopt_long_loop (argc, argv, "abp::q::", long_options_optional,
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
+      ASSERT (a_seen == 1);
+      ASSERT (b_seen == 0);
+      ASSERT (p_value == NULL);
+      ASSERT (q_value == NULL);
+      ASSERT (non_options_count == 0);
+      ASSERT (unrecognized == 0);
+      ASSERT (optind == 3);
+    }
+
+  /* Test processing of long options with optional arguments.  */
+  for (start = 0; start <= 1; start++)
+    {
+      const char *p_value = NULL;
+      const char *q_value = NULL;
+      int non_options_count = 0;
+      const char *non_options[10];
+      int unrecognized = 0;
+      int argc = 0;
+      const char *argv[10];
+      a_seen = 0;
+      b_seen = 0;
+
+      argv[argc++] = "program";
+      argv[argc++] = "--p=foo";
+      argv[argc++] = "bar";
+      argv[argc] = NULL;
+      optind = start;
+      getopt_long_loop (argc, argv, "p::q::", long_options_optional,
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
+      ASSERT (a_seen == 0);
+      ASSERT (b_seen == 0);
+      ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0);
+      ASSERT (q_value == NULL);
+      ASSERT (non_options_count == 0);
+      ASSERT (unrecognized == 0);
+      ASSERT (optind == 2);
+    }
+  for (start = 0; start <= 1; start++)
+    {
+      const char *p_value = NULL;
+      const char *q_value = NULL;
+      int non_options_count = 0;
+      const char *non_options[10];
+      int unrecognized = 0;
+      int argc = 0;
+      const char *argv[10];
+      a_seen = 0;
+      b_seen = 0;
+
+      argv[argc++] = "program";
+      argv[argc++] = "--p";
+      argv[argc++] = "foo";
+      argv[argc++] = "bar";
+      argv[argc] = NULL;
+      optind = start;
+      getopt_long_loop (argc, argv, "p::q::", long_options_optional,
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
+      ASSERT (a_seen == 0);
+      ASSERT (b_seen == 0);
+      ASSERT (p_value == NULL);
+      ASSERT (q_value == NULL);
+      ASSERT (non_options_count == 0);
+      ASSERT (unrecognized == 0);
+      ASSERT (optind == 2);
+    }
+  for (start = 0; start <= 1; start++)
+    {
+      const char *p_value = NULL;
+      const char *q_value = NULL;
+      int non_options_count = 0;
+      const char *non_options[10];
+      int unrecognized = 0;
+      int argc = 0;
+      const char *argv[10];
+      a_seen = 0;
+      b_seen = 0;
+
+      argv[argc++] = "program";
+      argv[argc++] = "--p=";
+      argv[argc++] = "foo";
+      argv[argc++] = "bar";
+      argv[argc] = NULL;
+      optind = start;
+      getopt_long_loop (argc, argv, "p::q::", long_options_optional,
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
+      ASSERT (a_seen == 0);
+      ASSERT (b_seen == 0);
+      ASSERT (p_value != NULL && *p_value == '\0');
+      ASSERT (q_value == NULL);
+      ASSERT (non_options_count == 0);
+      ASSERT (unrecognized == 0);
+      ASSERT (optind == 2);
+    }
+  for (start = 0; start <= 1; start++)
+    {
+      const char *p_value = NULL;
+      const char *q_value = NULL;
+      int non_options_count = 0;
+      const char *non_options[10];
+      int unrecognized = 0;
+      int argc = 0;
+      const char *argv[10];
+      a_seen = 0;
+      b_seen = 0;
+
+      argv[argc++] = "program";
+      argv[argc++] = "--p";
+      argv[argc++] = "-a";
+      argv[argc++] = "bar";
+      argv[argc] = NULL;
+      optind = start;
+      getopt_long_loop (argc, argv, "abp::q::", long_options_optional,
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
+      ASSERT (a_seen == 1);
+      ASSERT (b_seen == 0);
+      ASSERT (p_value == NULL);
+      ASSERT (q_value == NULL);
+      ASSERT (non_options_count == 0);
+      ASSERT (unrecognized == 0);
+      ASSERT (optind == 3);
+    }
+
+  /* Test processing of long options with optional arguments via -W.  */
+  for (start = 0; start <= 1; start++)
+    {
+      const char *p_value = NULL;
+      const char *q_value = NULL;
+      int non_options_count = 0;
+      const char *non_options[10];
+      int unrecognized = 0;
+      int argc = 0;
+      const char *argv[10];
+      a_seen = 0;
+      b_seen = 0;
+
+      argv[argc++] = "program";
+      argv[argc++] = "-Wp=foo";
+      argv[argc++] = "bar";
+      argv[argc] = NULL;
+      optind = start;
+      getopt_long_loop (argc, argv, "p::q::W;", long_options_optional,
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
+      ASSERT (a_seen == 0);
+      ASSERT (b_seen == 0);
+      ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0);
+      ASSERT (q_value == NULL);
+      ASSERT (non_options_count == 0);
+      ASSERT (unrecognized == 0);
+      ASSERT (optind == 2);
+    }
+  for (start = 0; start <= 1; start++)
+    {
+      const char *p_value = NULL;
+      const char *q_value = NULL;
+      int non_options_count = 0;
+      const char *non_options[10];
+      int unrecognized = 0;
+      int argc = 0;
+      const char *argv[10];
+      a_seen = 0;
+      b_seen = 0;
+
+      argv[argc++] = "program";
+      argv[argc++] = "-Wp";
+      argv[argc++] = "foo";
+      argv[argc++] = "bar";
+      argv[argc] = NULL;
+      optind = start;
+      getopt_long_loop (argc, argv, "p::q::W;", long_options_optional,
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
+      ASSERT (a_seen == 0);
+      ASSERT (b_seen == 0);
+      ASSERT (p_value == NULL);
+      ASSERT (q_value == NULL);
+      ASSERT (non_options_count == 0);
+      ASSERT (unrecognized == 0);
+      ASSERT (optind == 2);
+    }
+  for (start = 0; start <= 1; start++)
+    {
+      const char *p_value = NULL;
+      const char *q_value = NULL;
+      int non_options_count = 0;
+      const char *non_options[10];
+      int unrecognized = 0;
+      int argc = 0;
+      const char *argv[10];
+      a_seen = 0;
+      b_seen = 0;
+
+      argv[argc++] = "program";
+      argv[argc++] = "-Wp=";
+      argv[argc++] = "foo";
+      argv[argc++] = "bar";
+      argv[argc] = NULL;
+      optind = start;
+      getopt_long_loop (argc, argv, "W;p::q::", long_options_optional,
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
       ASSERT (a_seen == 0);
       ASSERT (b_seen == 0);
-      ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0);
+      ASSERT (p_value != NULL && *p_value == '\0');
       ASSERT (q_value == NULL);
       ASSERT (non_options_count == 0);
       ASSERT (unrecognized == 0);
       ASSERT (optind == 2);
     }
-  for (start = OPTIND_MIN; start <= 1; start++)
+  for (start = 0; start <= 1; start++)
     {
       const char *p_value = NULL;
       const char *q_value = NULL;
@@ -397,23 +1218,24 @@ test_getopt_long (void)
       b_seen = 0;
 
       argv[argc++] = "program";
-      argv[argc++] = "-p";
+      argv[argc++] = "-W";
+      argv[argc++] = "p=";
       argv[argc++] = "foo";
       argv[argc++] = "bar";
       argv[argc] = NULL;
       optind = start;
-      getopt_long_loop (argc, argv, "p:q:", long_options_required,
-                       &p_value, &q_value,
-                       &non_options_count, non_options, &unrecognized);
+      getopt_long_loop (argc, argv, "W;p::q::", long_options_optional,
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
       ASSERT (a_seen == 0);
       ASSERT (b_seen == 0);
-      ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0);
+      ASSERT (p_value != NULL && *p_value == '\0');
       ASSERT (q_value == NULL);
       ASSERT (non_options_count == 0);
       ASSERT (unrecognized == 0);
       ASSERT (optind == 3);
     }
-  for (start = OPTIND_MIN; start <= 1; start++)
+  for (start = 0; start <= 1; start++)
     {
       const char *p_value = NULL;
       const char *q_value = NULL;
@@ -426,27 +1248,26 @@ test_getopt_long (void)
       b_seen = 0;
 
       argv[argc++] = "program";
-      argv[argc++] = "-ab";
-      argv[argc++] = "-q";
-      argv[argc++] = "baz";
-      argv[argc++] = "-pfoo";
+      argv[argc++] = "-W";
+      argv[argc++] = "p";
+      argv[argc++] = "-a";
       argv[argc++] = "bar";
       argv[argc] = NULL;
       optind = start;
-      getopt_long_loop (argc, argv, "abp:q:", long_options_required,
-                       &p_value, &q_value,
-                       &non_options_count, non_options, &unrecognized);
+      getopt_long_loop (argc, argv, "W;abp::q::", long_options_optional,
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
       ASSERT (a_seen == 1);
-      ASSERT (b_seen == 1);
-      ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0);
-      ASSERT (q_value != NULL && strcmp (q_value, "baz") == 0);
+      ASSERT (b_seen == 0);
+      /* ASSERT (p_value == NULL); */
+      ASSERT (q_value == NULL);
       ASSERT (non_options_count == 0);
       ASSERT (unrecognized == 0);
-      ASSERT (optind == 5);
+      ASSERT (optind == 4);
     }
 
-  /* Test processing of options with optional arguments.  */
-  for (start = OPTIND_MIN; start <= 1; start++)
+  /* Check that invalid options are recognized.  */
+  for (start = 0; start <= 1; start++)
     {
       const char *p_value = NULL;
       const char *q_value = NULL;
@@ -459,22 +1280,25 @@ test_getopt_long (void)
       b_seen = 0;
 
       argv[argc++] = "program";
-      argv[argc++] = "-pfoo";
+      argv[argc++] = "-p";
+      argv[argc++] = "foo";
+      argv[argc++] = "-x";
+      argv[argc++] = "-a";
       argv[argc++] = "bar";
       argv[argc] = NULL;
       optind = start;
-      getopt_long_loop (argc, argv, "p::q::", long_options_optional,
-                       &p_value, &q_value,
-                       &non_options_count, non_options, &unrecognized);
-      ASSERT (a_seen == 0);
+      getopt_long_loop (argc, argv, "abp:q:", long_options_required,
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
+      ASSERT (a_seen == 1);
       ASSERT (b_seen == 0);
       ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0);
       ASSERT (q_value == NULL);
       ASSERT (non_options_count == 0);
-      ASSERT (unrecognized == 0);
-      ASSERT (optind == 2);
+      ASSERT (unrecognized == 'x');
+      ASSERT (optind == 5);
     }
-  for (start = OPTIND_MIN; start <= 1; start++)
+  for (start = 0; start <= 1; start++)
     {
       const char *p_value = NULL;
       const char *q_value = NULL;
@@ -489,21 +1313,25 @@ test_getopt_long (void)
       argv[argc++] = "program";
       argv[argc++] = "-p";
       argv[argc++] = "foo";
+      argv[argc++] = "-:";
+      argv[argc++] = "-a";
       argv[argc++] = "bar";
       argv[argc] = NULL;
       optind = start;
-      getopt_long_loop (argc, argv, "p::q::", long_options_optional,
-                       &p_value, &q_value,
-                       &non_options_count, non_options, &unrecognized);
-      ASSERT (a_seen == 0);
+      getopt_long_loop (argc, argv, "abp:q:", long_options_required,
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
+      ASSERT (a_seen == 1);
       ASSERT (b_seen == 0);
-      ASSERT (p_value == NULL);
+      ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0);
       ASSERT (q_value == NULL);
       ASSERT (non_options_count == 0);
-      ASSERT (unrecognized == 0);
-      ASSERT (optind == 2);
+      ASSERT (unrecognized == ':');
+      ASSERT (optind == 5);
     }
-  for (start = OPTIND_MIN; start <= 1; start++)
+
+  /* Check that unexpected arguments are recognized.  */
+  for (start = 0; start <= 1; start++)
     {
       const char *p_value = NULL;
       const char *q_value = NULL;
@@ -517,24 +1345,23 @@ test_getopt_long (void)
 
       argv[argc++] = "program";
       argv[argc++] = "-p";
-      argv[argc++] = "-a";
+      argv[argc++] = "foo";
+      argv[argc++] = "--a=";
       argv[argc++] = "bar";
       argv[argc] = NULL;
       optind = start;
-      getopt_long_loop (argc, argv, "abp::q::", long_options_optional,
-                       &p_value, &q_value,
-                       &non_options_count, non_options, &unrecognized);
-      ASSERT (a_seen == 1);
+      getopt_long_loop (argc, argv, "abp:q:", long_options_required,
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
+      ASSERT (a_seen == 0);
       ASSERT (b_seen == 0);
-      ASSERT (p_value == NULL);
+      ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0);
       ASSERT (q_value == NULL);
       ASSERT (non_options_count == 0);
-      ASSERT (unrecognized == 0);
-      ASSERT (optind == 3);
+      ASSERT (unrecognized == 'a');
+      ASSERT (optind == 4);
     }
-
-  /* Check that invalid options are recognized.  */
-  for (start = OPTIND_MIN; start <= 1; start++)
+  for (start = 0; start <= 1; start++)
     {
       const char *p_value = NULL;
       const char *q_value = NULL;
@@ -549,25 +1376,26 @@ test_getopt_long (void)
       argv[argc++] = "program";
       argv[argc++] = "-p";
       argv[argc++] = "foo";
-      argv[argc++] = "-x";
-      argv[argc++] = "-a";
+      argv[argc++] = "--b=";
       argv[argc++] = "bar";
       argv[argc] = NULL;
       optind = start;
       getopt_long_loop (argc, argv, "abp:q:", long_options_required,
-                       &p_value, &q_value,
-                       &non_options_count, non_options, &unrecognized);
-      ASSERT (a_seen == 1);
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
+      ASSERT (a_seen == 0);
       ASSERT (b_seen == 0);
       ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0);
       ASSERT (q_value == NULL);
       ASSERT (non_options_count == 0);
-      ASSERT (unrecognized == 'x');
-      ASSERT (optind == 5);
+      /* When flag is non-zero, glibc sets optopt anyway, but BSD
+         leaves optopt unchanged.  */
+      ASSERT (unrecognized == 1 || unrecognized == 0);
+      ASSERT (optind == 4);
     }
 
   /* Check that by default, non-options arguments are moved to the end.  */
-  for (start = OPTIND_MIN; start <= 1; start++)
+  for (start = 0; start <= 1; start++)
     {
       const char *p_value = NULL;
       const char *q_value = NULL;
@@ -589,8 +1417,8 @@ test_getopt_long (void)
       argv[argc] = NULL;
       optind = start;
       getopt_long_loop (argc, argv, "abp:q:", long_options_required,
-                       &p_value, &q_value,
-                       &non_options_count, non_options, &unrecognized);
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
       ASSERT (strcmp (argv[0], "program") == 0);
       ASSERT (strcmp (argv[1], "-p") == 0);
       ASSERT (strcmp (argv[2], "billy") == 0);
@@ -609,7 +1437,7 @@ test_getopt_long (void)
     }
 
   /* Check that '--' ends the argument processing.  */
-  for (start = OPTIND_MIN; start <= 1; start++)
+  for (start = 0; start <= 1; start++)
     {
       const char *p_value = NULL;
       const char *q_value = NULL;
@@ -636,8 +1464,8 @@ test_getopt_long (void)
       argv[argc] = NULL;
       optind = start;
       getopt_long_loop (argc, argv, "abp:q:", long_options_required,
-                       &p_value, &q_value,
-                       &non_options_count, non_options, &unrecognized);
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
       ASSERT (strcmp (argv[0], "program") == 0);
       ASSERT (strcmp (argv[1], "-p") == 0);
       ASSERT (strcmp (argv[2], "billy") == 0);
@@ -661,7 +1489,7 @@ test_getopt_long (void)
     }
 
   /* Check that the '-' flag causes non-options to be returned in order.  */
-  for (start = OPTIND_MIN; start <= 1; start++)
+  for (start = 0; start <= 1; start++)
     {
       const char *p_value = NULL;
       const char *q_value = NULL;
@@ -683,8 +1511,8 @@ test_getopt_long (void)
       argv[argc] = NULL;
       optind = start;
       getopt_long_loop (argc, argv, "-abp:q:", long_options_required,
-                       &p_value, &q_value,
-                       &non_options_count, non_options, &unrecognized);
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
       ASSERT (strcmp (argv[0], "program") == 0);
       ASSERT (strcmp (argv[1], "donald") == 0);
       ASSERT (strcmp (argv[2], "-p") == 0);
@@ -706,7 +1534,7 @@ test_getopt_long (void)
     }
 
   /* Check that '--' ends the argument processing.  */
-  for (start = OPTIND_MIN; start <= 1; start++)
+  for (start = 0; start <= 1; start++)
     {
       const char *p_value = NULL;
       const char *q_value = NULL;
@@ -733,8 +1561,8 @@ test_getopt_long (void)
       argv[argc] = NULL;
       optind = start;
       getopt_long_loop (argc, argv, "-abp:q:", long_options_required,
-                       &p_value, &q_value,
-                       &non_options_count, non_options, &unrecognized);
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
       ASSERT (strcmp (argv[0], "program") == 0);
       ASSERT (strcmp (argv[1], "donald") == 0);
       ASSERT (strcmp (argv[2], "-p") == 0);
@@ -754,31 +1582,31 @@ test_getopt_long (void)
       ASSERT (q_value == NULL);
       if (non_options_count == 2)
       {
-       /* glibc behaviour.  */
-       ASSERT (non_options_count == 2);
-       ASSERT (strcmp (non_options[0], "donald") == 0);
-       ASSERT (strcmp (non_options[1], "duck") == 0);
-       ASSERT (unrecognized == 0);
-       ASSERT (optind == 7);
+        /* glibc behaviour.  */
+        ASSERT (non_options_count == 2);
+        ASSERT (strcmp (non_options[0], "donald") == 0);
+        ASSERT (strcmp (non_options[1], "duck") == 0);
+        ASSERT (unrecognized == 0);
+        ASSERT (optind == 7);
       }
       else
       {
-       /* Another valid behaviour.  */
-       ASSERT (non_options_count == 7);
-       ASSERT (strcmp (non_options[0], "donald") == 0);
-       ASSERT (strcmp (non_options[1], "duck") == 0);
-       ASSERT (strcmp (non_options[2], "-b") == 0);
-       ASSERT (strcmp (non_options[3], "foo") == 0);
-       ASSERT (strcmp (non_options[4], "-q") == 0);
-       ASSERT (strcmp (non_options[5], "johnny") == 0);
-       ASSERT (strcmp (non_options[6], "bar") == 0);
-       ASSERT (unrecognized == 0);
-       ASSERT (optind == 12);
+        /* Another valid behaviour.  */
+        ASSERT (non_options_count == 7);
+        ASSERT (strcmp (non_options[0], "donald") == 0);
+        ASSERT (strcmp (non_options[1], "duck") == 0);
+        ASSERT (strcmp (non_options[2], "-b") == 0);
+        ASSERT (strcmp (non_options[3], "foo") == 0);
+        ASSERT (strcmp (non_options[4], "-q") == 0);
+        ASSERT (strcmp (non_options[5], "johnny") == 0);
+        ASSERT (strcmp (non_options[6], "bar") == 0);
+        ASSERT (unrecognized == 0);
+        ASSERT (optind == 12);
       }
     }
 
   /* Check that the '-' flag has to come first.  */
-  for (start = OPTIND_MIN; start <= 1; start++)
+  for (start = 0; start <= 1; start++)
     {
       const char *p_value = NULL;
       const char *q_value = NULL;
@@ -800,8 +1628,8 @@ test_getopt_long (void)
       argv[argc] = NULL;
       optind = start;
       getopt_long_loop (argc, argv, "abp:q:-", long_options_required,
-                       &p_value, &q_value,
-                       &non_options_count, non_options, &unrecognized);
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
       ASSERT (strcmp (argv[0], "program") == 0);
       ASSERT (strcmp (argv[1], "-p") == 0);
       ASSERT (strcmp (argv[2], "billy") == 0);
@@ -821,7 +1649,7 @@ test_getopt_long (void)
 
   /* Check that the '+' flag causes the first non-option to terminate the
      loop.  */
-  for (start = OPTIND_MIN; start <= 1; start++)
+  for (start = 0; start <= 1; start++)
     {
       const char *p_value = NULL;
       const char *q_value = NULL;
@@ -843,8 +1671,8 @@ test_getopt_long (void)
       argv[argc] = NULL;
       optind = start;
       getopt_long_loop (argc, argv, "+abp:q:", long_options_required,
-                       &p_value, &q_value,
-                       &non_options_count, non_options, &unrecognized);
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
       ASSERT (strcmp (argv[0], "program") == 0);
       ASSERT (strcmp (argv[1], "donald") == 0);
       ASSERT (strcmp (argv[2], "-p") == 0);
@@ -861,7 +1689,7 @@ test_getopt_long (void)
       ASSERT (unrecognized == 0);
       ASSERT (optind == 1);
     }
-  for (start = OPTIND_MIN; start <= 1; start++)
+  for (start = 0; start <= 1; start++)
     {
       const char *p_value = NULL;
       const char *q_value = NULL;
@@ -878,8 +1706,8 @@ test_getopt_long (void)
       argv[argc] = NULL;
       optind = start;
       getopt_long_loop (argc, argv, "+abp:q:", long_options_required,
-                       &p_value, &q_value,
-                       &non_options_count, non_options, &unrecognized);
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
       ASSERT (a_seen == 0);
       ASSERT (b_seen == 0);
       ASSERT (p_value == NULL);
@@ -890,7 +1718,7 @@ test_getopt_long (void)
     }
 
   /* Check that '--' ends the argument processing.  */
-  for (start = OPTIND_MIN; start <= 1; start++)
+  for (start = 0; start <= 1; start++)
     {
       const char *p_value = NULL;
       const char *q_value = NULL;
@@ -917,8 +1745,8 @@ test_getopt_long (void)
       argv[argc] = NULL;
       optind = start;
       getopt_long_loop (argc, argv, "+abp:q:", long_options_required,
-                       &p_value, &q_value,
-                       &non_options_count, non_options, &unrecognized);
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
       ASSERT (strcmp (argv[0], "program") == 0);
       ASSERT (strcmp (argv[1], "donald") == 0);
       ASSERT (strcmp (argv[2], "-p") == 0);
@@ -938,11 +1766,11 @@ test_getopt_long (void)
       ASSERT (q_value == NULL);
       ASSERT (non_options_count == 0);
       ASSERT (unrecognized == 0);
-      ASSERT (optind = 1);
+      ASSERT (optind == 1);
     }
 
   /* Check that the '+' flag has to come first.  */
-  for (start = OPTIND_MIN; start <= 1; start++)
+  for (start = 0; start <= 1; start++)
     {
       const char *p_value = NULL;
       const char *q_value = NULL;
@@ -964,8 +1792,8 @@ test_getopt_long (void)
       argv[argc] = NULL;
       optind = start;
       getopt_long_loop (argc, argv, "abp:q:+", long_options_required,
-                       &p_value, &q_value,
-                       &non_options_count, non_options, &unrecognized);
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
       ASSERT (strcmp (argv[0], "program") == 0);
       ASSERT (strcmp (argv[1], "-p") == 0);
       ASSERT (strcmp (argv[2], "billy") == 0);
@@ -993,8 +1821,50 @@ test_getopt_long_posix (void)
 {
   int start;
 
+  /* Check that POSIXLY_CORRECT stops parsing the same as leading '+'.  */
+  for (start = 0; start <= 1; start++)
+    {
+      const char *p_value = NULL;
+      const char *q_value = NULL;
+      int non_options_count = 0;
+      const char *non_options[10];
+      int unrecognized = 0;
+      int argc = 0;
+      const char *argv[10];
+      a_seen = 0;
+      b_seen = 0;
+
+      argv[argc++] = "program";
+      argv[argc++] = "donald";
+      argv[argc++] = "-p";
+      argv[argc++] = "billy";
+      argv[argc++] = "duck";
+      argv[argc++] = "-a";
+      argv[argc++] = "bar";
+      argv[argc] = NULL;
+      optind = start;
+      getopt_long_loop (argc, argv, "abp:q:", long_options_required,
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
+      ASSERT (strcmp (argv[0], "program") == 0);
+      ASSERT (strcmp (argv[1], "donald") == 0);
+      ASSERT (strcmp (argv[2], "-p") == 0);
+      ASSERT (strcmp (argv[3], "billy") == 0);
+      ASSERT (strcmp (argv[4], "duck") == 0);
+      ASSERT (strcmp (argv[5], "-a") == 0);
+      ASSERT (strcmp (argv[6], "bar") == 0);
+      ASSERT (argv[7] == NULL);
+      ASSERT (a_seen == 0);
+      ASSERT (b_seen == 0);
+      ASSERT (p_value == NULL);
+      ASSERT (q_value == NULL);
+      ASSERT (non_options_count == 0);
+      ASSERT (unrecognized == 0);
+      ASSERT (optind == 1);
+    }
+
   /* Check that POSIXLY_CORRECT doesn't change optional arguments.  */
-  for (start = OPTIND_MIN; start <= 1; start++)
+  for (start = 0; start <= 1; start++)
     {
       const char *p_value = NULL;
       const char *q_value = NULL;
@@ -1012,8 +1882,8 @@ test_getopt_long_posix (void)
       argv[argc] = NULL;
       optind = start;
       getopt_long_loop (argc, argv, "p::", long_options_required,
-                       &p_value, &q_value,
-                       &non_options_count, non_options, &unrecognized);
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
       ASSERT (a_seen == 0);
       ASSERT (b_seen == 0);
       ASSERT (p_value == NULL);
@@ -1024,7 +1894,7 @@ test_getopt_long_posix (void)
     }
 
   /* Check that leading - still sees options after non-options.  */
-  for (start = OPTIND_MIN; start <= 1; start++)
+  for (start = 0; start <= 1; start++)
     {
       const char *p_value = NULL;
       const char *q_value = NULL;
@@ -1043,8 +1913,8 @@ test_getopt_long_posix (void)
       argv[argc] = NULL;
       optind = start;
       getopt_long_loop (argc, argv, "-ab", long_options_required,
-                       &p_value, &q_value,
-                       &non_options_count, non_options, &unrecognized);
+                        &p_value, &q_value,
+                        &non_options_count, non_options, &unrecognized);
       ASSERT (a_seen == 1);
       ASSERT (b_seen == 1);
       ASSERT (p_value == NULL);
@@ -1055,3 +1925,220 @@ test_getopt_long_posix (void)
       ASSERT (optind == 4);
     }
 }
+
+/* Reduce casting, so we can use string literals elsewhere.
+   getopt_long_only takes an array of char*, but luckily does not
+   modify those elements, so we can pass const char*.  */
+static int
+do_getopt_long_only (int argc, const char **argv, const char *shortopts,
+                     const struct option *longopts, int *longind)
+{
+  return getopt_long_only (argc, (char **) argv, shortopts, longopts, longind);
+}
+
+static void
+test_getopt_long_only (void)
+{
+  /* Test disambiguation of options.  */
+  {
+    int argc = 0;
+    const char *argv[10];
+    int option_index;
+    int c;
+
+    argv[argc++] = "program";
+    argv[argc++] = "-x";
+    argv[argc] = NULL;
+    optind = 1;
+    opterr = 0;
+    c = do_getopt_long_only (argc, argv, "ab", long_options_required,
+                             &option_index);
+    ASSERT (c == '?');
+    ASSERT (optopt == 0);
+  }
+  {
+    int argc = 0;
+    const char *argv[10];
+    int option_index;
+    int c;
+
+    argv[argc++] = "program";
+    argv[argc++] = "-x";
+    argv[argc] = NULL;
+    optind = 1;
+    opterr = 0;
+    c = do_getopt_long_only (argc, argv, "abx", long_options_required,
+                             &option_index);
+    ASSERT (c == 'x');
+    ASSERT (optopt == 0);
+  }
+  {
+    int argc = 0;
+    const char *argv[10];
+    int option_index;
+    int c;
+
+    argv[argc++] = "program";
+    argv[argc++] = "--x";
+    argv[argc] = NULL;
+    optind = 1;
+    opterr = 0;
+    c = do_getopt_long_only (argc, argv, "abx", long_options_required,
+                             &option_index);
+    ASSERT (c == '?');
+    ASSERT (optopt == 0);
+  }
+  {
+    int argc = 0;
+    const char *argv[10];
+    int option_index;
+    int c;
+
+    argv[argc++] = "program";
+    argv[argc++] = "-b";
+    argv[argc] = NULL;
+    optind = 1;
+    opterr = 0;
+    b_seen = 0;
+    c = do_getopt_long_only (argc, argv, "abx", long_options_required,
+                             &option_index);
+    ASSERT (c == 'b');
+    ASSERT (b_seen == 0);
+  }
+  {
+    int argc = 0;
+    const char *argv[10];
+    int option_index;
+    int c;
+
+    argv[argc++] = "program";
+    argv[argc++] = "--b";
+    argv[argc] = NULL;
+    optind = 1;
+    opterr = 0;
+    b_seen = 0;
+    c = do_getopt_long_only (argc, argv, "abx", long_options_required,
+                             &option_index);
+    ASSERT (c == 0);
+    ASSERT (b_seen == 1);
+  }
+  {
+    int argc = 0;
+    const char *argv[10];
+    int option_index;
+    int c;
+
+    argv[argc++] = "program";
+    argv[argc++] = "-xt";
+    argv[argc] = NULL;
+    optind = 1;
+    opterr = 0;
+    c = do_getopt_long_only (argc, argv, "ab", long_options_required,
+                             &option_index);
+    ASSERT (c == '?');
+    ASSERT (optopt == 0);
+  }
+  {
+    int argc = 0;
+    const char *argv[10];
+    int option_index;
+    int c;
+
+    argv[argc++] = "program";
+    argv[argc++] = "-xt";
+    argv[argc] = NULL;
+    optind = 1;
+    opterr = 0;
+    c = do_getopt_long_only (argc, argv, "abx", long_options_required,
+                             &option_index);
+    ASSERT (c == '?');
+    ASSERT (optopt == 0);
+  }
+  {
+    int argc = 0;
+    const char *argv[10];
+    int option_index;
+    int c;
+
+    argv[argc++] = "program";
+    argv[argc++] = "-xtra";
+    argv[argc] = NULL;
+    optind = 1;
+    opterr = 0;
+    c = do_getopt_long_only (argc, argv, "ab", long_options_required,
+                             &option_index);
+    ASSERT (c == 1001);
+  }
+  {
+    int argc = 0;
+    const char *argv[10];
+    int option_index;
+    int c;
+
+    argv[argc++] = "program";
+    argv[argc++] = "-xtreme";
+    argv[argc] = NULL;
+    optind = 1;
+    opterr = 0;
+    c = do_getopt_long_only (argc, argv, "abx:", long_options_required,
+                             &option_index);
+    ASSERT (c == 1002);
+  }
+  {
+    int argc = 0;
+    const char *argv[10];
+    int option_index;
+    int c;
+
+    argv[argc++] = "program";
+    argv[argc++] = "-xtremel";
+    argv[argc] = NULL;
+    optind = 1;
+    opterr = 0;
+    c = do_getopt_long_only (argc, argv, "ab", long_options_required,
+                             &option_index);
+    /* glibc getopt_long_only is intentionally different from
+       getopt_long when handling a prefix that is common to two
+       spellings, when both spellings have the same option directives.
+       BSD getopt_long_only treats both cases the same.  */
+    ASSERT (c == 1003 || c == '?');
+    ASSERT (optind == 2);
+  }
+  {
+    int argc = 0;
+    const char *argv[10];
+    int option_index;
+    int c;
+
+    argv[argc++] = "program";
+    argv[argc++] = "-xtremel";
+    argv[argc] = NULL;
+    optind = 1;
+    opterr = 0;
+    c = do_getopt_long_only (argc, argv, "abx::", long_options_required,
+                             &option_index);
+    /* glibc getopt_long_only is intentionally different from
+       getopt_long when handling a prefix that is common to two
+       spellings, when both spellings have the same option directives.
+       BSD getopt_long_only treats both cases the same.  */
+    ASSERT (c == 1003 || c == '?');
+    ASSERT (optind == 2);
+    ASSERT (optarg == NULL);
+  }
+  {
+    int argc = 0;
+    const char *argv[10];
+    int option_index;
+    int c;
+
+    argv[argc++] = "program";
+    argv[argc++] = "-xtras";
+    argv[argc] = NULL;
+    optind = 1;
+    opterr = 0;
+    c = do_getopt_long_only (argc, argv, "abx::", long_options_required,
+                             &option_index);
+    ASSERT (c == 'x');
+    ASSERT (strcmp (optarg, "tras") == 0);
+  }
+}