1 // ANNA - Anna is Not Nothingness Anymore
3 // (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo
5 // http://redmine.teslayout.com/projects/anna-suite
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
11 // * Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
13 // * Redistributions in binary form must reproduce the above
14 // copyright notice, this list of conditions and the following disclaimer
15 // in the documentation and/or other materials provided with the
17 // * Neither the name of the copyright holder nor the names of its
18 // contributors may be used to endorse or promote products derived from
19 // this software without specific prior written permission.
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 // Authors: eduardo.ramos.testillano@gmail.com
34 // cisco.tierra@gmail.com
39 #include <anna/config/defines.hpp>
40 #include <anna/core/RuntimeException.hpp>
41 #include <anna/xml/xml.hpp>
43 #include <anna/core/util/CommandLine.hpp>
48 #ifndef TOKENINDICATOR
49 #define TOKENINDICATOR '-'
52 //--------------------------------------------------------------------------------
53 // Notifica al Parser que la opcion 'argumentName' es soportada
55 // (1) Verifica que la opcion no haya sido registrada previamente.
56 //--------------------------------------------------------------------------------
57 void CommandLine::add(const char* argumentName, Argument::Type type, const char* comment, const bool needValue)
59 Guard guard(a_mutex, "CommandLine::add");
61 if(search(argumentName) == NULL)
62 a_arguments.push_back(new Variable(argumentName, type, comment, needValue));
65 //--------------------------------------------------------------------------------
66 // Verifica que todos los argumentNameos declarados como obligatorios estan en la
68 //--------------------------------------------------------------------------------
69 void CommandLine::verify()
70 throw(RuntimeException) {
72 throw RuntimeException("CommandLine was not initialized", ANNA_FILE_LOCATION);
74 for(int i = 0, maxi = a_arguments.size(); i < maxi; i ++) {
75 if(a_arguments [i]->getType() == Argument::Mandatory)
76 getValue(a_arguments [i]->getName().c_str()); // JEDS 24/09/2003
80 //--------------------------------------------------------------------------------
81 // Obtiene el valor para opcion 'argumentName'.
83 // (1) Realiza el analisis de la linea de comandos.
84 // (2) Verifica que la opcion recibida existe en la lista de opciones registradas.
85 // (3) Si la opcion 'argumentName' existe en la linea de comandos ...
86 // (3.1) Si el argumentNameo debe ir seguido por un valor/valores y no existe
88 // (3.2) Si el argumentNameo no necesita valor, simplemente, le asigna una cadena
89 // que contiene 'true', en otro caso devolvera NULL.
91 // (4) Si no existe en la linea de comandos y es un argumentNameo obligatorio => error.
93 // Si el arguemento solicitado no esta en la LC y es opcional devolvera NULL.
94 //--------------------------------------------------------------------------------
95 const char* CommandLine::getValue(const char* argumentName, const bool exitOnFault)
97 const char* result = NULL;
98 const Variable* argument = NULL;
102 if((analized = analize()) == true) { // (1)
103 if((argument = search(argumentName)) != NULL) { // (2)
105 result = argument->getValue();
107 if(argument->getIsOn() == true) { // (3)
108 if(argument->getNeedValue() == true && result == NULL) // (3.1)
110 else if(argument->getNeedValue() == false) {
116 } else if(argument->getType() == Argument::Mandatory) // (4)
121 if(analized == false) {
124 } else if(error == true && exitOnFault == true) {
125 cout << "Variable: '" << argumentName << "' is not valid" << endl << endl;
133 //--------------------------------------------------------------------------------
134 // Analiza la linea de comandos para completar la informacion de los argumentNameos.
136 // (1) Comprueba que el analisis no se ha completado con existo previamente.
137 // (2) El primer argumentNameo despues del nombre del ejecutable debe comenzar por
138 // el caracter de indicador de argumentNameo.
139 // (3) Comprueba si el argumentNameo de la LC esta registrado como posible argumentNameo.
140 // (4) Recoge todo lo que haya entre el argumentNameo actual y el siguiente argumentNameo
141 // (si lo hay) y todo esto lo asigna como valor del argumentNameo actual.
142 // (5) Quita el ltimo car�ter
143 //--------------------------------------------------------------------------------
144 bool CommandLine::analize()
151 if(a_wasParsed == true)
154 Guard guard(a_mutex, "CommandLine::analize");
156 if(a_wasParsed == true)
159 while(i < a_argc && result == true) {
160 if(i == 1 && a_argv [1][0] != TOKENINDICATOR) { // (2)
165 if((argument = const_cast <Variable*>(search(a_argv [i]))) != NULL) { // (3)
167 argument->setIsOn(true);
168 // @Eduardo (allow dashes on values)
169 // while (++ i < a_argc && a_argv [i][0] != TOKENINDICATOR) { // (4)
170 // aux += a_argv [i];
173 bool notArgument = true;
175 while(notArgument && (++ i < a_argc)) { // (4)
176 if(a_argv [i][0] == TOKENINDICATOR)
177 notArgument = (search(a_argv[i]) == NULL);
185 if(aux.length() > 0) {
186 aux.erase(aux.length() - 1, 1); // 5)
187 argument->setValue(aux.c_str()); // JEDS 24/09/2003
190 cout << "Variable: " << a_argv [i] << " unreconized" << endl;
195 return (a_wasParsed = result);
198 const CommandLine::Variable* CommandLine::search(const char *argumentName) const
200 const Variable* result = NULL;
201 vector <Variable*>::const_iterator ii, maxii;
203 if(*argumentName == TOKENINDICATOR) argumentName ++;
205 for(ii = a_arguments.begin(), maxii = a_arguments.end(); ii != maxii; ii ++) {
206 if(anna_strcmp((*ii)->getName().c_str(), argumentName) == 0) {
215 void CommandLine::printUsage() const
217 int i, maxi(a_arguments.size());
218 cout << "Use: " << a_argv [0] << " ";
220 for(i = 0; i < maxi; i ++)
221 cout << a_arguments [i]->asString() << " ";
223 cout << endl << "Where: " << endl;
225 for(i = 0; i < maxi; i ++) {
226 cout << " " << a_arguments [i]->getName() << ": " << endl;
227 cout << " " << a_arguments [i]->getComment() << endl;
231 string CommandLine::Variable::asString() const
234 result = ((a_type == Argument::Optional) ? "[ " : "");
235 result += TOKENINDICATOR;
238 if(a_needValue == true) {
239 result += " <value_";
244 if(a_type == Argument::Optional)
251 string CommandLine::asString() const
253 string result = "Provided command-line parameters:\n\n";
254 vector <Variable*>::const_iterator ii, maxii;
257 for(ii = a_arguments.begin(), maxii = a_arguments.end(); ii != maxii; ii ++) {
258 value = (*ii)->getValue();
261 result += (*ii)->getName();
271 xml::Node* CommandLine::asXML(xml::Node* parent) const throw() {
272 xml::Node* result = parent->createChild("CommandLine");
273 vector <Variable*>::const_iterator ii, maxii;
276 for(ii = a_arguments.begin(), maxii = a_arguments.end(); ii != maxii; ii ++) {
277 value = (*ii)->getValue();
280 result->createAttribute((*ii)->getName().c_str(), value);