1 /* Frobby: Software for monomial ideal computations.
2    Copyright (C) 2009 University of Aarhus
3    Contact Bjarke Hammersholt Roune for license information (www.broune.com)
4 
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9 
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14 
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see http://www.gnu.org/licenses/.
17 */
18 #include "stdinc.h"
19 #include "CliParams.h"
20 
21 #include "error.h"
22 #include "ParameterGroup.h"
23 #include "IntegerParameter.h"
24 #include "BoolParameter.h"
25 #include "StringParameter.h"
26 #include "NameFactory.h"
27 
28 namespace {
29   typedef void* Dummy;
30   typedef NameFactory<Dummy> ParamNames;
31 
getParamNames(vector<Parameter * > params)32   ParamNames getParamNames(vector<Parameter*> params) {
33     struct HoldsFunction {
34       static auto_ptr<Dummy> dummyCreate() {
35         return auto_ptr<Dummy>(0);
36       }
37     };
38 
39     ParamNames names("option");
40     for (size_t i = 0; i < params.size(); ++i)
41       names.registerProduct(params[i]->getName(), HoldsFunction::dummyCreate);
42     return names;
43   }
44 }
45 
CliParams()46 CliParams::CliParams():
47   _paramsDeleter(_ownedParams) {
48 }
49 
parseCommandLine(unsigned int tokenCount,const char ** tokens)50 void CliParams::parseCommandLine(unsigned int tokenCount, const char** tokens) {
51   ParamNames names = getParamNames(_params);
52 
53   unsigned int i = 0;
54   while (i < tokenCount) {
55     if (tokens[i][0] != '-')
56       reportError(string("Expected an option when reading \"") +
57                   tokens[i] + "\", but options start with a dash (-).\n");
58     string prefix(tokens[i] + 1); // +1 to skip the '-'
59 
60     string name = getUniqueNameWithPrefix(names, prefix);
61 
62     // Parse list of arguments to option.
63     size_t argCount = 0;
64     while (i + 1 + argCount < tokenCount &&
65            tokens[i + 1 + argCount][0] != '-')
66       ++argCount;
67 
68     processOption(name, tokens + i + 1, argCount);
69 
70     i += argCount + 1;
71   }
72 }
73 
processOption(const string & optionName,const char ** args,unsigned int argCount)74 void CliParams::processOption(const string& optionName,
75                               const char** args,
76                               unsigned int argCount) {
77   for (vector<Parameter*>::iterator it = _params.begin();
78     it != _params.end(); ++it) {
79     if ((*it)->getName() == optionName) {
80       (*it)->processArguments(args, argCount);
81       return;
82     }
83   }
84 
85   reportInternalError("Processing non-existent option \"" + optionName + "\".");
86 }
87 
add(auto_ptr<Parameter> param)88 void CliParams::add(auto_ptr<Parameter> param) {
89   ASSERT(!hasParam(param->getName()));
90   Parameter& paramRef = *param;
91   exceptionSafePushBack(_ownedParams, param);
92   add(paramRef);
93 }
94 
add(Parameter & param)95 void CliParams::add(Parameter& param) {
96   ASSERT(!hasParam(param.getName()));
97   _params.push_back(&param);
98 }
99 
add(ParameterGroup & params)100 void CliParams::add(ParameterGroup& params) {
101   for (ParameterGroup::iterator it = params.begin(); it != params.end(); ++it)
102     add(**it);
103 }
104 
hasParam(const string & name) const105 bool CliParams::hasParam(const string& name) const {
106   for (const_iterator it = _params.begin(); it != _params.end(); ++it)
107     if ((*it)->getName() == name)
108       return true;
109   return false;
110 }
111 
getParam(const string & name) const112 const Parameter& CliParams::getParam(const string& name) const {
113   return const_cast<CliParams*>(this)->getParam(name);
114 }
115 
getParam(const string & name)116 Parameter& CliParams::getParam(const string& name) {
117   for (const_iterator it = _params.begin(); it != _params.end(); ++it)
118     if ((*it)->getName() == name)
119       return **it;
120 
121   INTERNAL_ERROR("Unknown parameter " + name + ".");
122 }
123 
getBool(const CliParams & params,const string & name)124 bool getBool(const CliParams& params, const string& name) {
125   const Parameter& param = params.getParam(name);
126   ASSERT(dynamic_cast<const BoolParameter*>(&param) != 0);
127   return static_cast<const BoolParameter&>(param);
128 }
129 
getString(const CliParams & params,const string & name)130 const string& getString(const CliParams& params, const string& name) {
131   const Parameter& param = params.getParam(name);
132   ASSERT(dynamic_cast<const StringParameter*>(&param) != 0);
133   return static_cast<const StringParameter&>(param);
134 }
135 
getInt(const CliParams & params,const string & name)136 unsigned int getInt(const CliParams& params, const string& name) {
137   const Parameter& param = params.getParam(name);
138   ASSERT(dynamic_cast<const IntegerParameter*>(&param) != 0);
139   return static_cast<const IntegerParameter&>(param);
140 }
141 
setBool(CliParams & params,const string & name,bool newValue)142 void setBool(CliParams& params, const string& name, bool newValue) {
143   Parameter& param = params.getParam(name);
144   ASSERT(dynamic_cast<BoolParameter*>(&param) != 0);
145   static_cast<BoolParameter&>(param) = newValue;
146 }
147