ENH: Add support for multi-arguments: -f arg1 arg2 arg3 ... and support for lists: -f arg1 -f arg2 -f arg3 ... and for boolean to be stored as strings and doubles

This commit is contained in:
Andy Cedilnik 2006-07-14 09:13:23 -04:00
parent fc49142fc6
commit d2a3ccd505
5 changed files with 463 additions and 173 deletions

View File

@ -819,6 +819,24 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
ENDIF(NOT CYGWIN) ENDIF(NOT CYGWIN)
ADD_TEST(kwsys.testHashSTL ${EXEC_DIR}/testHashSTL) ADD_TEST(kwsys.testHashSTL ${EXEC_DIR}/testHashSTL)
ADD_TEST(kwsys.testRegistry ${EXEC_DIR}/testRegistry) ADD_TEST(kwsys.testRegistry ${EXEC_DIR}/testRegistry)
ADD_TEST(kwsys.testCommandLineArguments ${EXEC_DIR}/testCommandLineArguments
--another-bool-variable
--long3=opt
--set-bool-arg1
-SSS ken brad bill andy
--some-bool-variable=true
--some-double-variable12.5
--some-int-variable 14
"--some-string-variable=test string with space"
--some-multi-argument 5 1 8 3 7 1 3 9 7 1
-N 12.5 -SS=andy -N 1.31 -N 22
-SS=bill -BBtrue -SS=brad
-BBtrue
-BBfalse
-SS=ken
-A
-C=test
--long2 hello)
IF(COMMAND SET_TESTS_PROPERTIES AND COMMAND GET_TEST_PROPERTY AND KWSYS_STANDALONE) IF(COMMAND SET_TESTS_PROPERTIES AND COMMAND GET_TEST_PROPERTY AND KWSYS_STANDALONE)
ADD_TEST(kwsys.testFail ${EXEC_DIR}/testFail) ADD_TEST(kwsys.testFail ${EXEC_DIR}/testFail)
# We expect test to fail # We expect test to fail

View File

@ -15,6 +15,7 @@
#include KWSYS_HEADER(CommandLineArguments.hxx) #include KWSYS_HEADER(CommandLineArguments.hxx)
#include KWSYS_HEADER(Configure.hxx) #include KWSYS_HEADER(Configure.hxx)
#include KWSYS_HEADER(String.hxx)
#include KWSYS_HEADER(stl/vector) #include KWSYS_HEADER(stl/vector)
#include KWSYS_HEADER(stl/map) #include KWSYS_HEADER(stl/map)
@ -44,22 +45,18 @@
# pragma set woff 1375 /* base class destructor not virtual */ # pragma set woff 1375 /* base class destructor not virtual */
#endif #endif
#if 0
# define CommandLineArguments_DEBUG(x) \
kwsys_ios::cout << __LINE__ << " CLA: " << x << kwsys_ios::endl
#else
# define CommandLineArguments_DEBUG(x)
#endif
namespace KWSYS_NAMESPACE namespace KWSYS_NAMESPACE
{ {
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
//============================================================================ //============================================================================
class CommandLineArgumentsString : public kwsys_stl::string
{
public:
typedef kwsys_stl::string StdString;
CommandLineArgumentsString(): StdString() {}
CommandLineArgumentsString(const value_type* s): StdString(s) {}
CommandLineArgumentsString(const value_type* s, size_type n): StdString(s, n) {}
CommandLineArgumentsString(const StdString& s, size_type pos=0, size_type n=npos):
StdString(s, pos, n) {}
};
struct CommandLineArgumentsCallbackStructure struct CommandLineArgumentsCallbackStructure
{ {
const char* Argument; const char* Argument;
@ -72,11 +69,11 @@ struct CommandLineArgumentsCallbackStructure
}; };
class CommandLineArgumentsVectorOfStrings : class CommandLineArgumentsVectorOfStrings :
public kwsys_stl::vector<CommandLineArgumentsString> {}; public kwsys_stl::vector<kwsys::String> {};
class CommandLineArgumentsSetOfStrings : class CommandLineArgumentsSetOfStrings :
public kwsys_stl::set<CommandLineArgumentsString> {}; public kwsys_stl::set<kwsys::String> {};
class CommandLineArgumentsMapOfStrucs : class CommandLineArgumentsMapOfStrucs :
public kwsys_stl::map<CommandLineArgumentsString, public kwsys_stl::map<kwsys::String,
CommandLineArgumentsCallbackStructure> {}; CommandLineArgumentsCallbackStructure> {};
class CommandLineArgumentsInternal class CommandLineArgumentsInternal
@ -91,7 +88,7 @@ public:
typedef CommandLineArgumentsVectorOfStrings VectorOfStrings; typedef CommandLineArgumentsVectorOfStrings VectorOfStrings;
typedef CommandLineArgumentsMapOfStrucs CallbacksMap; typedef CommandLineArgumentsMapOfStrucs CallbacksMap;
typedef CommandLineArgumentsString String; typedef kwsys::String String;
typedef CommandLineArgumentsSetOfStrings SetOfStrings; typedef CommandLineArgumentsSetOfStrings SetOfStrings;
VectorOfStrings Argv; VectorOfStrings Argv;
@ -153,38 +150,47 @@ void CommandLineArguments::ProcessArgument(const char* arg)
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
int CommandLineArguments::Parse() bool CommandLineArguments::GetMatchedArguments(
kwsys_stl::vector<kwsys_stl::string>* matches,
const kwsys_stl::string& arg)
{ {
CommandLineArguments::Internal::VectorOfStrings::size_type cc; matches->clear();
CommandLineArguments::Internal::VectorOfStrings matches; CommandLineArguments::Internal::CallbacksMap::iterator it;
for ( cc = 0; cc < this->Internals->Argv.size(); cc ++ )
{
this->Internals->LastArgument = cc;
matches.clear();
CommandLineArguments::Internal::String& arg = this->Internals->Argv[cc];
CommandLineArguments::Internal::CallbacksMap::iterator it;
// Does the argument match to any we know about? // Does the argument match to any we know about?
for ( it = this->Internals->Callbacks.begin(); for ( it = this->Internals->Callbacks.begin();
it != this->Internals->Callbacks.end(); it != this->Internals->Callbacks.end();
it ++ ) it ++ )
{
const CommandLineArguments::Internal::String& parg = it->first;
CommandLineArgumentsCallbackStructure *cs = &it->second;
if (cs->ArgumentType == CommandLineArguments::NO_ARGUMENT ||
cs->ArgumentType == CommandLineArguments::SPACE_ARGUMENT)
{ {
const CommandLineArguments::Internal::String& parg = it->first; if ( arg == parg )
CommandLineArgumentsCallbackStructure *cs = &it->second;
if (cs->ArgumentType == CommandLineArguments::NO_ARGUMENT ||
cs->ArgumentType == CommandLineArguments::SPACE_ARGUMENT)
{ {
if ( arg == parg ) matches->push_back(parg);
{
matches.push_back(parg);
}
}
else if ( arg.find( parg ) == 0 )
{
matches.push_back(parg);
} }
} }
if ( matches.size() > 0 ) else if ( arg.find( parg ) == 0 )
{
matches->push_back(parg);
}
}
return matches->size() > 0;
}
//----------------------------------------------------------------------------
int CommandLineArguments::Parse()
{
kwsys_stl::vector<kwsys_stl::string>::size_type cc;
kwsys_stl::vector<kwsys_stl::string> matches;
for ( cc = 0; cc < this->Internals->Argv.size(); cc ++ )
{
const kwsys_stl::string& arg = this->Internals->Argv[cc];
CommandLineArguments_DEBUG("Process argument: " << arg);
this->Internals->LastArgument = cc;
if ( this->GetMatchedArguments(&matches, arg) )
{ {
// Ok, we found one or more arguments that match what user specified. // Ok, we found one or more arguments that match what user specified.
// Let's find the longest one. // Let's find the longest one.
@ -201,112 +207,84 @@ int CommandLineArguments::Parse()
} }
// So, the longest one is probably the right one. Now see if it has any // So, the longest one is probably the right one. Now see if it has any
// additional value // additional value
const char* value = 0;
CommandLineArgumentsCallbackStructure *cs CommandLineArgumentsCallbackStructure *cs
= &this->Internals->Callbacks[matches[maxidx]]; = &this->Internals->Callbacks[matches[maxidx]];
const CommandLineArguments::Internal::String& sarg = matches[maxidx]; const CommandLineArguments::Internal::String& sarg = matches[maxidx];
if ( cs->ArgumentType == NO_ARGUMENT ) if ( cs->Argument != sarg )
{ {
// No value abort();
} }
else if ( cs->ArgumentType == SPACE_ARGUMENT ) switch ( cs->ArgumentType )
{ {
case NO_ARGUMENT:
// No value
if ( !this->PopulateVariable(cs, 0) )
{
return 0;
}
break;
case SPACE_ARGUMENT:
if ( cc == this->Internals->Argv.size()-1 ) if ( cc == this->Internals->Argv.size()-1 )
{ {
this->Internals->LastArgument --; this->Internals->LastArgument --;
return 0; return 0;
} }
CommandLineArguments_DEBUG("This is a space argument: " << arg
<< " value: " << this->Internals->Argv[cc+1].c_str());
// Value is the next argument // Value is the next argument
value = this->Internals->Argv[cc+1].c_str(); if ( !this->PopulateVariable(cs, this->Internals->Argv[cc+1].c_str()) )
{
return 0;
}
cc ++; cc ++;
} break;
else if ( cs->ArgumentType == EQUAL_ARGUMENT ) case EQUAL_ARGUMENT:
{
if ( arg.size() == sarg.size() || *(arg.c_str() + sarg.size()) != '=' ) if ( arg.size() == sarg.size() || *(arg.c_str() + sarg.size()) != '=' )
{ {
this->Internals->LastArgument --; this->Internals->LastArgument --;
return 0; return 0;
} }
// Value is everythng followed the '=' sign // Value is everythng followed the '=' sign
value = arg.c_str() + sarg.size()+1; if ( !this->PopulateVariable(cs, arg.c_str() + sarg.size() + 1) )
} {
else if ( cs->ArgumentType == CONCAT_ARGUMENT ) return 0;
{ }
break;
case CONCAT_ARGUMENT:
// Value is whatever follows the argument // Value is whatever follows the argument
value = arg.c_str() + sarg.size(); if ( !this->PopulateVariable(cs, arg.c_str() + sarg.size()) )
}
// Call the callback
if ( cs->Callback )
{
if ( !cs->Callback(sarg.c_str(), value, cs->CallData) )
{ {
this->Internals->LastArgument --;
return 0; return 0;
} }
} break;
if ( cs->Variable ) case MULTI_ARGUMENT:
{ // Suck in all the rest of the arguments
kwsys_stl::string var = "1"; CommandLineArguments_DEBUG("This is a multi argument: " << arg);
if ( value ) for (cc++; cc < this->Internals->Argv.size(); ++ cc )
{ {
var = value; const kwsys_stl::string& marg = this->Internals->Argv[cc];
} CommandLineArguments_DEBUG(" check multi argument value: " << marg);
if ( cs->VariableType == CommandLineArguments::INT_TYPE ) if ( this->GetMatchedArguments(&matches, marg) )
{
int* variable = static_cast<int*>(cs->Variable);
char* res = 0;
*variable = strtol(var.c_str(), &res, 10);
//if ( res && *res )
// {
// Can handle non-int
// }
}
else if ( cs->VariableType == CommandLineArguments::DOUBLE_TYPE )
{
double* variable = static_cast<double*>(cs->Variable);
char* res = 0;
*variable = strtod(var.c_str(), &res);
//if ( res && *res )
// {
// Can handle non-int
// }
}
else if ( cs->VariableType == CommandLineArguments::STRING_TYPE )
{
char** variable = static_cast<char**>(cs->Variable);
if ( *variable )
{ {
delete [] *variable; CommandLineArguments_DEBUG("End of multi argument " << arg << " with value: " << marg);
*variable = 0; break;
} }
*variable = new char[ strlen(var.c_str()) + 1 ]; CommandLineArguments_DEBUG(" populate multi argument value: " << marg);
strcpy(*variable, var.c_str()); if ( !this->PopulateVariable(cs, marg.c_str()) )
}
else if ( cs->VariableType == CommandLineArguments::STL_STRING_TYPE )
{
kwsys_stl::string* variable = static_cast<kwsys_stl::string*>(cs->Variable);
*variable = var;
}
else if ( cs->VariableType == CommandLineArguments::BOOL_TYPE )
{
bool* variable = static_cast<bool*>(cs->Variable);
if ( var == "1" || var == "ON" || var == "TRUE" || var == "true" || var == "on" ||
var == "True" || var == "yes" || var == "Yes" || var == "YES" )
{ {
*variable = true; return 0;
}
else
{
*variable = false;
} }
} }
else if ( cc != this->Internals->Argv.size() )
{ {
kwsys_ios::cerr << "Got unknown argument type: \"" << cs->VariableType << "\"" << kwsys_ios::endl; CommandLineArguments_DEBUG("Again End of multi argument " << arg);
this->Internals->LastArgument --; cc--;
return 0; continue;
} }
default:
kwsys_ios::cerr << "Got unknown argument type: \"" << cs->ArgumentType << "\"" << kwsys_ios::endl;
this->Internals->LastArgument --;
return 0;
} }
} }
else else
@ -404,55 +382,45 @@ void CommandLineArguments::AddArgument(const char* argument, ArgumentTypeEnum ty
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void CommandLineArguments::AddArgument(const char* argument, ArgumentTypeEnum type, #define CommandLineArgumentsAddArgumentMacro(type, ctype) \
int* variable, const char* help) void CommandLineArguments::AddArgument(const char* argument, ArgumentTypeEnum type, \
{ ctype* variable, const char* help) \
this->AddArgument(argument, type, CommandLineArguments::INT_TYPE, variable, help); { \
} this->AddArgument(argument, type, CommandLineArguments::type##_TYPE, variable, help); \
}
CommandLineArgumentsAddArgumentMacro(BOOL, bool);
CommandLineArgumentsAddArgumentMacro(INT, int);
CommandLineArgumentsAddArgumentMacro(DOUBLE, double);
CommandLineArgumentsAddArgumentMacro(STRING, char*);
CommandLineArgumentsAddArgumentMacro(STL_STRING, kwsys_stl::string);
CommandLineArgumentsAddArgumentMacro(VECTOR_BOOL, kwsys_stl::vector<bool>);
CommandLineArgumentsAddArgumentMacro(VECTOR_INT, kwsys_stl::vector<int>);
CommandLineArgumentsAddArgumentMacro(VECTOR_DOUBLE, kwsys_stl::vector<double>);
CommandLineArgumentsAddArgumentMacro(VECTOR_STRING, kwsys_stl::vector<char*>);
CommandLineArgumentsAddArgumentMacro(VECTOR_STL_STRING, kwsys_stl::vector<kwsys_stl::string>);
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void CommandLineArguments::AddArgument(const char* argument, ArgumentTypeEnum type, #define CommandLineArgumentsAddBooleanArgumentMacro(type, ctype) \
double* variable, const char* help) void CommandLineArguments::AddBooleanArgument(const char* argument, \
{ ctype* variable, const char* help) \
this->AddArgument(argument, type, CommandLineArguments::DOUBLE_TYPE, variable, help); { \
} this->AddArgument(argument, CommandLineArguments::NO_ARGUMENT, \
CommandLineArguments::type##_TYPE, variable, help); \
}
//---------------------------------------------------------------------------- CommandLineArgumentsAddBooleanArgumentMacro(BOOL, bool);
void CommandLineArguments::AddArgument(const char* argument, ArgumentTypeEnum type, CommandLineArgumentsAddBooleanArgumentMacro(INT, int);
char** variable, const char* help) CommandLineArgumentsAddBooleanArgumentMacro(DOUBLE, double);
{ CommandLineArgumentsAddBooleanArgumentMacro(STRING, char*);
this->AddArgument(argument, type, CommandLineArguments::STRING_TYPE, variable, help); CommandLineArgumentsAddBooleanArgumentMacro(STL_STRING, kwsys_stl::string);
}
//---------------------------------------------------------------------------- CommandLineArgumentsAddBooleanArgumentMacro(VECTOR_BOOL, kwsys_stl::vector<bool>);
void CommandLineArguments::AddArgument(const char* argument, ArgumentTypeEnum type, CommandLineArgumentsAddBooleanArgumentMacro(VECTOR_INT, kwsys_stl::vector<int>);
kwsys_stl::string* variable, const char* help) CommandLineArgumentsAddBooleanArgumentMacro(VECTOR_DOUBLE, kwsys_stl::vector<double>);
{ CommandLineArgumentsAddBooleanArgumentMacro(VECTOR_STRING, kwsys_stl::vector<char*>);
this->AddArgument(argument, type, CommandLineArguments::STL_STRING_TYPE, variable, help); CommandLineArgumentsAddBooleanArgumentMacro(VECTOR_STL_STRING, kwsys_stl::vector<kwsys_stl::string>);
}
//----------------------------------------------------------------------------
void CommandLineArguments::AddArgument(const char* argument, ArgumentTypeEnum type,
bool* variable, const char* help)
{
this->AddArgument(argument, type, CommandLineArguments::BOOL_TYPE, variable, help);
}
//----------------------------------------------------------------------------
void CommandLineArguments::AddBooleanArgument(const char* argument, bool*
variable, const char* help)
{
this->AddArgument(argument, CommandLineArguments::NO_ARGUMENT,
CommandLineArguments::BOOL_TYPE, variable, help);
}
//----------------------------------------------------------------------------
void CommandLineArguments::AddBooleanArgument(const char* argument, int*
variable, const char* help)
{
this->AddArgument(argument, CommandLineArguments::NO_ARGUMENT,
CommandLineArguments::INT_TYPE, variable, help);
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void CommandLineArguments::SetClientData(void* client_data) void CommandLineArguments::SetClientData(void* client_data)
@ -614,6 +582,7 @@ void CommandLineArguments::GenerateHelp()
case CommandLineArguments::CONCAT_ARGUMENT: strcat(argument, "opt"); break; case CommandLineArguments::CONCAT_ARGUMENT: strcat(argument, "opt"); break;
case CommandLineArguments::SPACE_ARGUMENT: strcat(argument, " opt"); break; case CommandLineArguments::SPACE_ARGUMENT: strcat(argument, " opt"); break;
case CommandLineArguments::EQUAL_ARGUMENT: strcat(argument, "=opt"); break; case CommandLineArguments::EQUAL_ARGUMENT: strcat(argument, "=opt"); break;
case CommandLineArguments::MULTI_ARGUMENT: strcat(argument, " opt opt ..."); break;
} }
char buffer[80]; char buffer[80];
sprintf(buffer, format, argument); sprintf(buffer, format, argument);
@ -678,4 +647,181 @@ void CommandLineArguments::GenerateHelp()
this->Help = str.str(); this->Help = str.str();
} }
//----------------------------------------------------------------------------
void CommandLineArguments::PopulateVariable(
bool* variable, const kwsys_stl::string& value)
{
if ( value == "1" || value == "ON" || value == "on" || value == "On" ||
value == "TRUE" || value == "true" || value == "True" ||
value == "yes" || value == "Yes" || value == "YES" )
{
*variable = true;
}
else
{
*variable = false;
}
}
//----------------------------------------------------------------------------
void CommandLineArguments::PopulateVariable(
int* variable, const kwsys_stl::string& value)
{
char* res = 0;
*variable = strtol(value.c_str(), &res, 10);
//if ( res && *res )
// {
// Can handle non-int
// }
}
//----------------------------------------------------------------------------
void CommandLineArguments::PopulateVariable(
double* variable, const kwsys_stl::string& value)
{
char* res = 0;
*variable = strtod(value.c_str(), &res);
//if ( res && *res )
// {
// Can handle non-double
// }
}
//----------------------------------------------------------------------------
void CommandLineArguments::PopulateVariable(
char** variable, const kwsys_stl::string& value)
{
if ( *variable )
{
delete [] *variable;
*variable = 0;
}
*variable = new char[ value.size() + 1 ];
strcpy(*variable, value.c_str());
}
//----------------------------------------------------------------------------
void CommandLineArguments::PopulateVariable(
kwsys_stl::string* variable, const kwsys_stl::string& value)
{
*variable = value;
}
//----------------------------------------------------------------------------
void CommandLineArguments::PopulateVariable(
kwsys_stl::vector<bool>* variable, const kwsys_stl::string& value)
{
bool val = false;
if ( value == "1" || value == "ON" || value == "on" || value == "On" ||
value == "TRUE" || value == "true" || value == "True" ||
value == "yes" || value == "Yes" || value == "YES" )
{
val = true;
}
variable->push_back(val);
}
//----------------------------------------------------------------------------
void CommandLineArguments::PopulateVariable(
kwsys_stl::vector<int>* variable, const kwsys_stl::string& value)
{
char* res = 0;
variable->push_back(strtol(value.c_str(), &res, 10));
//if ( res && *res )
// {
// Can handle non-int
// }
}
//----------------------------------------------------------------------------
void CommandLineArguments::PopulateVariable(
kwsys_stl::vector<double>* variable, const kwsys_stl::string& value)
{
char* res = 0;
variable->push_back(strtod(value.c_str(), &res));
//if ( res && *res )
// {
// Can handle non-int
// }
}
//----------------------------------------------------------------------------
void CommandLineArguments::PopulateVariable(
kwsys_stl::vector<char*>* variable, const kwsys_stl::string& value)
{
char* var = new char[ value.size() + 1 ];
strcpy(var, value.c_str());
variable->push_back(var);
}
//----------------------------------------------------------------------------
void CommandLineArguments::PopulateVariable(
kwsys_stl::vector<kwsys_stl::string>* variable,
const kwsys_stl::string& value)
{
variable->push_back(value);
}
//----------------------------------------------------------------------------
bool CommandLineArguments::PopulateVariable(CommandLineArgumentsCallbackStructure* cs,
const char* value)
{
// Call the callback
if ( cs->Callback )
{
if ( !cs->Callback(cs->Argument, value, cs->CallData) )
{
this->Internals->LastArgument --;
return 0;
}
}
if ( cs->Variable )
{
kwsys_stl::string var = "1";
if ( value )
{
var = value;
}
switch ( cs->VariableType )
{
case CommandLineArguments::INT_TYPE:
this->PopulateVariable(static_cast<int*>(cs->Variable), var);
break;
case CommandLineArguments::DOUBLE_TYPE:
this->PopulateVariable(static_cast<double*>(cs->Variable), var);
break;
case CommandLineArguments::STRING_TYPE:
this->PopulateVariable(static_cast<char**>(cs->Variable), var);
break;
case CommandLineArguments::STL_STRING_TYPE:
this->PopulateVariable(static_cast<kwsys_stl::string*>(cs->Variable), var);
break;
case CommandLineArguments::BOOL_TYPE:
this->PopulateVariable(static_cast<bool*>(cs->Variable), var);
break;
case CommandLineArguments::VECTOR_BOOL_TYPE:
this->PopulateVariable(static_cast<kwsys_stl::vector<bool>*>(cs->Variable), var);
break;
case CommandLineArguments::VECTOR_INT_TYPE:
this->PopulateVariable(static_cast<kwsys_stl::vector<int>*>(cs->Variable), var);
break;
case CommandLineArguments::VECTOR_DOUBLE_TYPE:
this->PopulateVariable(static_cast<kwsys_stl::vector<double>*>(cs->Variable), var);
break;
case CommandLineArguments::VECTOR_STRING_TYPE:
this->PopulateVariable(static_cast<kwsys_stl::vector<char*>*>(cs->Variable), var);
break;
case CommandLineArguments::VECTOR_STL_STRING_TYPE:
this->PopulateVariable(static_cast<kwsys_stl::vector<kwsys_stl::string>*>(cs->Variable), var);
break;
default:
kwsys_ios::cerr << "Got unknown variable type: \"" << cs->VariableType << "\"" << kwsys_ios::endl;
this->Internals->LastArgument --;
return 0;
}
}
return 1;
}
} // namespace KWSYS_NAMESPACE } // namespace KWSYS_NAMESPACE

View File

@ -18,6 +18,7 @@
#include <@KWSYS_NAMESPACE@/Configure.hxx> #include <@KWSYS_NAMESPACE@/Configure.hxx>
#include <@KWSYS_NAMESPACE@/stl/string> #include <@KWSYS_NAMESPACE@/stl/string>
#include <@KWSYS_NAMESPACE@/stl/vector>
/* Define this macro temporarily to keep the code readable. */ /* Define this macro temporarily to keep the code readable. */
#if !defined (KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS #if !defined (KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
@ -28,6 +29,7 @@ namespace @KWSYS_NAMESPACE@
{ {
class CommandLineArgumentsInternal; class CommandLineArgumentsInternal;
class CommandLineArgumentsCallbackStructure;
/** \class CommandLineArguments /** \class CommandLineArguments
* \brief Command line arguments processing code. * \brief Command line arguments processing code.
@ -53,6 +55,7 @@ class CommandLineArgumentsInternal;
* CONCAT_ARGUMENT - The argument takes value after no space : --Aval * CONCAT_ARGUMENT - The argument takes value after no space : --Aval
* SPACE_ARGUMENT - The argument takes value after space : --A val * SPACE_ARGUMENT - The argument takes value after space : --A val
* EQUAL_ARGUMENT - The argument takes value after equal : --A=val * EQUAL_ARGUMENT - The argument takes value after equal : --A=val
* MULTI_ARGUMENT - The argument takes values after space : --A val1 val2 val3 ...
* *
* Example use: * Example use:
* *
@ -82,7 +85,8 @@ public:
NO_ARGUMENT, NO_ARGUMENT,
CONCAT_ARGUMENT, CONCAT_ARGUMENT,
SPACE_ARGUMENT, SPACE_ARGUMENT,
EQUAL_ARGUMENT EQUAL_ARGUMENT,
MULTI_ARGUMENT
}; };
/** /**
@ -95,7 +99,13 @@ public:
BOOL_TYPE, // The vairable is boolean (bool) BOOL_TYPE, // The vairable is boolean (bool)
DOUBLE_TYPE, // The variable is float (double) DOUBLE_TYPE, // The variable is float (double)
STRING_TYPE, // The variable is string (char*) STRING_TYPE, // The variable is string (char*)
STL_STRING_TYPE // The variable is string (char*) STL_STRING_TYPE, // The variable is string (char*)
VECTOR_INT_TYPE, // The variable is integer (int)
VECTOR_BOOL_TYPE, // The vairable is boolean (bool)
VECTOR_DOUBLE_TYPE, // The variable is float (double)
VECTOR_STRING_TYPE, // The variable is string (char*)
VECTOR_STL_STRING_TYPE, // The variable is string (char*)
LAST_VARIABLE_TYPE
}; };
/** /**
@ -138,10 +148,10 @@ public:
* specified value. If the argument is specified, the option is casted to the * specified value. If the argument is specified, the option is casted to the
* apropriate type. * apropriate type.
*/ */
void AddArgument(const char* argument, ArgumentTypeEnum type, bool* variable, void AddArgument(const char* argument, ArgumentTypeEnum type,
const char* help); bool* variable, const char* help);
void AddArgument(const char* argument, ArgumentTypeEnum type, int* variable, void AddArgument(const char* argument, ArgumentTypeEnum type,
const char* help); int* variable, const char* help);
void AddArgument(const char* argument, ArgumentTypeEnum type, void AddArgument(const char* argument, ArgumentTypeEnum type,
double* variable, const char* help); double* variable, const char* help);
void AddArgument(const char* argument, ArgumentTypeEnum type, void AddArgument(const char* argument, ArgumentTypeEnum type,
@ -149,15 +159,53 @@ public:
void AddArgument(const char* argument, ArgumentTypeEnum type, void AddArgument(const char* argument, ArgumentTypeEnum type,
kwsys_stl::string* variable, const char* help); kwsys_stl::string* variable, const char* help);
/**
* Add handler for argument which is going to set the variable to the
* specified value. If the argument is specified, the option is casted to the
* apropriate type. This will handle the multi argument values.
*/
void AddArgument(const char* argument, ArgumentTypeEnum type,
kwsys_stl::vector<bool>* variable, const char* help);
void AddArgument(const char* argument, ArgumentTypeEnum type,
kwsys_stl::vector<int>* variable, const char* help);
void AddArgument(const char* argument, ArgumentTypeEnum type,
kwsys_stl::vector<double>* variable, const char* help);
void AddArgument(const char* argument, ArgumentTypeEnum type,
kwsys_stl::vector<char*>* variable, const char* help);
void AddArgument(const char* argument, ArgumentTypeEnum type,
kwsys_stl::vector<kwsys_stl::string>* variable, const char* help);
/** /**
* Add handler for boolean argument. The argument does not take any option * Add handler for boolean argument. The argument does not take any option
* and if it is specified, the value of the variable is true/1, otherwise it * and if it is specified, the value of the variable is true/1, otherwise it
* is false/0. * is false/0.
*/ */
void AddBooleanArgument(const char* argument, bool* variable, const char* void AddBooleanArgument(const char* argument,
help); bool* variable, const char* help);
void AddBooleanArgument(const char* argument, int* variable, const char* void AddBooleanArgument(const char* argument,
help); int* variable, const char* help);
void AddBooleanArgument(const char* argument,
double* variable, const char* help);
void AddBooleanArgument(const char* argument,
char** variable, const char* help);
void AddBooleanArgument(const char* argument,
kwsys_stl::string* variable, const char* help);
/**
* Add handler for boolean argument. The argument does not take any option
* and if it is specified, the value of the variable is true/1, otherwise it
* is false/0. This will handle the multi argument values.
*/
void AddBooleanArgument(const char* argument,
kwsys_stl::vector<bool>* variable, const char* help);
void AddBooleanArgument(const char* argument,
kwsys_stl::vector<int>* variable, const char* help);
void AddBooleanArgument(const char* argument,
kwsys_stl::vector<double>* variable, const char* help);
void AddBooleanArgument(const char* argument,
kwsys_stl::vector<char*>* variable, const char* help);
void AddBooleanArgument(const char* argument,
kwsys_stl::vector<kwsys_stl::string>* variable, const char* help);
/** /**
* Set the callbacks for error handling. * Set the callbacks for error handling.
@ -205,6 +253,25 @@ protected:
void AddArgument(const char* argument, ArgumentTypeEnum type, void AddArgument(const char* argument, ArgumentTypeEnum type,
VariableTypeEnum vtype, void* variable, const char* help); VariableTypeEnum vtype, void* variable, const char* help);
bool GetMatchedArguments(kwsys_stl::vector<kwsys_stl::string>* matches,
const kwsys_stl::string& arg);
//! Populate individual variables
bool PopulateVariable(CommandLineArgumentsCallbackStructure* cs,
const char* value);
//! Populate individual variables of type ...
void PopulateVariable(bool* variable, const kwsys_stl::string& value);
void PopulateVariable(int* variable, const kwsys_stl::string& value);
void PopulateVariable(double* variable, const kwsys_stl::string& value);
void PopulateVariable(char** variable, const kwsys_stl::string& value);
void PopulateVariable(kwsys_stl::string* variable, const kwsys_stl::string& value);
void PopulateVariable(kwsys_stl::vector<bool>* variable, const kwsys_stl::string& value);
void PopulateVariable(kwsys_stl::vector<int>* variable, const kwsys_stl::string& value);
void PopulateVariable(kwsys_stl::vector<double>* variable, const kwsys_stl::string& value);
void PopulateVariable(kwsys_stl::vector<char*>* variable, const kwsys_stl::string& value);
void PopulateVariable(kwsys_stl::vector<kwsys_stl::string>* variable, const kwsys_stl::string& value);
typedef CommandLineArgumentsInternal Internal; typedef CommandLineArgumentsInternal Internal;
Internal* Internals; Internal* Internals;
kwsys_stl::string Help; kwsys_stl::string Help;

View File

@ -3157,7 +3157,7 @@ bool SystemTools::LocateFileInDir(const char *filename,
{ {
filename_dir = SystemTools::GetFilenamePath(filename_dir); filename_dir = SystemTools::GetFilenamePath(filename_dir);
filename_dir_base = SystemTools::GetFilenameName(filename_dir); filename_dir_base = SystemTools::GetFilenameName(filename_dir);
#if _WIN32 #if defined( _WIN32 )
if (!filename_dir_base.size() || if (!filename_dir_base.size() ||
filename_dir_base[filename_dir_base.size() - 1] == ':') filename_dir_base[filename_dir_base.size() - 1] == ':')
#else #else

View File

@ -14,6 +14,7 @@
#include "kwsysPrivate.h" #include "kwsysPrivate.h"
#include KWSYS_HEADER(CommandLineArguments.hxx) #include KWSYS_HEADER(CommandLineArguments.hxx)
#include KWSYS_HEADER(ios/iostream) #include KWSYS_HEADER(ios/iostream)
#include KWSYS_HEADER(stl/vector)
// Work-around CMake dependency scanning limitation. This must // Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers. // duplicate the above list of headers.
@ -46,6 +47,12 @@ int unknown_argument(const char* argument, void* call_data)
return 1; return 1;
} }
bool CompareTwoItemsOnList(bool i1, bool i2) { return i1 == i2; }
bool CompareTwoItemsOnList(int i1, int i2) { return i1 == i2; }
bool CompareTwoItemsOnList(double i1, double i2) { return i1 == i2; }
bool CompareTwoItemsOnList(const kwsys_stl::string& i1,
const kwsys_stl::string& i2) { return i1 == i2; }
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
// Example run: ./testCommandLineArguments --some-int-variable 4 // Example run: ./testCommandLineArguments --some-int-variable 4
@ -70,6 +77,21 @@ int main(int argc, char* argv[])
bool bool_arg1 = false; bool bool_arg1 = false;
int bool_arg2 = 0; int bool_arg2 = 0;
kwsys_stl::vector<int> numbers_argument;
int valid_numbers[] = { 5, 1, 8, 3, 7, 1, 3, 9, 7, 1 };
kwsys_stl::vector<double> doubles_argument;
double valid_doubles[] = { 12.5, 1.31, 22 };
kwsys_stl::vector<bool> bools_argument;
bool valid_bools[] = { true, true, false };
kwsys_stl::vector<char*> strings_argument;
char* valid_strings[] = { "andy", "bill", "brad", "ken" };
kwsys_stl::vector<kwsys_stl::string> stl_strings_argument;
kwsys_stl::string valid_stl_strings[] = { "ken", "brad", "bill", "andy" };
typedef kwsys::CommandLineArguments argT; typedef kwsys::CommandLineArguments argT;
arg.AddArgument("--some-int-variable", argT::SPACE_ARGUMENT, &some_int_variable, "Set some random int variable"); arg.AddArgument("--some-int-variable", argT::SPACE_ARGUMENT, &some_int_variable, "Set some random int variable");
@ -80,6 +102,11 @@ int main(int argc, char* argv[])
arg.AddArgument("--another-bool-variable", argT::NO_ARGUMENT, &some_bool_variable1, "Set some random bool variable 1"); arg.AddArgument("--another-bool-variable", argT::NO_ARGUMENT, &some_bool_variable1, "Set some random bool variable 1");
arg.AddBooleanArgument("--set-bool-arg1", &bool_arg1, "Test AddBooleanArgument 1"); arg.AddBooleanArgument("--set-bool-arg1", &bool_arg1, "Test AddBooleanArgument 1");
arg.AddBooleanArgument("--set-bool-arg2", &bool_arg2, "Test AddBooleanArgument 2"); arg.AddBooleanArgument("--set-bool-arg2", &bool_arg2, "Test AddBooleanArgument 2");
arg.AddArgument("--some-multi-argument", argT::MULTI_ARGUMENT, &numbers_argument, "Some multiple values variable");
arg.AddArgument("-N", argT::SPACE_ARGUMENT, &doubles_argument, "Some explicit multiple values variable");
arg.AddArgument("-BB", argT::CONCAT_ARGUMENT, &bools_argument, "Some explicit multiple values variable");
arg.AddArgument("-SS", argT::EQUAL_ARGUMENT, &strings_argument, "Some explicit multiple values variable");
arg.AddArgument("-SSS", argT::MULTI_ARGUMENT, &stl_strings_argument, "Some explicit multiple values variable");
arg.AddCallback("-A", argT::NO_ARGUMENT, argument, random_ptr, "Some option -A. This option has a multiline comment. It should demonstrate how the code splits lines."); arg.AddCallback("-A", argT::NO_ARGUMENT, argument, random_ptr, "Some option -A. This option has a multiline comment. It should demonstrate how the code splits lines.");
arg.AddCallback("-B", argT::SPACE_ARGUMENT, argument, random_ptr, "Option -B takes argument with space"); arg.AddCallback("-B", argT::SPACE_ARGUMENT, argument, random_ptr, "Option -B takes argument with space");
@ -99,7 +126,7 @@ int main(int argc, char* argv[])
kwsys_ios::cout << "Some int variable was set to: " << some_int_variable << kwsys_ios::endl; kwsys_ios::cout << "Some int variable was set to: " << some_int_variable << kwsys_ios::endl;
kwsys_ios::cout << "Some double variable was set to: " << some_double_variable << kwsys_ios::endl; kwsys_ios::cout << "Some double variable was set to: " << some_double_variable << kwsys_ios::endl;
if ( some_string_variable ) if ( some_string_variable && strcmp(some_string_variable, "test string with space") == 0)
{ {
kwsys_ios::cout << "Some string variable was set to: " << some_string_variable << kwsys_ios::endl; kwsys_ios::cout << "Some string variable was set to: " << some_string_variable << kwsys_ios::endl;
delete [] some_string_variable; delete [] some_string_variable;
@ -109,6 +136,38 @@ int main(int argc, char* argv[])
kwsys_ios::cerr << "Problem setting string variable" << kwsys_ios::endl; kwsys_ios::cerr << "Problem setting string variable" << kwsys_ios::endl;
res = 1; res = 1;
} }
size_t cc;
#define CompareTwoLists(list1, list_valid, lsize) \
if ( list1.size() != lsize ) \
{ \
kwsys_ios::cerr << "Problem setting " #list1 ". Size is: " << list1.size() \
<< " should be: " << lsize << kwsys_ios::endl; \
res = 1; \
} \
else \
{ \
kwsys_ios::cout << #list1 " argument set:"; \
for ( cc =0; cc < lsize; ++ cc ) \
{ \
kwsys_ios::cout << " " << list1[cc]; \
if ( !CompareTwoItemsOnList(list1[cc], list_valid[cc]) ) \
{ \
kwsys_ios::cerr << "Problem setting " #list1 ". Value of " \
<< cc << " is: [" << list1[cc] << "] <> [" \
<< list_valid[cc] << "]" << kwsys_ios::endl; \
res = 1; \
break; \
} \
} \
kwsys_ios::cout << kwsys_ios::endl; \
}
CompareTwoLists(numbers_argument, valid_numbers, 10);
CompareTwoLists(doubles_argument, valid_doubles, 3);
CompareTwoLists(bools_argument, valid_bools, 3);
CompareTwoLists(strings_argument, valid_strings, 4);
CompareTwoLists(stl_strings_argument, valid_stl_strings, 4);
kwsys_ios::cout << "Some STL String variable was set to: " << some_stl_string_variable.c_str() << kwsys_ios::endl; kwsys_ios::cout << "Some STL String variable was set to: " << some_stl_string_variable.c_str() << kwsys_ios::endl;
kwsys_ios::cout << "Some bool variable was set to: " << some_bool_variable << kwsys_ios::endl; kwsys_ios::cout << "Some bool variable was set to: " << some_bool_variable << kwsys_ios::endl;
kwsys_ios::cout << "Some bool variable was set to: " << some_bool_variable1 << kwsys_ios::endl; kwsys_ios::cout << "Some bool variable was set to: " << some_bool_variable1 << kwsys_ios::endl;