Argp Example 3 (The GNU C Library)

#### 26.3.11.3 A Program Using Argp with User Options ¶

This program uses the same features as example 2, adding user options and arguments.

We now use the first four fields in `argp` (see Specifying Argp Parsers) and specify `parse_opt` as the parser function. See Argp Parser Functions.

Note that in this example, `main` uses a structure to communicate with the `parse_opt` function, a pointer to which it passes in the `input` argument to `argp_parse`. See Parsing Program Options with Argp. It is retrieved by `parse_opt` through the `input` field in its `state` argument. See Argp Parsing State. Of course, it’s also possible to use global variables instead, but using a structure like this is somewhat more flexible and clean.

    /* This program uses the same features as example 2, and uses options and
       arguments.

       We now use the first four fields in ARGP, so here’s a description of them:
         OPTIONS  – A pointer to a vector of struct argp_option (see below)
         PARSER   – A function to parse a single option, called by argp
         ARGS_DOC – A string describing how the non-option arguments should look
         DOC      – A descriptive string about this program; if it contains a
                     vertical tab character (\v), the part after it will be
                     printed *following* the options

       The function PARSER takes the following arguments:
         KEY  – An integer specifying which option this is (taken
                 from the KEY field in each struct argp_option), or
                 a special key specifying something else; the only
                 special keys we use here are ARGP_KEY_ARG, meaning
                 a non-option argument, and ARGP_KEY_END, meaning
                 that all arguments have been parsed
         ARG  – For an option KEY, the string value of its
                 argument, or NULL if it has none
         STATE– A pointer to a struct argp_state, containing
                 various useful information about the parsing state; used here
                 are the INPUT field, which reflects the INPUT argument to
                 argp_parse, and the ARG_NUM field, which is the number of the
                 current non-option argument being parsed
       It should return either 0, meaning success, ARGP_ERR_UNKNOWN, meaning the
       given KEY wasn’t recognized, or an errno value indicating some other
       error.

       Note that in this example, main uses a structure to communicate with the
       parse_opt function, a pointer to which it passes in the INPUT argument to
       argp_parse.  Of course, it’s also possible to use global variables
       instead, but this is somewhat more flexible.

       The OPTIONS field contains a pointer to a vector of struct argp_option’s;
       that structure has the following fields (if you assign your option
       structures using array initialization like this example, unspecified
       fields will be defaulted to 0, and need not be specified):
         NAME   – The name of this option’s long option (may be zero)
         KEY    – The KEY to pass to the PARSER function when parsing this option,
                   *and* the name of this option’s short option, if it is a
                   printable ascii character
         ARG    – The name of this option’s argument, if any
         FLAGS  – Flags describing this option; some of them are:
                     OPTION_ARG_OPTIONAL – The argument to this option is optional
                     OPTION_ALIAS        – This option is an alias for the
                                            previous option
                     OPTION_HIDDEN       – Don’t show this option in –help output
         DOC    – A documentation string for this option, shown in –help output

       An options vector should be terminated by an option with all fields zero. */

    #include <stdlib.h>
    #include <argp.h>

    const char *argp_program_version =
      "argp-ex3 1.0";
    const char *argp_program_bug_address =
      "<bug-gnu-utils@gnu.org>";

    /* Program documentation. */
    static char doc[] =
      "Argp example #3 -- a program with options and arguments using argp";

    /* A description of the arguments we accept. */
    static char args_doc[] = "ARG1 ARG2";

    /* The options we understand. */
    static struct argp_option options[] = {
      {"verbose",  'v', 0,      0,  "Produce verbose output" },
      {"quiet",    'q', 0,      0,  "Don't produce any output" },
      {"silent",   's', 0,      OPTION_ALIAS },
      {"output",   'o', "FILE", 0,
       "Output to FILE instead of standard output" },
      { 0 }
    };

    /* Used by main to communicate with parse_opt. */
    struct arguments
    {
      char *args[2];                /* arg1 & arg2 */
      int silent, verbose;
      char *output_file;
    };

    /* Parse a single option. */
    static error_t
    parse_opt (int key, char *arg, struct argp_state *state)
    {
      /* Get the input argument from argp_parse, which we
         know is a pointer to our arguments structure. */
      struct arguments *arguments = state->input;

      switch (key)
        {
        case 'q': case 's':
          arguments->silent = 1;
          break;
        case 'v':
          arguments->verbose = 1;
          break;
        case 'o':
          arguments->output_file = arg;
          break;

        case ARGP_KEY_ARG:
          if (state->arg_num >= 2)
            /* Too many arguments. */
            argp_usage (state);

          arguments->args[state->arg_num] = arg;

          break;

        case ARGP_KEY_END:
          if (state->arg_num < 2)
            /* Not enough arguments. */
            argp_usage (state);
          break;

        default:
          return ARGP_ERR_UNKNOWN;
        }
      return 0;
    }

    /* Our argp parser. */
    static struct argp argp = { options, parse_opt, args_doc, doc };

    int
    main (int argc, char **argv)
    {
      struct arguments arguments;

      /* Default values. */
      arguments.silent = 0;
      arguments.verbose = 0;
      arguments.output_file = "-";

      /* Parse our arguments; every option seen by parse_opt will
         be reflected in arguments. */
      argp_parse (&argp, argc, argv, 0, 0, &arguments);

      printf ("ARG1 = %s\nARG2 = %s\nOUTPUT_FILE = %s\n"
              "VERBOSE = %s\nSILENT = %s\n",
              arguments.args[0], arguments.args[1],
              arguments.output_file,
              arguments.verbose ? "yes" : "no",
              arguments.silent ? "yes" : "no");

      exit (0);
    }