summaryrefslogtreecommitdiff
path: root/libshouldbeinlibc/argp-ex3.c
blob: 5899e7935eb23b25da4d8961280201bf144b5b8f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/* Argp example #3 -- a program with options and arguments using argp */

/* 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 argumens 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 <argp.h>

const char *argp_program_version = "argp-ex3 1.0";
const char *argp_program_bug_address = "<bug-gnu-utils@prep.ai.mit.edu>";

static char doc[] =
  "Argp example #3 -- a program with options and arguments using argp";
static char args_doc[] = "ARG1 ARG2";

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;
};

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;
}

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 = "-";

  argp_parse (&argp, argc, argv, 0, 0, &arguments);

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

  exit (0);
}