ENH: Refactor CTest command argument handling
The previous approach to handling of arguments to ctest_* commands worked only for keyword/value arguments with a single value. This refactors the approach to allow some commands to define alternative argument forms.
This commit is contained in:
parent
02fb5880c1
commit
ae2c4143d2
|
@ -38,10 +38,29 @@ cmCTestHandlerCommand::cmCTestHandlerCommand()
|
||||||
bool cmCTestHandlerCommand
|
bool cmCTestHandlerCommand
|
||||||
::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
|
::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
|
||||||
{
|
{
|
||||||
if ( !this->ProcessArguments(args, (unsigned int)this->Last,
|
// Allocate space for argument values.
|
||||||
&*this->Arguments.begin(),this->Values) )
|
this->Values.clear();
|
||||||
|
this->Values.resize(this->Last, 0);
|
||||||
|
|
||||||
|
// Process input arguments.
|
||||||
|
this->ArgumentDoing = ArgumentDoingNone;
|
||||||
|
for(unsigned int i=0; i < args.size(); ++i)
|
||||||
{
|
{
|
||||||
return false;
|
// Check this argument.
|
||||||
|
if(!this->CheckArgumentKeyword(args[i]) &&
|
||||||
|
!this->CheckArgumentValue(args[i]))
|
||||||
|
{
|
||||||
|
cmOStringStream e;
|
||||||
|
e << "called with unknown argument \"" << args[i] << "\".";
|
||||||
|
this->SetError(e.str().c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Quit if an argument is invalid.
|
||||||
|
if(this->ArgumentDoing == ArgumentDoingError)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cmCTestLog(this->CTest, DEBUG, "Initialize handler" << std::endl;);
|
cmCTestLog(this->CTest, DEBUG, "Initialize handler" << std::endl;);
|
||||||
|
@ -121,57 +140,41 @@ bool cmCTestHandlerCommand
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cmCTestHandlerCommand::ProcessArguments(
|
//----------------------------------------------------------------------------
|
||||||
std::vector<std::string> const& args, int last, const char** strings,
|
bool cmCTestHandlerCommand::CheckArgumentKeyword(std::string const& arg)
|
||||||
std::vector<const char*>& values)
|
|
||||||
{
|
{
|
||||||
int state = 0;
|
// Check for a keyword in our argument/value table.
|
||||||
int cc;
|
for(unsigned int k=0; k < this->Arguments.size(); ++k)
|
||||||
values.resize(last);
|
|
||||||
for ( cc = 0; cc < last; ++ cc )
|
|
||||||
{
|
{
|
||||||
values[cc] = 0;
|
if(this->Arguments[k] && arg == this->Arguments[k])
|
||||||
}
|
|
||||||
|
|
||||||
for(size_t i=0; i < args.size(); ++i)
|
|
||||||
{
|
|
||||||
if ( state > 0 && state < last )
|
|
||||||
{
|
{
|
||||||
values[state] = args[i].c_str();
|
this->ArgumentDoing = ArgumentDoingKeyword;
|
||||||
cmCTestLog(this->CTest, DEBUG, "Set " << strings[state] << " to "
|
this->ArgumentIndex = k;
|
||||||
<< args[i].c_str() << std::endl);
|
return true;
|
||||||
state = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bool found = false;
|
|
||||||
for ( cc = 0; cc < last; ++ cc )
|
|
||||||
{
|
|
||||||
if ( strings[cc] && args[i] == strings[cc] )
|
|
||||||
{
|
|
||||||
state = cc;
|
|
||||||
if ( values[state] )
|
|
||||||
{
|
|
||||||
cmOStringStream ostr;
|
|
||||||
ostr << "called with incorrect number of arguments. "
|
|
||||||
<< strings[state] << " specified twice.";
|
|
||||||
this->SetError(ostr.str().c_str());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( !found )
|
|
||||||
{
|
|
||||||
cmOStringStream str;
|
|
||||||
str
|
|
||||||
<< "called with incorrect number of arguments. Extra argument is: "
|
|
||||||
<< args[i].c_str() << ".";
|
|
||||||
this->SetError(str.str().c_str());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
bool cmCTestHandlerCommand::CheckArgumentValue(std::string const& arg)
|
||||||
|
{
|
||||||
|
if(this->ArgumentDoing == ArgumentDoingKeyword)
|
||||||
|
{
|
||||||
|
this->ArgumentDoing = ArgumentDoingNone;
|
||||||
|
unsigned int k = this->ArgumentIndex;
|
||||||
|
if(this->Values[k])
|
||||||
|
{
|
||||||
|
cmOStringStream e;
|
||||||
|
e << "Called with more than one value for " << this->Arguments[k];
|
||||||
|
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
|
||||||
|
this->ArgumentDoing = ArgumentDoingError;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
this->Values[k] = arg.c_str();
|
||||||
|
cmCTestLog(this->CTest, DEBUG, "Set " << this->Arguments[k]
|
||||||
|
<< " to " << arg << "\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,8 +52,19 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual cmCTestGenericHandler* InitializeHandler() = 0;
|
virtual cmCTestGenericHandler* InitializeHandler() = 0;
|
||||||
bool ProcessArguments(std::vector<std::string> const& args,
|
|
||||||
int last, const char** strings, std::vector<const char*>& values);
|
// Command argument handling.
|
||||||
|
virtual bool CheckArgumentKeyword(std::string const& arg);
|
||||||
|
virtual bool CheckArgumentValue(std::string const& arg);
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
ArgumentDoingNone,
|
||||||
|
ArgumentDoingError,
|
||||||
|
ArgumentDoingKeyword,
|
||||||
|
ArgumentDoingLast1
|
||||||
|
};
|
||||||
|
int ArgumentDoing;
|
||||||
|
unsigned int ArgumentIndex;
|
||||||
|
|
||||||
std::string ReturnVariable;
|
std::string ReturnVariable;
|
||||||
std::vector<const char*> Arguments;
|
std::vector<const char*> Arguments;
|
||||||
|
|
Loading…
Reference in New Issue