Commit dff9940f authored by Andy Cedilnik's avatar Andy Cedilnik

ENH: Move command line argument parsing code to kwsys

parent 5741a11e
......@@ -78,6 +78,7 @@ IF(NOT KWSYS_NAMESPACE)
SET(KWSYS_USE_Process 1)
SET(KWSYS_USE_RegularExpression 1)
SET(KWSYS_USE_SystemTools 1)
SET(KWSYS_USE_CommandLineArguments 1)
ENDIF(NOT KWSYS_NAMESPACE)
#-----------------------------------------------------------------------------
......@@ -248,12 +249,20 @@ IF(KWSYS_USE_SystemTools)
ENDIF(KWSYS_USE_SystemTools)
# Add selected C++ classes.
FOREACH(c Directory RegularExpression SystemTools)
FOREACH(c Directory RegularExpression SystemTools CommandLineArguments)
IF(KWSYS_USE_${c})
SET(KWSYS_CLASSES ${KWSYS_CLASSES} ${c})
ENDIF(KWSYS_USE_${c})
ENDFOREACH(c)
IF(KWSYS_USE_CommandLineArguments)
IF(NOT ParaView_SOURCE_DIR)
IF(NOT KWSYS_STANDALONE)
MESSAGE("Command Line Arguments is experimental code for now")
ENDIF(NOT KWSYS_STANDALONE)
ENDIF(NOT ParaView_SOURCE_DIR)
ENDIF(KWSYS_USE_CommandLineArguments)
# Add selected C components.
FOREACH(c Process Base64)
IF(KWSYS_USE_${c})
......@@ -411,9 +420,11 @@ IF(KWSYS_STANDALONE)
ADD_EXECUTABLE(testIOS testIOS.cxx)
ADD_EXECUTABLE(testProcess testProcess.c)
ADD_EXECUTABLE(test1 test1.cxx)
ADD_EXECUTABLE(testCommandLineArguments testCommandLineArguments.cxx)
TARGET_LINK_LIBRARIES(testIOS ${KWSYS_NAMESPACE})
TARGET_LINK_LIBRARIES(testProcess ${KWSYS_NAMESPACE}_c)
TARGET_LINK_LIBRARIES(test1 ${KWSYS_NAMESPACE})
TARGET_LINK_LIBRARIES(testCommandLineArguments ${KWSYS_NAMESPACE})
IF(BUILD_TESTING)
ADD_TEST(testProcess-1 testProcess 1)
......
This diff is collapsed.
/*=========================================================================
Program: KWSys - Kitware System Library
Module: CommandLineArguments.hxx.in
Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef @KWSYS_NAMESPACE@_CommandLineArguments_hxx
#define @KWSYS_NAMESPACE@_CommandLineArguments_hxx
#include <@KWSYS_NAMESPACE@/Configure.h>
#include <@KWSYS_NAMESPACE@/Configure.hxx>
#include <@KWSYS_NAMESPACE@/stl/string>
/* Define this macro temporarily to keep the code readable. */
#if !defined (KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
# define kwsys_stl @KWSYS_NAMESPACE@_stl
#endif
namespace @KWSYS_NAMESPACE@
{
class CommandLineArgumentsInternal;
/** \class CommandLineArguments
* \brief Command line arguments processing code.
*
* Find specified arguments with optional options and execute specified methods
* or set given variables.
*/
class @KWSYS_NAMESPACE@_EXPORT CommandLineArguments
{
public:
CommandLineArguments();
~CommandLineArguments();
/**
* Various argument types.
*/
enum ArgumentTypeEnum {
NO_ARGUMENT, // The option takes no argument --foo
CONCAT_ARGUMENT,// The option takes argument after no space --foobar
SPACE_ARGUMENT, // The option takes argument after space --foo bar
EQUAL_ARGUMENT // The option takes argument after equal --foo=bar
};
/**
* Various string types.
*/
enum VariableTypeEnum {
NO_VARIABLE_TYPE = 0, // The variable is not specified
INT_TYPE, // The variable is integer (int)
BOOL_TYPE, // The vairable is boolean (bool)
DOUBLE_TYPE, // The variable is float (double)
STRING_TYPE, // The variable is string (char*)
STL_STRING_TYPE // The variable is string (char*)
};
/**
* Prototypes for callbacks for callback interface.
*/
typedef int(*CallbackType)(const char* argument, const char* value,
void* call_data);
typedef int(*ErrorCallbackType)(const char* argument, void* client_data);
struct CallbackStructure
{
const char* Argument;
int ArgumentType;
CallbackType Callback;
void* CallData;
void* Variable;
int VariableType;
const char* Help;
};
/**
* Initialize internal data structures. This should be called before parsing.
*/
void Initialize(int argc, char* argv[]);
/**
* Initialize internal data structure and pass arguments one by one. This is
* convinience method for use from scripting languages where argc and argv
* are not available.
*/
void Initialize();
void ProcessArgument(const char* arg);
/**
* This method will parse arguments and call apropriate methods.
*/
int Parse();
/**
* This method will add a callback for a specific argument. The arguments to
* it are argument, argument type, callback method, and call data. The
* argument help specifies the help string used with this option. The
* callback and call_data can be skipped.
*/
void AddCallback(const char* argument, ArgumentTypeEnum type, CallbackType callback,
void* call_data, const char* help);
/**
* Add handler for argument which is going to set the variable to the
* specified value.
*/
void AddArgument(const char* argument, ArgumentTypeEnum type, VariableTypeEnum vtype, void* variable, const char* help);
void AddArgument(const char* argument, ArgumentTypeEnum type, bool* variable, const char* help);
void AddArgument(const char* argument, ArgumentTypeEnum type, int* variable, const char* help);
void AddArgument(const char* argument, ArgumentTypeEnum type, double* variable, const char* help);
void AddArgument(const char* argument, ArgumentTypeEnum type, char** variable, const char* help);
void AddArgument(const char* argument, ArgumentTypeEnum type, kwsys_stl::string* variable, const char* help);
void AddBooleanArgument(const char* argument, bool* variable, const char* help);
void AddBooleanArgument(const char* argument, int* variable, const char* help);
/**
* Set the callbacks for error handling.
*/
void SetClientData(void* client_data);
void SetUnknownArgumentCallback(ErrorCallbackType callback);
/**
* Get remaining arguments. It allocates space for argv, so you have to call
* delete[] on it.
*/
void GetRemainingArguments(int* argc, char*** argv);
/**
* Return string containing help. If the argument is specified, only return
* help for that argument.
*/
const char* GetHelp() { return this->Help.c_str(); }
const char* GetHelp(const char* arg);
/**
* Get / Set the help line length. Default length is 80.
*/
void SetLineLength();
unsigned int GetLineLength();
protected:
void GenerateHelp();
typedef CommandLineArgumentsInternal Internal;
Internal* Internals;
kwsys_stl::string Help;
unsigned int LineLength;
};
} // namespace @KWSYS_NAMESPACE@
/* Undefine temporary macro. */
#if !defined (KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
# undef kwsys_stl
#endif
#endif
/*=========================================================================
Program: KWSys - Kitware System Library
Module: testCommandLineArguments.cxx
Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include <kwsys/CommandLineArguments.hxx>
void* random_ptr = (void*)0x123;
int argument(const char* arg, const char* value, void* call_data)
{
cout << "Got argument: \"" << arg << "\" value: \"" << (value?value:"(null)") << "\"" << endl;
if ( call_data != random_ptr )
{
cerr << "Problem processing call_data" << endl;
return 0;
}
return 1;
}
int unknown_argument(const char* argument, void* call_data)
{
cout << "Got unknown argument: \"" << argument << "\"" << endl;
if ( call_data != random_ptr )
{
cerr << "Problem processing call_data" << endl;
return 0;
}
return 1;
}
int main(int argc, char* argv[])
{
// Example run: ./testCommandLineArguments --some-int-variable 4
// --another-bool-variable --some-bool-variable=yes
// --some-stl-string-variable=foobar --set-bool-arg1 --set-bool-arg2
// --some-string-variable=hello
int res = 0;
kwsys::CommandLineArguments arg;
arg.Initialize(argc, argv);
// For error handling
arg.SetClientData(random_ptr);
arg.SetUnknownArgumentCallback(unknown_argument);
int some_int_variable = 10;
double some_double_variable = 10.10;
char* some_string_variable = 0;
kwsys_stl::string some_stl_string_variable = "";
bool some_bool_variable = false;
bool some_bool_variable1 = false;
bool bool_arg1 = false;
int bool_arg2 = 0;
typedef kwsys::CommandLineArguments argT;
arg.AddArgument("--some-int-variable", argT::SPACE_ARGUMENT, &some_int_variable, "Set some random int variable");
arg.AddArgument("--some-double-variable", argT::CONCAT_ARGUMENT, &some_double_variable, "Set some random double variable");
arg.AddArgument("--some-string-variable", argT::EQUAL_ARGUMENT, &some_string_variable, "Set some random string variable");
arg.AddArgument("--some-stl-string-variable", argT::EQUAL_ARGUMENT, &some_stl_string_variable, "Set some random stl string variable");
arg.AddArgument("--some-bool-variable", argT::EQUAL_ARGUMENT, &some_bool_variable, "Set some random bool variable");
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-arg2", &bool_arg2, "Test AddBooleanArgument 2");
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("-C", argT::EQUAL_ARGUMENT, argument, random_ptr, "Option -C takes argument after =");
arg.AddCallback("-D", argT::CONCAT_ARGUMENT, argument, random_ptr, "This option takes concatinated argument");
arg.AddCallback("--long1", argT::NO_ARGUMENT, argument, random_ptr, "-A");
arg.AddCallback("--long2", argT::SPACE_ARGUMENT, argument, random_ptr, "-B");
arg.AddCallback("--long3", argT::EQUAL_ARGUMENT, argument, random_ptr, "Same as -C but a bit different");
arg.AddCallback("--long4", argT::CONCAT_ARGUMENT, argument, random_ptr, "-C");
if ( !arg.Parse() )
{
cerr << "Problem parsing arguments" << endl;
res = 1;
}
cout << "Help: " << arg.GetHelp() << endl;
cout << "Some int variable was set to: " << some_int_variable << endl;
cout << "Some double variable was set to: " << some_double_variable << endl;
if ( some_string_variable )
{
cout << "Some string variable was set to: " << some_string_variable << endl;
delete [] some_string_variable;
}
else
{
cerr << "Problem setting string variable" << endl;
res = 1;
}
cout << "Some STL String variable was set to: " << some_stl_string_variable.c_str() << endl;
cout << "Some bool variable was set to: " << some_bool_variable << endl;
cout << "Some bool variable was set to: " << some_bool_variable1 << endl;
cout << "bool_arg1 variable was set to: " << bool_arg1 << endl;
cout << "bool_arg2 variable was set to: " << bool_arg2 << endl;
cout << endl;
return res;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment