source: src/UIElements/CommandLineUI/CommandLineParser.cpp@ 0b6b77

Action_Thermostats Add_AtomRandomPerturbation Add_FitFragmentPartialChargesAction Add_RotateAroundBondAction Add_SelectAtomByNameAction Added_ParseSaveFragmentResults AddingActions_SaveParseParticleParameters Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_ParticleName_to_Atom Adding_StructOpt_integration_tests AtomFragments Automaking_mpqc_open AutomationFragmentation_failures Candidate_v1.5.4 Candidate_v1.6.0 Candidate_v1.6.1 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator CombiningParticlePotentialParsing Combining_Subpackages Debian_Package_split Debian_package_split_molecuildergui_only Disabling_MemDebug Docu_Python_wait EmpiricalPotential_contain_HomologyGraph EmpiricalPotential_contain_HomologyGraph_documentation Enable_parallel_make_install Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph FitPartialCharges_GlobalError Fix_BoundInBox_CenterInBox_MoleculeActions Fix_ChargeSampling_PBC Fix_ChronosMutex Fix_FitPartialCharges Fix_FitPotential_needs_atomicnumbers Fix_ForceAnnealing Fix_IndependentFragmentGrids Fix_ParseParticles Fix_ParseParticles_split_forward_backward_Actions Fix_PopActions Fix_QtFragmentList_sorted_selection Fix_Restrictedkeyset_FragmentMolecule Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns Fix_fitting_potentials Fixes ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion FragmentAction_writes_AtomFragments FragmentMolecule_checks_bonddegrees GeometryObjects Gui_Fixes Gui_displays_atomic_force_velocity ImplicitCharges IndependentFragmentGrids IndependentFragmentGrids_IndividualZeroInstances IndependentFragmentGrids_IntegrationTest IndependentFragmentGrids_Sole_NN_Calculation JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix MoreRobust_FragmentAutomation ODR_violation_mpqc_open PartialCharges_OrthogonalSummation PdbParser_setsAtomName PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks Rewrite_FitPartialCharges RotateToPrincipalAxisSystem_UndoRedo SaturateAtoms_findBestMatching SaturateAtoms_singleDegree StoppableMakroAction Subpackage_CodePatterns Subpackage_JobMarket Subpackage_LinearAlgebra Subpackage_levmar Subpackage_mpqc_open Subpackage_vmg Switchable_LogView ThirdParty_MPQC_rebuilt_buildsystem TrajectoryDependenant_MaxOrder TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps TremoloParser_setsAtomName Ubuntu_1604_changes stable
Last change on this file since 0b6b77 was 690741, checked in by Frederik Heber <heber@…>, 11 years ago

Added getListOfActions() and getActionsTrait() to completely wrap ActionRegistry.

  • Property mode set to 100644
File size: 21.0 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/filesystem.hpp>
38#include <boost/program_options.hpp>
39#include <fstream>
40#include <iostream>
41#include <set>
42#include <map>
43
44#include "Actions/Action.hpp"
45#include "Actions/ActionQueue.hpp"
46#include "Actions/ActionTrait.hpp"
47#include "Actions/OptionRegistry.hpp"
48#include "Actions/OptionTrait.hpp"
49#include "Actions/Values.hpp"
50#include "CodePatterns/Log.hpp"
51#include "CodePatterns/Verbose.hpp"
52#include "CommandLineParser.hpp"
53#include "CommandLineParser_validate.hpp"
54
55#include "CodePatterns/Singleton_impl.hpp"
56
57using namespace MoleCuilder;
58
59class element;
60
61/** Constructor of class CommandLineParser.
62 *
63 */
64CommandLineParser::CommandLineParser() :
65 analysis("Analysis options"),
66 atom("Atom options"),
67 bond("Bond options"),
68 command("Command options"),
69 fill("fill options"),
70 shape("shape options"),
71 fragmentation("Fragmentation options"),
72 graph("Graph options"),
73 molecule("Molecule options"),
74 options("Secondary options"),
75 parser("Parser options"),
76 potential("Potential options"),
77 selection("Selection options"),
78 tesselation("Tesselation options"),
79 world("World options")
80{
81 // put all options lists into a lookup
82 CmdParserLookup["analysis"] = &analysis;
83 CmdParserLookup["atom"] = &atom;
84 CmdParserLookup["bond"] = &bond;
85 CmdParserLookup["command"] = &command;
86 CmdParserLookup["edit"] = &edit;
87 CmdParserLookup["fill"] = &fill;
88 CmdParserLookup["shape"] = &shape;
89 CmdParserLookup["fragmentation"] = &fragmentation;
90 CmdParserLookup["graph"] = &graph;
91 CmdParserLookup["options"] = &options;
92 CmdParserLookup["molecule"] = &molecule;
93 CmdParserLookup["parser"] = &parser;
94 CmdParserLookup["potential"] = &potential;
95 CmdParserLookup["selection"] = &selection;
96 CmdParserLookup["tesselation"] = &tesselation;
97 CmdParserLookup["world"] = &world;
98}
99
100/** Destructor of class CommandLineParser.
101 *
102 */
103CommandLineParser::~CommandLineParser()
104{}
105
106/** Initializes command arguments to accept.
107 * Goes through ActionRegistry and puts all actions therein into the map.
108 */
109void CommandLineParser::InitializeCommandArguments()
110{
111 // we need a list of already added options, otherwise we get ambigious exceptions
112 std::set<std::string> AlreadyAddedOptionNames;
113
114 bool ActionAlreadyAdded_flag = false;
115 ActionQueue &AQ = ActionQueue::getInstance();
116 ActionQueue::ActionTokens_t tokens = AQ.getListOfActions();
117 for (ActionQueue::ActionTokens_t::const_iterator iter = tokens.begin();
118 iter != tokens.end(); ++iter) {
119 const ActionTrait &CurrentTrait = AQ.getActionsTrait(*iter);
120 ActionAlreadyAdded_flag = false;
121 //std::cout << "Current Action to initialize is: " << actioniter->first << std::endl;
122
123 for (ActionTrait::options_const_iterator optioniter = CurrentTrait.getBeginIter();
124 optioniter != CurrentTrait.getEndIter();
125 ++optioniter) {
126 if (optioniter->first == *iter)
127 ActionAlreadyAdded_flag = true;
128 ASSERT( OptionRegistry::getInstance().isOptionPresentByName(optioniter->first),
129 "CommandLineParser::Init() - Option "+optioniter->first+" not present in OptionRegistry." );
130 const OptionTrait* const currentOption = OptionRegistry::getInstance().getOptionByName(optioniter->first);
131
132 if (AlreadyAddedOptionNames.find(optioniter->first) == AlreadyAddedOptionNames.end()) {
133 // add the option
134// std::cout << "Registering Option "
135// << currentOption->getName()
136// << " with type '" << currentOption->getTypeName() << "' "
137// << " with description '" << currentOption->getDescription() << "' ";
138// if (currentOption->hasShortForm())
139// std::cout << ", with short form " << currentOption->getShortForm();
140// else
141// std::cout << ", with no short form ";
142// if (currentOption->hasDefaultValue())
143// std::cout << ", with default value " << currentOption->getDefaultValue();
144// else
145// std::cout << ", with no default value ";
146// std::cout << std::endl;
147
148 AddOptionToParser(currentOption, (CmdParserLookup["options"]));
149
150 AlreadyAddedOptionNames.insert(optioniter->first);
151 } else {
152// std::cout << "Option " << currentOption->getName() << " already registered." << std::endl;
153 }
154 }
155
156 if (!ActionAlreadyAdded_flag) {
157 // add the action
158// std::cout << "Registering Action "
159// << currentAction->Traits.getName()
160// << " in menu " << currentAction->Traits.getMenuName()
161// << " with type '" << currentAction->Traits.getTypeName() << "' "
162// << " with description '" << currentAction->Traits.getDescription() << "' ";
163// if (currentAction->Traits.hasShortForm())
164// std::cout << ", with short form " << currentAction->Traits.getShortForm();
165// else
166// std::cout << ", with no short form ";
167// if (currentAction->Traits.hasDefaultValue())
168// std::cout << ", with default value " << currentAction->Traits.getDefaultValue();
169// else
170// std::cout << ", with no default value ";
171// std::cout << std::endl;
172
173 ASSERT(CmdParserLookup.find(CurrentTrait.getMenuName()) != CmdParserLookup.end(),
174 "CommandLineParser: boost::program_options::options_description for this Action not present.");
175 AddOptionToParser(dynamic_cast<const OptionTrait * const>(&CurrentTrait),(CmdParserLookup[CurrentTrait.getMenuName()]));
176 }
177 }
178 // note: positioning is not important on the command line
179}
180
181/** Adds an Action or Option to the CommandLineParser.
182 * Note that Action is derived from Option(Trait)
183 *
184 * This ugly switch function is necessary because of the compile-time problem:
185 * po::value<T> has to be instantiated at compile-time however we do know the type not until run-time.
186 * Not even a templated function like po::value<T> getProgramOptionValuefromType() does help, specialized
187 * to each available type, as the signatures of all the functions differ. Hence, they cannot not put into
188 * one type_info -> po::value<T> map ...
189 *
190 * \param *currentOption pointer to Action/Option to add
191 * \param *OptionList program_options list to add to
192 */
193void CommandLineParser::AddOptionToParser(const OptionTrait * const currentOption, po::options_description* OptionList)
194{
195 // check whether dynamic_cast in Init() suceeded
196 ASSERT(currentOption != NULL, "CommandLineParser::AddOptionToParser() - currentOption is NULL!");
197 // add other options
198// std::cout << "Adding Action " << currentOption->getName() << " with type "
199// << currentOption->getType()->name() << ", " << (currentOption->hasDefaultValue() ? "with" : "without")
200// << " default value, and KeyandShortform " << currentOption->getKeyAndShortForm()
201// << " to CommandLineParser." << std::endl;
202 switch(TypeToEnums.getEnumforType(currentOption->getType())) {
203 default:
204 case TypeEnumContainer::NoneType:
205 OptionList->add_options()
206 (currentOption->getKeyAndShortForm().c_str(), currentOption->getDescription().c_str())
207 ;
208 break;
209 case TypeEnumContainer::BooleanType:
210 OptionList->add_options()
211 (currentOption->getKeyAndShortForm().c_str(),
212 currentOption->hasDefaultValue() ?
213 po::value < bool >()->default_value(boost::lexical_cast<int>(currentOption->getDefaultValue().c_str())) :
214 po::value < bool >(),
215 currentOption->getDescription().c_str())
216 ;
217 break;
218 case TypeEnumContainer::FileType:
219 OptionList->add_options()
220 (currentOption->getKeyAndShortForm().c_str(),
221// currentOption->hasDefaultValue() ?
222// po::value < boost::filesystem::path >()->default_value(boost::lexical_cast<boost::filesystem::path>(currentOption->getDefaultValue().c_str())) :
223 po::value < boost::filesystem::path >(),
224 currentOption->getDescription().c_str())
225 ;
226 break;
227 case TypeEnumContainer::ListOfFilesType:
228 OptionList->add_options()
229 (currentOption->getKeyAndShortForm().c_str(),
230// currentOption->hasDefaultValue() ?
231// po::value < std::vector<boost::filesystem::path> >()->default_value(boost::lexical_cast< std::vector<boost::filesystem::path> >(currentOption->getDefaultValue().c_str())) :
232 po::value < std::vector<boost::filesystem::path> >()->multitoken(),
233 currentOption->getDescription().c_str())
234 ;
235 break;
236 case TypeEnumContainer::IntegerType:
237 OptionList->add_options()
238 (currentOption->getKeyAndShortForm().c_str(),
239 currentOption->hasDefaultValue() ?
240 po::value < int >()->default_value(boost::lexical_cast<int>(currentOption->getDefaultValue().c_str())) :
241 po::value < int >(),
242 currentOption->getDescription().c_str())
243 ;
244 break;
245 case TypeEnumContainer::ListOfIntegersType:
246 OptionList->add_options()
247 (currentOption->getKeyAndShortForm().c_str(),
248// currentOption->hasDefaultValue() ?
249// po::value < std::vector<int> >()->default_value(boost::lexical_cast< std::vector<int> >(currentOption->getDefaultValue().c_str())) :
250 po::value < std::vector<int> >()->multitoken(),
251 currentOption->getDescription().c_str())
252 ;
253 break;
254 case TypeEnumContainer::UnsignedIntegerType:
255 OptionList->add_options()
256 (currentOption->getKeyAndShortForm().c_str(),
257 currentOption->hasDefaultValue() ?
258 po::value < unsigned int >()->default_value(boost::lexical_cast<unsigned int>(currentOption->getDefaultValue().c_str())) :
259 po::value < unsigned int >(),
260 currentOption->getDescription().c_str())
261 ;
262 break;
263 case TypeEnumContainer::ListOfUnsignedIntegersType:
264 OptionList->add_options()
265 (currentOption->getKeyAndShortForm().c_str(),
266// currentOption->hasDefaultValue() ?
267// po::value < std::vector<unsigned int> >()->default_value(boost::lexical_cast< std::vector<unsigned int> >(currentOption->getDefaultValue().c_str())) :
268 po::value < std::vector<unsigned int> >()->multitoken(),
269 currentOption->getDescription().c_str())
270 ;
271 break;
272 case TypeEnumContainer::DoubleType:
273 OptionList->add_options()
274 (currentOption->getKeyAndShortForm().c_str(),
275 currentOption->hasDefaultValue() ?
276 po::value < double >()->default_value(boost::lexical_cast<double>(currentOption->getDefaultValue().c_str())) :
277 po::value < double >(),
278 currentOption->getDescription().c_str())
279 ;
280 break;
281 case TypeEnumContainer::ListOfDoublesType:
282 OptionList->add_options()
283 (currentOption->getKeyAndShortForm().c_str(),
284// currentOption->hasDefaultValue() ?
285// po::value < std::vector<double> >()->default_value(boost::lexical_cast< std::vector<double> >(currentOption->getDefaultValue().c_str())) :
286 po::value < std::vector<double> >()->multitoken(),
287 currentOption->getDescription().c_str())
288 ;
289 break;
290 case TypeEnumContainer::StringType:
291 OptionList->add_options()
292 (currentOption->getKeyAndShortForm().c_str(),
293 currentOption->hasDefaultValue() ?
294 po::value < std::string >()->default_value(currentOption->getDefaultValue()) :
295 po::value < std::string >(),
296 currentOption->getDescription().c_str())
297 ;
298 break;
299 case TypeEnumContainer::ListOfStringsType:
300 OptionList->add_options()
301 (currentOption->getKeyAndShortForm().c_str(),
302// currentOption->hasDefaultValue() ?
303// po::value < std::vector<std::string> >()->default_value(boost::lexical_cast< std::vector<std::string> >(currentOption->getDefaultValue().c_str())) :
304 po::value < std::vector<std::string> >()->multitoken(),
305 currentOption->getDescription().c_str())
306 ;
307 break;
308 case TypeEnumContainer::VectorType:
309 OptionList->add_options()
310 (currentOption->getKeyAndShortForm().c_str(),
311// currentOption->hasDefaultValue() ?
312// po::value < VectorValue >()->default_value(boost::lexical_cast<VectorValue>(currentOption->getDefaultValue().c_str())) :
313 po::value < VectorValue >(),
314 currentOption->getDescription().c_str())
315 ;
316 break;
317 case TypeEnumContainer::ListOfVectorsType:
318 OptionList->add_options()
319 (currentOption->getKeyAndShortForm().c_str(),
320// currentOption->hasDefaultValue() ?
321// po::value < std::vector<VectorValue> >()->default_value(boost::lexical_cast< std::vector<VectorValue> >(currentOption->getDefaultValue().c_str())) :
322 po::value < std::vector<VectorValue> >()->multitoken(),
323 currentOption->getDescription().c_str())
324 ;
325 break;
326 case TypeEnumContainer::MoleculeType:
327 OptionList->add_options()
328 (currentOption->getKeyAndShortForm().c_str(),
329// currentOption->hasDefaultValue() ?
330// po::value < const molecule * >()->default_value(boost::lexical_cast<const molecule *>(currentOption->getDefaultValue().c_str())) :
331 po::value < int >(),
332 currentOption->getDescription().c_str())
333 ;
334 break;
335 case TypeEnumContainer::ListOfMoleculesType:
336 OptionList->add_options()
337 (currentOption->getKeyAndShortForm().c_str(),
338// currentOption->hasDefaultValue() ?
339// po::value < std::vector<const molecule *> >()->default_value(boost::lexical_cast< std::vector<const molecule *> >(currentOption->getDefaultValue().c_str())) :
340 po::value < std::vector<int> >()->multitoken(),
341 currentOption->getDescription().c_str())
342 ;
343 break;
344 case TypeEnumContainer::AtomType:
345 OptionList->add_options()
346 (currentOption->getKeyAndShortForm().c_str(),
347 currentOption->hasDefaultValue() ?
348 po::value < int >()->default_value(boost::lexical_cast<int>(currentOption->getDefaultValue().c_str())) :
349 po::value < int >(),
350 currentOption->getDescription().c_str())
351 ;
352 break;
353 case TypeEnumContainer::ListOfAtomsType:
354 OptionList->add_options()
355 (currentOption->getKeyAndShortForm().c_str(),
356// currentOption->hasDefaultValue() ?
357// po::value < std::vector<const atom *> >()->default_value(boost::lexical_cast< std::vector<const atom *> >(currentOption->getDefaultValue().c_str())) :
358 po::value < std::vector<int> >()->multitoken(),
359 currentOption->getDescription().c_str())
360 ;
361 break;
362 case TypeEnumContainer::ElementType:
363 OptionList->add_options()
364 (currentOption->getKeyAndShortForm().c_str(),
365// currentOption->hasDefaultValue() ?
366// po::value < const element * >()->default_value(boost::lexical_cast<const element *>(currentOption->getDefaultValue().c_str())) :
367 po::value < int >(),
368 currentOption->getDescription().c_str())
369 ;
370 break;
371 case TypeEnumContainer::ListOfElementsType:
372 OptionList->add_options()
373 (currentOption->getKeyAndShortForm().c_str(),
374// currentOption->hasDefaultValue() ?
375// po::value < std::vector<const element *> >()->default_value(boost::lexical_cast< std::vector<const element *> >(currentOption->getDefaultValue().c_str())) :
376 po::value < std::vector<int> >()->multitoken(),
377 currentOption->getDescription().c_str())
378 ;
379 break;
380 case TypeEnumContainer::RandomNumberDistribution_ParametersType:
381 OptionList->add_options()
382 (currentOption->getKeyAndShortForm().c_str(),
383 currentOption->hasDefaultValue() ?
384 po::value < std::string >()->default_value(boost::lexical_cast< std::string >(currentOption->getDefaultValue().c_str())) :
385 po::value < std::string >(),
386 currentOption->getDescription().c_str())
387 ;
388 break;
389 case TypeEnumContainer::RealSpaceMatrixType:
390 OptionList->add_options()
391 (currentOption->getKeyAndShortForm().c_str(),
392// currentOption->hasDefaultValue() ?
393// po::value < RealSpaceMatrixValue >()->default_value(boost::lexical_cast<BoxValue>(currentOption->getDefaultValue().c_str())) :
394 po::value < RealSpaceMatrixValue >(),
395 currentOption->getDescription().c_str())
396 ;
397 break;
398 }
399}
400
401/** States whether there are command line arguments.
402 * \return true - there are none, false - there is at least one command line argument
403 */
404bool CommandLineParser::isEmpty()
405{
406 return vm.empty();
407}
408
409/** Sets the options.
410 * \param _argc arg count from main()
411 * \param **_argv argument array from main()
412 */
413void CommandLineParser::setOptions(int _argc, char **_argv)
414{
415 argc = _argc;
416 argv = _argv;
417 config_file_options.add(options);
418 // append all option_descriptions to both cmdline_options and visible
419 for (CmdParserLookupMap::iterator iter = CmdParserLookup.begin();
420 iter != CmdParserLookup.end();
421 ++iter) {
422 cmdline_options.add(*(iter->second));
423 visible.add(*(iter->second));
424 }
425}
426
427/** Parses the command line arguments.
428 * Calls program_options::store() and program_options::notify()
429 */
430void CommandLineParser::Parse()
431{
432 po::store(po::command_line_parser(argc,argv).options(cmdline_options).run(), vm);
433 std::ifstream input;
434 input.open("example.cfg");
435 if (!input.fail())
436 po::store(po::parse_config_file(input, config_file_options), vm);
437 input.close();
438 po::notify(vm);
439}
440
441/** Scan the argument list for -a or --arguments and store their order for later use.
442 */
443void CommandLineParser::scanforSequenceOfArguments()
444{
445 std::map <std::string, std::string> ShortFormToActionMap = getShortFormToActionMap();
446 LOG(0, "Scanning command line arguments and recognizing Actions.");
447 // go through all arguments
448 for (int i=1;i<argc;i++) {
449 LOG(2, "Checking on " << argv[i]);
450 // check whether they
451 if (argv[i][0] == '-') { // .. begin with -
452 LOG(2, "Possible argument: " << argv[i]);
453 if (argv[i][1] == '-') { // .. or --
454 LOG(1, "Putting " << argv[i] << " into the sequence.");
455 SequenceOfActions.push_back(&(argv[i][2]));
456 // .. and check that next letter is not numeric, if so insert
457 } else if (((argv[i][1] < '0') || (argv[i][1] > '9')) && ((argv[i][1] != '.'))) {
458 std::map <std::string, std::string>::iterator iter = ShortFormToActionMap.find(&(argv[i][1]));
459 if (iter != ShortFormToActionMap.end()) {
460 LOG(1, "Putting " << iter->second << " for " << iter->first << " into the sequence.");
461 SequenceOfActions.push_back(iter->second);
462 }
463 }
464 }
465 }
466}
467
468/** Makes the Parser parse the command line options with current known options.
469 * \param _argc arg count from main()
470 * \param **_argv argument array from main()
471 */
472void CommandLineParser::Run(int _argc, char **_argv)
473{
474 setOptions(_argc,_argv);
475 Parse();
476 scanforSequenceOfArguments();
477}
478
479/** Go through all Actions and create a map from short form to their token.
480 * \return map from Action's ShortForm to token.
481 */
482std::map <std::string, std::string> CommandLineParser::getShortFormToActionMap() const
483{
484 std::map <std::string, std::string> result;
485
486 ActionQueue &AQ = ActionQueue::getInstance();
487 ActionQueue::ActionTokens_t tokens = AQ.getListOfActions();
488 for (ActionQueue::ActionTokens_t::const_iterator iter = tokens.begin();
489 iter != tokens.end(); ++iter) {
490 const ActionTrait &CurrentTrait = AQ.getActionsTrait(*iter);
491 if (CurrentTrait.hasShortForm()) {
492 ASSERT(result.find(CurrentTrait.getShortForm()) == result.end(),
493 "Short form "+toString(CurrentTrait.getShortForm())+
494 " for action "+toString(*iter)+" already present from "+
495 std::string(result[CurrentTrait.getShortForm()])+"!");
496 result[CurrentTrait.getShortForm()] = *iter;
497 }
498 }
499
500 return result;
501}
502
503CONSTRUCT_SINGLETON(CommandLineParser)
Note: See TracBrowser for help on using the repository browser.