1// Copyright 2010 The Kyua Authors.
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
8// * Redistributions of source code must retain the above copyright
9//   notice, this list of conditions and the following disclaimer.
10// * Redistributions in binary form must reproduce the above copyright
11//   notice, this list of conditions and the following disclaimer in the
12//   documentation and/or other materials provided with the distribution.
13// * Neither the name of Google Inc. nor the names of its contributors
14//   may be used to endorse or promote products derived from this software
15//   without specific prior written permission.
16//
17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29#include "utils/cmdline/base_command.hpp"
30
31#include "utils/cmdline/exceptions.hpp"
32#include "utils/cmdline/options.hpp"
33#include "utils/cmdline/parser.ipp"
34#include "utils/sanity.hpp"
35
36namespace cmdline = utils::cmdline;
37
38
39/// Creates a new command.
40///
41/// \param name_ The name of the command.  Must be unique within the context of
42///     a program and have no spaces.
43/// \param arg_list_ A textual description of the arguments received by the
44///     command.  May be empty.
45/// \param min_args_ The minimum number of arguments required by the command.
46/// \param max_args_ The maximum number of arguments required by the command.
47///     -1 means infinity.
48/// \param short_description_ A description of the purpose of the command.
49cmdline::command_proto::command_proto(const std::string& name_,
50                                      const std::string& arg_list_,
51                                      const int min_args_,
52                                      const int max_args_,
53                                      const std::string& short_description_) :
54    _name(name_),
55    _arg_list(arg_list_),
56    _min_args(min_args_),
57    _max_args(max_args_),
58    _short_description(short_description_)
59{
60    PRE(name_.find(' ') == std::string::npos);
61    PRE(max_args_ == -1 || min_args_ <= max_args_);
62}
63
64
65/// Destructor for a command.
66cmdline::command_proto::~command_proto(void)
67{
68    for (options_vector::const_iterator iter = _options.begin();
69         iter != _options.end(); iter++)
70        delete *iter;
71}
72
73
74/// Internal method to register a dynamically-allocated option.
75///
76/// Always use add_option() from subclasses to add options.
77///
78/// \param option_ The option to add.  Must have been dynamically allocated.
79///     This grabs ownership of the pointer, which is released when the command
80///     is destroyed.
81void
82cmdline::command_proto::add_option_ptr(const cmdline::base_option* option_)
83{
84    try {
85        _options.push_back(option_);
86    } catch (...) {
87        delete option_;
88        throw;
89    }
90}
91
92
93/// Processes the command line based on the command description.
94///
95/// \param args The raw command line to be processed.
96///
97/// \return An object containing the list of options and free arguments found in
98/// args.
99///
100/// \throw cmdline::usage_error If there is a problem processing the command
101///     line.  This error is caused by invalid input from the user.
102cmdline::parsed_cmdline
103cmdline::command_proto::parse_cmdline(const cmdline::args_vector& args) const
104{
105    PRE(name() == args[0]);
106    const parsed_cmdline cmdline = cmdline::parse(args, options());
107
108    const int argc = cmdline.arguments().size();
109    if (argc < _min_args)
110        throw usage_error("Not enough arguments");
111    if (_max_args != -1 && argc > _max_args)
112        throw usage_error("Too many arguments");
113
114    return cmdline;
115}
116
117
118/// Gets the name of the command.
119///
120/// \return The command name.
121const std::string&
122cmdline::command_proto::name(void) const
123{
124    return _name;
125}
126
127
128/// Gets the textual representation of the arguments list.
129///
130/// \return The description of the arguments list.
131const std::string&
132cmdline::command_proto::arg_list(void) const
133{
134    return _arg_list;
135}
136
137
138/// Gets the description of the purpose of the command.
139///
140/// \return The description of the command.
141const std::string&
142cmdline::command_proto::short_description(void) const
143{
144    return _short_description;
145}
146
147
148/// Gets the definition of the options accepted by the command.
149///
150/// \return The list of options.
151const cmdline::options_vector&
152cmdline::command_proto::options(void) const
153{
154    return _options;
155}
156
157
158/// Creates a new command.
159///
160/// \param name_ The name of the command.  Must be unique within the context of
161///     a program and have no spaces.
162/// \param arg_list_ A textual description of the arguments received by the
163///     command.  May be empty.
164/// \param min_args_ The minimum number of arguments required by the command.
165/// \param max_args_ The maximum number of arguments required by the command.
166///     -1 means infinity.
167/// \param short_description_ A description of the purpose of the command.
168cmdline::base_command_no_data::base_command_no_data(
169    const std::string& name_,
170    const std::string& arg_list_,
171    const int min_args_,
172    const int max_args_,
173    const std::string& short_description_) :
174    command_proto(name_, arg_list_, min_args_, max_args_, short_description_)
175{
176}
177
178
179/// Entry point for the command.
180///
181/// This delegates execution to the run() abstract function after the command
182/// line provided in args has been parsed.
183///
184/// If this function returns, the command is assumed to have been executed
185/// successfully.  Any error must be reported by means of exceptions.
186///
187/// \param ui Object to interact with the I/O of the command.  The command must
188///     always use this object to write to stdout and stderr.
189/// \param args The command line passed to the command broken by word, which
190///     includes options and arguments.
191///
192/// \return The exit code that the program has to return.  0 on success, some
193///     other value on error.
194/// \throw usage_error If args is invalid (i.e. if the options are mispecified
195///     or if the arguments are invalid).
196int
197cmdline::base_command_no_data::main(cmdline::ui* ui,
198                                    const cmdline::args_vector& args)
199{
200    return run(ui, parse_cmdline(args));
201}
202