[Cmake-commits] [cmake-commits] king committed cmMakefile.cxx 1.493 1.494 cmMakefile.h 1.243 1.244

cmake-commits at cmake.org cmake-commits at cmake.org
Wed Jan 21 09:48:02 EST 2009


Update of /cvsroot/CMake/CMake/Source
In directory public:/mounts/ram/cvs-serv8272/Source

Modified Files:
	cmMakefile.cxx cmMakefile.h 
Log Message:
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.


Index: cmMakefile.h
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmMakefile.h,v
retrieving revision 1.243
retrieving revision 1.244
diff -C 2 -d -r1.243 -r1.244
*** cmMakefile.h	20 Jan 2009 19:36:18 -0000	1.243
--- cmMakefile.h	21 Jan 2009 14:48:00 -0000	1.244
***************
*** 99,102 ****
--- 99,115 ----
    RemoveFunctionBlocker(const cmListFileFunction& lff);
  
+   /** Push/pop a lexical (function blocker) barrier automatically.  */
+   class LexicalPushPop
+   {
+   public:
+     LexicalPushPop(cmMakefile* mf);
+     ~LexicalPushPop();
+     void Quiet() { this->ReportError = false; }
+   private:
+     cmMakefile* Makefile;
+     bool ReportError;
+   };
+   friend class LexicalPushPop;
+ 
    /**
     * Try running cmake and building a file. This is used for dynalically
***************
*** 877,881 ****
  
    void AddDefaultDefinitions();
!   std::list<cmFunctionBlocker *> FunctionBlockers;
  
    typedef std::map<cmStdString, cmData*> DataMapType;
--- 890,898 ----
  
    void AddDefaultDefinitions();
!   typedef std::vector<cmFunctionBlocker*> FunctionBlockersType;
!   FunctionBlockersType FunctionBlockers;
!   std::vector<FunctionBlockersType::size_type> FunctionBlockerBarriers;
!   void PushFunctionBlockerBarrier();
!   void PopFunctionBlockerBarrier(bool reportError = true);
  
    typedef std::map<cmStdString, cmData*> DataMapType;

Index: cmMakefile.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmMakefile.cxx,v
retrieving revision 1.493
retrieving revision 1.494
diff -C 2 -d -r1.493 -r1.494
*** cmMakefile.cxx	20 Jan 2009 19:36:18 -0000	1.493
--- cmMakefile.cxx	21 Jan 2009 14:48:00 -0000	1.494
***************
*** 207,211 ****
        }
      }
!   std::list<cmFunctionBlocker *>::iterator pos;
    for (pos = this->FunctionBlockers.begin();
         pos != this->FunctionBlockers.end(); ++pos)
--- 207,211 ----
        }
      }
!   std::vector<cmFunctionBlocker*>::iterator pos;
    for (pos = this->FunctionBlockers.begin();
         pos != this->FunctionBlockers.end(); ++pos)
***************
*** 454,461 ****
    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;
--- 454,457 ----
***************
*** 488,499 ****
      }
  
-   // 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;
--- 484,487 ----
***************
*** 542,545 ****
--- 530,537 ----
    // 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;
  
***************
*** 553,561 ****
      cmExecutionStatus status;
      this->ExecuteCommand(cacheFile.Functions[i],status);
!     if (status.GetReturnInvoked() ||
!         cmSystemTools::GetFatalErrorOccured() )
        {
!       // Exit early from processing this file.
        endScopeNicely = false;
        break;
        }
--- 545,558 ----
      cmExecutionStatus status;
      this->ExecuteCommand(cacheFile.Functions[i],status);
!     if(cmSystemTools::GetFatalErrorOccured())
        {
!       // Exit early due to error.
        endScopeNicely = false;
+       lexScope.Quiet();
+       break;
+       }
+     if(status.GetReturnInvoked())
+       {
+       // Exit early due to return command.
        break;
        }
***************
*** 572,592 ****
      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
--- 569,573 ----
      this->PopPolicy(false);
      }
!   }
  
    // If this is the directory-level CMakeLists.txt file then perform
***************
*** 2354,2358 ****
    // 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;
    for (pos = this->FunctionBlockers.rbegin();
         pos != this->FunctionBlockers.rend(); ++pos)
--- 2335,2339 ----
    // loop over all function blockers to see if any block this command
    // evaluate in reverse, this is critical for balanced IF statements etc
!   std::vector<cmFunctionBlocker*>::reverse_iterator pos;
    for (pos = this->FunctionBlockers.rbegin();
         pos != this->FunctionBlockers.rend(); ++pos)
***************
*** 2367,2370 ****
--- 2348,2377 ----
  }
  
+ //----------------------------------------------------------------------------
+ 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,
***************
*** 2399,2411 ****
  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)
      {
      if ((*pos)->ShouldRemove(lff, *this))
        {
        cmFunctionBlocker* b = *pos;
!       this->FunctionBlockers.remove(b);
        return cmsys::auto_ptr<cmFunctionBlocker>(b);
        }
--- 2406,2427 ----
  cmMakefile::RemoveFunctionBlocker(const cmListFileFunction& lff)
  {
!   // 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.erase(pos);
        return cmsys::auto_ptr<cmFunctionBlocker>(b);
        }
***************
*** 2415,2418 ****
--- 2431,2447 ----
  }
  
+ //----------------------------------------------------------------------------
+ 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)
  {



More information about the Cmake-commits mailing list