To wrap this up and get if off my plate, here is the updated patch,
and a testcase program together with what should be (imvho) the
correct output.

Please do NOT assume that I'm insisting or that I have any personal
interest to have this included, considered, etc.

The testcase is a stripped down version of a much messier thing which
was also handling getopt_long() and getopt_long_only().

The output of the testcase in is in the form:

<< "q" ["prog", "-pq", "a1", "a2"]
gopts: unknown option -- p
>> {prog} #Up <q> | {a1} {a2}

ie '<< input', '>> expected output' with the expected error messages
in between.

===== patch to lib/libc/stdlib/getopt_long.c ======

--- getopt-long.c~      2020-03-12 02:23:29.028903616 +0200
+++ getopt-long.c       2020-03-15 23:46:07.988119523 +0200
@@ -418,15 +418,7 @@
        }
 
        if ((optchar = (int)*place++) == (int)':' ||
-           (optchar == (int)'-' && *place != '\0') ||
            (oli = strchr(options, optchar)) == NULL) {
-               /*
-                * If the user specified "-" and  '-' isn't listed in
-                * options, return -1 (non-option) as per POSIX.
-                * Otherwise, it is an unknown option character (or ':').
-                */
-               if (optchar == (int)'-' && *place == '\0')
-                       return (-1);
                if (!*place)
                        ++optind;
                if (PRINT_ERROR)

====== gopts.c =====================================
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

static void showargs(int ac, char **av, char *os){
        int c, i;
        if(ac > 0) printf("{%s} ", av[0]);
        for(optarg = 0; (c = getopt(ac, av, os)) != -1; optarg = 0)
                switch(c){
                case '?':
                        printf("#U%c ", optopt); break;
                case ':':
                        printf("#A%c ", optopt); break;
                default:
                        printf(c >= ' ' && c <= '~' ? "<%c>" :
                                c < 8 ? "<\\%d>" : "<\\x%02x", c);
                        if(optarg) printf("={%s}", optarg);
                        printf(" ");
                }
        printf("|");
        for(i = optind; i < ac; i++) printf(" {%s}", av[i]);
        printf("\n");
}
static void test(int oi, char *os, char **av, char *buf, int blen){
        int ac, l; char *s;
        printf("<< %s\n>> ", buf);
        for(ac = 0, s = buf; av[ac]; ac++, s += l + 1){
                l = strlen(av[ac]);
                memcpy(s, av[ac], l + 1);
                av[ac] = s;
        }
        optind = oi; showargs(ac, av, os);
        printf("\n");
        memset(buf, ':', blen); /* clobber it */
}
#define TEST(oi, os, ...) do{\
        char *av[] = { __VA_ARGS__, NULL };\
        static char buf[] = #os " [" #__VA_ARGS__ "]";\
        test(oi, os, av, buf, sizeof buf);\
}while(0)

int main(int ac, char **av){
        char *t;
        int oi = (t = getenv("OI")) ? *t - '0' : 1;
        if(ac > 1){ optind = oi; showargs(ac - 2, av + 2, av[1]); return 0; }

        dup2(1, 2);
        setvbuf(stdout, NULL, _IOLBF, 0);
        setvbuf(stderr, NULL, _IOLBF, 0);

        TEST(oi, "q", "prog", "-q-");
        TEST(oi, "-q", "prog", "-q--", "--", "arg");
        TEST(oi, "p-:", "prog", "-p--", "--", "arg");
        TEST(oi, "q-", "---", "--", "arg");
        TEST(oi, "q-", "---", "arg");

        TEST(oi, "p:", "prog", "-p");
        TEST(oi, "p", "prog", "-p", "arg");
        TEST(oi, "q", "prog", "-q", "arg");

        TEST(oi, "-q", "prog", "-q", "a1", "a2");
}

====== gopts.output ================================
<< "q" ["prog", "-q-"]
gogs-o: unknown option -- -
>> {prog} <q> #U- |

<< "-q" ["prog", "-q--", "--", "arg"]
gogs-o: unknown option -- -
gogs-o: unknown option -- -
>> {prog} <q> #U- #U- | {arg}

<< "p-:" ["prog", "-p--", "--", "arg"]
>> {prog} <p> <->={-} | {arg}

<< "q-" ["---", "--", "arg"]
>> {---} | {arg}

<< "q-" ["---", "arg"]
>> {---} | {arg}

<< "p:" ["prog", "-p"]
gogs-o: option requires an argument -- p
>> {prog} #Up |

<< "p" ["prog", "-p", "arg"]
>> {prog} <p> | {arg}

<< "q" ["prog", "-q", "arg"]
>> {prog} <q> | {arg}

<< "-q" ["prog", "-q", "a1", "a2"]
>> {prog} <q> <\1>={a1} <\1>={a2} |

Reply via email to