1

I use getopt_long on GNU/Linux machine. Initialize options list as:

static struct option long_options[] = {
     {"mode", required_argument, 0, 9},
     {0, 0, 0, 0}
};

Have following line of code

c = getopt_long(argc, argv, "", long_options, index_ptr);

When I run my program with command:

prog --mode

Above shown line of code returns '?' in c, but not ':' as expected according to getopt(3) man page: "Error and -1 returns are the same as for getopt()"

Yes, when using/parsing short options one could write in options list something like ":m:", so that variable c on missing argument would contain ':', not '?', but what one should do to distinguish between two cases(missing argument, invalid option) when parsing only long options?

How could one distinguish between invalid option and option with missing required argument?

Bulat M.
  • 680
  • 9
  • 25
  • Why in the `long_options` array you have used 9 as val to be returned instead of a character '9' and why the `optstring/shortopts` parameter is not containing "9:" ? (see [Example of Parsing Long Options](https://www.gnu.org/software/libc/manual/html_node/Getopt-Long-Option-Example.html#Getopt-Long-Option-Example)) – J. Piquard Oct 20 '16 at 21:02
  • @DavidBowling `.val` is an `int`, but mainly to be used when the `.flag` pointer is not NULL. Because `9` is could not be used to detect a shortcut argument, it is better to use a character like `'m'` (for mode). – J. Piquard Oct 20 '16 at 21:46
  • Yes, I read getopt[_long] section of glibc reference manual before asking the question. But it is not clear what should be returned in that case. – Bulat M. Oct 21 '16 at 04:48
  • @Piquard, it does not really matter what they return, because I want to distinguish two error cases(missing argument, invalid option) and I want to parse only long options. – Bulat M. Oct 21 '16 at 04:56

1 Answers1

3

The only way that I can see to accomplish your goal of distinguishing between an invalid option and a valid option with a missing argument is to set the has_arg field of the options struct to optional_argument, and then to test manually for an argument. Then getopt_long() will only return a value of '?' when there is an invalid option, and you can check to see if a specified option has an argument by looking in optarg. Here is an example:

#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>

int main(int argc, char *argv[])
{
    int i, opt;
    int index = -1;

    static struct option long_options[] = {
        {"mode", optional_argument, NULL, 'm'},
        {0, 0, 0, 0}
    };

    /* suppress error messages */
    //opterr = 0;

    while ((opt = getopt_long(argc, argv, "", long_options, &index)) != -1) {
        if (opt == '?') {
            /* do something, perhaps: */
            //printf("Invalid option \n");
            //      exit(EXIT_FAILURE);
        }
        if (opt == 'm' && optarg == NULL) {
            printf("Missing argument in '--mode' option\n");
            exit(EXIT_FAILURE);
        }        
    }

    return 0;
}
ad absurdum
  • 19,498
  • 5
  • 37
  • 60
  • I thought about it too, the issue is that the body with if conditionals will grow if one has a lot of options like --mode. – Bulat M. Oct 21 '16 at 20:42
  • 2
    @BulatM.-- have you considered using [Argp](https://www.gnu.org/software/libc/manual/html_node/Argp.html#Argp)? It looks a bit more involved than the `getopt`-style functions, but it looks more flexible. It might be able to do what you want. – ad absurdum Oct 21 '16 at 20:49