diff --git a/CMakeLists.txt b/CMakeLists.txt index fab3ad79c3a5a222f595dc43fb7bcae3495eda16..353cdc67212bdd36811702d593c20b4de15b1a26 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -768,6 +768,7 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR) testIOS testHashSTL testCommandLineArguments + testCommandLineArguments1 testRegistry ${EXTRA_TESTS} ) @@ -837,6 +838,14 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR) -A -C=test --long2 hello) + ADD_TEST(kwsys.testCommandLineArguments1 ${EXEC_DIR}/testCommandLineArguments1 + --ignored + -n 24 + --second-ignored + "-m=test value" + third-ignored + -p + some junk at the end) IF(COMMAND SET_TESTS_PROPERTIES AND COMMAND GET_TEST_PROPERTY AND KWSYS_STANDALONE) ADD_TEST(kwsys.testFail ${EXEC_DIR}/testFail) # We expect test to fail diff --git a/CommandLineArguments.cxx b/CommandLineArguments.cxx index ad3b5500c7cd80f7e8d9d25d17fcc5ed15e20cd7..bebe3cf61deb6c6c19f9ef51403d20c00bc87b41 100644 --- a/CommandLineArguments.cxx +++ b/CommandLineArguments.cxx @@ -99,6 +99,8 @@ public: void* ClientData; VectorOfStrings::size_type LastArgument; + + VectorOfStrings UnusedArguments; }; //============================================================================ //---------------------------------------------------------------------------- @@ -109,6 +111,7 @@ CommandLineArguments::CommandLineArguments() this->Internals = new CommandLineArguments::Internal; this->Help = ""; this->LineLength = 80; + this->StoreUnusedArgumentsFlag = false; } //---------------------------------------------------------------------------- @@ -185,6 +188,10 @@ int CommandLineArguments::Parse() { kwsys_stl::vector<kwsys_stl::string>::size_type cc; kwsys_stl::vector<kwsys_stl::string> matches; + if ( this->StoreUnusedArgumentsFlag ) + { + this->Internals->UnusedArguments.clear(); + } for ( cc = 0; cc < this->Internals->Argv.size(); cc ++ ) { const kwsys_stl::string& arg = this->Internals->Argv[cc]; @@ -281,6 +288,7 @@ int CommandLineArguments::Parse() cc--; continue; } + break; default: kwsys_ios::cerr << "Got unknown argument type: \"" << cs->ArgumentType << "\"" << kwsys_ios::endl; this->Internals->LastArgument --; @@ -300,6 +308,11 @@ int CommandLineArguments::Parse() } return 1; } + else if ( this->StoreUnusedArgumentsFlag ) + { + CommandLineArguments_DEBUG("Store unused argument " << arg); + this->Internals->UnusedArguments.push_back(arg.c_str()); + } else { kwsys_ios::cerr << "Got unknown argument: \"" << arg.c_str() << "\"" << kwsys_ios::endl; @@ -336,6 +349,32 @@ void CommandLineArguments::GetRemainingArguments(int* argc, char*** argv) *argv = args; } +//---------------------------------------------------------------------------- +void CommandLineArguments::GetUnusedArguments(int* argc, char*** argv) +{ + CommandLineArguments::Internal::VectorOfStrings::size_type size + = this->Internals->UnusedArguments.size() + 1; + CommandLineArguments::Internal::VectorOfStrings::size_type cc; + + // Copy Argv0 as the first argument + char** args = new char*[ size ]; + args[0] = new char[ this->Internals->Argv0.size() + 1 ]; + strcpy(args[0], this->Internals->Argv0.c_str()); + int cnt = 1; + + // Copy everything after the LastArgument, since that was not parsed. + for ( cc = 0; + cc < this->Internals->UnusedArguments.size(); cc ++ ) + { + kwsys::String &str = this->Internals->UnusedArguments[cc]; + args[cnt] = new char[ str.size() + 1]; + strcpy(args[cnt], str.c_str()); + cnt ++; + } + *argc = cnt; + *argv = args; +} + //---------------------------------------------------------------------------- void CommandLineArguments::DeleteRemainingArguments(int argc, char*** argv) { @@ -769,6 +808,7 @@ bool CommandLineArguments::PopulateVariable(CommandLineArgumentsCallbackStructur return 0; } } + CommandLineArguments_DEBUG("Set argument: " << cs->Argument << " to " << value); if ( cs->Variable ) { kwsys_stl::string var = "1"; diff --git a/CommandLineArguments.hxx.in b/CommandLineArguments.hxx.in index 01b292f6588bf0917050433b4fe7537450d3a036..53a8f532bbb367896e16edc00aa60e701a76ae13 100644 --- a/CommandLineArguments.hxx.in +++ b/CommandLineArguments.hxx.in @@ -204,6 +204,14 @@ public: void GetRemainingArguments(int* argc, char*** argv); void DeleteRemainingArguments(int argc, char*** argv); + /** + * If StoreUnusedArguments is set to true, then all unknown arguments will be + * stored and the user can access the modified argc, argv without known + * arguments. + */ + void StoreUnusedArguments(bool val) { this->StoreUnusedArgumentsFlag = val; } + void GetUnusedArguments(int* argc, char*** argv); + /** * Return string containing help. If the argument is specified, only return * help for that argument. @@ -261,6 +269,8 @@ protected: kwsys_stl::string Help; unsigned int LineLength; + + bool StoreUnusedArgumentsFlag; }; } // namespace @KWSYS_NAMESPACE@ diff --git a/testCommandLineArguments.cxx b/testCommandLineArguments.cxx index 4c412adee323cf10ceaac9b6e7aee7e247555f11..9eb43e29969ad12aec61ff29b24bf44d6a7c7ba1 100644 --- a/testCommandLineArguments.cxx +++ b/testCommandLineArguments.cxx @@ -50,6 +50,8 @@ int unknown_argument(const char* argument, void* call_data) 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 char* i1, + const char* i2) { return strcmp(i1, i2) == 0; } bool CompareTwoItemsOnList(const kwsys_stl::string& i1, const kwsys_stl::string& i2) { return i1 == i2; } diff --git a/testCommandLineArguments1.cxx b/testCommandLineArguments1.cxx new file mode 100644 index 0000000000000000000000000000000000000000..f443ccdb3c5a01f74e7d6d8d47d4a69b38da491c --- /dev/null +++ b/testCommandLineArguments1.cxx @@ -0,0 +1,106 @@ +/*========================================================================= + + Program: KWSys - Kitware System Library + Module: testCommandLineArguments1.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 "kwsysPrivate.h" +#include KWSYS_HEADER(CommandLineArguments.hxx) +#include KWSYS_HEADER(ios/iostream) +#include KWSYS_HEADER(stl/vector) + +// Work-around CMake dependency scanning limitation. This must +// duplicate the above list of headers. +#if 0 +# include "CommandLineArguments.hxx.in" +# include "kwsys_ios_iostream.h.in" +#endif + +int main(int argc, char* argv[]) +{ + kwsys::CommandLineArguments arg; + arg.Initialize(argc, argv); + + int n = 0; + char* m = 0; + kwsys_stl::string p; + int res = 0; + + typedef kwsys::CommandLineArguments argT; + arg.AddArgument("-n", argT::SPACE_ARGUMENT, &n, "Argument N"); + arg.AddArgument("-m", argT::EQUAL_ARGUMENT, &m, "Argument M"); + arg.AddBooleanArgument("-p", &p, "Argument P"); + + arg.StoreUnusedArguments(true); + + if ( !arg.Parse() ) + { + kwsys_ios::cerr << "Problem parsing arguments" << kwsys_ios::endl; + res = 1; + } + if ( n != 24 ) + { + kwsys_ios::cout << "Problem setting N. Value of N: " << n << kwsys_ios::endl; + res = 1; + } + if ( !m || strcmp(m, "test value") != 0 ) + { + kwsys_ios::cout << "Problem setting M. Value of M: " << m << kwsys_ios::endl; + res = 1; + } + if ( p != "1" ) + { + kwsys_ios::cout << "Problem setting P. Value of P: " << p.c_str() << kwsys_ios::endl; + res = 1; + } + kwsys_ios::cout << "Value of N: " << n << kwsys_ios::endl; + kwsys_ios::cout << "Value of M: " << m << kwsys_ios::endl; + kwsys_ios::cout << "Value of P: " << p.c_str() << kwsys_ios::endl; + + char** newArgv = 0; + int newArgc = 0; + arg.GetUnusedArguments(&newArgc, &newArgv); + int cc; + char* valid_unused_args[9] = { + 0, "--ignored", "--second-ignored", "third-ignored", + "some", "junk", "at", "the", "end" + }; + if ( newArgc != 9 ) + { + kwsys_ios::cerr << "Bad number of unused arguments: " << newArgc << kwsys_ios::endl; + res = 1; + } + for ( cc = 0; cc < newArgc; ++ cc ) + { + kwsys_ios::cout << "Unused argument[" << cc << "] = [" << newArgv[cc] << "]" + << kwsys_ios::endl; + if ( cc >= 9 ) + { + kwsys_ios::cerr << "Too many unused arguments: " << cc << kwsys_ios::endl; + res = 1; + } + else if ( valid_unused_args[cc] && + strcmp(valid_unused_args[cc], newArgv[cc]) != 0 ) + { + kwsys_ios::cerr << "Bad unused argument [" << cc << "] \"" + << newArgv[cc] << "\" should be: \"" << valid_unused_args[cc] << "\"" + << kwsys_ios::endl; + res = 1; + } + } + arg.DeleteRemainingArguments(newArgc, &newArgv); + + if ( m ) + { + delete [] m; + } + return res; +} +