source: src/UIElements/CommandLineUI/CommandLineParser.cpp@ 13e5be

stable v1.7.0
Last change on this file since 13e5be was 30def8, checked in by Frederik Heber <frederik.heber@…>, 3 years ago

FIX: CommandLineParser's implicit argument does not work anymore.

  • Property mode set to 100644
File size: 26.2 KB
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2010-2012 University of Bonn. All rights reserved.
5 *
6 *
7 * This file is part of MoleCuilder.
8 *
9 * MoleCuilder is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * MoleCuilder is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with MoleCuilder. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23/*
24 * CommandLineParser.cpp
25 *
26 * Created on: May 8, 2010
27 * Author: heber
28 */
29
30// include config.h
31#ifdef HAVE_CONFIG_H
32#include <config.h>
33#endif
34
35//#include "CodePatterns/MemDebug.hpp"
36
37#include <boost/algorithm/string.hpp>
38#include <boost/filesystem.hpp>
39#include <boost/lexical_cast.hpp>
40#include <boost/program_options/option.hpp>
41#include <boost/program_options/value_semantic.hpp>
42#include <boost/program_options.hpp>
43#include <fstream>
44#include <iostream>
45#include <set>
46#include <map>
47
48#include "Actions/Action.hpp"
49#include "Actions/ActionQueue.hpp"
50#include "Actions/ActionTrait.hpp"
51#include "Actions/OptionRegistry.hpp"
52#include "Actions/OptionTrait.hpp"
53#include "Actions/Values.hpp"
54#include "CodePatterns/Log.hpp"
55#include "CodePatterns/Verbose.hpp"
56#include "CommandLineParser.hpp"
57#include "CommandLineParser_validate.hpp"
58#include "Parameters/Specifics/KeyValuePair.hpp"
59#include "World.hpp"
60
61#include "CodePatterns/Singleton_impl.hpp"
62
63using namespace MoleCuilder;
64
65class element;
66
67/** Constructor of class CommandLineParser.
68 *
69 */
70CommandLineParser::CommandLineParser() :
71 analysis("Analysis options"),
72 atom("Atom options"),
73 bond("Bond options"),
74 command("Command options"),
75 fill("fill options"),
76 shape("shape options"),
77 fragmentation("Fragmentation options"),
78 geometry("Geometry options"),
79 graph("Graph options"),
80 molecule("Molecule options"),
81 options("Secondary options"),
82 parser("Parser options"),
83 potential("Potential options"),
84 selection("Selection options"),
85 tesselation("Tesselation options"),
86 world("World options")
87{
88 // put all options lists into a lookup
89 CmdParserLookup["analysis"] = &analysis;
90 CmdParserLookup["atom"] = &atom;
91 CmdParserLookup["bond"] = &bond;
92 CmdParserLookup["command"] = &command;
93 CmdParserLookup["edit"] = &edit;
94 CmdParserLookup["fill"] = &fill;
95 CmdParserLookup["shape"] = &shape;
96 CmdParserLookup["fragmentation"] = &fragmentation;
97 CmdParserLookup["geometry"] = &geometry;
98 CmdParserLookup["graph"] = &graph;
99 CmdParserLookup["options"] = &options;
100 CmdParserLookup["molecule"] = &molecule;
101 CmdParserLookup["parser"] = &parser;
102 CmdParserLookup["potential"] = &potential;
103 CmdParserLookup["selection"] = &selection;
104 CmdParserLookup["tesselation"] = &tesselation;
105 CmdParserLookup["world"] = &world;
106}
107
108/** Destructor of class CommandLineParser.
109 *
110 */
111CommandLineParser::~CommandLineParser()
112{}
113
114/** Initializes command arguments to accept.
115 * Goes through ActionRegistry and puts all actions therein into the map.
116 */
117void CommandLineParser::InitializeCommandArguments()
118{
119 // we need a list of already added options, otherwise we get ambigious exceptions
120 std::set<std::string> AlreadyAddedOptionNames;
121
122 bool ActionAlreadyAdded_flag = false;
123 ActionQueue &AQ = ActionQueue::getInstance();
124 ActionQueue::ActionTokens_t tokens = AQ.getListOfActions();
125 for (ActionQueue::ActionTokens_t::const_iterator iter = tokens.begin();
126 iter != tokens.end(); ++iter) {
127 const ActionTrait &CurrentTrait = AQ.getActionsTrait(*iter);
128 ActionAlreadyAdded_flag = false;
129 //std::cout << "Current Action to initialize is: " << actioniter->first << std::endl;
130
131 for (ActionTrait::options_const_iterator optioniter = CurrentTrait.getBeginIter();
132 optioniter != CurrentTrait.getEndIter();
133 ++optioniter) {
134 if (optioniter->first == *iter)
135 ActionAlreadyAdded_flag = true;
136 ASSERT( OptionRegistry::getInstance().isOptionPresentByName(optioniter->first),
137 "CommandLineParser::Init() - Option "+optioniter->first+" not present in OptionRegistry." );
138 const OptionTrait* const currentOption = OptionRegistry::getInstance().getOptionByName(optioniter->first);
139
140 if (AlreadyAddedOptionNames.find(optioniter->first) == AlreadyAddedOptionNames.end()) {
141 // add the option
142// std::cout << "Registering Option "
143// << currentOption->getName()
144// << " with type '" << currentOption->getTypeName() << "' "
145// << " with description '" << currentOption->getDescription() << "' ";
146// if (currentOption->hasShortForm())
147// std::cout << ", with short form " << currentOption->getShortForm();
148// else
149// std::cout << ", with no short form ";
150// if (currentOption->hasDefaultValue())
151// std::cout << ", with default value " << currentOption->getDefaultValue();
152// else
153// std::cout << ", with no default value ";
154// std::cout << std::endl;
155
156 AddOptionToParser(currentOption, (CmdParserLookup["options"]),
157 (optioniter->first == *iter) ?
158 true : false);
159
160 AlreadyAddedOptionNames.insert(optioniter->first);
161 } else {
162// std::cout << "Option " << currentOption->getName() << " already registered." << std::endl;
163 }
164 }
165
166 if (!ActionAlreadyAdded_flag) {
167 // add the action
168// std::cout << "Registering Action "
169// << currentAction->Traits.getName()
170// << " in menu " << currentAction->Traits.getMenuName()
171// << " with type '" << currentAction->Traits.getTypeName() << "' "
172// << " with description '" << currentAction->Traits.getDescription() << "' ";
173// if (currentAction->Traits.hasShortForm())
174// std::cout << ", with short form " << currentAction->Traits.getShortForm();
175// else
176// std::cout << ", with no short form ";
177// if (currentAction->Traits.hasDefaultValue())
178// std::cout << ", with default value " << currentAction->Traits.getDefaultValue();
179// else
180// std::cout << ", with no default value ";
181// std::cout << std::endl;
182
183 ASSERT(CmdParserLookup.find(CurrentTrait.getMenuName()) != CmdParserLookup.end(),
184 "CommandLineParser: boost::program_options::options_description for this Action not present.");
185 AddOptionToParser(
186 dynamic_cast<const OptionTrait * const>(&CurrentTrait),
187 (CmdParserLookup[CurrentTrait.getMenuName()]),
188 false);
189 }
190 }
191 // note: positioning is not important on the command line
192}
193
194/**
195 * This is a fix by Benedek Thaler given on the boost mailing list to get back
196 * to the old behavior before the breaking change in 1.63 for
197 * boost::program_options.
198 *
199 * The problem is that for an implicit value "-a foo" will not recognize the
200 * value for "a". It now needs to read "-a=foo" to store the value "foo" for
201 * the action "a". This broke our behavior for all action that have same-named
202 * options.
203 *
204 * See https://lists.boost.org/Archives/boost/2017/01/232272.php
205 */
206#if BOOST_VERSION >= 106300 and BOOST_VERSION < 106900
207template <typename T>
208struct greedy_implicit_value : public po::typed_value<T>
209{
210 using base = po::typed_value<T>;
211
212 greedy_implicit_value(const T& value) : base(nullptr)
213 {
214 base::implicit_value(value);
215 }
216
217 bool adjacent_tokens_only() const override { return false; }
218unsigned max_tokens() const override { return 1; }
219};
220
221template <typename T>
222po::typed_value<T>* implicit_value(const T& value)
223{
224 return new greedy_implicit_value<T>(value);
225}
226#endif
227#if BOOST_VERSION < 106300
228template <typename T>
229po::typed_value<T>* implicit_value(const T& value)
230{
231 return new po::typed_value<T>()->implicit_value(value);
232}
233#endif
234#if BOOST_VERSION >= 106900
235template <typename T>
236po::typed_value<T>* implicit_value(const T& value)
237{
238 return (new po::typed_value<T>(NULL))->implicit_value(value);
239}
240#endif
241
242
243/** Adds an Action or Option to the CommandLineParser.
244 * Note that Action is derived from Option(Trait)
245 *
246 * This ugly switch function is necessary because of the compile-time problem:
247 * po::value<T> has to be instantiated at compile-time however we do know the type not until run-time.
248 * Not even a templated function like po::value<T> getProgramOptionValuefromType() does help, specialized
249 * to each available type, as the signatures of all the functions differ. Hence, they cannot not put into
250 * one type_info -> po::value<T> map ...
251 *
252 * \param *currentOption pointer to Action/Option to add
253 * \param *OptionList program_options list to add to
254 * \param _DefaultAsImplicit whether to add a default value as default_value or
255 * as implicit_value (default = option token present or not, implicit =
256 option token present but not necessarily followed by argument)
257 */
258void CommandLineParser::AddOptionToParser(
259 const OptionTrait * const currentOption,
260 po::options_description* OptionList,
261 const bool _DefaultAsImplicit)
262{
263 // check whether dynamic_cast in Init() suceeded
264 ASSERT(currentOption != NULL, "CommandLineParser::AddOptionToParser() - currentOption is NULL!");
265 // add other options
266// std::cout << "Adding Action " << currentOption->getName() << " with type "
267// << currentOption->getType()->name() << ", " << (currentOption->hasDefaultValue() ? "with" : "without")
268// << " default value, and KeyandShortform " << currentOption->getKeyAndShortForm()
269// << " to CommandLineParser." << std::endl;
270 switch(TypeToEnums.getEnumforType(currentOption->getType())) {
271 default:
272 case TypeEnumContainer::NoneType:
273 OptionList->add_options()
274 (currentOption->getKeyAndShortForm().c_str(), currentOption->getDescription().c_str())
275 ;
276 break;
277 case TypeEnumContainer::BooleanType:
278 OptionList->add_options()
279 (currentOption->getKeyAndShortForm().c_str(),
280 currentOption->hasDefaultValue() ?
281 (_DefaultAsImplicit ?
282 implicit_value(bool(boost::lexical_cast<int>(currentOption->getDefaultValue().c_str()))) :
283 po::value < bool >()->default_value(boost::lexical_cast<int>(currentOption->getDefaultValue().c_str()))) :
284 po::value < bool >(),
285 currentOption->getDescription().c_str())
286 ;
287 break;
288 case TypeEnumContainer::FileType:
289 OptionList->add_options()
290 (currentOption->getKeyAndShortForm().c_str(),
291// currentOption->hasDefaultValue() ?
292// po::value < boost::filesystem::path >()->default_value(boost::lexical_cast<boost::filesystem::path>(currentOption->getDefaultValue().c_str())) :
293 po::value < boost::filesystem::path >(),
294 currentOption->getDescription().c_str())
295 ;
296 break;
297 case TypeEnumContainer::ListOfFilesType:
298 OptionList->add_options()
299 (currentOption->getKeyAndShortForm().c_str(),
300// currentOption->hasDefaultValue() ?
301// po::value < std::vector<boost::filesystem::path> >()->default_value(boost::lexical_cast< std::vector<boost::filesystem::path> >(currentOption->getDefaultValue().c_str())) :
302 po::value < std::vector<boost::filesystem::path> >()->multitoken(),
303 currentOption->getDescription().c_str())
304 ;
305 break;
306 case TypeEnumContainer::IntegerType:
307 OptionList->add_options()
308 (currentOption->getKeyAndShortForm().c_str(),
309 currentOption->hasDefaultValue() ?
310 (_DefaultAsImplicit ?
311 implicit_value(boost::lexical_cast<int>(currentOption->getDefaultValue().c_str())) :
312 po::value < int >()->default_value(boost::lexical_cast<int>(currentOption->getDefaultValue().c_str()))) :
313 po::value < int >(),
314 currentOption->getDescription().c_str())
315 ;
316 break;
317 case TypeEnumContainer::ListOfIntegersType:
318 OptionList->add_options()
319 (currentOption->getKeyAndShortForm().c_str(),
320// currentOption->hasDefaultValue() ?
321// po::value < std::vector<int> >()->default_value(boost::lexical_cast< std::vector<int> >(currentOption->getDefaultValue().c_str())) :
322 po::value < std::vector<int> >()->multitoken(),
323 currentOption->getDescription().c_str())
324 ;
325 break;
326 case TypeEnumContainer::UnsignedIntegerType:
327 OptionList->add_options()
328 (currentOption->getKeyAndShortForm().c_str(),
329 currentOption->hasDefaultValue() ?
330 (_DefaultAsImplicit ?
331 implicit_value(boost::lexical_cast<unsigned int>(currentOption->getDefaultValue().c_str())) :
332 po::value < unsigned int >()->default_value(boost::lexical_cast<unsigned int>(currentOption->getDefaultValue().c_str()))) :
333 po::value < unsigned int >(),
334 currentOption->getDescription().c_str())
335 ;
336 break;
337 case TypeEnumContainer::ListOfUnsignedIntegersType:
338 OptionList->add_options()
339 (currentOption->getKeyAndShortForm().c_str(),
340// currentOption->hasDefaultValue() ?
341// po::value < std::vector<unsigned int> >()->default_value(boost::lexical_cast< std::vector<unsigned int> >(currentOption->getDefaultValue().c_str())) :
342 po::value < std::vector<unsigned int> >()->multitoken(),
343 currentOption->getDescription().c_str())
344 ;
345 break;
346 case TypeEnumContainer::DoubleType:
347 OptionList->add_options()
348 (currentOption->getKeyAndShortForm().c_str(),
349 currentOption->hasDefaultValue() ?
350 (_DefaultAsImplicit ?
351 implicit_value(boost::lexical_cast<double>(currentOption->getDefaultValue().c_str())) :
352 po::value < double >()->default_value(boost::lexical_cast<double>(currentOption->getDefaultValue().c_str()))) :
353 po::value < double >(),
354 currentOption->getDescription().c_str())
355 ;
356 break;
357 case TypeEnumContainer::ListOfDoublesType:
358 OptionList->add_options()
359 (currentOption->getKeyAndShortForm().c_str(),
360// currentOption->hasDefaultValue() ?
361// po::value < std::vector<double> >()->default_value(boost::lexical_cast< std::vector<double> >(currentOption->getDefaultValue().c_str())) :
362 po::value < std::vector<double> >()->multitoken(),
363 currentOption->getDescription().c_str())
364 ;
365 break;
366 case TypeEnumContainer::StringType:
367 OptionList->add_options()
368 (currentOption->getKeyAndShortForm().c_str(),
369 currentOption->hasDefaultValue() ?
370 (_DefaultAsImplicit ?
371 implicit_value(currentOption->getDefaultValue()) :
372 po::value < std::string >()->default_value(currentOption->getDefaultValue())) :
373 po::value < std::string >(),
374 currentOption->getDescription().c_str())
375 ;
376 break;
377 case TypeEnumContainer::ListOfStringsType:
378 OptionList->add_options()
379 (currentOption->getKeyAndShortForm().c_str(),
380// currentOption->hasDefaultValue() ?
381// po::value < std::vector<std::string> >()->default_value(boost::lexical_cast< std::vector<std::string> >(currentOption->getDefaultValue().c_str())) :
382 po::value < std::vector<std::string> >()->multitoken(),
383 currentOption->getDescription().c_str())
384 ;
385 break;
386 case TypeEnumContainer::VectorType:
387 OptionList->add_options()
388 (currentOption->getKeyAndShortForm().c_str(),
389// currentOption->hasDefaultValue() ?
390// po::value < VectorValue >()->default_value(boost::lexical_cast<VectorValue>(currentOption->getDefaultValue().c_str())) :
391 po::value < VectorValue >(),
392 currentOption->getDescription().c_str())
393 ;
394 break;
395 case TypeEnumContainer::ListOfVectorsType:
396 OptionList->add_options()
397 (currentOption->getKeyAndShortForm().c_str(),
398// currentOption->hasDefaultValue() ?
399// po::value < std::vector<VectorValue> >()->default_value(boost::lexical_cast< std::vector<VectorValue> >(currentOption->getDefaultValue().c_str())) :
400 po::value < std::vector<VectorValue> >()->multitoken(),
401 currentOption->getDescription().c_str())
402 ;
403 break;
404 case TypeEnumContainer::MoleculeType:
405 OptionList->add_options()
406 (currentOption->getKeyAndShortForm().c_str(),
407// currentOption->hasDefaultValue() ?
408// po::value < const molecule * >()->default_value(boost::lexical_cast<const molecule *>(currentOption->getDefaultValue().c_str())) :
409 po::value < int >(),
410 currentOption->getDescription().c_str())
411 ;
412 break;
413 case TypeEnumContainer::ListOfMoleculesType:
414 OptionList->add_options()
415 (currentOption->getKeyAndShortForm().c_str(),
416// currentOption->hasDefaultValue() ?
417// po::value < std::vector<const molecule *> >()->default_value(boost::lexical_cast< std::vector<const molecule *> >(currentOption->getDefaultValue().c_str())) :
418 po::value < std::vector<int> >()->multitoken(),
419 currentOption->getDescription().c_str())
420 ;
421 break;
422 case TypeEnumContainer::AtomType:
423 OptionList->add_options()
424 (currentOption->getKeyAndShortForm().c_str(),
425 currentOption->hasDefaultValue() ?
426 (_DefaultAsImplicit ?
427 implicit_value(boost::lexical_cast<int>(currentOption->getDefaultValue().c_str())) :
428 po::value < int >()->default_value(boost::lexical_cast<int>(currentOption->getDefaultValue().c_str()))) :
429 po::value < int >(),
430 currentOption->getDescription().c_str())
431 ;
432 break;
433 case TypeEnumContainer::ListOfAtomsType:
434 OptionList->add_options()
435 (currentOption->getKeyAndShortForm().c_str(),
436// currentOption->hasDefaultValue() ?
437// po::value < std::vector<const atom *> >()->default_value(boost::lexical_cast< std::vector<const atom *> >(currentOption->getDefaultValue().c_str())) :
438 po::value < std::vector<int> >()->multitoken(),
439 currentOption->getDescription().c_str())
440 ;
441 break;
442 case TypeEnumContainer::ElementType:
443 OptionList->add_options()
444 (currentOption->getKeyAndShortForm().c_str(),
445// currentOption->hasDefaultValue() ?
446// po::value < const element * >()->default_value(boost::lexical_cast<const element *>(currentOption->getDefaultValue().c_str())) :
447 po::value < std::string >(),
448 currentOption->getDescription().c_str())
449 ;
450 break;
451 case TypeEnumContainer::ListOfElementsType:
452 OptionList->add_options()
453 (currentOption->getKeyAndShortForm().c_str(),
454// currentOption->hasDefaultValue() ?
455// po::value < std::vector<const element *> >()->default_value(boost::lexical_cast< std::vector<const element *> >(currentOption->getDefaultValue().c_str())) :
456 po::value < std::vector<std::string> >()->multitoken(),
457 currentOption->getDescription().c_str())
458 ;
459 break;
460 case TypeEnumContainer::RealSpaceMatrixType:
461 OptionList->add_options()
462 (currentOption->getKeyAndShortForm().c_str(),
463// currentOption->hasDefaultValue() ?
464// po::value < RealSpaceMatrixValue >()->default_value(boost::lexical_cast<BoxValue>(currentOption->getDefaultValue().c_str())) :
465 po::value < RealSpaceMatrixValue >(),
466 currentOption->getDescription().c_str())
467 ;
468 break;
469 case TypeEnumContainer::KeyValueType:
470 OptionList->add_options()
471 (currentOption->getKeyAndShortForm().c_str(),
472 currentOption->hasDefaultValue() ?
473 (_DefaultAsImplicit ?
474 implicit_value(boost::lexical_cast< KeyValuePair >(currentOption->getDefaultValue().c_str())) :
475 po::value < KeyValuePair >()->default_value(boost::lexical_cast< KeyValuePair >(currentOption->getDefaultValue().c_str()))) :
476 po::value < KeyValuePair >(),
477 currentOption->getDescription().c_str())
478 ;
479 break;
480 case TypeEnumContainer::ListOfKeyValuesType:
481 OptionList->add_options()
482 (currentOption->getKeyAndShortForm().c_str(),
483// currentOption->hasDefaultValue() ?
484// po::value < std::vector<KeyValuePair> >()->default_value(boost::lexical_cast< std::vector<KeyValuePair> >(currentOption->getDefaultValue().c_str())) :
485 po::value < std::vector<KeyValuePair> >()->multitoken(),
486 currentOption->getDescription().c_str())
487 ;
488 break;
489 }
490}
491
492/** States whether there are command line arguments.
493 * \return true - there are none, false - there is at least one command line argument
494 */
495bool CommandLineParser::isEmpty()
496{
497 return vm.empty();
498}
499
500/** Sets the options.
501 * \param _argc arg count from main()
502 * \param **_argv argument array from main()
503 */
504void CommandLineParser::setOptions(int _argc, char **_argv)
505{
506 argc = _argc;
507 argv = _argv;
508 config_file_options.add(options);
509 // append all option_descriptions to both cmdline_options and visible
510 for (CmdParserLookupMap::iterator iter = CmdParserLookup.begin();
511 iter != CmdParserLookup.end();
512 ++iter) {
513 cmdline_options.add(*(iter->second));
514 visible.add(*(iter->second));
515 }
516}
517
518/** This is due to the answer by Aleksey Vitebskiy
519 * in http://stackoverflow.com/questions/4107087/accepting-negative-doubles-with-boostprogram-options
520 *
521 */
522std::vector<po::option> ignore_numbers(std::vector<std::string>& args)
523{
524 std::vector<po::option> result;
525 int pos = 0;
526 while(!args.empty()) {
527 const std::string& arg = args[0];
528 bool isNumber = true;
529 try {
530 boost::lexical_cast<double>(arg);
531 } catch(boost::bad_lexical_cast) {
532 isNumber = false;
533 }
534 if (isNumber) {
535 result.push_back(po::option());
536 po::option& opt = result.back();
537
538 opt.position_key = pos++;
539 opt.value.push_back(arg);
540 opt.original_tokens.push_back(arg);
541
542 args.erase(args.begin());
543 } else {
544 break;
545 }
546 }
547
548 return result;
549}
550
551/** Parses the command line arguments.
552 * Calls program_options::store() and program_options::notify()
553 *
554 * @return true - all is ok, false - command-line options could not be parsed
555 * correctly
556 */
557bool CommandLineParser::Parse()
558{
559 bool status = true;
560 try {
561 po::store(po::command_line_parser(argc,argv).extra_style_parser(&ignore_numbers).options(cmdline_options).run(), vm);
562 } catch (std::exception &e) {
563 std::cerr << "Something went wrong with parsing the command-line arguments: "
564 << e.what() << std::endl;
565 World::getInstance().setExitFlag(134);
566#ifdef HAVE_ACTION_THREAD
567 // force action queue to stop thread
568 ActionQueue::getInstance().stop();
569 ActionQueue::getInstance().clearTempQueue();
570#endif
571 ActionQueue::getInstance().clearQueue();
572 status = false;
573 }
574 if (status) {
575 std::ifstream input;
576 input.open("example.cfg");
577 if (!input.fail())
578 po::store(po::parse_config_file(input, config_file_options), vm);
579 input.close();
580 po::notify(vm);
581 }
582 return status;
583}
584
585/** Scan the argument list for -a or --arguments and store their order for later use.
586 */
587void CommandLineParser::scanforSequenceOfArguments()
588{
589 std::map <std::string, std::string> ShortFormToActionMap = getShortFormToActionMap();
590 LOG(0, "Scanning command line arguments and recognizing Actions.");
591 // go through all arguments
592 for (int i=1;i<argc;i++) {
593 LOG(2, "Checking on " << argv[i]);
594 // check whether they
595 if (argv[i][0] == '-') { // .. begin with -
596 LOG(2, "Possible argument: " << argv[i]);
597 if (argv[i][1] == '-') { // .. or --
598 LOG(1, "Putting " << argv[i] << " into the sequence.");
599 std::vector<std::string> fields;
600 boost::split(fields, argv[i], boost::is_any_of("="));
601 SequenceOfActions.push_back(&(fields[0][2]));
602 // .. and check that next letter is not numeric, if so insert
603 } else if (((argv[i][1] < '0') || (argv[i][1] > '9')) && ((argv[i][1] != '.'))) {
604 std::map <std::string, std::string>::iterator iter = ShortFormToActionMap.find(&(argv[i][1]));
605 if (iter != ShortFormToActionMap.end()) {
606 LOG(1, "Putting " << iter->second << " for " << iter->first << " into the sequence.");
607 SequenceOfActions.push_back(iter->second);
608 }
609 }
610 }
611 }
612}
613
614/** Makes the Parser parse the command line options with current known options.
615 * \param _argc arg count from main()
616 * \param **_argv argument array from main()
617 */
618void CommandLineParser::Run(int _argc, char **_argv)
619{
620 setOptions(_argc,_argv);
621 const bool status = Parse();
622 if (status)
623 scanforSequenceOfArguments();
624}
625
626/** Go through all Actions and create a map from short form to their token.
627 * \return map from Action's ShortForm to token.
628 */
629std::map <std::string, std::string> CommandLineParser::getShortFormToActionMap() const
630{
631 std::map <std::string, std::string> result;
632
633 ActionQueue &AQ = ActionQueue::getInstance();
634 ActionQueue::ActionTokens_t tokens = AQ.getListOfActions();
635 for (ActionQueue::ActionTokens_t::const_iterator iter = tokens.begin();
636 iter != tokens.end(); ++iter) {
637 const ActionTrait &CurrentTrait = AQ.getActionsTrait(*iter);
638 if (CurrentTrait.hasShortForm()) {
639 ASSERT(result.find(CurrentTrait.getShortForm()) == result.end(),
640 "Short form "+toString(CurrentTrait.getShortForm())+
641 " for action "+toString(*iter)+" already present from "+
642 std::string(result[CurrentTrait.getShortForm()])+"!");
643 result[CurrentTrait.getShortForm()] = *iter;
644 }
645 }
646
647 return result;
648}
649
650CONSTRUCT_SINGLETON(CommandLineParser)
Note: See TracBrowser for help on using the repository browser.