Thread (60 messages) 60 messages, 5 authors, 2021-10-17

Re: [PATCH 10/23] getopt.3: Further clarification of optstring

From: Michael Kerrisk (man-pages) <hidden>
Date: 2021-08-08 22:11:45

Hello James and Alex,

On 8/8/21 10:41 AM, Alejandro Colomar wrote:
quoted hunk ↗ jump to hunk
From: "James O. D. Hunt" <redacted>

Explain that `optstring` cannot contain a semi-colon (`;`) character.

Also explain that `optstring` can include `+` as an option character,
possibly in addition to that character being used as the first character
in `optstring` to denote `POSIXLY_CORRECT` behaviour.

Signed-off-by: James O. D. Hunt <redacted>
Signed-off-by: Alejandro Colomar <redacted>
---
 man3/getopt.3 | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/man3/getopt.3 b/man3/getopt.3
index ce4c28088..315224c64 100644
--- a/man3/getopt.3
+++ b/man3/getopt.3
@@ -130,7 +130,7 @@ A legitimate option character is any visible one byte
 .BR ascii (7)
 character (for which
 .BR isgraph (3)
-would return nonzero) that is not \(aq\-\(aq or \(aq:\(aq.
+would return nonzero) that is not \(aq\-\(aq, \(aq:\(aq  or \(aq;\(aq.
 If such a
 character is followed by a colon, the option requires an argument, so
 .BR getopt ()
@@ -166,6 +166,14 @@ If the first character of
 .B POSIXLY_CORRECT
 is set, then option processing stops as soon as a nonoption argument is
 encountered.
+If \(aq+\(aq is not the first character of
+.IR optstring ,
+it is treated as a normal option.
+If
+.B POSIXLY_CORRECT
+behaviour is required in this case
+.I optstring
+will contain two \(aq+\(aq symbols.
 If the first character of \fIoptstring\fP is \(aq\-\(aq, then
 each nonoption \fIargv\fP-element is handled as if it were the argument of
 an option with character code 1.  (This is used by programs that were
Thanks. The patch is good and I applied it

@James: it would be helpful to explain in the commit
message how you verified these details.

@Alex: do not be shy of asking people to improve there commit
messages in this way :-).

See my modified commit message below.

Cheers,

Michael

    getopt.3: Further clarification of optstring
    
    Explain that `optstring` cannot contain a semi-colon (`;`)
    character.
    [mtk: verfiried with a small test program; see also posix/getopt.c
    in the glibc sources:
    
        if (temp == NULL || c == ':' || c == ';')
          {
            if (print_errors)
              fprintf (stderr, _("%s: invalid option -- '%c'\n"), argv[0], c);
            d->optopt = c;
            return '?';
          }
    ]
    
    Also explain that `optstring` can include `+` as an option
    character, possibly in addition to that character being used as
    the first character in `optstring` to denote `POSIXLY_CORRECT`
    behaviour.
    [mtk: verified with a small test program.]
    
    Test program below. Example runs:
    
    $ ./a.out -+
    opt = 43 (+); optind = 2
    Got plus
    $ ./a.out -';'
    ./a.out: invalid option -- ';'
    opt = 63 (?); optind = 2; optopt = 59 (;)
    Unrecognized option (-;)
    Usage: ./a.out [-p arg] [-x]
    
    Signed-off-by: James O. D. Hunt [off-list ref]
    Signed-off-by: Alejandro Colomar [off-list ref]
    Signed-off-by: Michael Kerrisk [off-list ref]
    
    8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---
    #include <ctype.h>
    #include <sys/types.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    
    #define printable(ch) (isprint((unsigned char) ch) ? ch : '#')
    
    static void             /* Print "usage" message and exit */
    usageError(char *progName, char *msg, int opt)
    {
        if (msg != NULL && opt != 0)
            fprintf(stderr, "%s (-%c)\n", msg, printable(opt));
        fprintf(stderr, "Usage: %s [-p arg] [-x]\n", progName);
        exit(EXIT_FAILURE);
    }
    
    int
    main(int argc, char *argv[])
    {
        int opt, xfnd;
        char *pstr;
    
        xfnd = 0;
        pstr = NULL;
    
        while ((opt = getopt(argc, argv, "p:x+;")) != -1) {
            printf("opt =%3d (%c); optind = %d", opt, printable(opt), optind);
            if (opt == '?' || opt == ':')
                printf("; optopt =%3d (%c)", optopt, printable(optopt));
            printf("\n");
    
            switch (opt) {
            case 'p': pstr = optarg;                break;
            case 'x': xfnd++;                       break;
            case ';': printf("Got semicolon\n");    break;
            case '+': printf("Got plus\n"); break;
            case ':': usageError(argv[0], "Missing argument", optopt);
            case '?': usageError(argv[0], "Unrecognized option", optopt);
            default:
                      printf("Unexpected case in switch()\n");
                      exit(EXIT_FAILURE);
            }
        }

        if (xfnd != 0)
            printf("-x was specified (count=%d)\n", xfnd);
        if (pstr != NULL)
            printf("-p was specified with the value \"%s\"\n", pstr);
        if (optind < argc)
            printf("First nonoption argument is \"%s\" at argv[%d]\n",
                    argv[optind], optind);
        exit(EXIT_SUCCESS);
    }

-- 
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help