GetoptParser.cpp
Go to the documentation of this file.
1 // this is for emacs file handling -*- mode: c++; indent-tabs-mode: nil -*-
2 
3 // -- BEGIN LICENSE BLOCK ----------------------------------------------
4 // This file is part of FZIs ic_workspace.
5 //
6 // This program is free software licensed under the LGPL
7 // (GNU LESSER GENERAL PUBLIC LICENSE Version 3).
8 // You can find a copy of this license in LICENSE folder in the top
9 // directory of the source code.
10 //
11 // © Copyright 2016 FZI Forschungszentrum Informatik, Karlsruhe, Germany
12 //
13 // -- END LICENSE BLOCK ------------------------------------------------
14 
15 //----------------------------------------------------------------------
21 //----------------------------------------------------------------------
22 #include <iostream>
23 #include <stdlib.h>
24 #include <boost/regex.hpp>
25 #include <boost/foreach.hpp>
26 
27 #include "icl_core/List.h"
29 
30 namespace icl_core {
31 namespace config {
32 
34 {
35  static Getopt instance;
36  return instance;
37 }
38 
40 {
42  m_extra_cmd_param_delimiter = delimiter;
43 }
44 
45 void Getopt::addParameter(const GetoptParameter& parameter)
46 {
47  if (parameter.isPrefixOption())
48  {
49  m_prefix_parameters.insert(std::make_pair(parameter.option(), parameter));
50  if (parameter.shortOption() != "")
51  {
52  m_short_prefix_parameters.insert(std::make_pair(parameter.shortOption(), parameter));
53  }
54  }
55  else
56  {
57  m_parameters.insert(std::make_pair(parameter.option(), parameter));
58  if (parameter.shortOption() != "")
59  {
60  m_short_parameters.insert(std::make_pair(parameter.shortOption(), parameter));
61  }
62  }
63 }
64 
66 {
67  for (GetoptParameterList::const_iterator opt_it = parameters.begin();
68  opt_it != parameters.end(); ++opt_it)
69  {
70  addParameter(*opt_it);
71  }
72 }
73 
75 {
76  if (parameter.isOptional())
77  {
78  m_optional_positional_parameters.push_back(parameter);
79  }
80  else
81  {
82  m_required_positional_parameters.push_back(parameter);
83  }
84 }
85 
87 {
88  for (GetoptPositionalParameterList::const_iterator opt_it = parameters.begin();
89  opt_it != parameters.end(); ++opt_it)
90  {
91  addParameter(*opt_it);
92  }
93 }
94 
95 bool Getopt::initialize(int& argc, char *argv[], bool remove_read_arguments)
96 {
97  return initialize(argc, argv, remove_read_arguments ? eCLC_Cleanup : eCLC_None, ePRC_Strict);
98 }
99 
100 bool Getopt::initialize(int& argc, char *argv[], CommandLineCleaning cleanup,
101  ParameterRegistrationCheck registration_check)
102 {
103  if (argc == 0)
104  {
105  return false;
106  }
107 
108  if (isInitialized())
109  {
110  std::cerr << "GETOPT WARNING: The commandline option framework is already initialized!" << std::endl;
111  return true;
112  }
113 
114  // Store the full argc and argv
115  m_argc = argc;
116  m_argv = argv;
117 
118 
119  // Store the program name.
120  m_program_name = argv[0];
121 
122  // Store all parameters in a temporary list.
124  for (int index = 1; index < argc; ++index)
125  {
126  arguments.push_back(argv[index]);
127  }
128 
129  // Scan the commandline parameters and check for
130  // registered options.
131  size_t positional_parameters_counter = 0;
132  bool extra_cmd_params_reached = false;
133  boost::regex long_opt_regex("--([^-][^=]*)(=(.*))?");
134  boost::regex short_opt_regex("-([^-].*)");
135  boost::smatch mres;
136  for (icl_core::List<icl_core::String>::const_iterator arg_it = arguments.begin();
137  arg_it != arguments.end(); ++arg_it)
138  {
139  if (extra_cmd_params_reached)
140  {
141  m_extra_cmd_param.push_back(*arg_it);
142  }
143  else if (boost::regex_match(*arg_it, mres, long_opt_regex))
144  {
145  // Found a long option parameter!
146  icl_core::String name = mres[1];
147  ParameterMap::const_iterator find_it = m_parameters.find(name);
148  if (find_it != m_parameters.end())
149  {
150  if (find_it->second.hasValue())
151  {
152  // According to the regular expression the value has to be
153  // the 3rd (and last) match result.
154  if (mres.size() == 4)
155  {
156  m_param_opt[name] = mres[3];
157  }
158  else
159  {
160  std::cerr << "Found option " << *arg_it << " but the value is missing." << std::endl;
161  printHelp();
162  return false;
163  }
164  }
165  else
166  {
167  m_param_opt[name] = "yes";
168  }
169  }
170  else
171  {
172  // Parameter not found in the list of configured parameters.
173  // Check if a matching prefix option has been registered.
174  bool found = false;
175  boost::smatch prefix_res;
176  for (ParameterMap::const_iterator prefix_it = m_prefix_parameters.begin();
177  !found && prefix_it != m_prefix_parameters.end(); ++prefix_it)
178  {
179  if (boost::regex_match(name, prefix_res, boost::regex(prefix_it->first + "(.*)")))
180  {
181  found = true;
182 
183  if (prefix_it->second.hasValue())
184  {
185  if (mres.size() == 4)
186  {
187  m_prefix_param_opt[prefix_it->first].push_back(KeyValue(prefix_res[1], mres[3]));
188  }
189  else
190  {
191  std::cerr << "Found prefix option " << name << " but the value is missing." << std::endl;
192  printHelp();
193  return false;
194  }
195  }
196  else
197  {
198  m_prefix_param_opt[prefix_it->first].push_back(KeyValue(prefix_res[1], "yes"));
199  }
200  }
201  }
202 
203  // Also not a prefix option!
204  if (!found)
205  {
206  if (registration_check == ePRC_Strict)
207  {
208  std::cerr << "Found unknown option " << *arg_it << "." << std::endl;
209  printHelp();
210  return false;
211  }
212  else
213  {
214  m_param_non_opt.push_back(*arg_it);
215  }
216  }
217  }
218  }
219  else if (boost::regex_match(*arg_it, mres, short_opt_regex))
220  {
221  // Found a short option parameter!
222  icl_core::String name = mres[1];
223  ParameterMap::const_iterator find_it = m_short_parameters.find(name);
224  if (find_it != m_short_parameters.end())
225  {
226  if (find_it->second.hasValue())
227  {
228  // The value is the next commandline argument.
229  ++arg_it;
230  if (arg_it == arguments.end())
231  {
232  std::cerr << "Found option -" << name << " but the value is missing." << std::endl;
233  printHelp();
234  return false;
235  }
236  else
237  {
238  m_param_opt[find_it->second.option()] = *arg_it;
239  }
240  }
241  else
242  {
243  m_param_opt[find_it->second.option()] = "yes";
244  }
245  }
246  else
247  {
248  // Parameter not found in the list of configured parameters.
249  // Check if a matching prefix option has been registered.
250  bool found = false;
251  boost::smatch prefix_res;
252  for (ParameterMap::const_iterator prefix_it = m_short_prefix_parameters.begin();
253  !found && prefix_it != m_short_prefix_parameters.end(); ++prefix_it)
254  {
255  if (boost::regex_match(name, prefix_res, boost::regex(prefix_it->first + "(.*)")))
256  {
257  found = true;
258 
259  if (prefix_it->second.hasValue())
260  {
261  // The value is the next commandline argument.
262  ++arg_it;
263  if (arg_it == arguments.end())
264  {
265  std::cerr << "Found prefix option " << name << " but the value is missing." << std::endl;
266  printHelp();
267  return false;
268  }
269  else
270  {
271  m_prefix_param_opt[prefix_it->second.option()].push_back(KeyValue(prefix_res[1], *arg_it));
272  }
273  }
274  else
275  {
276  m_prefix_param_opt[prefix_it->second.option()].push_back(KeyValue(prefix_res[1], "yes"));
277  }
278  }
279  }
280 
281  // Also not a prefix option!
282  if (!found)
283  {
284  if (registration_check == ePRC_Strict)
285  {
286  std::cerr << "Found unknown option " << *arg_it << "." << std::endl;
287  printHelp();
288  return false;
289  }
290  else
291  {
292  m_param_non_opt.push_back(*arg_it);
293  }
294  }
295  }
296  }
298  {
299  extra_cmd_params_reached = true;
300  }
301  else if (positional_parameters_counter < m_required_positional_parameters.size())
302  {
303  // Found a required positional parameter
304  const GetoptPositionalParameter& param = m_required_positional_parameters[positional_parameters_counter];
305  m_param_opt[param.name()] = *arg_it;
306  positional_parameters_counter++;
307  }
308  else if (positional_parameters_counter < m_required_positional_parameters.size() + m_optional_positional_parameters.size())
309  {
310  // Found an optional positional parameter
311  const GetoptPositionalParameter& param = m_optional_positional_parameters[positional_parameters_counter - m_required_positional_parameters.size()];
312  m_param_opt[param.name()] = *arg_it;
313  positional_parameters_counter++;
314  }
315  else if (positional_parameters_counter >= m_required_positional_parameters.size() + m_optional_positional_parameters.size())
316  {
321 // if (registration_check == ePRC_Strict)
322 // {
323 // std::cerr << "Found unknown positional parameter \"" << *arg_it << "\" and registration_check is ePRC_Strict. Aborting." << std::endl;
324 // printHelp();
325 // return false;
326 // }
327 // else
328  {
329  m_param_non_opt.push_back(*arg_it);
330  }
331  }
332  }
333 
334  // Check if all required positional parameters are given
335  if (positional_parameters_counter < m_required_positional_parameters.size())
336  {
337  std::cerr << "Not all required parameters are given. Aborting." << std::endl;
338  printHelp();
339  exit(0);
340  }
341 
342  // Check if the help text has to be printed.
343  if (m_param_opt.find("help") != m_param_opt.end())
344  {
345  printHelp();
346  exit(0);
347  }
348 
349  // Remove all option parameters from the "real" commandline.
350  if (cleanup == eCLC_Cleanup)
351  {
352  int check = 1;
353  while (check < argc)
354  {
356  std::find(m_param_non_opt.begin(), m_param_non_opt.end(), icl_core::String(argv[check]));
357  if (find_it == m_param_non_opt.end())
358  {
359  for (int move = check + 1; move < argc; ++move)
360  {
361  argv[move - 1] = argv[move];
362  }
363  --argc;
364  }
365  else
366  {
367  ++check;
368  }
369  }
370  }
371 
372  return true;
373 }
374 
376 {
377  return m_argc;
378 }
379 
380 char **Getopt::argv() const
381 {
382  return m_argv;
383 }
384 
386 {
387  return m_extra_cmd_param[index];
388 }
389 
391 {
392  return m_extra_cmd_param.size();
393 }
394 
396 {
398  if (find_it == m_param_opt.end())
399  {
400  return "";
401  }
402  else
403  {
404  return find_it->second;
405  }
406 }
407 
409 {
410  return m_param_opt.find(name) != m_param_opt.end();
411 }
412 
414 {
416  if (find_it == m_prefix_param_opt.end())
417  {
418  return KeyValueList();
419  }
420  else
421  {
422  return find_it->second;
423  }
424 }
425 
427 {
428  return m_prefix_param_opt.find(prefix) != m_prefix_param_opt.end();
429 }
430 
432 {
433  if (index < m_param_non_opt.size())
434  {
435  return m_param_non_opt.at(index);
436  }
437  else
438  {
439  return "";
440  }
441 }
442 
444 {
445  return m_param_non_opt.size();
446 }
447 
449 {
450  return m_program_name;
451 }
452 
454 {
455  return m_program_version;
456 }
457 
459 {
460  m_program_version = version;
461 }
462 
464 {
465  return m_program_description;
466 }
467 
469 {
470  m_program_description = description;
471 }
472 
473 void Getopt::printHelp() const
474 {
475  // prepare list of all positional parameters
477  std::copy(m_optional_positional_parameters.begin(), m_optional_positional_parameters.end(), std::back_inserter(positional_parameters));
478 
479  std::cerr << programName();
480  if (programVersion() != "")
481  {
482  std::cerr << " (version " << programVersion() << ")";
483  }
484  std::cerr << std::endl << std::endl;
485 
486  std::cerr << "Usage: ";
487  std::cerr << programName();
488 
489  std::cerr << " [OPTIONS...]";
490 
491  BOOST_FOREACH(const GetoptPositionalParameter param, positional_parameters)
492  {
493  if (param.isOptional())
494  {
495  std::cerr << " [<" << param.name() << ">]";
496  }
497  else
498  {
499  std::cerr << " <" << param.name() << ">";
500  }
501  }
502 
503  std::cerr << std::endl << std::endl << programDescription() << std::endl << std::endl;
504 
505  if (positional_parameters.size() > 0 )
506  {
507  std::cerr << "Positional Parameters:" << std::endl;
508 
509  BOOST_FOREACH(const GetoptPositionalParameter param, positional_parameters)
510  {
511  std::cerr << " <" << param.name() << ">" << ":" << std::endl << "\t"
512  << boost::regex_replace(param.help(), boost::regex("\\n"), "\n\t")
513  << std::endl;
514  }
515  std::cerr << std::endl;
516  }
517 
518  for (int i=0; i<2; ++i)
519  {
520  std::cerr << (i == 0 ? "Generic options:" : "Options:") << std::endl;
521  for (ParameterMap::const_iterator it = m_parameters.begin(); it != m_parameters.end(); ++it)
522  {
523  bool const is_generic =
524  it->second.option() == "configfile" ||
525  it->second.option() == "dump-config" ||
526  it->second.option() == "help" ||
527  it->second.option() == "log-level" ||
528  it->second.option() == "quick-debug";
529  if (!i==is_generic)
530  {
531  std::cerr << " ";
532  // Short option.
533  if (it->second.shortOption() != "")
534  {
535  std::cerr << "-" << it->second.shortOption();
536  if (it->second.hasValue())
537  {
538  std::cerr << " <value>";
539  }
540  std::cerr << ", ";
541  }
542 
543  // Long option.
544  std::cerr << "--" << it->second.option();
545  if (it->second.hasValue())
546  {
547  std::cerr << "=<value>";
548  }
549 
550  // Help text
551  std::cerr << ":" << std::endl << "\t"
552  << boost::regex_replace(it->second.help(), boost::regex("\\n"), "\n\t")
553  << std::endl;
554  }
555  }
556  std::cerr << std::endl;
557  }
558 }
559 
561 #ifdef _IC_BUILDER_DEPRECATED_STYLE_
562 
566 Getopt& Getopt::Instance()
567 {
568  return instance();
569 }
570 
575 {
576  activateExtraCmdParams(delimiter);
577 }
578 
582 void Getopt::AddParameter(const GetoptParameter& parameter)
583 {
584  addParameter(parameter);
585 }
586 
590 void Getopt::AddParameter(const GetoptParameterList& parameters)
591 {
592  addParameter(parameters);
593 }
594 
598 bool Getopt::Initialize(int& argc, char *argv[], bool remove_read_arguments)
599 {
600  return initialize(argc, argv, remove_read_arguments);
601 }
602 
606 bool Getopt::Initialize(int& argc, char *argv[],
607  CommandLineCleaning cleanup,
608  ParameterRegistrationCheck registration_check)
609 {
610  return initialize(argc, argv, cleanup, registration_check);
611 }
612 
616 bool Getopt::IsInitialized() const
617 {
618  return isInitialized();
619 }
620 
624 icl_core::String Getopt::ExtraCmdParam(size_t index) const
625 {
626  return extraCmdParam(index);
627 }
628 
632 size_t Getopt::ExtraCmdParamCount() const
633 {
634  return extraCmdParamCount();
635 }
636 
641 {
642  return paramOpt(name);
643 }
644 
648 bool Getopt::ParamOptPresent(const icl_core::String& name) const
649 {
650  return paramOptPresent(name);
651 }
652 
656 Getopt::KeyValueList Getopt::ParamPrefixOpt(const icl_core::String& prefix) const
657 {
658  return paramPrefixOpt(prefix);
659 }
660 
664 bool Getopt::ParamPrefixOptPresent(const icl_core::String& prefix) const
665 {
666  return paramPrefixOptPresent(prefix);
667 }
668 
672 icl_core::String Getopt::ParamNonOpt(size_t index) const
673 {
674  return paramNonOpt(index);
675 }
676 
680 size_t Getopt::ParamNonOptCount() const
681 {
682  return paramNonOptCount();
683 }
684 
688 icl_core::String Getopt::ProgramName() const
689 {
690  return programName();
691 }
692 
696 void Getopt::PrintHelp() const
697 {
698  printHelp();
699 }
700 
701 #endif
702 
706  m_initialized(false)
707 {
708  addParameter(GetoptParameter("help", "h", "Print commandline help."));
709 }
710 
711 }
712 }
icl_core::String m_extra_cmd_param_delimiter
Definition: GetoptParser.h:318
all options have to be registered
Definition: GetoptParser.h:59
char ** argv() const
Get the original argv.
ParameterMap m_short_prefix_parameters
Definition: GetoptParser.h:314
void setProgramDescription(icl_core::String const &description)
icl_core::Map< icl_core::String, icl_core::String > m_param_opt
Definition: GetoptParser.h:328
Handles commandline parameters.
Definition: GetoptParser.h:54
ICL_CORE_VC_DEPRECATE_STYLE icl_core::String ExtraCmdParam(size_t index) ICL_CORE_GCC_DEPRECATE_STYLE
Definition: Config.h:854
icl_core::Vector< icl_core::String > m_extra_cmd_param
Definition: GetoptParser.h:330
icl_core::String m_program_version
Definition: GetoptParser.h:325
icl_core::Vector< icl_core::String > m_param_non_opt
Definition: GetoptParser.h:327
known command line options are removed
Definition: GetoptParser.h:67
Contains Getopt.
ICL_CORE_VC_DEPRECATE_STYLE void AddParameter(const ConfigParameter &parameter) ICL_CORE_GCC_DEPRECATE_STYLE
Definition: Config.h:872
icl_core::String paramOpt(const icl_core::String &name) const
icl_core::List< KeyValue > KeyValueList
Definition: GetoptParser.h:81
bool paramOptPresent(const icl_core::String &name) const
icl_core::String programVersion() const
KeyValueList paramPrefixOpt(const icl_core::String &prefix) const
bool isPrefixOption() const
Check if this is a prefix option.
bool isInitialized() const
Definition: GetoptParser.h:135
icl_core::String programName() const
ICL_CORE_VC_DEPRECATE_STYLE size_t ExtraCmdParamCount() ICL_CORE_GCC_DEPRECATE_STYLE
Definition: Config.h:848
size_t paramNonOptCount() const
ParameterMap m_short_parameters
Definition: GetoptParser.h:313
ICL_CORE_VC_DEPRECATE_STYLE bool Initialize(int &argc, char *argv[], bool remove_read_arguments) ICL_CORE_GCC_DEPRECATE_STYLE
Definition: Config.h:902
icl_core::String name() const
Get the option name.
int & argc()
Get the original argc.
size_t extraCmdParamCount() const
GetoptPositionalParameterList m_required_positional_parameters
Definition: GetoptParser.h:315
icl_core::String help() const
Get the help text.
ParameterMap m_prefix_parameters
Definition: GetoptParser.h:312
void setProgramVersion(icl_core::String const &version)
ThreadStream & endl(ThreadStream &stream)
Definition: ThreadStream.h:249
icl_core::String m_program_description
Definition: GetoptParser.h:326
bool ParamOpt(const icl_core::String &name, typename icl_core::ConvertToRef< T >::ToRef value) ICL_CORE_GCC_DEPRECATE_STYLE
Definition: Config.h:774
icl_core::String extraCmdParam(size_t index) const
ConfigIterator find(const ::icl_core::String &query)
Definition: Config.cpp:45
icl_core::String m_program_name
Definition: GetoptParser.h:324
command line options are left untouched
Definition: GetoptParser.h:66
icl_core::String option() const
Get the long option name.
bool initialize(int &argc, char *argv[], bool remove_read_arguments)
std::string String
Definition: BaseTypes.h:43
void activateExtraCmdParams(const icl_core::String &delimiter="--")
bool isOptional() const
Get if the parameter is optional.
bool ParamNonOpt(size_t index, typename icl_core::ConvertToRef< T >::ToRef value) ICL_CORE_GCC_DEPRECATE_STYLE
Definition: Config.h:826
ICL_CORE_VC_DEPRECATE_STYLE size_t ParamNonOptCount() ICL_CORE_GCC_DEPRECATE_STYLE
Definition: Config.h:866
static Getopt & instance()
icl_core::Map< icl_core::String, KeyValueList > m_prefix_param_opt
Definition: GetoptParser.h:329
void addParameter(const GetoptParameter &parameter)
bool paramPrefixOptPresent(const icl_core::String &prefix) const
icl_core::String programDescription() const
icl_core::String shortOption() const
Get the short option name.
ICL_CORE_VC_DEPRECATE_STYLE void ActivateExtraCmdParams(const icl_core::String &delimiter="--") ICL_CORE_GCC_DEPRECATE_STYLE
Definition: Config.h:860
ICL_CORE_VC_DEPRECATE_STYLE bool ParamOptPresent(const icl_core::String &name) ICL_CORE_GCC_DEPRECATE_STYLE
Definition: Config.h:766
ICL_CORE_VC_DEPRECATE_STYLE void PrintHelp() ICL_CORE_GCC_DEPRECATE_STYLE
Definition: Config.h:896
GetoptPositionalParameterList m_optional_positional_parameters
Definition: GetoptParser.h:316
icl_core::String paramNonOpt(size_t index) const


fzi_icl_core
Author(s):
autogenerated on Mon Jun 10 2019 13:17:58