1*11be35a1SLionel Sambuc // Copyright 2010 Google Inc.
2*11be35a1SLionel Sambuc // All rights reserved.
3*11be35a1SLionel Sambuc //
4*11be35a1SLionel Sambuc // Redistribution and use in source and binary forms, with or without
5*11be35a1SLionel Sambuc // modification, are permitted provided that the following conditions are
6*11be35a1SLionel Sambuc // met:
7*11be35a1SLionel Sambuc //
8*11be35a1SLionel Sambuc // * Redistributions of source code must retain the above copyright
9*11be35a1SLionel Sambuc // notice, this list of conditions and the following disclaimer.
10*11be35a1SLionel Sambuc // * Redistributions in binary form must reproduce the above copyright
11*11be35a1SLionel Sambuc // notice, this list of conditions and the following disclaimer in the
12*11be35a1SLionel Sambuc // documentation and/or other materials provided with the distribution.
13*11be35a1SLionel Sambuc // * Neither the name of Google Inc. nor the names of its contributors
14*11be35a1SLionel Sambuc // may be used to endorse or promote products derived from this software
15*11be35a1SLionel Sambuc // without specific prior written permission.
16*11be35a1SLionel Sambuc //
17*11be35a1SLionel Sambuc // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18*11be35a1SLionel Sambuc // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19*11be35a1SLionel Sambuc // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20*11be35a1SLionel Sambuc // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21*11be35a1SLionel Sambuc // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22*11be35a1SLionel Sambuc // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23*11be35a1SLionel Sambuc // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24*11be35a1SLionel Sambuc // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25*11be35a1SLionel Sambuc // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26*11be35a1SLionel Sambuc // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27*11be35a1SLionel Sambuc // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*11be35a1SLionel Sambuc
29*11be35a1SLionel Sambuc #include "utils/cmdline/parser.hpp"
30*11be35a1SLionel Sambuc
31*11be35a1SLionel Sambuc #if defined(HAVE_CONFIG_H)
32*11be35a1SLionel Sambuc # include "config.h"
33*11be35a1SLionel Sambuc #endif
34*11be35a1SLionel Sambuc
35*11be35a1SLionel Sambuc extern "C" {
36*11be35a1SLionel Sambuc #include <getopt.h>
37*11be35a1SLionel Sambuc }
38*11be35a1SLionel Sambuc
39*11be35a1SLionel Sambuc #include <cstdlib>
40*11be35a1SLionel Sambuc #include <cstring>
41*11be35a1SLionel Sambuc #include <limits>
42*11be35a1SLionel Sambuc
43*11be35a1SLionel Sambuc #include "utils/auto_array.ipp"
44*11be35a1SLionel Sambuc #include "utils/cmdline/exceptions.hpp"
45*11be35a1SLionel Sambuc #include "utils/cmdline/options.hpp"
46*11be35a1SLionel Sambuc #include "utils/format/macros.hpp"
47*11be35a1SLionel Sambuc #include "utils/noncopyable.hpp"
48*11be35a1SLionel Sambuc #include "utils/sanity.hpp"
49*11be35a1SLionel Sambuc
50*11be35a1SLionel Sambuc namespace cmdline = utils::cmdline;
51*11be35a1SLionel Sambuc
52*11be35a1SLionel Sambuc namespace {
53*11be35a1SLionel Sambuc
54*11be35a1SLionel Sambuc
55*11be35a1SLionel Sambuc /// Auxiliary data to call getopt_long(3).
56*11be35a1SLionel Sambuc struct getopt_data : utils::noncopyable {
57*11be35a1SLionel Sambuc /// Plain-text representation of the short options.
58*11be35a1SLionel Sambuc ///
59*11be35a1SLionel Sambuc /// This string follows the syntax expected by getopt_long(3) in the
60*11be35a1SLionel Sambuc /// argument to describe the short options.
61*11be35a1SLionel Sambuc std::string short_options;
62*11be35a1SLionel Sambuc
63*11be35a1SLionel Sambuc /// Representation of the long options as expected by getopt_long(3).
64*11be35a1SLionel Sambuc utils::auto_array< ::option > long_options;
65*11be35a1SLionel Sambuc
66*11be35a1SLionel Sambuc /// Auto-generated identifiers to be able to parse long options.
67*11be35a1SLionel Sambuc std::map< int, const cmdline::base_option* > ids;
68*11be35a1SLionel Sambuc };
69*11be35a1SLionel Sambuc
70*11be35a1SLionel Sambuc
71*11be35a1SLionel Sambuc /// Converts a cmdline::options_vector to a getopt_data.
72*11be35a1SLionel Sambuc ///
73*11be35a1SLionel Sambuc /// \param options The high-level definition of the options.
74*11be35a1SLionel Sambuc /// \param [out] data An object containing the necessary data to call
75*11be35a1SLionel Sambuc /// getopt_long(3) and interpret its results.
76*11be35a1SLionel Sambuc static void
options_to_getopt_data(const cmdline::options_vector & options,getopt_data & data)77*11be35a1SLionel Sambuc options_to_getopt_data(const cmdline::options_vector& options,
78*11be35a1SLionel Sambuc getopt_data& data)
79*11be35a1SLionel Sambuc {
80*11be35a1SLionel Sambuc data.short_options.clear();
81*11be35a1SLionel Sambuc data.long_options.reset(new ::option[options.size() + 1]);
82*11be35a1SLionel Sambuc
83*11be35a1SLionel Sambuc int cur_id = 512;
84*11be35a1SLionel Sambuc
85*11be35a1SLionel Sambuc for (cmdline::options_vector::size_type i = 0; i < options.size(); i++) {
86*11be35a1SLionel Sambuc const cmdline::base_option* option = options[i];
87*11be35a1SLionel Sambuc ::option& long_option = data.long_options[i];
88*11be35a1SLionel Sambuc
89*11be35a1SLionel Sambuc long_option.name = option->long_name().c_str();
90*11be35a1SLionel Sambuc if (option->needs_arg())
91*11be35a1SLionel Sambuc long_option.has_arg = required_argument;
92*11be35a1SLionel Sambuc else
93*11be35a1SLionel Sambuc long_option.has_arg = no_argument;
94*11be35a1SLionel Sambuc
95*11be35a1SLionel Sambuc int id = -1;
96*11be35a1SLionel Sambuc if (option->has_short_name()) {
97*11be35a1SLionel Sambuc data.short_options += option->short_name();
98*11be35a1SLionel Sambuc if (option->needs_arg())
99*11be35a1SLionel Sambuc data.short_options += ':';
100*11be35a1SLionel Sambuc id = option->short_name();
101*11be35a1SLionel Sambuc } else {
102*11be35a1SLionel Sambuc id = cur_id++;
103*11be35a1SLionel Sambuc }
104*11be35a1SLionel Sambuc long_option.flag = NULL;
105*11be35a1SLionel Sambuc long_option.val = id;
106*11be35a1SLionel Sambuc data.ids[id] = option;
107*11be35a1SLionel Sambuc }
108*11be35a1SLionel Sambuc
109*11be35a1SLionel Sambuc ::option& last_long_option = data.long_options[options.size()];
110*11be35a1SLionel Sambuc last_long_option.name = NULL;
111*11be35a1SLionel Sambuc last_long_option.has_arg = 0;
112*11be35a1SLionel Sambuc last_long_option.flag = NULL;
113*11be35a1SLionel Sambuc last_long_option.val = 0;
114*11be35a1SLionel Sambuc }
115*11be35a1SLionel Sambuc
116*11be35a1SLionel Sambuc
117*11be35a1SLionel Sambuc /// Converts an argc/argv pair to an args_vector.
118*11be35a1SLionel Sambuc ///
119*11be35a1SLionel Sambuc /// \param argc The value of argc as passed to main().
120*11be35a1SLionel Sambuc /// \param argv The value of argv as passed to main().
121*11be35a1SLionel Sambuc ///
122*11be35a1SLionel Sambuc /// \return An args_vector with the same contents of argc/argv.
123*11be35a1SLionel Sambuc static cmdline::args_vector
argv_to_vector(int argc,const char * const argv[])124*11be35a1SLionel Sambuc argv_to_vector(int argc, const char* const argv[])
125*11be35a1SLionel Sambuc {
126*11be35a1SLionel Sambuc PRE(argv[argc] == NULL);
127*11be35a1SLionel Sambuc cmdline::args_vector args;
128*11be35a1SLionel Sambuc for (int i = 0; i < argc; i++)
129*11be35a1SLionel Sambuc args.push_back(argv[i]);
130*11be35a1SLionel Sambuc return args;
131*11be35a1SLionel Sambuc }
132*11be35a1SLionel Sambuc
133*11be35a1SLionel Sambuc
134*11be35a1SLionel Sambuc /// Creates a mutable version of argv.
135*11be35a1SLionel Sambuc ///
136*11be35a1SLionel Sambuc /// \param argc The value of argc as passed to main().
137*11be35a1SLionel Sambuc /// \param argv The value of argv as passed to main().
138*11be35a1SLionel Sambuc ///
139*11be35a1SLionel Sambuc /// \return A new argv, with mutable buffers. The returned array must be
140*11be35a1SLionel Sambuc /// released using the free_mutable_argv() function.
141*11be35a1SLionel Sambuc static char**
make_mutable_argv(const int argc,const char * const * argv)142*11be35a1SLionel Sambuc make_mutable_argv(const int argc, const char* const* argv)
143*11be35a1SLionel Sambuc {
144*11be35a1SLionel Sambuc char** mutable_argv = new char*[argc + 1];
145*11be35a1SLionel Sambuc for (int i = 0; i < argc; i++)
146*11be35a1SLionel Sambuc mutable_argv[i] = ::strdup(argv[i]);
147*11be35a1SLionel Sambuc mutable_argv[argc] = NULL;
148*11be35a1SLionel Sambuc return mutable_argv;
149*11be35a1SLionel Sambuc }
150*11be35a1SLionel Sambuc
151*11be35a1SLionel Sambuc
152*11be35a1SLionel Sambuc /// Releases the object returned by make_mutable_argv().
153*11be35a1SLionel Sambuc ///
154*11be35a1SLionel Sambuc /// \param argv A dynamically-allocated argv as returned by make_mutable_argv().
155*11be35a1SLionel Sambuc static void
free_mutable_argv(char ** argv)156*11be35a1SLionel Sambuc free_mutable_argv(char** argv)
157*11be35a1SLionel Sambuc {
158*11be35a1SLionel Sambuc char** ptr = argv;
159*11be35a1SLionel Sambuc while (*ptr != NULL) {
160*11be35a1SLionel Sambuc ::free(*ptr);
161*11be35a1SLionel Sambuc ptr++;
162*11be35a1SLionel Sambuc }
163*11be35a1SLionel Sambuc delete [] argv;
164*11be35a1SLionel Sambuc }
165*11be35a1SLionel Sambuc
166*11be35a1SLionel Sambuc
167*11be35a1SLionel Sambuc /// Finds the name of the offending option after a getopt_long error.
168*11be35a1SLionel Sambuc ///
169*11be35a1SLionel Sambuc /// \param data Our internal getopt data used for the call to getopt_long.
170*11be35a1SLionel Sambuc /// \param getopt_optopt The value of getopt(3)'s optopt after the error.
171*11be35a1SLionel Sambuc /// \param argv The argv passed to getopt_long.
172*11be35a1SLionel Sambuc /// \param getopt_optind The value of getopt(3)'s optind after the error.
173*11be35a1SLionel Sambuc ///
174*11be35a1SLionel Sambuc /// \return A fully-specified option name (i.e. an option name prefixed by
175*11be35a1SLionel Sambuc /// either '-' or '--').
176*11be35a1SLionel Sambuc static std::string
find_option_name(const getopt_data & data,const int getopt_optopt,char ** argv,const int getopt_optind)177*11be35a1SLionel Sambuc find_option_name(const getopt_data& data, const int getopt_optopt,
178*11be35a1SLionel Sambuc char** argv, const int getopt_optind)
179*11be35a1SLionel Sambuc {
180*11be35a1SLionel Sambuc PRE(getopt_optopt >= 0);
181*11be35a1SLionel Sambuc
182*11be35a1SLionel Sambuc if (getopt_optopt == 0) {
183*11be35a1SLionel Sambuc return argv[getopt_optind - 1];
184*11be35a1SLionel Sambuc } else if (getopt_optopt < std::numeric_limits< char >::max()) {
185*11be35a1SLionel Sambuc INV(getopt_optopt > 0);
186*11be35a1SLionel Sambuc const char ch = static_cast< char >(getopt_optopt);
187*11be35a1SLionel Sambuc return F("-%s") % ch;
188*11be35a1SLionel Sambuc } else {
189*11be35a1SLionel Sambuc for (const ::option* opt = &data.long_options[0]; opt->name != NULL;
190*11be35a1SLionel Sambuc opt++) {
191*11be35a1SLionel Sambuc if (opt->val == getopt_optopt)
192*11be35a1SLionel Sambuc return F("--%s") % opt->name;
193*11be35a1SLionel Sambuc }
194*11be35a1SLionel Sambuc UNREACHABLE;
195*11be35a1SLionel Sambuc }
196*11be35a1SLionel Sambuc }
197*11be35a1SLionel Sambuc
198*11be35a1SLionel Sambuc
199*11be35a1SLionel Sambuc } // anonymous namespace
200*11be35a1SLionel Sambuc
201*11be35a1SLionel Sambuc
202*11be35a1SLionel Sambuc /// Constructs a new parsed_cmdline.
203*11be35a1SLionel Sambuc ///
204*11be35a1SLionel Sambuc /// Use the cmdline::parse() free functions to construct.
205*11be35a1SLionel Sambuc ///
206*11be35a1SLionel Sambuc /// \param option_values_ A mapping of long option names to values. This
207*11be35a1SLionel Sambuc /// contains a representation of the options provided by the user. Note
208*11be35a1SLionel Sambuc /// that each value is actually a collection values: a user may specify a
209*11be35a1SLionel Sambuc /// flag multiple times, and depending on the case we want to honor one or
210*11be35a1SLionel Sambuc /// the other. For those options that support no argument, the argument
211*11be35a1SLionel Sambuc /// value is the empty string.
212*11be35a1SLionel Sambuc /// \param arguments_ The list of non-option arguments in the command line.
parsed_cmdline(const std::map<std::string,std::vector<std::string>> & option_values_,const cmdline::args_vector & arguments_)213*11be35a1SLionel Sambuc cmdline::parsed_cmdline::parsed_cmdline(
214*11be35a1SLionel Sambuc const std::map< std::string, std::vector< std::string > >& option_values_,
215*11be35a1SLionel Sambuc const cmdline::args_vector& arguments_) :
216*11be35a1SLionel Sambuc _option_values(option_values_),
217*11be35a1SLionel Sambuc _arguments(arguments_)
218*11be35a1SLionel Sambuc {
219*11be35a1SLionel Sambuc }
220*11be35a1SLionel Sambuc
221*11be35a1SLionel Sambuc
222*11be35a1SLionel Sambuc /// Checks if the given option has been given in the command line.
223*11be35a1SLionel Sambuc ///
224*11be35a1SLionel Sambuc /// \param name The long option name to check for presence.
225*11be35a1SLionel Sambuc ///
226*11be35a1SLionel Sambuc /// \return True if the option has been given; false otherwise.
227*11be35a1SLionel Sambuc bool
has_option(const std::string & name) const228*11be35a1SLionel Sambuc cmdline::parsed_cmdline::has_option(const std::string& name) const
229*11be35a1SLionel Sambuc {
230*11be35a1SLionel Sambuc return _option_values.find(name) != _option_values.end();
231*11be35a1SLionel Sambuc }
232*11be35a1SLionel Sambuc
233*11be35a1SLionel Sambuc
234*11be35a1SLionel Sambuc /// Gets the raw value of an option.
235*11be35a1SLionel Sambuc ///
236*11be35a1SLionel Sambuc /// The raw value of an option is a collection of strings that represent all the
237*11be35a1SLionel Sambuc /// values passed to the option on the command line. It is up to the consumer
238*11be35a1SLionel Sambuc /// if he wants to honor only the last value or all of them.
239*11be35a1SLionel Sambuc ///
240*11be35a1SLionel Sambuc /// The caller has to use get_option() instead; this function is internal.
241*11be35a1SLionel Sambuc ///
242*11be35a1SLionel Sambuc /// \pre has_option(name) must be true.
243*11be35a1SLionel Sambuc ///
244*11be35a1SLionel Sambuc /// \param name The option to query.
245*11be35a1SLionel Sambuc ///
246*11be35a1SLionel Sambuc /// \return The value of the option as a plain string.
247*11be35a1SLionel Sambuc const std::vector< std::string >&
get_option_raw(const std::string & name) const248*11be35a1SLionel Sambuc cmdline::parsed_cmdline::get_option_raw(const std::string& name) const
249*11be35a1SLionel Sambuc {
250*11be35a1SLionel Sambuc std::map< std::string, std::vector< std::string > >::const_iterator iter =
251*11be35a1SLionel Sambuc _option_values.find(name);
252*11be35a1SLionel Sambuc INV_MSG(iter != _option_values.end(), F("Undefined option --%s") % name);
253*11be35a1SLionel Sambuc return (*iter).second;
254*11be35a1SLionel Sambuc }
255*11be35a1SLionel Sambuc
256*11be35a1SLionel Sambuc
257*11be35a1SLionel Sambuc /// Returns the non-option arguments found in the command line.
258*11be35a1SLionel Sambuc ///
259*11be35a1SLionel Sambuc /// \return The arguments, if any.
260*11be35a1SLionel Sambuc const cmdline::args_vector&
arguments(void) const261*11be35a1SLionel Sambuc cmdline::parsed_cmdline::arguments(void) const
262*11be35a1SLionel Sambuc {
263*11be35a1SLionel Sambuc return _arguments;
264*11be35a1SLionel Sambuc }
265*11be35a1SLionel Sambuc
266*11be35a1SLionel Sambuc
267*11be35a1SLionel Sambuc /// Parses a command line.
268*11be35a1SLionel Sambuc ///
269*11be35a1SLionel Sambuc /// \param args The command line to parse, broken down by words.
270*11be35a1SLionel Sambuc /// \param options The description of the supported options.
271*11be35a1SLionel Sambuc ///
272*11be35a1SLionel Sambuc /// \return The parsed command line.
273*11be35a1SLionel Sambuc ///
274*11be35a1SLionel Sambuc /// \pre args[0] must be the program or command name.
275*11be35a1SLionel Sambuc ///
276*11be35a1SLionel Sambuc /// \throw cmdline::error See the description of parse(argc, argv, options) for
277*11be35a1SLionel Sambuc /// more details on the raised errors.
278*11be35a1SLionel Sambuc cmdline::parsed_cmdline
parse(const cmdline::args_vector & args,const cmdline::options_vector & options)279*11be35a1SLionel Sambuc cmdline::parse(const cmdline::args_vector& args,
280*11be35a1SLionel Sambuc const cmdline::options_vector& options)
281*11be35a1SLionel Sambuc {
282*11be35a1SLionel Sambuc PRE_MSG(args.size() >= 1, "No progname or command name found");
283*11be35a1SLionel Sambuc
284*11be35a1SLionel Sambuc utils::auto_array< const char* > argv(new const char*[args.size() + 1]);
285*11be35a1SLionel Sambuc for (args_vector::size_type i = 0; i < args.size(); i++)
286*11be35a1SLionel Sambuc argv[i] = args[i].c_str();
287*11be35a1SLionel Sambuc argv[args.size()] = NULL;
288*11be35a1SLionel Sambuc return parse(static_cast< int >(args.size()), argv.get(), options);
289*11be35a1SLionel Sambuc }
290*11be35a1SLionel Sambuc
291*11be35a1SLionel Sambuc
292*11be35a1SLionel Sambuc /// Parses a command line.
293*11be35a1SLionel Sambuc ///
294*11be35a1SLionel Sambuc /// \param argc The number of arguments in argv, without counting the
295*11be35a1SLionel Sambuc /// terminating NULL.
296*11be35a1SLionel Sambuc /// \param argv The arguments to parse. The array is NULL-terminated.
297*11be35a1SLionel Sambuc /// \param options The description of the supported options.
298*11be35a1SLionel Sambuc ///
299*11be35a1SLionel Sambuc /// \return The parsed command line.
300*11be35a1SLionel Sambuc ///
301*11be35a1SLionel Sambuc /// \pre args[0] must be the program or command name.
302*11be35a1SLionel Sambuc ///
303*11be35a1SLionel Sambuc /// \throw cmdline::missing_option_argument_error If the user specified an
304*11be35a1SLionel Sambuc /// option that requires an argument, but no argument was provided.
305*11be35a1SLionel Sambuc /// \throw cmdline::unknown_option_error If the user specified an unknown
306*11be35a1SLionel Sambuc /// option (i.e. an option not defined in options).
307*11be35a1SLionel Sambuc /// \throw cmdline::option_argument_value_error If the user passed an invalid
308*11be35a1SLionel Sambuc /// argument to a supported option.
309*11be35a1SLionel Sambuc cmdline::parsed_cmdline
parse(const int argc,const char * const * argv,const cmdline::options_vector & options)310*11be35a1SLionel Sambuc cmdline::parse(const int argc, const char* const* argv,
311*11be35a1SLionel Sambuc const cmdline::options_vector& options)
312*11be35a1SLionel Sambuc {
313*11be35a1SLionel Sambuc PRE_MSG(argc >= 1, "No progname or command name found");
314*11be35a1SLionel Sambuc
315*11be35a1SLionel Sambuc getopt_data data;
316*11be35a1SLionel Sambuc options_to_getopt_data(options, data);
317*11be35a1SLionel Sambuc
318*11be35a1SLionel Sambuc std::map< std::string, std::vector< std::string > > option_values;
319*11be35a1SLionel Sambuc
320*11be35a1SLionel Sambuc for (cmdline::options_vector::const_iterator iter = options.begin();
321*11be35a1SLionel Sambuc iter != options.end(); iter++) {
322*11be35a1SLionel Sambuc const cmdline::base_option* option = *iter;
323*11be35a1SLionel Sambuc if (option->needs_arg() && option->has_default_value())
324*11be35a1SLionel Sambuc option_values[option->long_name()].push_back(
325*11be35a1SLionel Sambuc option->default_value());
326*11be35a1SLionel Sambuc }
327*11be35a1SLionel Sambuc
328*11be35a1SLionel Sambuc args_vector args;
329*11be35a1SLionel Sambuc
330*11be35a1SLionel Sambuc int mutable_argc = argc;
331*11be35a1SLionel Sambuc char** mutable_argv = make_mutable_argv(argc, argv);
332*11be35a1SLionel Sambuc const int old_opterr = ::opterr;
333*11be35a1SLionel Sambuc try {
334*11be35a1SLionel Sambuc int ch;
335*11be35a1SLionel Sambuc
336*11be35a1SLionel Sambuc ::opterr = 0;
337*11be35a1SLionel Sambuc
338*11be35a1SLionel Sambuc while ((ch = ::getopt_long(mutable_argc, mutable_argv,
339*11be35a1SLionel Sambuc ("+:" + data.short_options).c_str(),
340*11be35a1SLionel Sambuc data.long_options.get(), NULL)) != -1) {
341*11be35a1SLionel Sambuc if (ch == ':' ) {
342*11be35a1SLionel Sambuc const std::string name = find_option_name(
343*11be35a1SLionel Sambuc data, ::optopt, mutable_argv, ::optind);
344*11be35a1SLionel Sambuc throw cmdline::missing_option_argument_error(name);
345*11be35a1SLionel Sambuc } else if (ch == '?') {
346*11be35a1SLionel Sambuc const std::string name = find_option_name(
347*11be35a1SLionel Sambuc data, ::optopt, mutable_argv, ::optind);
348*11be35a1SLionel Sambuc throw cmdline::unknown_option_error(name);
349*11be35a1SLionel Sambuc }
350*11be35a1SLionel Sambuc
351*11be35a1SLionel Sambuc const std::map< int, const cmdline::base_option* >::const_iterator
352*11be35a1SLionel Sambuc id = data.ids.find(ch);
353*11be35a1SLionel Sambuc INV(id != data.ids.end());
354*11be35a1SLionel Sambuc const cmdline::base_option* option = (*id).second;
355*11be35a1SLionel Sambuc
356*11be35a1SLionel Sambuc if (option->needs_arg()) {
357*11be35a1SLionel Sambuc if (::optarg != NULL) {
358*11be35a1SLionel Sambuc option->validate(::optarg);
359*11be35a1SLionel Sambuc option_values[option->long_name()].push_back(::optarg);
360*11be35a1SLionel Sambuc } else
361*11be35a1SLionel Sambuc INV(option->has_default_value());
362*11be35a1SLionel Sambuc } else {
363*11be35a1SLionel Sambuc option_values[option->long_name()].push_back("");
364*11be35a1SLionel Sambuc }
365*11be35a1SLionel Sambuc }
366*11be35a1SLionel Sambuc args = argv_to_vector(mutable_argc - optind, mutable_argv + optind);
367*11be35a1SLionel Sambuc
368*11be35a1SLionel Sambuc ::opterr = old_opterr;
369*11be35a1SLionel Sambuc ::optind = GETOPT_OPTIND_RESET_VALUE;
370*11be35a1SLionel Sambuc #if defined(HAVE_GETOPT_WITH_OPTRESET)
371*11be35a1SLionel Sambuc ::optreset = 1;
372*11be35a1SLionel Sambuc #endif
373*11be35a1SLionel Sambuc } catch (...) {
374*11be35a1SLionel Sambuc free_mutable_argv(mutable_argv);
375*11be35a1SLionel Sambuc ::opterr = old_opterr;
376*11be35a1SLionel Sambuc ::optind = GETOPT_OPTIND_RESET_VALUE;
377*11be35a1SLionel Sambuc #if defined(HAVE_GETOPT_WITH_OPTRESET)
378*11be35a1SLionel Sambuc ::optreset = 1;
379*11be35a1SLionel Sambuc #endif
380*11be35a1SLionel Sambuc throw;
381*11be35a1SLionel Sambuc }
382*11be35a1SLionel Sambuc free_mutable_argv(mutable_argv);
383*11be35a1SLionel Sambuc
384*11be35a1SLionel Sambuc return parsed_cmdline(option_values, args);
385*11be35a1SLionel Sambuc }
386