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:
Brad King 2009-01-12 09:10:47 -05:00
parent 02fb5880c1
commit ae2c4143d2
2 changed files with 67 additions and 53 deletions

View File

@ -38,10 +38,29 @@ cmCTestHandlerCommand::cmCTestHandlerCommand()
bool cmCTestHandlerCommand
::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
{
if ( !this->ProcessArguments(args, (unsigned int)this->Last,
&*this->Arguments.begin(),this->Values) )
// Allocate space for argument 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;);
@ -121,57 +140,41 @@ bool cmCTestHandlerCommand
return true;
}
bool cmCTestHandlerCommand::ProcessArguments(
std::vector<std::string> const& args, int last, const char** strings,
std::vector<const char*>& values)
//----------------------------------------------------------------------------
bool cmCTestHandlerCommand::CheckArgumentKeyword(std::string const& arg)
{
int state = 0;
int cc;
values.resize(last);
for ( cc = 0; cc < last; ++ cc )
// Check for a keyword in our argument/value table.
for(unsigned int k=0; k < this->Arguments.size(); ++k)
{
values[cc] = 0;
}
for(size_t i=0; i < args.size(); ++i)
{
if ( state > 0 && state < last )
if(this->Arguments[k] && arg == this->Arguments[k])
{
values[state] = args[i].c_str();
cmCTestLog(this->CTest, DEBUG, "Set " << strings[state] << " to "
<< args[i].c_str() << std::endl);
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;
}
this->ArgumentDoing = ArgumentDoingKeyword;
this->ArgumentIndex = k;
return true;
}
}
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;
}

View File

@ -52,8 +52,19 @@ public:
protected:
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::vector<const char*> Arguments;