#### 26.2.3 Parsing Long Options with `getopt_long` ¶

To accept GNU-style long options as well as single-character options, use `getopt_long` instead of `getopt`. This function is declared in `getopt.h`, not `unistd.h`. You should make every program accept long options if it uses any options, for this takes little extra work and helps beginners remember how to use the program.

Data Type: struct option ¶

  This structure describes a single long option name for the sake of `getopt_long`. The argument longopts must be an array of these structures, one for each long option. Terminate the array with an element containing all zeros.

  The `struct option` structure has these fields:

  `const char *name`

    This field is the name of the option. It is a string.

  `int has_arg`

    This field says whether the option takes an argument. It is an integer, and there are three legitimate values: `no_argument`, `required_argument` and `optional_argument`.

  `int *flag`
  `int val`

    These fields control how to report or act on the option when it occurs.

    If `flag` is a null pointer, then the `val` is a value which identifies this option. Often these values are chosen to uniquely identify particular long options.

    If `flag` is not a null pointer, it should be the address of an `int` variable which is the flag for this option. The value in `val` is the value to store in the flag to indicate that the option was seen.

Function: `int` getopt_long `(int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *indexptr)` ¶

  Preliminary: | MT-Unsafe race:getopt env | AS-Unsafe heap i18n lock corrupt | AC-Unsafe mem lock corrupt | See POSIX Safety Concepts.

  Decode options from the vector argv (whose length is argc). The argument shortopts describes the short options to accept, just as it does in `getopt`. The argument longopts describes the long options to accept (see above).

  When `getopt_long` encounters a short option, it does the same thing that `getopt` would do: it returns the character code for the option, and stores the option’s argument (if it has one) in `optarg`.

  When `getopt_long` encounters a long option, it takes actions based on the `flag` and `val` fields of the definition of that option. The option name may be abbreviated as long as the abbreviation is unique.

  If `flag` is a null pointer, then `getopt_long` returns the contents of `val` to indicate which option it found. You should arrange distinct values in the `val` field for options with different meanings, so you can decode these values after `getopt_long` returns. If the long option is equivalent to a short option, you can use the short option’s character code in `val`.

  If `flag` is not a null pointer, that means this option should just set a flag in the program. The flag is a variable of type `int` that you define. Put the address of the flag in the `flag` field. Put in the `val` field the value you would like this option to store in the flag. In this case, `getopt_long` returns `0`.

  For any long option, `getopt_long` tells you the index in the array longopts of the options definition, by storing it into `*indexptr`. You can get the name of the option with `longopts[*indexptr].name`. So you can distinguish among long options either by the values in their `val` fields or by their indices. You can also distinguish in this way among long options that set flags.

  When a long option has an argument, `getopt_long` puts the argument value in the variable `optarg` before returning. When the option has no argument, the value in `optarg` is a null pointer. This is how you can tell whether an optional argument was supplied.

  When `getopt_long` has no more options to handle, it returns `-1`, and leaves in the variable `optind` the index in argv of the next remaining argument.

Since long option names were used before `getopt_long` was invented there are program interfaces which require programs to recognize options like ‘`-option value`’ instead of ‘`--option value`’. To enable these programs to use the GNU getopt functionality there is one more function available.

Function: `int` getopt_long_only `(int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *indexptr)` ¶

  Preliminary: | MT-Unsafe race:getopt env | AS-Unsafe heap i18n lock corrupt | AC-Unsafe mem lock corrupt | See POSIX Safety Concepts.

  The `getopt_long_only` function is equivalent to the `getopt_long` function but it allows the user of the application to pass long options with only ‘`-`’ instead of ‘`--`’. The ‘`--`’ prefix is still recognized but instead of looking through the short options if a ‘`-`’ is seen it is first tried whether this parameter names a long option. If not, it is parsed as a short option. In case both short and long options could be matched (this can happen with single letter long options), the short option is preferred (with some caveats). For long options, abbreviations are detected as well.

  Assuming `getopt_long_only` is used starting an application with

        app -foo

  the `getopt_long_only` will first look for a long option named ‘`foo`’. If this is not found, the short options ‘`f`’, ‘`o`’, and again ‘`o`’ are recognized.

  It gets more interesting with single letter long options. If we define options in the following way

        static struct option long_options[] = {
                {"f",       no_argument,       0,  0 },
                {"foo",     no_argument,       0,  0 },
                {0,         0,                 0,  0 },
        };

  use `"f"` (as a C string) as an option string and start the application with `-f`, the short option will be matched. `--f` will match the long one. And both `-fo` and `-foo` will match the long option `"foo"`.

  Be aware that if the option string would be `"f:"` (thus the short option requires an argument), using just `-f` leads to an error. But using `-fo` results in the long option being matched. For passing an argument in this situation, you need to do it as two arguments (`-f`, `o`). Though any other value would work in a single argument (e.g., `-f1`), since it would not match a long option (or its abbreviation).