OpenASIP  2.0
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 
44 const int CmdLineParser::SHORT_FLAG = 2;
45 const int CmdLineParser::LONG_FLAG = 22;
46 
47 using std::vector;
48 using std::map;
49 using std::string;
50 using std::setw;
51 using 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  */
59 CmdLineParser::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  */
82 void
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  */
108 void
109 CmdLineParser::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  */
128 void
129 CmdLineParser::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  */
160 CmdLineParser::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  */
181 void
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  */
276 bool
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  */
326 bool
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 }
Options
Definition: Options.hh:51
Exception.hh
CmdLineParser.hh
CmdLineParser::storeOptions
virtual void storeOptions(Options &options)
Definition: CmdLineParser.cc:83
Options.hh
CmdLineParser::LONG_FLAG
static const int LONG_FLAG
Number of characters reserved for printing long version of commandline flag.
Definition: CmdLineParser.hh:117
IllegalCommandLine
Definition: Exception.hh:438
CmdLineParser::constMapIter
std::map< std::string, CmdLineOptionParser * >::const_iterator constMapIter
For traversing const maps.
Definition: CmdLineParser.hh:97
CmdLineParser::commandLine_
std::vector< std::string > commandLine_
Command line is stored here.
Definition: CmdLineParser.hh:84
CmdLineParser::optionLongNames_
std::map< std::string, CmdLineOptionParser * > optionLongNames_
Database for holding options with their long names as a key.
Definition: CmdLineParser.hh:79
CmdLineParser::~CmdLineParser
virtual ~CmdLineParser()
Definition: CmdLineParser.cc:68
CmdLineParser::parseAll
void parseAll()
Definition: CmdLineParser.cc:182
CmdLineOptionParser::parseValue
virtual bool parseValue(std::string arguments, std::string prefix)=0
Pure virtual function that parses the value of option.
CmdLineParser::parseOption
bool parseOption(std::string option, std::string &name, std::string &arguments, std::string &prefix, bool &hasArgument) const
Definition: CmdLineParser.cc:277
CmdLineParser::mapIter
std::map< std::string, CmdLineOptionParser * >::iterator mapIter
For traversing non-const maps.
Definition: CmdLineParser.hh:94
CmdLineOptionParser::copy
virtual OptionValue * copy() const =0
CmdLineOptionParser
Definition: CmdLineOptionParser.hh:56
CmdLineParser::arguments_
std::vector< std::string > arguments_
Command line arguments are stored here.
Definition: CmdLineParser.hh:86
BoolCmdLineOptionParser
Definition: CmdLineOptionParser.hh:278
CmdLineParser::readPrefix
bool readPrefix(std::string &option, std::string &prefix, bool &longOption) const
Definition: CmdLineParser.cc:327
CmdLineParser::CmdLineParser
CmdLineParser(std::string description)
Definition: CmdLineParser.cc:59
CmdLineParser::progName_
std::string progName_
The name of the program.
Definition: CmdLineParser.hh:107
options
static MachInfoCmdLineOptions options
Definition: MachInfo.cc:46
CmdLineParser::optionShortNames_
std::map< std::string, CmdLineOptionParser * > optionShortNames_
Database for holding options with their short names as a key.
Definition: CmdLineParser.hh:81
CmdLineParser::SHORT_FLAG
static const int SHORT_FLAG
Number of characters reserved for printing short version of commandline flag.
Definition: CmdLineParser.hh:113
CmdLineParser::parse
virtual void parse(char *argv[], int argc)
Definition: CmdLineParser.cc:109
CmdLineParser::findOption
CmdLineOptionParser * findOption(std::string name) const
Definition: CmdLineParser.cc:160
CmdLineParser::prefixes_
std::vector< std::string > prefixes_
Legal prefixes are stored here.
Definition: CmdLineParser.hh:88