ENH: allow loose loop constructs

This commit is contained in:
Ken Martin 2006-05-18 13:50:01 -04:00
parent 095e975c81
commit 29a03db7ce
5 changed files with 74 additions and 63 deletions

View File

@ -25,14 +25,18 @@ IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf)
{ {
return false; return false;
} }
// at end of for each execute recorded commands if (cmSystemTools::LowerCase(lff.Name) == "foreach")
if (cmSystemTools::LowerCase(lff.Name) == "endforeach")
{ {
std::vector<std::string> expandedArguments; // record the number of nested foreach commands
mf.ExpandArguments(lff.Arguments, expandedArguments); this->Depth++;
if(!expandedArguments.empty() && (expandedArguments[0] == this->Args[0])) }
else if (cmSystemTools::LowerCase(lff.Name) == "endforeach")
{
// if this is the endofreach for this statement
if (!this->Depth)
{ {
// at end of for each execute recorded commands
// store the old value // store the old value
std::string oldDef; std::string oldDef;
if (mf.GetDefinition(this->Args[0].c_str())) if (mf.GetDefinition(this->Args[0].c_str()))
@ -60,8 +64,13 @@ IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf)
mf.RemoveFunctionBlocker(lff); mf.RemoveFunctionBlocker(lff);
return true; return true;
} }
else
{
// close out a nested foreach
this->Depth--;
}
} }
// record the command // record the command
this->Functions.push_back(lff); this->Functions.push_back(lff);
@ -76,7 +85,9 @@ ShouldRemove(const cmListFileFunction& lff, cmMakefile& mf)
{ {
std::vector<std::string> expandedArguments; std::vector<std::string> expandedArguments;
mf.ExpandArguments(lff.Arguments, expandedArguments); mf.ExpandArguments(lff.Arguments, expandedArguments);
if(!expandedArguments.empty() && (expandedArguments[0] == this->Args[0])) if ((!expandedArguments.empty() &&
(expandedArguments[0] == this->Args[0]))
|| mf.IsOn("CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS"))
{ {
return true; return true;
} }

View File

@ -29,7 +29,7 @@
class cmForEachFunctionBlocker : public cmFunctionBlocker class cmForEachFunctionBlocker : public cmFunctionBlocker
{ {
public: public:
cmForEachFunctionBlocker() {this->Executing = false;} cmForEachFunctionBlocker() {this->Executing = false; Depth = 0;}
virtual ~cmForEachFunctionBlocker() {} virtual ~cmForEachFunctionBlocker() {}
virtual bool IsFunctionBlocked(const cmListFileFunction& lff, virtual bool IsFunctionBlocked(const cmListFileFunction& lff,
cmMakefile &mf); cmMakefile &mf);
@ -39,6 +39,8 @@ public:
std::vector<std::string> Args; std::vector<std::string> Args;
std::vector<cmListFileFunction> Functions; std::vector<cmListFileFunction> Functions;
bool Executing; bool Executing;
private:
int Depth;
}; };
/** \class cmForEachCommand /** \class cmForEachCommand

View File

@ -34,53 +34,34 @@ IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf)
if (cmSystemTools::LowerCase(lff.Name) == "else" || if (cmSystemTools::LowerCase(lff.Name) == "else" ||
cmSystemTools::LowerCase(lff.Name) == "endif") cmSystemTools::LowerCase(lff.Name) == "endif")
{ {
if (args == this->Args) // if it was an else statement then we should change state
{ // and block this Else Command
// if it was an else statement then we should change state if (cmSystemTools::LowerCase(lff.Name) == "else")
// and block this Else Command
if (cmSystemTools::LowerCase(lff.Name) == "else")
{ {
this->IsBlocking = !this->IsBlocking; this->IsBlocking = !this->IsBlocking;
return true; return true;
} }
// otherwise it must be an ENDIF statement, in that case remove the // otherwise it must be an ENDIF statement, in that case remove the
// function blocker // function blocker
mf.RemoveFunctionBlocker(lff); mf.RemoveFunctionBlocker(lff);
return true; return true;
} }
else if(args.empty())
{
std::string err = "Empty arguments for ";
err += name;
err += ". Did you mean ";
err += name;
err += "( ";
for(std::vector<cmListFileArgument>::const_iterator a =
this->Args.begin();
a != this->Args.end();++a)
{
err += (a->Quoted?"\"":"");
err += a->Value;
err += (a->Quoted?"\"":"");
err += " ";
}
err += ")?";
cmSystemTools::Error(err.c_str());
}
}
return this->IsBlocking; return this->IsBlocking;
} }
bool cmIfFunctionBlocker::ShouldRemove(const cmListFileFunction& lff, bool cmIfFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
cmMakefile&) cmMakefile& mf)
{ {
if (cmSystemTools::LowerCase(lff.Name) == "endif") if (cmSystemTools::LowerCase(lff.Name) == "endif")
{ {
if (lff.Arguments == this->Args) if (mf.IsOn("CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS")
|| lff.Arguments == this->Args)
{ {
return true; return true;
} }
} }
return false; return false;
} }

View File

@ -28,30 +28,44 @@ IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf)
} }
// at end of for each execute recorded commands // at end of for each execute recorded commands
if (cmSystemTools::LowerCase(lff.Name) == "endwhile") if (cmSystemTools::LowerCase(lff.Name) == "while")
{ {
char* errorString = 0; // record the number of while commands past this one
this->Depth++;
}
else if (cmSystemTools::LowerCase(lff.Name) == "endwhile")
{
// if this is the endwhile for this while loop then execute
if (!this->Depth)
{
char* errorString = 0;
std::vector<std::string> expandedArguments; std::vector<std::string> expandedArguments;
mf.ExpandArguments(this->Args, expandedArguments);
bool isTrue =
cmIfCommand::IsTrue(expandedArguments,&errorString,&mf);
this->Executing = true;
while (isTrue)
{
// Invoke all the functions that were collected in the block.
for(unsigned int c = 0; c < this->Functions.size(); ++c)
{
mf.ExecuteCommand(this->Functions[c]);
}
expandedArguments.clear();
mf.ExpandArguments(this->Args, expandedArguments); mf.ExpandArguments(this->Args, expandedArguments);
isTrue = bool isTrue =
cmIfCommand::IsTrue(expandedArguments,&errorString,&mf); cmIfCommand::IsTrue(expandedArguments,&errorString,&mf);
this->Executing = true;
while (isTrue)
{
// Invoke all the functions that were collected in the block.
for(unsigned int c = 0; c < this->Functions.size(); ++c)
{
mf.ExecuteCommand(this->Functions[c]);
}
expandedArguments.clear();
mf.ExpandArguments(this->Args, expandedArguments);
isTrue =
cmIfCommand::IsTrue(expandedArguments,&errorString,&mf);
}
mf.RemoveFunctionBlocker(lff);
return true;
}
else
{
// decrement for each nested while that ends
this->Depth--;
} }
mf.RemoveFunctionBlocker(lff);
return true;
} }
// record the command // record the command
@ -62,11 +76,12 @@ IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf)
} }
bool cmWhileFunctionBlocker:: bool cmWhileFunctionBlocker::
ShouldRemove(const cmListFileFunction& lff, cmMakefile& ) ShouldRemove(const cmListFileFunction& lff, cmMakefile& mf)
{ {
if(cmSystemTools::LowerCase(lff.Name) == "endwhile") if(cmSystemTools::LowerCase(lff.Name) == "endwhile")
{ {
if (lff.Arguments == this->Args) if (lff.Arguments == this->Args
|| mf.IsOn("CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS"))
{ {
return true; return true;
} }

View File

@ -29,7 +29,7 @@
class cmWhileFunctionBlocker : public cmFunctionBlocker class cmWhileFunctionBlocker : public cmFunctionBlocker
{ {
public: public:
cmWhileFunctionBlocker() {Executing = false;} cmWhileFunctionBlocker() {Executing = false; Depth=0;}
virtual ~cmWhileFunctionBlocker() {} virtual ~cmWhileFunctionBlocker() {}
virtual bool IsFunctionBlocked(const cmListFileFunction& lff, virtual bool IsFunctionBlocked(const cmListFileFunction& lff,
cmMakefile &mf); cmMakefile &mf);
@ -39,6 +39,8 @@ public:
std::vector<cmListFileArgument> Args; std::vector<cmListFileArgument> Args;
std::vector<cmListFileFunction> Functions; std::vector<cmListFileFunction> Functions;
bool Executing; bool Executing;
private:
int Depth;
}; };
/** \class cmWhileCommand /** \class cmWhileCommand