source: src/UIElements/CommandLineUI/CommandLineParser.cpp@ f71fc8

Candidate_v1.7.0 stable
Last change on this file since f71fc8 was b56827, checked in by Frederik Heber <frederik.heber@…>, 5 years ago

Program_options 1.63 behavior breaks.

  • in program_options with 1.63 a behaviorial change for implicit values was introduced: "-a foo" needs to be "-a=foo" if foo is an implicit value. This completely breaks with the current behavior.
  • here, we generally fix that an action whose name is identical to an option may have its value given by following right after the action name with an equality sign and the value. This now works as well (splitting off the actual open name). Before the action was then never scheduled to run.
  • using a fix from Benedek Thaler suggest on the boost mailing list to regain the old behavior.
  • Property mode set to 100644
File size: 26.0 KB
RevLine 
[e4afb4]1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
[0aa122]4 * Copyright (C) 2010-2012 University of Bonn. All rights reserved.
[94d5ac6]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/>.
[e4afb4]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
[9eb71b3]35//#include "CodePatterns/MemDebug.hpp"
[e4afb4]36
[b56827]37#include <boost/algorithm/string.hpp>
[e4afb4]38#include <boost/filesystem.hpp>
[15d21e]39#include <boost/lexical_cast.hpp>
40#include <boost/program_options/option.hpp>
41#include <boost/program_options/value_semantic.hpp>
[e4afb4]42#include <boost/program_options.hpp>
43#include <fstream>
44#include <iostream>
[5a8f38]45#include <set>
[e4afb4]46#include <map>
47
48#include "Actions/Action.hpp"
[628577]49#include "Actions/ActionQueue.hpp"
[3139b2]50#include "Actions/ActionTrait.hpp"
[e4afb4]51#include "Actions/OptionRegistry.hpp"
52#include "Actions/OptionTrait.hpp"
53#include "Actions/Values.hpp"
[ad011c]54#include "CodePatterns/Log.hpp"
55#include "CodePatterns/Verbose.hpp"
[e4afb4]56#include "CommandLineParser.hpp"
[3a21a7]57#include "CommandLineParser_validate.hpp"
[33e801]58#include "Parameters/Specifics/KeyValuePair.hpp"
[11d433]59#include "World.hpp"
[e4afb4]60
[ad011c]61#include "CodePatterns/Singleton_impl.hpp"
[e4afb4]62
[ce7fdc]63using namespace MoleCuilder;
64
[e4afb4]65class element;
66
67/** Constructor of class CommandLineParser.
68 *
69 */
70CommandLineParser::CommandLineParser() :
71 analysis("Analysis options"),
72 atom("Atom options"),
[f63e41]73 bond("Bond options"),
[e4afb4]74 command("Command options"),
[a88452]75 fill("fill options"),
[4dc309]76 shape("shape options"),
[e4afb4]77 fragmentation("Fragmentation options"),
[987145]78 geometry("Geometry options"),
[d09093]79 graph("Graph options"),
[e4afb4]80 molecule("Molecule options"),
[d09093]81 options("Secondary options"),
[e4afb4]82 parser("Parser options"),
[f5724f]83 potential("Potential options"),
[e4afb4]84 selection("Selection options"),
85 tesselation("Tesselation options"),
[d09093]86 world("World options")
[e4afb4]87{
88 // put all options lists into a lookup
89 CmdParserLookup["analysis"] = &analysis;
90 CmdParserLookup["atom"] = &atom;
[f63e41]91 CmdParserLookup["bond"] = &bond;
[e4afb4]92 CmdParserLookup["command"] = &command;
93 CmdParserLookup["edit"] = &edit;
[a88452]94 CmdParserLookup["fill"] = &fill;
[4dc309]95 CmdParserLookup["shape"] = &shape;
[e4afb4]96 CmdParserLookup["fragmentation"] = &fragmentation;
[987145]97 CmdParserLookup["geometry"] = &geometry;
[d09093]98 CmdParserLookup["graph"] = &graph;
99 CmdParserLookup["options"] = &options;
[e4afb4]100 CmdParserLookup["molecule"] = &molecule;
101 CmdParserLookup["parser"] = &parser;
[f5724f]102 CmdParserLookup["potential"] = &potential;
[e4afb4]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{
[5a8f38]119 // we need a list of already added options, otherwise we get ambigious exceptions
120 std::set<std::string> AlreadyAddedOptionNames;
121
[e4afb4]122 bool ActionAlreadyAdded_flag = false;
[690741]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);
[e4afb4]128 ActionAlreadyAdded_flag = false;
129 //std::cout << "Current Action to initialize is: " << actioniter->first << std::endl;
130
[690741]131 for (ActionTrait::options_const_iterator optioniter = CurrentTrait.getBeginIter();
132 optioniter != CurrentTrait.getEndIter();
[e4afb4]133 ++optioniter) {
[690741]134 if (optioniter->first == *iter)
[e4afb4]135 ActionAlreadyAdded_flag = true;
136 ASSERT( OptionRegistry::getInstance().isOptionPresentByName(optioniter->first),
[5a8f38]137 "CommandLineParser::Init() - Option "+optioniter->first+" not present in OptionRegistry." );
[e4afb4]138 const OptionTrait* const currentOption = OptionRegistry::getInstance().getOptionByName(optioniter->first);
139
[5a8f38]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
[7912e9]156 AddOptionToParser(currentOption, (CmdParserLookup["options"]),
157 (optioniter->first == *iter) ?
158 true : false);
[5a8f38]159
160 AlreadyAddedOptionNames.insert(optioniter->first);
161 } else {
162// std::cout << "Option " << currentOption->getName() << " already registered." << std::endl;
163 }
[e4afb4]164 }
165
166 if (!ActionAlreadyAdded_flag) {
167 // add the action
[ad7270]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;
[e4afb4]182
[690741]183 ASSERT(CmdParserLookup.find(CurrentTrait.getMenuName()) != CmdParserLookup.end(),
[e4afb4]184 "CommandLineParser: boost::program_options::options_description for this Action not present.");
[7912e9]185 AddOptionToParser(
186 dynamic_cast<const OptionTrait * const>(&CurrentTrait),
187 (CmdParserLookup[CurrentTrait.getMenuName()]),
188 false);
[e4afb4]189 }
190 }
191 // note: positioning is not important on the command line
192}
193
[b56827]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
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#else
227template <typename T>
228po::typed_value<T>* implicit_value(const T& value)
229{
230 return new po::typed_value<T>()->implicit_value(value);
231}
232#endif
233
234
[e4afb4]235/** Adds an Action or Option to the CommandLineParser.
236 * Note that Action is derived from Option(Trait)
237 *
238 * This ugly switch function is necessary because of the compile-time problem:
239 * po::value<T> has to be instantiated at compile-time however we do know the type not until run-time.
240 * Not even a templated function like po::value<T> getProgramOptionValuefromType() does help, specialized
241 * to each available type, as the signatures of all the functions differ. Hence, they cannot not put into
242 * one type_info -> po::value<T> map ...
243 *
244 * \param *currentOption pointer to Action/Option to add
245 * \param *OptionList program_options list to add to
[7912e9]246 * \param _DefaultAsImplicit whether to add a default value as default_value or
247 * as implicit_value (default = option token present or not, implicit =
248 option token present but not necessarily followed by argument)
[e4afb4]249 */
[7912e9]250void CommandLineParser::AddOptionToParser(
251 const OptionTrait * const currentOption,
252 po::options_description* OptionList,
253 const bool _DefaultAsImplicit)
[e4afb4]254{
255 // check whether dynamic_cast in Init() suceeded
256 ASSERT(currentOption != NULL, "CommandLineParser::AddOptionToParser() - currentOption is NULL!");
257 // add other options
[ec098d]258// std::cout << "Adding Action " << currentOption->getName() << " with type "
259// << currentOption->getType()->name() << ", " << (currentOption->hasDefaultValue() ? "with" : "without")
260// << " default value, and KeyandShortform " << currentOption->getKeyAndShortForm()
261// << " to CommandLineParser." << std::endl;
[e4afb4]262 switch(TypeToEnums.getEnumforType(currentOption->getType())) {
263 default:
264 case TypeEnumContainer::NoneType:
265 OptionList->add_options()
266 (currentOption->getKeyAndShortForm().c_str(), currentOption->getDescription().c_str())
267 ;
268 break;
269 case TypeEnumContainer::BooleanType:
270 OptionList->add_options()
271 (currentOption->getKeyAndShortForm().c_str(),
272 currentOption->hasDefaultValue() ?
[7912e9]273 (_DefaultAsImplicit ?
[b56827]274 implicit_value(bool(boost::lexical_cast<int>(currentOption->getDefaultValue().c_str()))) :
[7912e9]275 po::value < bool >()->default_value(boost::lexical_cast<int>(currentOption->getDefaultValue().c_str()))) :
[e4afb4]276 po::value < bool >(),
277 currentOption->getDescription().c_str())
278 ;
279 break;
280 case TypeEnumContainer::FileType:
281 OptionList->add_options()
282 (currentOption->getKeyAndShortForm().c_str(),
283// currentOption->hasDefaultValue() ?
284// po::value < boost::filesystem::path >()->default_value(boost::lexical_cast<boost::filesystem::path>(currentOption->getDefaultValue().c_str())) :
285 po::value < boost::filesystem::path >(),
286 currentOption->getDescription().c_str())
287 ;
288 break;
289 case TypeEnumContainer::ListOfFilesType:
290 OptionList->add_options()
291 (currentOption->getKeyAndShortForm().c_str(),
292// currentOption->hasDefaultValue() ?
293// po::value < std::vector<boost::filesystem::path> >()->default_value(boost::lexical_cast< std::vector<boost::filesystem::path> >(currentOption->getDefaultValue().c_str())) :
294 po::value < std::vector<boost::filesystem::path> >()->multitoken(),
295 currentOption->getDescription().c_str())
296 ;
297 break;
298 case TypeEnumContainer::IntegerType:
299 OptionList->add_options()
300 (currentOption->getKeyAndShortForm().c_str(),
301 currentOption->hasDefaultValue() ?
[7912e9]302 (_DefaultAsImplicit ?
[b56827]303 implicit_value(boost::lexical_cast<int>(currentOption->getDefaultValue().c_str())) :
[7912e9]304 po::value < int >()->default_value(boost::lexical_cast<int>(currentOption->getDefaultValue().c_str()))) :
[e4afb4]305 po::value < int >(),
306 currentOption->getDescription().c_str())
307 ;
308 break;
309 case TypeEnumContainer::ListOfIntegersType:
310 OptionList->add_options()
311 (currentOption->getKeyAndShortForm().c_str(),
312// currentOption->hasDefaultValue() ?
313// po::value < std::vector<int> >()->default_value(boost::lexical_cast< std::vector<int> >(currentOption->getDefaultValue().c_str())) :
314 po::value < std::vector<int> >()->multitoken(),
315 currentOption->getDescription().c_str())
316 ;
317 break;
[838cd0]318 case TypeEnumContainer::UnsignedIntegerType:
319 OptionList->add_options()
320 (currentOption->getKeyAndShortForm().c_str(),
321 currentOption->hasDefaultValue() ?
[7912e9]322 (_DefaultAsImplicit ?
[b56827]323 implicit_value(boost::lexical_cast<unsigned int>(currentOption->getDefaultValue().c_str())) :
[7912e9]324 po::value < unsigned int >()->default_value(boost::lexical_cast<unsigned int>(currentOption->getDefaultValue().c_str()))) :
[838cd0]325 po::value < unsigned int >(),
326 currentOption->getDescription().c_str())
327 ;
328 break;
[12948c]329 case TypeEnumContainer::ListOfUnsignedIntegersType:
330 OptionList->add_options()
331 (currentOption->getKeyAndShortForm().c_str(),
332// currentOption->hasDefaultValue() ?
333// po::value < std::vector<unsigned int> >()->default_value(boost::lexical_cast< std::vector<unsigned int> >(currentOption->getDefaultValue().c_str())) :
334 po::value < std::vector<unsigned int> >()->multitoken(),
335 currentOption->getDescription().c_str())
336 ;
337 break;
[e4afb4]338 case TypeEnumContainer::DoubleType:
339 OptionList->add_options()
340 (currentOption->getKeyAndShortForm().c_str(),
341 currentOption->hasDefaultValue() ?
[7912e9]342 (_DefaultAsImplicit ?
[b56827]343 implicit_value(boost::lexical_cast<double>(currentOption->getDefaultValue().c_str())) :
[7912e9]344 po::value < double >()->default_value(boost::lexical_cast<double>(currentOption->getDefaultValue().c_str()))) :
[e4afb4]345 po::value < double >(),
346 currentOption->getDescription().c_str())
347 ;
348 break;
349 case TypeEnumContainer::ListOfDoublesType:
350 OptionList->add_options()
351 (currentOption->getKeyAndShortForm().c_str(),
352// currentOption->hasDefaultValue() ?
353// po::value < std::vector<double> >()->default_value(boost::lexical_cast< std::vector<double> >(currentOption->getDefaultValue().c_str())) :
354 po::value < std::vector<double> >()->multitoken(),
355 currentOption->getDescription().c_str())
356 ;
357 break;
358 case TypeEnumContainer::StringType:
359 OptionList->add_options()
360 (currentOption->getKeyAndShortForm().c_str(),
361 currentOption->hasDefaultValue() ?
[7912e9]362 (_DefaultAsImplicit ?
[b56827]363 implicit_value(currentOption->getDefaultValue()) :
[7912e9]364 po::value < std::string >()->default_value(currentOption->getDefaultValue())) :
[e4afb4]365 po::value < std::string >(),
366 currentOption->getDescription().c_str())
367 ;
368 break;
369 case TypeEnumContainer::ListOfStringsType:
370 OptionList->add_options()
371 (currentOption->getKeyAndShortForm().c_str(),
372// currentOption->hasDefaultValue() ?
373// po::value < std::vector<std::string> >()->default_value(boost::lexical_cast< std::vector<std::string> >(currentOption->getDefaultValue().c_str())) :
374 po::value < std::vector<std::string> >()->multitoken(),
375 currentOption->getDescription().c_str())
376 ;
377 break;
378 case TypeEnumContainer::VectorType:
379 OptionList->add_options()
380 (currentOption->getKeyAndShortForm().c_str(),
381// currentOption->hasDefaultValue() ?
382// po::value < VectorValue >()->default_value(boost::lexical_cast<VectorValue>(currentOption->getDefaultValue().c_str())) :
383 po::value < VectorValue >(),
384 currentOption->getDescription().c_str())
385 ;
386 break;
387 case TypeEnumContainer::ListOfVectorsType:
388 OptionList->add_options()
389 (currentOption->getKeyAndShortForm().c_str(),
390// currentOption->hasDefaultValue() ?
391// po::value < std::vector<VectorValue> >()->default_value(boost::lexical_cast< std::vector<VectorValue> >(currentOption->getDefaultValue().c_str())) :
392 po::value < std::vector<VectorValue> >()->multitoken(),
393 currentOption->getDescription().c_str())
394 ;
395 break;
396 case TypeEnumContainer::MoleculeType:
397 OptionList->add_options()
398 (currentOption->getKeyAndShortForm().c_str(),
399// currentOption->hasDefaultValue() ?
400// po::value < const molecule * >()->default_value(boost::lexical_cast<const molecule *>(currentOption->getDefaultValue().c_str())) :
401 po::value < int >(),
402 currentOption->getDescription().c_str())
403 ;
404 break;
405 case TypeEnumContainer::ListOfMoleculesType:
406 OptionList->add_options()
407 (currentOption->getKeyAndShortForm().c_str(),
408// currentOption->hasDefaultValue() ?
409// po::value < std::vector<const molecule *> >()->default_value(boost::lexical_cast< std::vector<const molecule *> >(currentOption->getDefaultValue().c_str())) :
410 po::value < std::vector<int> >()->multitoken(),
411 currentOption->getDescription().c_str())
412 ;
413 break;
414 case TypeEnumContainer::AtomType:
415 OptionList->add_options()
416 (currentOption->getKeyAndShortForm().c_str(),
417 currentOption->hasDefaultValue() ?
[7912e9]418 (_DefaultAsImplicit ?
[b56827]419 implicit_value(boost::lexical_cast<int>(currentOption->getDefaultValue().c_str())) :
[7912e9]420 po::value < int >()->default_value(boost::lexical_cast<int>(currentOption->getDefaultValue().c_str()))) :
[e4afb4]421 po::value < int >(),
422 currentOption->getDescription().c_str())
423 ;
424 break;
425 case TypeEnumContainer::ListOfAtomsType:
426 OptionList->add_options()
427 (currentOption->getKeyAndShortForm().c_str(),
428// currentOption->hasDefaultValue() ?
429// po::value < std::vector<const atom *> >()->default_value(boost::lexical_cast< std::vector<const atom *> >(currentOption->getDefaultValue().c_str())) :
430 po::value < std::vector<int> >()->multitoken(),
431 currentOption->getDescription().c_str())
432 ;
433 break;
434 case TypeEnumContainer::ElementType:
435 OptionList->add_options()
436 (currentOption->getKeyAndShortForm().c_str(),
437// currentOption->hasDefaultValue() ?
438// po::value < const element * >()->default_value(boost::lexical_cast<const element *>(currentOption->getDefaultValue().c_str())) :
[2f429e]439 po::value < std::string >(),
[e4afb4]440 currentOption->getDescription().c_str())
441 ;
442 break;
443 case TypeEnumContainer::ListOfElementsType:
444 OptionList->add_options()
445 (currentOption->getKeyAndShortForm().c_str(),
446// currentOption->hasDefaultValue() ?
447// po::value < std::vector<const element *> >()->default_value(boost::lexical_cast< std::vector<const element *> >(currentOption->getDefaultValue().c_str())) :
[2f429e]448 po::value < std::vector<std::string> >()->multitoken(),
[e4afb4]449 currentOption->getDescription().c_str())
450 ;
451 break;
[7d9416]452 case TypeEnumContainer::RealSpaceMatrixType:
453 OptionList->add_options()
454 (currentOption->getKeyAndShortForm().c_str(),
455// currentOption->hasDefaultValue() ?
456// po::value < RealSpaceMatrixValue >()->default_value(boost::lexical_cast<BoxValue>(currentOption->getDefaultValue().c_str())) :
457 po::value < RealSpaceMatrixValue >(),
458 currentOption->getDescription().c_str())
459 ;
460 break;
[33e801]461 case TypeEnumContainer::KeyValueType:
462 OptionList->add_options()
463 (currentOption->getKeyAndShortForm().c_str(),
464 currentOption->hasDefaultValue() ?
465 (_DefaultAsImplicit ?
[b56827]466 implicit_value(boost::lexical_cast< KeyValuePair >(currentOption->getDefaultValue().c_str())) :
[33e801]467 po::value < KeyValuePair >()->default_value(boost::lexical_cast< KeyValuePair >(currentOption->getDefaultValue().c_str()))) :
468 po::value < KeyValuePair >(),
469 currentOption->getDescription().c_str())
470 ;
471 break;
472 case TypeEnumContainer::ListOfKeyValuesType:
473 OptionList->add_options()
474 (currentOption->getKeyAndShortForm().c_str(),
475// currentOption->hasDefaultValue() ?
476// po::value < std::vector<KeyValuePair> >()->default_value(boost::lexical_cast< std::vector<KeyValuePair> >(currentOption->getDefaultValue().c_str())) :
477 po::value < std::vector<KeyValuePair> >()->multitoken(),
478 currentOption->getDescription().c_str())
479 ;
480 break;
[e4afb4]481 }
482}
483
484/** States whether there are command line arguments.
485 * \return true - there are none, false - there is at least one command line argument
486 */
487bool CommandLineParser::isEmpty()
488{
489 return vm.empty();
490}
491
492/** Sets the options.
493 * \param _argc arg count from main()
494 * \param **_argv argument array from main()
495 */
496void CommandLineParser::setOptions(int _argc, char **_argv)
497{
498 argc = _argc;
499 argv = _argv;
500 config_file_options.add(options);
[c6e5eb]501 // append all option_descriptions to both cmdline_options and visible
502 for (CmdParserLookupMap::iterator iter = CmdParserLookup.begin();
503 iter != CmdParserLookup.end();
504 ++iter) {
505 cmdline_options.add(*(iter->second));
506 visible.add(*(iter->second));
507 }
[e4afb4]508}
509
[15d21e]510/** This is due to the answer by Aleksey Vitebskiy
511 * in http://stackoverflow.com/questions/4107087/accepting-negative-doubles-with-boostprogram-options
512 *
513 */
514std::vector<po::option> ignore_numbers(std::vector<std::string>& args)
515{
516 std::vector<po::option> result;
517 int pos = 0;
518 while(!args.empty()) {
519 const std::string& arg = args[0];
520 bool isNumber = true;
521 try {
522 boost::lexical_cast<double>(arg);
523 } catch(boost::bad_lexical_cast) {
524 isNumber = false;
525 }
526 if (isNumber) {
527 result.push_back(po::option());
528 po::option& opt = result.back();
529
530 opt.position_key = pos++;
531 opt.value.push_back(arg);
532 opt.original_tokens.push_back(arg);
533
534 args.erase(args.begin());
535 } else {
536 break;
537 }
538 }
539
540 return result;
541}
542
[e4afb4]543/** Parses the command line arguments.
544 * Calls program_options::store() and program_options::notify()
[06b5df]545 *
546 * @return true - all is ok, false - command-line options could not be parsed
547 * correctly
[e4afb4]548 */
[06b5df]549bool CommandLineParser::Parse()
[e4afb4]550{
[06b5df]551 bool status = true;
[11d433]552 try {
[15d21e]553 po::store(po::command_line_parser(argc,argv).extra_style_parser(&ignore_numbers).options(cmdline_options).run(), vm);
[11d433]554 } catch (std::exception &e) {
[7912e9]555 std::cerr << "Something went wrong with parsing the command-line arguments: "
556 << e.what() << std::endl;
[11d433]557 World::getInstance().setExitFlag(134);
558#ifdef HAVE_ACTION_THREAD
559 // force action queue to stop thread
560 ActionQueue::getInstance().stop();
[601ef8]561 ActionQueue::getInstance().clearTempQueue();
[11d433]562#endif
563 ActionQueue::getInstance().clearQueue();
[06b5df]564 status = false;
565 }
566 if (status) {
567 std::ifstream input;
568 input.open("example.cfg");
569 if (!input.fail())
570 po::store(po::parse_config_file(input, config_file_options), vm);
571 input.close();
572 po::notify(vm);
[11d433]573 }
[06b5df]574 return status;
[e4afb4]575}
576
577/** Scan the argument list for -a or --arguments and store their order for later use.
578 */
579void CommandLineParser::scanforSequenceOfArguments()
580{
[3a21a7]581 std::map <std::string, std::string> ShortFormToActionMap = getShortFormToActionMap();
[47d041]582 LOG(0, "Scanning command line arguments and recognizing Actions.");
[e4afb4]583 // go through all arguments
584 for (int i=1;i<argc;i++) {
[47d041]585 LOG(2, "Checking on " << argv[i]);
[e4afb4]586 // check whether they
587 if (argv[i][0] == '-') { // .. begin with -
[47d041]588 LOG(2, "Possible argument: " << argv[i]);
[e4afb4]589 if (argv[i][1] == '-') { // .. or --
[47d041]590 LOG(1, "Putting " << argv[i] << " into the sequence.");
[b56827]591 std::vector<std::string> fields;
592 boost::split(fields, argv[i], boost::is_any_of("="));
593 SequenceOfActions.push_back(&(fields[0][2]));
[e4afb4]594 // .. and check that next letter is not numeric, if so insert
595 } else if (((argv[i][1] < '0') || (argv[i][1] > '9')) && ((argv[i][1] != '.'))) {
[3a21a7]596 std::map <std::string, std::string>::iterator iter = ShortFormToActionMap.find(&(argv[i][1]));
[e4afb4]597 if (iter != ShortFormToActionMap.end()) {
[47d041]598 LOG(1, "Putting " << iter->second << " for " << iter->first << " into the sequence.");
[e4afb4]599 SequenceOfActions.push_back(iter->second);
600 }
601 }
602 }
603 }
604}
605
606/** Makes the Parser parse the command line options with current known options.
607 * \param _argc arg count from main()
608 * \param **_argv argument array from main()
609 */
610void CommandLineParser::Run(int _argc, char **_argv)
611{
612 setOptions(_argc,_argv);
[06b5df]613 const bool status = Parse();
614 if (status)
615 scanforSequenceOfArguments();
[e4afb4]616}
617
618/** Go through all Actions and create a map from short form to their token.
619 * \return map from Action's ShortForm to token.
620 */
[2a0a9e3]621std::map <std::string, std::string> CommandLineParser::getShortFormToActionMap() const
[e4afb4]622{
[3a21a7]623 std::map <std::string, std::string> result;
[e4afb4]624
[690741]625 ActionQueue &AQ = ActionQueue::getInstance();
626 ActionQueue::ActionTokens_t tokens = AQ.getListOfActions();
627 for (ActionQueue::ActionTokens_t::const_iterator iter = tokens.begin();
628 iter != tokens.end(); ++iter) {
629 const ActionTrait &CurrentTrait = AQ.getActionsTrait(*iter);
630 if (CurrentTrait.hasShortForm()) {
631 ASSERT(result.find(CurrentTrait.getShortForm()) == result.end(),
632 "Short form "+toString(CurrentTrait.getShortForm())+
633 " for action "+toString(*iter)+" already present from "+
634 std::string(result[CurrentTrait.getShortForm()])+"!");
635 result[CurrentTrait.getShortForm()] = *iter;
[e4afb4]636 }
[690741]637 }
[e4afb4]638
639 return result;
640}
641
642CONSTRUCT_SINGLETON(CommandLineParser)
Note: See TracBrowser for help on using the repository browser.