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/base_command.hpp"
30*11be35a1SLionel Sambuc
31*11be35a1SLionel Sambuc #include "utils/cmdline/exceptions.hpp"
32*11be35a1SLionel Sambuc #include "utils/cmdline/options.hpp"
33*11be35a1SLionel Sambuc #include "utils/sanity.hpp"
34*11be35a1SLionel Sambuc
35*11be35a1SLionel Sambuc namespace cmdline = utils::cmdline;
36*11be35a1SLionel Sambuc
37*11be35a1SLionel Sambuc
38*11be35a1SLionel Sambuc /// Creates a new command.
39*11be35a1SLionel Sambuc ///
40*11be35a1SLionel Sambuc /// \param name_ The name of the command. Must be unique within the context of
41*11be35a1SLionel Sambuc /// a program and have no spaces.
42*11be35a1SLionel Sambuc /// \param arg_list_ A textual description of the arguments received by the
43*11be35a1SLionel Sambuc /// command. May be empty.
44*11be35a1SLionel Sambuc /// \param min_args_ The minimum number of arguments required by the command.
45*11be35a1SLionel Sambuc /// \param max_args_ The maximum number of arguments required by the command.
46*11be35a1SLionel Sambuc /// -1 means infinity.
47*11be35a1SLionel Sambuc /// \param short_description_ A description of the purpose of the command.
command_proto(const std::string & name_,const std::string & arg_list_,const int min_args_,const int max_args_,const std::string & short_description_)48*11be35a1SLionel Sambuc cmdline::command_proto::command_proto(const std::string& name_,
49*11be35a1SLionel Sambuc const std::string& arg_list_,
50*11be35a1SLionel Sambuc const int min_args_,
51*11be35a1SLionel Sambuc const int max_args_,
52*11be35a1SLionel Sambuc const std::string& short_description_) :
53*11be35a1SLionel Sambuc _name(name_),
54*11be35a1SLionel Sambuc _arg_list(arg_list_),
55*11be35a1SLionel Sambuc _min_args(min_args_),
56*11be35a1SLionel Sambuc _max_args(max_args_),
57*11be35a1SLionel Sambuc _short_description(short_description_)
58*11be35a1SLionel Sambuc {
59*11be35a1SLionel Sambuc PRE(name_.find(' ') == std::string::npos);
60*11be35a1SLionel Sambuc PRE(max_args_ == -1 || min_args_ <= max_args_);
61*11be35a1SLionel Sambuc }
62*11be35a1SLionel Sambuc
63*11be35a1SLionel Sambuc
64*11be35a1SLionel Sambuc /// Destructor for a command.
~command_proto(void)65*11be35a1SLionel Sambuc cmdline::command_proto::~command_proto(void)
66*11be35a1SLionel Sambuc {
67*11be35a1SLionel Sambuc for (options_vector::const_iterator iter = _options.begin();
68*11be35a1SLionel Sambuc iter != _options.end(); iter++)
69*11be35a1SLionel Sambuc delete *iter;
70*11be35a1SLionel Sambuc }
71*11be35a1SLionel Sambuc
72*11be35a1SLionel Sambuc
73*11be35a1SLionel Sambuc /// Internal method to register a dynamically-allocated option.
74*11be35a1SLionel Sambuc ///
75*11be35a1SLionel Sambuc /// Always use add_option() from subclasses to add options.
76*11be35a1SLionel Sambuc ///
77*11be35a1SLionel Sambuc /// \param option_ The option to add. Must have been dynamically allocated.
78*11be35a1SLionel Sambuc /// This grabs ownership of the pointer, which is released when the command
79*11be35a1SLionel Sambuc /// is destroyed.
80*11be35a1SLionel Sambuc void
add_option_ptr(const cmdline::base_option * option_)81*11be35a1SLionel Sambuc cmdline::command_proto::add_option_ptr(const cmdline::base_option* option_)
82*11be35a1SLionel Sambuc {
83*11be35a1SLionel Sambuc try {
84*11be35a1SLionel Sambuc _options.push_back(option_);
85*11be35a1SLionel Sambuc } catch (...) {
86*11be35a1SLionel Sambuc delete option_;
87*11be35a1SLionel Sambuc throw;
88*11be35a1SLionel Sambuc }
89*11be35a1SLionel Sambuc }
90*11be35a1SLionel Sambuc
91*11be35a1SLionel Sambuc
92*11be35a1SLionel Sambuc /// Processes the command line based on the command description.
93*11be35a1SLionel Sambuc ///
94*11be35a1SLionel Sambuc /// \param args The raw command line to be processed.
95*11be35a1SLionel Sambuc ///
96*11be35a1SLionel Sambuc /// \return An object containing the list of options and free arguments found in
97*11be35a1SLionel Sambuc /// args.
98*11be35a1SLionel Sambuc ///
99*11be35a1SLionel Sambuc /// \throw cmdline::usage_error If there is a problem processing the command
100*11be35a1SLionel Sambuc /// line. This error is caused by invalid input from the user.
101*11be35a1SLionel Sambuc cmdline::parsed_cmdline
parse_cmdline(const cmdline::args_vector & args) const102*11be35a1SLionel Sambuc cmdline::command_proto::parse_cmdline(const cmdline::args_vector& args) const
103*11be35a1SLionel Sambuc {
104*11be35a1SLionel Sambuc PRE(name() == args[0]);
105*11be35a1SLionel Sambuc const parsed_cmdline cmdline = cmdline::parse(args, options());
106*11be35a1SLionel Sambuc
107*11be35a1SLionel Sambuc const int argc = cmdline.arguments().size();
108*11be35a1SLionel Sambuc if (argc < _min_args)
109*11be35a1SLionel Sambuc throw usage_error("Not enough arguments");
110*11be35a1SLionel Sambuc if (_max_args != -1 && argc > _max_args)
111*11be35a1SLionel Sambuc throw usage_error("Too many arguments");
112*11be35a1SLionel Sambuc
113*11be35a1SLionel Sambuc return cmdline;
114*11be35a1SLionel Sambuc }
115*11be35a1SLionel Sambuc
116*11be35a1SLionel Sambuc
117*11be35a1SLionel Sambuc /// Gets the name of the command.
118*11be35a1SLionel Sambuc ///
119*11be35a1SLionel Sambuc /// \return The command name.
120*11be35a1SLionel Sambuc const std::string&
name(void) const121*11be35a1SLionel Sambuc cmdline::command_proto::name(void) const
122*11be35a1SLionel Sambuc {
123*11be35a1SLionel Sambuc return _name;
124*11be35a1SLionel Sambuc }
125*11be35a1SLionel Sambuc
126*11be35a1SLionel Sambuc
127*11be35a1SLionel Sambuc /// Gets the textual representation of the arguments list.
128*11be35a1SLionel Sambuc ///
129*11be35a1SLionel Sambuc /// \return The description of the arguments list.
130*11be35a1SLionel Sambuc const std::string&
arg_list(void) const131*11be35a1SLionel Sambuc cmdline::command_proto::arg_list(void) const
132*11be35a1SLionel Sambuc {
133*11be35a1SLionel Sambuc return _arg_list;
134*11be35a1SLionel Sambuc }
135*11be35a1SLionel Sambuc
136*11be35a1SLionel Sambuc
137*11be35a1SLionel Sambuc /// Gets the description of the purpose of the command.
138*11be35a1SLionel Sambuc ///
139*11be35a1SLionel Sambuc /// \return The description of the command.
140*11be35a1SLionel Sambuc const std::string&
short_description(void) const141*11be35a1SLionel Sambuc cmdline::command_proto::short_description(void) const
142*11be35a1SLionel Sambuc {
143*11be35a1SLionel Sambuc return _short_description;
144*11be35a1SLionel Sambuc }
145*11be35a1SLionel Sambuc
146*11be35a1SLionel Sambuc
147*11be35a1SLionel Sambuc /// Gets the definition of the options accepted by the command.
148*11be35a1SLionel Sambuc ///
149*11be35a1SLionel Sambuc /// \return The list of options.
150*11be35a1SLionel Sambuc const cmdline::options_vector&
options(void) const151*11be35a1SLionel Sambuc cmdline::command_proto::options(void) const
152*11be35a1SLionel Sambuc {
153*11be35a1SLionel Sambuc return _options;
154*11be35a1SLionel Sambuc }
155*11be35a1SLionel Sambuc
156*11be35a1SLionel Sambuc
157*11be35a1SLionel Sambuc /// Creates a new command.
158*11be35a1SLionel Sambuc ///
159*11be35a1SLionel Sambuc /// \param name_ The name of the command. Must be unique within the context of
160*11be35a1SLionel Sambuc /// a program and have no spaces.
161*11be35a1SLionel Sambuc /// \param arg_list_ A textual description of the arguments received by the
162*11be35a1SLionel Sambuc /// command. May be empty.
163*11be35a1SLionel Sambuc /// \param min_args_ The minimum number of arguments required by the command.
164*11be35a1SLionel Sambuc /// \param max_args_ The maximum number of arguments required by the command.
165*11be35a1SLionel Sambuc /// -1 means infinity.
166*11be35a1SLionel Sambuc /// \param short_description_ A description of the purpose of the command.
base_command_no_data(const std::string & name_,const std::string & arg_list_,const int min_args_,const int max_args_,const std::string & short_description_)167*11be35a1SLionel Sambuc cmdline::base_command_no_data::base_command_no_data(
168*11be35a1SLionel Sambuc const std::string& name_,
169*11be35a1SLionel Sambuc const std::string& arg_list_,
170*11be35a1SLionel Sambuc const int min_args_,
171*11be35a1SLionel Sambuc const int max_args_,
172*11be35a1SLionel Sambuc const std::string& short_description_) :
173*11be35a1SLionel Sambuc command_proto(name_, arg_list_, min_args_, max_args_, short_description_)
174*11be35a1SLionel Sambuc {
175*11be35a1SLionel Sambuc }
176*11be35a1SLionel Sambuc
177*11be35a1SLionel Sambuc
178*11be35a1SLionel Sambuc /// Entry point for the command.
179*11be35a1SLionel Sambuc ///
180*11be35a1SLionel Sambuc /// This delegates execution to the run() abstract function after the command
181*11be35a1SLionel Sambuc /// line provided in args has been parsed.
182*11be35a1SLionel Sambuc ///
183*11be35a1SLionel Sambuc /// If this function returns, the command is assumed to have been executed
184*11be35a1SLionel Sambuc /// successfully. Any error must be reported by means of exceptions.
185*11be35a1SLionel Sambuc ///
186*11be35a1SLionel Sambuc /// \param ui Object to interact with the I/O of the command. The command must
187*11be35a1SLionel Sambuc /// always use this object to write to stdout and stderr.
188*11be35a1SLionel Sambuc /// \param args The command line passed to the command broken by word, which
189*11be35a1SLionel Sambuc /// includes options and arguments.
190*11be35a1SLionel Sambuc ///
191*11be35a1SLionel Sambuc /// \return The exit code that the program has to return. 0 on success, some
192*11be35a1SLionel Sambuc /// other value on error.
193*11be35a1SLionel Sambuc /// \throw usage_error If args is invalid (i.e. if the options are mispecified
194*11be35a1SLionel Sambuc /// or if the arguments are invalid).
195*11be35a1SLionel Sambuc int
main(cmdline::ui * ui,const cmdline::args_vector & args)196*11be35a1SLionel Sambuc cmdline::base_command_no_data::main(cmdline::ui* ui,
197*11be35a1SLionel Sambuc const cmdline::args_vector& args)
198*11be35a1SLionel Sambuc {
199*11be35a1SLionel Sambuc return run(ui, parse_cmdline(args));
200*11be35a1SLionel Sambuc }
201