summaryrefslogtreecommitdiffstats
path: root/Source/cmMakefile.cxx
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2009-01-21 14:48:00 (GMT)
committerBrad King <brad.king@kitware.com>2009-01-21 14:48:00 (GMT)
commitb8f5a934ecb83f0124be8485708d4d6d763682fd (patch)
treed0fe8d5148a7f56eb62e222dd4e2bcbde633d438 /Source/cmMakefile.cxx
parentf4d37eebb26a62d2522e7d321b09f19242826d8d (diff)
downloadCMake-b8f5a934ecb83f0124be8485708d4d6d763682fd.zip
CMake-b8f5a934ecb83f0124be8485708d4d6d763682fd.tar.gz
CMake-b8f5a934ecb83f0124be8485708d4d6d763682fd.tar.bz2
ENH: Refactor logical block enforcement
This uses a stack of 'barriers' to efficiently divide function blockers into groups corresponding to each input file. It simplifies detection of missing block close commands and factors it out of ReadListFile.
Diffstat (limited to 'Source/cmMakefile.cxx')
-rw-r--r--Source/cmMakefile.cxx107
1 files changed, 68 insertions, 39 deletions
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index ed70c07..34b4855 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -206,7 +206,7 @@ cmMakefile::~cmMakefile()
delete d->second;
}
}
- std::list<cmFunctionBlocker *>::iterator pos;
+ std::vector<cmFunctionBlocker*>::iterator pos;
for (pos = this->FunctionBlockers.begin();
pos != this->FunctionBlockers.end(); ++pos)
{
@@ -453,10 +453,6 @@ bool cmMakefile::ReadListFile(const char* filename_in,
= this->GetSafeDefinition("CMAKE_CURRENT_LIST_FILE");
this->AddDefinition("CMAKE_PARENT_LIST_FILE", filename_in);
- // used to watch for blockers going out of scope
- // e.g. mismatched IF statement
- std::set<cmFunctionBlocker *> originalBlockers;
-
const char* external = 0;
std::string external_abs;
@@ -487,14 +483,6 @@ bool cmMakefile::ReadListFile(const char* filename_in,
}
}
- // loop over current function blockers and record them
- for (std::list<cmFunctionBlocker *>::iterator pos
- = this->FunctionBlockers.begin();
- pos != this->FunctionBlockers.end(); ++pos)
- {
- originalBlockers.insert(*pos);
- }
-
// Now read the input file
const char *filenametoread= filename;
@@ -541,6 +529,10 @@ bool cmMakefile::ReadListFile(const char* filename_in,
}
// add this list file to the list of dependencies
this->ListFiles.push_back( filenametoread);
+
+ // Enforce balanced blocks (if/endif, function/endfunction, etc.).
+ {
+ LexicalPushPop lexScope(this);
bool endScopeNicely = true;
// Save the current policy stack depth.
@@ -552,11 +544,16 @@ bool cmMakefile::ReadListFile(const char* filename_in,
{
cmExecutionStatus status;
this->ExecuteCommand(cacheFile.Functions[i],status);
- if (status.GetReturnInvoked() ||
- cmSystemTools::GetFatalErrorOccured() )
+ if(cmSystemTools::GetFatalErrorOccured())
{
- // Exit early from processing this file.
+ // Exit early due to error.
endScopeNicely = false;
+ lexScope.Quiet();
+ break;
+ }
+ if(status.GetReturnInvoked())
+ {
+ // Exit early due to return command.
break;
}
}
@@ -571,23 +568,7 @@ bool cmMakefile::ReadListFile(const char* filename_in,
}
this->PopPolicy(false);
}
-
- // send scope ended to and function blockers
- if (endScopeNicely)
- {
- // loop over all function blockers to see if any block this command
- for (std::list<cmFunctionBlocker *>::iterator pos
- = this->FunctionBlockers.begin();
- pos != this->FunctionBlockers.end(); ++pos)
- {
- // if this blocker was not in the original then send a
- // scope ended message
- if (originalBlockers.find(*pos) == originalBlockers.end())
- {
- (*pos)->ScopeEnded(*this);
- }
- }
- }
+ }
// If this is the directory-level CMakeLists.txt file then perform
// some extra checks.
@@ -2353,7 +2334,7 @@ bool cmMakefile::IsFunctionBlocked(const cmListFileFunction& lff,
// loop over all function blockers to see if any block this command
// evaluate in reverse, this is critical for balanced IF statements etc
- std::list<cmFunctionBlocker *>::reverse_iterator pos;
+ std::vector<cmFunctionBlocker*>::reverse_iterator pos;
for (pos = this->FunctionBlockers.rbegin();
pos != this->FunctionBlockers.rend(); ++pos)
{
@@ -2366,6 +2347,32 @@ bool cmMakefile::IsFunctionBlocked(const cmListFileFunction& lff,
return false;
}
+//----------------------------------------------------------------------------
+void cmMakefile::PushFunctionBlockerBarrier()
+{
+ this->FunctionBlockerBarriers.push_back(this->FunctionBlockers.size());
+}
+
+//----------------------------------------------------------------------------
+void cmMakefile::PopFunctionBlockerBarrier(bool reportError)
+{
+ // Remove any extra entries pushed on the barrier.
+ FunctionBlockersType::size_type barrier =
+ this->FunctionBlockerBarriers.back();
+ while(this->FunctionBlockers.size() > barrier)
+ {
+ cmsys::auto_ptr<cmFunctionBlocker> fb(this->FunctionBlockers.back());
+ this->FunctionBlockers.pop_back();
+ if(reportError)
+ {
+ fb->ScopeEnded(*this);
+ }
+ }
+
+ // Remove the barrier.
+ this->FunctionBlockerBarriers.pop_back();
+}
+
bool cmMakefile::ExpandArguments(
std::vector<cmListFileArgument> const& inArgs,
std::vector<std::string>& outArgs)
@@ -2398,15 +2405,24 @@ bool cmMakefile::ExpandArguments(
cmsys::auto_ptr<cmFunctionBlocker>
cmMakefile::RemoveFunctionBlocker(const cmListFileFunction& lff)
{
- // loop over all function blockers to see if any block this command
- std::list<cmFunctionBlocker *>::reverse_iterator pos;
- for (pos = this->FunctionBlockers.rbegin();
- pos != this->FunctionBlockers.rend(); ++pos)
+ // Find the function blocker stack barrier for the current scope.
+ // We only remove a blocker whose index is not less than the barrier.
+ FunctionBlockersType::size_type barrier = 0;
+ if(!this->FunctionBlockerBarriers.empty())
{
+ barrier = this->FunctionBlockerBarriers.back();
+ }
+
+ // Search for the function blocker whose scope this command ends.
+ for(FunctionBlockersType::size_type
+ i = this->FunctionBlockers.size(); i > barrier; --i)
+ {
+ std::vector<cmFunctionBlocker*>::iterator pos =
+ this->FunctionBlockers.begin() + (i - 1);
if ((*pos)->ShouldRemove(lff, *this))
{
cmFunctionBlocker* b = *pos;
- this->FunctionBlockers.remove(b);
+ this->FunctionBlockers.erase(pos);
return cmsys::auto_ptr<cmFunctionBlocker>(b);
}
}
@@ -2414,6 +2430,19 @@ cmMakefile::RemoveFunctionBlocker(const cmListFileFunction& lff)
return cmsys::auto_ptr<cmFunctionBlocker>();
}
+//----------------------------------------------------------------------------
+cmMakefile::LexicalPushPop::LexicalPushPop(cmMakefile* mf):
+ Makefile(mf), ReportError(true)
+{
+ this->Makefile->PushFunctionBlockerBarrier();
+}
+
+//----------------------------------------------------------------------------
+cmMakefile::LexicalPushPop::~LexicalPushPop()
+{
+ this->Makefile->PopFunctionBlockerBarrier(this->ReportError);
+}
+
void cmMakefile::SetHomeDirectory(const char* dir)
{
this->cmHomeDirectory = dir;