1 /* Argp example #3 -- a program with options and arguments using argp
2    Copyright (C) 1991-2022 Free Software Foundation, Inc.
3 
4    This program is free software; you can redistribute it and/or
5    modify it under the terms of the GNU General Public License
6    as published by the Free Software Foundation; either version 2
7    of the License, or (at your option) any later version.
8 
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, see <https://www.gnu.org/licenses/>.
16 */
17 
18 /* This program uses the same features as example 2, and uses options and
19    arguments.
20 
21    We now use the first four fields in ARGP, so here's a description of them:
22      OPTIONS  -- A pointer to a vector of struct argp_option (see below)
23      PARSER   -- A function to parse a single option, called by argp
24      ARGS_DOC -- A string describing how the non-option arguments should look
25      DOC      -- A descriptive string about this program; if it contains a
26                  vertical tab character (\v), the part after it will be
27                  printed *following* the options
28 
29    The function PARSER takes the following arguments:
30      KEY  -- An integer specifying which option this is (taken
31              from the KEY field in each struct argp_option), or
32              a special key specifying something else; the only
33              special keys we use here are ARGP_KEY_ARG, meaning
34              a non-option argument, and ARGP_KEY_END, meaning
35              that all arguments have been parsed
36      ARG  -- For an option KEY, the string value of its
37              argument, or NULL if it has none
38      STATE-- A pointer to a struct argp_state, containing
39              various useful information about the parsing state; used here
40              are the INPUT field, which reflects the INPUT argument to
41              argp_parse, and the ARG_NUM field, which is the number of the
42              current non-option argument being parsed
43    It should return either 0, meaning success, ARGP_ERR_UNKNOWN, meaning the
44    given KEY wasn't recognized, or an errno value indicating some other
45    error.
46 
47    Note that in this example, main uses a structure to communicate with the
48    parse_opt function, a pointer to which it passes in the INPUT argument to
49    argp_parse.  Of course, it's also possible to use global variables
50    instead, but this is somewhat more flexible.
51 
52    The OPTIONS field contains a pointer to a vector of struct argp_option's;
53    that structure has the following fields (if you assign your option
54    structures using array initialization like this example, unspecified
55    fields will be defaulted to 0, and need not be specified):
56      NAME   -- The name of this option's long option (may be zero)
57      KEY    -- The KEY to pass to the PARSER function when parsing this option,
58                *and* the name of this option's short option, if it is a
59                printable ascii character
60      ARG    -- The name of this option's argument, if any
61      FLAGS  -- Flags describing this option; some of them are:
62                  OPTION_ARG_OPTIONAL -- The argument to this option is optional
63                  OPTION_ALIAS        -- This option is an alias for the
64                                         previous option
65                  OPTION_HIDDEN       -- Don't show this option in --help output
66      DOC    -- A documentation string for this option, shown in --help output
67 
68    An options vector should be terminated by an option with all fields zero. */
69 
70 #include <stdlib.h>
71 #include <argp.h>
72 
73 const char *argp_program_version =
74   "argp-ex3 1.0";
75 const char *argp_program_bug_address =
76   "<bug-gnu-utils@@gnu.org>";
77 
78 /* Program documentation.  */
79 static char doc[] =
80   "Argp example #3 -- a program with options and arguments using argp";
81 
82 /* A description of the arguments we accept.  */
83 static char args_doc[] = "ARG1 ARG2";
84 
85 /* The options we understand.  */
86 static struct argp_option options[] = {
87   {"verbose",  'v', 0,      0,  "Produce verbose output" },
88   {"quiet",    'q', 0,      0,  "Don't produce any output" },
89   {"silent",   's', 0,      OPTION_ALIAS },
90   {"output",   'o', "FILE", 0,
91    "Output to FILE instead of standard output" },
92   { 0 }
93 };
94 
95 /* Used by @code{main} to communicate with @code{parse_opt}.  */
96 struct arguments
97 {
98   char *args[2];		/* @var{arg1} & @var{arg2} */
99   int silent, verbose;
100   char *output_file;
101 };
102 
103 /* Parse a single option.  */
104 static error_t
parse_opt(int key,char * arg,struct argp_state * state)105 parse_opt (int key, char *arg, struct argp_state *state)
106 {
107   /* Get the @var{input} argument from @code{argp_parse}, which we
108      know is a pointer to our arguments structure.  */
109   struct arguments *arguments = state->input;
110 
111   switch (key)
112     {
113     case 'q': case 's':
114       arguments->silent = 1;
115       break;
116     case 'v':
117       arguments->verbose = 1;
118       break;
119     case 'o':
120       arguments->output_file = arg;
121       break;
122 
123     case ARGP_KEY_ARG:
124       if (state->arg_num >= 2)
125 	/* Too many arguments.  */
126 	argp_usage (state);
127 
128       arguments->args[state->arg_num] = arg;
129 
130       break;
131 
132     case ARGP_KEY_END:
133       if (state->arg_num < 2)
134 	/* Not enough arguments.  */
135 	argp_usage (state);
136       break;
137 
138     default:
139       return ARGP_ERR_UNKNOWN;
140     }
141   return 0;
142 }
143 
144 /* Our argp parser.  */
145 static struct argp argp = { options, parse_opt, args_doc, doc };
146 
147 int
main(int argc,char ** argv)148 main (int argc, char **argv)
149 {
150   struct arguments arguments;
151 
152   /* Default values.  */
153   arguments.silent = 0;
154   arguments.verbose = 0;
155   arguments.output_file = "-";
156 
157   /* Parse our arguments; every option seen by @code{parse_opt} will
158      be reflected in @code{arguments}.  */
159   argp_parse (&argp, argc, argv, 0, 0, &arguments);
160 
161   printf ("ARG1 = %s\nARG2 = %s\nOUTPUT_FILE = %s\n"
162 	  "VERBOSE = %s\nSILENT = %s\n",
163 	  arguments.args[0], arguments.args[1],
164 	  arguments.output_file,
165 	  arguments.verbose ? "yes" : "no",
166 	  arguments.silent ? "yes" : "no");
167 
168   exit (0);
169 }
170