OpenASIP 2.2
Loading...
Searching...
No Matches
CmdLineParser.cc
Go to the documentation of this file.
1/*
2 Copyright (c) 2002-2009 Tampere University.
3
4 This file is part of TTA-Based Codesign Environment (TCE).
5
6 Permission is hereby granted, free of charge, to any person obtaining a
7 copy of this software and associated documentation files (the "Software"),
8 to deal in the Software without restriction, including without limitation
9 the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 and/or sell copies of the Software, and to permit persons to whom the
11 Software is furnished to do so, subject to the following conditions:
12
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 DEALINGS IN THE SOFTWARE.
23 */
24/**
25 * @file CmdLineParser.cc
26 *
27 * Definition of CmdLineParser class.
28 *
29 * @author Jari Mäntyneva 2006 (jari.mantyneva-no.spam-tut.fi)
30 * @note rating: red
31 */
32
33
34#include <cstdlib>
35#include <vector>
36#include <map>
37#include <string>
38#include <iomanip>
39
40#include "CmdLineParser.hh"
41#include "Exception.hh"
42#include "Options.hh"
43
44const int CmdLineParser::SHORT_FLAG = 2;
45const int CmdLineParser::LONG_FLAG = 22;
46
47using std::vector;
48using std::map;
49using std::string;
50using std::setw;
51using std::left;
52
53/**
54 * Constructor.
55 *
56 * @param description Brief description of the program and how to use it.
57 * Only prefix is currently "no-".
58 */
59CmdLineParser::CmdLineParser(std::string description) :
60 progName_(""), description_(description) {
61
62 prefixes_.push_back(string("no-"));
63}
64
65/**
66 * Destructor.
67 */
69 mapIter i;
70 for (i = optionLongNames_.begin(); i != optionLongNames_.end(); i++) {
71 delete (*i).second;
72 }
73 optionShortNames_.clear();
74 commandLine_.clear();
75}
76
77/**
78 * Stores options to Options class.
79 *
80 * @param options Options-object where the options are stored.
81 */
82void
84
85 mapIter i = optionLongNames_.begin();
86 for (; i != optionLongNames_.end(); i++) {
87 string name = (*i).first;
88 CmdLineOptionParser* current = (*i).second;
89 options.addOptionValue(name, current->copy());
90 }
91
92 i = optionShortNames_.begin();
93 for (; i != optionShortNames_.end(); i++) {
94 string name = (*i).first;
95 CmdLineOptionParser* current = (*i).second;
96 options.addOptionValue(name, current->copy());
97 }
98}
99
100/**
101 * Loads all command line arguments and parses them.
102 *
103 * @param argv Command line options.
104 * @param argc The number of command line options.
105 * @exception IllegalCommandLine If parsing is not succesfull.
106 * @exception ParserStopRequest If help or version option is found.
107 */
108void
109CmdLineParser::parse(char* argv[], int argc) {
110 // command line is emptied
111 commandLine_.clear();
112 progName_ = string(argv[0]);
113
114 for (int i = 1; i < argc; i++) {
115 commandLine_.push_back(string(argv[i]));
116 }
117 parseAll();
118}
119
120/**
121 * Loads all command line arguments and parses them.
122 *
123 * @param options Command line options pre-parsed in vector.
124 * @param argc The number of command line options.
125 * @exception IllegalCommandLine If parsing is not succesfull.
126 * @exception ParserStopRequest If help or version option is found.
127 */
128void
129CmdLineParser::parse(std::vector<std::string> options) {
130 // command line is emptied
131 commandLine_.clear();
132
133 for (unsigned int i = 0; i < options.size(); i++) {
134 bool spaces = true;
135 string::size_type curPos = 0;
136 while (spaces) {
137 string::size_type pos = options[i].find(" ", curPos);
138 if (pos != string::npos) {
139 commandLine_.push_back(string(options[i].substr(pos, curPos)));
140 curPos = pos;
141 } else {
142 if (options[i].length() - curPos > 0) {
143 commandLine_.push_back(string(options[i].substr(curPos)));
144 }
145 spaces = false;
146 }
147 }
148 }
149 parseAll();
150}
151
152/**
153 * Try to find a particular option.
154 *
155 * @param name The name of the option.
156 * @return The option if it is found.
157 * @exception IllegalCommandLine If option is not found.
158 */
160CmdLineParser::findOption(std::string name) const {
161 constMapIter i = optionLongNames_.find(name);
162 if (i != optionLongNames_.end()) {
163 return (*i).second;
164 }
165
166 i = optionShortNames_.find(name);
167 if (i != optionShortNames_.end()) {
168 return (*i).second;
169 }
170
171 string msg = "Unknown option: " + name;
172 string method = "CmdLineParser::findOption()";
173 throw IllegalCommandLine(__FILE__, __LINE__, method, msg);
174}
175
176/**
177 * Parses all command line options.
178 *
179 * @exception IllegalCommandLine If parsing fails.
180 */
181void
183 // finished is set to true when options are parsed and the rest are
184 // command line arguments
185 bool finished = false;
186
187 // checkArguments is set to false when command line arguments can start
188 // with "-" or "--"
189 bool checkArguments = true;
190 unsigned int i = 0;
191
192 while (i < commandLine_.size()) {
193 string optString = commandLine_[i];
194
195 if (!finished) {
196 string prefix = "";
197 string name = "";
198 string arguments = "";
199
200 // hasArgument is true when option has argument
201 bool hasArgument = true;
202
203 if (!parseOption(optString, name, arguments, prefix, hasArgument)) {
204 finished = true;
205 if (optString == "--") {
206 checkArguments = false;
207 i++;
208 continue;
209 } else {
210 arguments_.push_back(optString);
211 i++;
212 continue;
213 }
214 }
215
216 CmdLineOptionParser* opt = findOption(name);
217
218 if (arguments == "" &&
219 dynamic_cast<BoolCmdLineOptionParser*>(opt) == NULL) {
220
221 // argument for an option may be separated with space
222 if (i < commandLine_.size() - 1 &&
223 commandLine_[i+1].substr(0, 1) != "-") {
224 hasArgument = true;
225 arguments = commandLine_[i+1];
226 i++;
227 }
228 }
229
230 bool doneWithParsing = opt->parseValue(arguments, prefix);
231
232 if (!doneWithParsing) {
233 if (hasArgument) {
234 // all the rest in command line are "extra" strings
235 arguments_.push_back(arguments);
236 finished = true;
237 i++;
238 } else {
239 // this is the situation when we have something like
240 // -abcd (multible flags put together)
241 for (unsigned int i = 0; i < arguments.length(); i++) {
242 opt = findOption(arguments.substr(i, 1));
243 opt->parseValue("", prefix);
244 }
245 }
246 }
247 } else {
248
249 // finished reading options, all rest are command line arguments
250 if (checkArguments && optString[0] == '-') {
251 string msg = "Illegal command line argument: " + optString;
252 string method = "CmdLineParser::parse()";
253 throw IllegalCommandLine(__FILE__, __LINE__, method, msg);
254 }
255 arguments_.push_back(optString);
256 }
257 i++;
258 }
259}
260
261/**
262 * Parses one option.
263 *
264 * Each option should have name and prefix (-, --, -no, or --no). Arguments are
265 * mandatory for all except Boolean options.
266 *
267 * @param option The whole option.
268 * @param name The name of the option.
269 * @param arguments The arguments for option.
270 * @param prefix The prefix of option.
271 * @param hasArgument False if argument is part of option body (eg. -abc).
272 * @return True if option is command line option, false if option is
273 * command line argument.
274 * @exception IllegalCommandLine If option is illegal.
275 */
276bool
278 std::string option, std::string& name, std::string& arguments,
279 std::string& prefix, bool& hasArgument) const {
280 // first there is either '-' or '--'
281 bool longOption = false;
282 if (!readPrefix(option, prefix, longOption)) {
283 return false;
284 }
285
286 if (longOption) {
287 // then there is the name of the option
288 unsigned int pos = 0;
289 while (pos < option.length() && option[pos] != '=') {
290 ++pos;
291 }
292 name = option.substr(0, pos);
293 option.erase(0, pos);
294 } else {
295 // option name is only one character
296 name = option.substr(0, 1);
297 option.erase(0, 1);
298 }
299
300 // then there might be value
301 if (option.length() > 0 && option[0] == '=') {
302 if (!longOption) {
303 string method = "CmdLineParser::parseOption()";
304 string message = "Illegal short option: = not allowed.";
305 throw IllegalCommandLine(__FILE__, __LINE__, method, message);
306 }
307 option.erase(0, 1);
308 arguments = option;
309 } else {
310 arguments = option;
311 if (arguments == "" || !longOption) {
312 hasArgument = false;
313 }
314 }
315 return true;
316}
317
318/**
319 * Reads prefix of option.
320 *
321 * @param option The whole option as a string.
322 * @param prefix The prefix of option.
323 * @param longOption True if option starts with "--".
324 * @return True, if prefix is found, false otherwise.
325 */
326bool
328 std::string& option,
329 std::string& prefix,
330 bool& longOption) const {
331
332 if (option == "--") {
333 return false;
334 } else if (option.substr(0, 1) != "-") {
335 return false;
336 } else {
337 option.erase(0, 1);
338 if (option.substr(0, 1) == "-") {
339 longOption = true;
340 option.erase(0, 1);
341 }
342
343 // then there might be also something else in the prefix
344 // (eg. --no-print, prefix is --no)
345 for (unsigned int i = 0; i < prefixes_.size(); i++) {
346
347 if (option.length() > prefixes_[i].length() &&
348 option.substr(0, prefixes_[i].length()) == prefixes_[i]) {
349
350 prefix = prefixes_[i];
351 option.erase(0, prefix.length());
352 break;
353 }
354 }
355 }
356 return true;
357}
static MachInfoCmdLineOptions options
Definition MachInfo.cc:46
virtual OptionValue * copy() const =0
virtual bool parseValue(std::string arguments, std::string prefix)=0
Pure virtual function that parses the value of option.
static const int SHORT_FLAG
Number of characters reserved for printing short version of commandline flag.
std::map< std::string, CmdLineOptionParser * >::const_iterator constMapIter
For traversing const maps.
std::map< std::string, CmdLineOptionParser * > optionLongNames_
Database for holding options with their long names as a key.
virtual void storeOptions(Options &options)
std::string progName_
The name of the program.
std::vector< std::string > prefixes_
Legal prefixes are stored here.
CmdLineParser(std::string description)
std::vector< std::string > commandLine_
Command line is stored here.
std::map< std::string, CmdLineOptionParser * >::iterator mapIter
For traversing non-const maps.
virtual ~CmdLineParser()
virtual void parse(char *argv[], int argc)
CmdLineOptionParser * findOption(std::string name) const
std::vector< std::string > arguments_
Command line arguments are stored here.
bool parseOption(std::string option, std::string &name, std::string &arguments, std::string &prefix, bool &hasArgument) const
bool readPrefix(std::string &option, std::string &prefix, bool &longOption) const
std::map< std::string, CmdLineOptionParser * > optionShortNames_
Database for holding options with their short names as a key.
static const int LONG_FLAG
Number of characters reserved for printing long version of commandline flag.