summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Cedilnik <andy.cedilnik@kitware.com>2004-09-13 20:15:02 (GMT)
committerAndy Cedilnik <andy.cedilnik@kitware.com>2004-09-13 20:15:02 (GMT)
commitc8fa6581428dd1899298034f93720882ac95488c (patch)
tree241d0956027d4e93e40eb60911f21945d6aa42be
parent3e03bed0acf45313c7eee351ab5047e926a5ee44 (diff)
downloadCMake-c8fa6581428dd1899298034f93720882ac95488c.zip
CMake-c8fa6581428dd1899298034f93720882ac95488c.tar.gz
CMake-c8fa6581428dd1899298034f93720882ac95488c.tar.bz2
ENH: Move command line argument parsing code to kwsys
-rw-r--r--Source/kwsys/CMakeLists.txt13
-rw-r--r--Source/kwsys/CommandLineArguments.cxx591
-rw-r--r--Source/kwsys/CommandLineArguments.hxx.in173
-rw-r--r--Source/kwsys/testCommandLineArguments.cxx110
4 files changed, 886 insertions, 1 deletions
diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt
index fa1bb7d..f4edfc9 100644
--- a/Source/kwsys/CMakeLists.txt
+++ b/Source/kwsys/CMakeLists.txt
@@ -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)
diff --git a/Source/kwsys/CommandLineArguments.cxx b/Source/kwsys/CommandLineArguments.cxx
new file mode 100644
index 0000000..054956f
--- /dev/null
+++ b/Source/kwsys/CommandLineArguments.cxx
@@ -0,0 +1,591 @@
+/*=========================================================================
+
+ Program: KWSys - Kitware System Library
+ Module: $RCSfile$
+
+ 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 "kwsysPrivate.h"
+#include KWSYS_HEADER(CommandLineArguments.hxx)
+
+#include KWSYS_HEADER(Configure.hxx)
+
+#include KWSYS_HEADER(stl/vector)
+#include KWSYS_HEADER(stl/map)
+#include KWSYS_HEADER(stl/set)
+#include KWSYS_HEADER(ios/sstream)
+
+#include <stdio.h>
+
+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) {}
+};
+
+class CommandLineArgumentsVectorOfStrings :
+ public kwsys_stl::vector<CommandLineArgumentsString> {};
+class CommandLineArgumentsSetOfStrings :
+ public kwsys_stl::set<CommandLineArgumentsString> {};
+class CommandLineArgumentsMapOfStrucs :
+ public kwsys_stl::map<CommandLineArgumentsString,
+ CommandLineArguments::CallbackStructure> {};
+
+class CommandLineArgumentsInternal
+{
+public:
+ CommandLineArgumentsInternal()
+ {
+ this->UnknownArgumentCallback = 0;
+ this->ClientData = 0;
+ this->LastArgument = 0;
+ }
+
+ typedef CommandLineArgumentsVectorOfStrings VectorOfStrings;
+ typedef CommandLineArgumentsMapOfStrucs CallbacksMap;
+ typedef CommandLineArgumentsString String;
+ typedef CommandLineArgumentsSetOfStrings SetOfStrings;
+
+ VectorOfStrings Argv;
+ CallbacksMap Callbacks;
+
+ CommandLineArguments::ErrorCallbackType UnknownArgumentCallback;
+ void* ClientData;
+
+ VectorOfStrings::size_type LastArgument;
+};
+//============================================================================
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+CommandLineArguments::CommandLineArguments()
+{
+ this->Internals = new CommandLineArguments::Internal;
+ this->Help = "";
+ this->LineLength = 80;
+}
+
+//----------------------------------------------------------------------------
+CommandLineArguments::~CommandLineArguments()
+{
+ delete this->Internals;
+}
+
+//----------------------------------------------------------------------------
+void CommandLineArguments::Initialize(int argc, char* argv[])
+{
+ int cc;
+
+ this->Initialize();
+ for ( cc = 1; cc < argc; cc ++ )
+ {
+ this->ProcessArgument(argv[cc]);
+ }
+}
+
+//----------------------------------------------------------------------------
+void CommandLineArguments::Initialize()
+{
+ this->Internals->Argv.clear();
+ this->Internals->LastArgument = 0;
+}
+
+//----------------------------------------------------------------------------
+void CommandLineArguments::ProcessArgument(const char* arg)
+{
+ this->Internals->Argv.push_back(arg);
+}
+
+//----------------------------------------------------------------------------
+int CommandLineArguments::Parse()
+{
+ CommandLineArguments::Internal::VectorOfStrings::size_type cc;
+ CommandLineArguments::Internal::VectorOfStrings matches;
+ for ( cc = 0; cc < this->Internals->Argv.size(); 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?
+ for ( it = this->Internals->Callbacks.begin();
+ it != this->Internals->Callbacks.end();
+ it ++ )
+ {
+ const CommandLineArguments::Internal::String& parg = it->first;
+ CommandLineArguments::CallbackStructure *cs = &it->second;
+ if (cs->ArgumentType == CommandLineArguments::NO_ARGUMENT ||
+ cs->ArgumentType == CommandLineArguments::SPACE_ARGUMENT)
+ {
+ if ( arg == parg )
+ {
+ matches.push_back(parg);
+ }
+ }
+ else if ( arg.find( parg ) == 0 )
+ {
+ matches.push_back(parg);
+ }
+ }
+ if ( matches.size() > 0 )
+ {
+ // Ok, we found one or more arguments that match what user specified.
+ // Let's find the longest one.
+ CommandLineArguments::Internal::VectorOfStrings::size_type kk;
+ CommandLineArguments::Internal::VectorOfStrings::size_type maxidx = 0;
+ CommandLineArguments::Internal::String::size_type maxlen = 0;
+ for ( kk = 0; kk < matches.size(); kk ++ )
+ {
+ if ( matches[kk].size() > maxlen )
+ {
+ maxlen = matches[kk].size();
+ maxidx = kk;
+ }
+ }
+ // So, the longest one is probably the right one. Now see if it has any
+ // additional value
+ const char* value = 0;
+ CommandLineArguments::CallbackStructure *cs
+ = &this->Internals->Callbacks[matches[maxidx]];
+ const CommandLineArguments::Internal::String& sarg = matches[maxidx];
+ if ( cs->ArgumentType == NO_ARGUMENT )
+ {
+ // No value
+ }
+ else if ( cs->ArgumentType == SPACE_ARGUMENT )
+ {
+ if ( cc == this->Internals->Argv.size()-1 )
+ {
+ return 0;
+ }
+ // Value is the next argument
+ value = this->Internals->Argv[cc+1].c_str();
+ cc ++;
+ }
+ else if ( cs->ArgumentType == EQUAL_ARGUMENT )
+ {
+ if ( arg.size() == sarg.size() || *(arg.c_str() + sarg.size()) != '=' )
+ {
+ return 0;
+ }
+ // Value is everythng followed the '=' sign
+ value = arg.c_str() + sarg.size()+1;
+ }
+ else if ( cs->ArgumentType == CONCAT_ARGUMENT )
+ {
+ // Value is whatever follows the argument
+ value = arg.c_str() + sarg.size();
+ }
+
+ // Call the callback
+ if ( cs->Callback )
+ {
+ if ( !cs->Callback(sarg.c_str(), value, cs->CallData) )
+ {
+ return 0;
+ }
+ }
+ if ( cs->Variable )
+ {
+ kwsys_stl::string var = "1";
+ if ( value )
+ {
+ var = value;
+ }
+ if ( cs->VariableType == CommandLineArguments::INT_TYPE )
+ {
+ 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;
+ *variable = 0;
+ }
+ *variable = new char[ strlen(var.c_str()) + 1 ];
+ strcpy(*variable, var.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;
+ }
+ else
+ {
+ *variable = false;
+ }
+ }
+ else
+ {
+ cerr << "Got unknown argument type: \"" << cs->VariableType << "\"" << endl;
+ return 0;
+ }
+ }
+ }
+ else
+ {
+ // Handle unknown arguments
+ if ( this->Internals->UnknownArgumentCallback )
+ {
+ if ( !this->Internals->UnknownArgumentCallback(arg.c_str(),
+ this->Internals->ClientData) )
+ {
+ return 0;
+ }
+ return 1;
+ }
+ else
+ {
+ cerr << "Got unknown argument: \"" << arg.c_str() << "\"" << endl;
+ return 0;
+ }
+ }
+ }
+ // We are done parsing, so remember what was the last argument
+ this->Internals->LastArgument = cc;
+ return 1;
+}
+
+//----------------------------------------------------------------------------
+void CommandLineArguments::GetRemainingArguments(int* argc, char*** argv)
+{
+ CommandLineArguments::Internal::VectorOfStrings::size_type size
+ = this->Internals->Argv.size() - this->Internals->LastArgument + 1;
+ CommandLineArguments::Internal::VectorOfStrings::size_type cc;
+
+ char** args = new char*[ size ];
+ args[0] = new char[ this->Internals->Argv[0].size() + 1 ];
+ strcpy(args[0], this->Internals->Argv[0].c_str());
+ int cnt = 1;
+ for ( cc = this->Internals->LastArgument;
+ cc < this->Internals->Argv.size(); cc ++ )
+ {
+ args[cnt] = new char[ this->Internals->Argv[cc].size() + 1];
+ strcpy(args[cnt], this->Internals->Argv[cc].c_str());
+ cnt ++;
+ }
+ *argc = cnt;
+ *argv = args;
+}
+
+//----------------------------------------------------------------------------
+void CommandLineArguments::AddCallback(const char* argument, ArgumentTypeEnum type,
+ CallbackType callback, void* call_data, const char* help)
+{
+ CommandLineArguments::CallbackStructure s;
+ s.Argument = argument;
+ s.ArgumentType = type;
+ s.Callback = callback;
+ s.CallData = call_data;
+ s.VariableType = CommandLineArguments::NO_VARIABLE_TYPE;
+ s.Variable = 0;
+ s.Help = help;
+
+ this->Internals->Callbacks[argument] = s;
+ this->GenerateHelp();
+}
+
+//----------------------------------------------------------------------------
+void CommandLineArguments::AddArgument(const char* argument, ArgumentTypeEnum type,
+ VariableTypeEnum vtype, void* variable, const char* help)
+{
+ CommandLineArguments::CallbackStructure s;
+ s.Argument = argument;
+ s.ArgumentType = type;
+ s.Callback = 0;
+ s.CallData = 0;
+ s.VariableType = vtype;
+ s.Variable = variable;
+ s.Help = help;
+
+ this->Internals->Callbacks[argument] = s;
+ this->GenerateHelp();
+}
+
+//----------------------------------------------------------------------------
+void CommandLineArguments::AddArgument(const char* argument, ArgumentTypeEnum type,
+ int* variable, const char* help)
+{
+ this->AddArgument(argument, type, CommandLineArguments::INT_TYPE, variable, help);
+}
+
+//----------------------------------------------------------------------------
+void CommandLineArguments::AddArgument(const char* argument, ArgumentTypeEnum type,
+ double* variable, const char* help)
+{
+ this->AddArgument(argument, type, CommandLineArguments::DOUBLE_TYPE, variable, help);
+}
+
+//----------------------------------------------------------------------------
+void CommandLineArguments::AddArgument(const char* argument, ArgumentTypeEnum type,
+ char** variable, const char* help)
+{
+ this->AddArgument(argument, type, CommandLineArguments::STRING_TYPE, variable, help);
+}
+
+//----------------------------------------------------------------------------
+void CommandLineArguments::AddArgument(const char* argument, ArgumentTypeEnum type,
+ kwsys_stl::string* variable, const char* help)
+{
+ this->AddArgument(argument, type, CommandLineArguments::STL_STRING_TYPE, variable, help);
+}
+
+//----------------------------------------------------------------------------
+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)
+{
+ this->Internals->ClientData = client_data;
+}
+
+//----------------------------------------------------------------------------
+void CommandLineArguments::SetUnknownArgumentCallback(
+ CommandLineArguments::ErrorCallbackType callback)
+{
+ this->Internals->UnknownArgumentCallback = callback;
+}
+
+//----------------------------------------------------------------------------
+const char* CommandLineArguments::GetHelp(const char* arg)
+{
+ CommandLineArguments::Internal::CallbacksMap::iterator it
+ = this->Internals->Callbacks.find(arg);
+ if ( it == this->Internals->Callbacks.end() )
+ {
+ return 0;
+ }
+
+ // Since several arguments may point to the same argument, find the one this
+ // one point to if this one is pointing to another argument.
+ CommandLineArguments::CallbackStructure *cs = &(it->second);
+ while ( 1 )
+ {
+ CommandLineArguments::Internal::CallbacksMap::iterator hit
+ = this->Internals->Callbacks.find(cs->Help);
+ if ( hit == this->Internals->Callbacks.end() )
+ {
+ return cs->Help;
+ }
+ cs = &(hit->second);
+ }
+ // Should never happened
+ return 0;
+}
+
+//----------------------------------------------------------------------------
+void CommandLineArguments::GenerateHelp()
+{
+ kwsys_ios::ostringstream str;
+
+ // Collapse all arguments into the map of vectors of all arguments that do
+ // the same thing.
+ CommandLineArguments::Internal::CallbacksMap::iterator it;
+ typedef kwsys_stl::map<CommandLineArguments::Internal::String,
+ CommandLineArguments::Internal::SetOfStrings > MapArgs;
+ MapArgs mp;
+ MapArgs::iterator mpit, smpit;
+ for ( it = this->Internals->Callbacks.begin();
+ it != this->Internals->Callbacks.end();
+ it ++ )
+ {
+ CommandLineArguments::CallbackStructure *cs = &(it->second);
+ mpit = mp.find(cs->Help);
+ if ( mpit != mp.end() )
+ {
+ mpit->second.insert(it->first);
+ mp[it->first].insert(it->first);
+ }
+ else
+ {
+ mp[it->first].insert(it->first);
+ }
+ }
+ for ( it = this->Internals->Callbacks.begin();
+ it != this->Internals->Callbacks.end();
+ it ++ )
+ {
+ CommandLineArguments::CallbackStructure *cs = &(it->second);
+ mpit = mp.find(cs->Help);
+ if ( mpit != mp.end() )
+ {
+ mpit->second.insert(it->first);
+ smpit = mp.find(it->first);
+ CommandLineArguments::Internal::SetOfStrings::iterator sit;
+ for ( sit = smpit->second.begin(); sit != smpit->second.end(); sit++ )
+ {
+ mpit->second.insert(*sit);
+ }
+ mp.erase(smpit);
+ }
+ else
+ {
+ mp[it->first].insert(it->first);
+ }
+ }
+
+ // Find the length of the longest string
+ CommandLineArguments::Internal::String::size_type maxlen = 0;
+ for ( mpit = mp.begin();
+ mpit != mp.end();
+ mpit ++ )
+ {
+ CommandLineArguments::Internal::SetOfStrings::iterator sit;
+ for ( sit = mpit->second.begin(); sit != mpit->second.end(); sit++ )
+ {
+ CommandLineArguments::Internal::String::size_type clen = sit->size();
+ switch ( this->Internals->Callbacks[*sit].ArgumentType )
+ {
+ case CommandLineArguments::NO_ARGUMENT: clen += 0; break;
+ case CommandLineArguments::CONCAT_ARGUMENT: clen += 6; break;
+ case CommandLineArguments::SPACE_ARGUMENT: clen += 7; break;
+ case CommandLineArguments::EQUAL_ARGUMENT: clen += 7; break;
+ }
+ if ( clen > maxlen )
+ {
+ maxlen = clen;
+ }
+ }
+ }
+
+ // Create format for that string
+ char format[80];
+ sprintf(format, "%%%ds", static_cast<unsigned int>(maxlen));
+
+
+ // Print help for each option
+ for ( mpit = mp.begin();
+ mpit != mp.end();
+ mpit ++ )
+ {
+ CommandLineArguments::Internal::SetOfStrings::iterator sit;
+ for ( sit = mpit->second.begin(); sit != mpit->second.end(); sit++ )
+ {
+ str << endl;
+ char argument[100];
+ sprintf(argument, sit->c_str());
+ switch ( this->Internals->Callbacks[*sit].ArgumentType )
+ {
+ case CommandLineArguments::NO_ARGUMENT: break;
+ case CommandLineArguments::CONCAT_ARGUMENT: strcat(argument, "option"); break;
+ case CommandLineArguments::SPACE_ARGUMENT: strcat(argument, " option"); break;
+ case CommandLineArguments::EQUAL_ARGUMENT: strcat(argument, "=option"); break;
+ }
+ char buffer[80];
+ sprintf(buffer, format, argument);
+ str << buffer;
+ }
+ str << "\t";
+ const char* ptr = this->Internals->Callbacks[mpit->first].Help;
+ int len = strlen(ptr);
+ int cnt = 0;
+ while ( len > 0)
+ {
+ // If argument with help is longer than line length, split it on previous
+ // space (or tab) and continue on the next line
+ CommandLineArguments::Internal::String::size_type cc;
+ for ( cc = 0; ptr[cc]; cc ++ )
+ {
+ if ( *ptr == ' ' || *ptr == '\t' )
+ {
+ ptr ++;
+ len --;
+ }
+ }
+ if ( cnt > 0 )
+ {
+ for ( cc = 0; cc < maxlen; cc ++ )
+ {
+ str << " ";
+ }
+ str << "\t";
+ }
+ CommandLineArguments::Internal::String::size_type skip = len;
+ if ( skip > this->LineLength - maxlen )
+ {
+ skip = this->LineLength - maxlen;
+ for ( cc = skip-1; cc > 0; cc -- )
+ {
+ if ( ptr[cc] == ' ' || ptr[cc] == '\t' )
+ {
+ break;
+ }
+ }
+ if ( cc != 0 )
+ {
+ skip = cc;
+ }
+ }
+ str.write(ptr, skip);
+ str << endl;
+ ptr += skip;
+ len -= skip;
+ cnt ++;
+ }
+ }
+ this->Help = str.str();
+}
+
+} // namespace KWSYS_NAMESPACE
diff --git a/Source/kwsys/CommandLineArguments.hxx.in b/Source/kwsys/CommandLineArguments.hxx.in
new file mode 100644
index 0000000..f4893b5
--- /dev/null
+++ b/Source/kwsys/CommandLineArguments.hxx.in
@@ -0,0 +1,173 @@
+/*=========================================================================
+
+ Program: KWSys - Kitware System Library
+ Module: $RCSfile$
+
+ 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
+
+
+
+
+
diff --git a/Source/kwsys/testCommandLineArguments.cxx b/Source/kwsys/testCommandLineArguments.cxx
new file mode 100644
index 0000000..3ac099a
--- /dev/null
+++ b/Source/kwsys/testCommandLineArguments.cxx
@@ -0,0 +1,110 @@
+/*=========================================================================
+
+ Program: KWSys - Kitware System Library
+ Module: $RCSfile$
+
+ 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;
+}