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

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 628577 was 628577, checked in by Frederik Heber <heber@…>, 11 years ago

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