Ken Martin 21 лет назад
Родитель
Сommit
0c225eb5b9
5 измененных файлов с 333 добавлено и 0 удалено
  1. 4 0
      Source/cmCommands.cxx
  2. 24 0
      Source/cmEndWhileCommand.cxx
  3. 88 0
      Source/cmEndWhileCommand.h
  4. 99 0
      Source/cmWhileCommand.cxx
  5. 118 0
      Source/cmWhileCommand.h

+ 4 - 0
Source/cmCommands.cxx

@@ -79,6 +79,7 @@
 #if defined(CMAKE_BUILD_WITH_CMAKE)
 #include "cmAbstractFilesCommand.cxx"
 #include "cmAuxSourceDirectoryCommand.cxx"
+#include "cmEndWhileCommand.cxx"
 #include "cmExportLibraryDependencies.cxx"
 #include "cmEnableLanguageCommand.cxx"
 #include "cmFLTKWrapUICommand.cxx"
@@ -104,6 +105,7 @@
 #include "cmQTWrapUICommand.cxx"
 #include "cmUseMangledMesaCommand.cxx"
 #include "cmUtilitySourceCommand.cxx"
+#include "cmWhileCommand.cxx"
 #include "cmWrapExcludeFilesCommand.cxx"
 
 // This one must be last because it includes windows.h and
@@ -173,6 +175,7 @@ void GetPredefinedCommands(std::list<cmCommand*>& commands)
   commands.push_back(new cmAbstractFilesCommand);
   commands.push_back(new cmAuxSourceDirectoryCommand);
   commands.push_back(new cmEnableLanguageCommand);
+  commands.push_back(new cmEndWhileCommand);
   commands.push_back(new cmExportLibraryDependenciesCommand);
   commands.push_back(new cmFLTKWrapUICommand);
   commands.push_back(new cmGetCMakePropertyCommand);
@@ -198,6 +201,7 @@ void GetPredefinedCommands(std::list<cmCommand*>& commands)
   commands.push_back(new cmQTWrapUICommand);
   commands.push_back(new cmUseMangledMesaCommand);
   commands.push_back(new cmUtilitySourceCommand);
+  commands.push_back(new cmWhileCommand);
   commands.push_back(new cmWrapExcludeFilesCommand);
 #endif
 }

+ 24 - 0
Source/cmEndWhileCommand.cxx

@@ -0,0 +1,24 @@
+/*=========================================================================
+
+  Program:   CMake - Cross-Platform Makefile Generator
+  Module:    $RCSfile$
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+  Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
+  See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even 
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+     PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+#include "cmEndWhileCommand.h"
+
+bool cmEndWhileCommand::InvokeInitialPass(std::vector<cmListFileArgument> const&)
+{
+  this->SetError("An ENDWHILE command was found outside of a proper WHILE ENDWHILE structure. Or its arguments did not match the opening WHILE command.");
+  return false;
+}
+

+ 88 - 0
Source/cmEndWhileCommand.h

@@ -0,0 +1,88 @@
+/*=========================================================================
+
+  Program:   CMake - Cross-Platform Makefile Generator
+  Module:    $RCSfile$
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+  Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
+  See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even 
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+     PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+#ifndef cmEndWhileCommand_h
+#define cmEndWhileCommand_h
+
+#include "cmCommand.h"
+
+/** \class cmEndWhileCommand
+ * \brief ends an if block
+ *
+ * cmEndWhileCommand ends an if block
+ */
+class cmEndWhileCommand : public cmCommand
+{
+public:
+  /**
+   * This is a virtual constructor for the command.
+   */
+  virtual cmCommand* Clone() 
+    {
+    return new cmEndWhileCommand;
+    }
+
+  /**
+   * Override cmCommand::InvokeInitialPass to get arguments before
+   * expansion.
+   */
+  virtual bool InvokeInitialPass(std::vector<cmListFileArgument> const&);
+  
+  /**
+   * This is called when the command is first encountered in
+   * the CMakeLists.txt file.
+   */
+  virtual bool InitialPass(std::vector<std::string> const&) {return false;}
+
+  /**
+   * This determines if the command gets propagated down
+   * to makefiles located in subdirectories.
+   */
+  virtual bool IsInherited() {return true;}
+
+  /**
+   * This determines if the command is invoked when in script mode.
+   */
+  virtual bool IsScriptable() { return true; }
+
+  /**
+   * The name of the command as specified in CMakeList.txt.
+   */
+  virtual const char* GetName() { return "ENDWHILE";}
+
+  /**
+   * Succinct documentation.
+   */
+  virtual const char* GetTerseDocumentation() 
+    {
+    return "Ends a list of commands in a WHILE block.";
+    }
+  
+  /**
+   * More documentation.
+   */
+  virtual const char* GetFullDocumentation()
+    {
+    return
+      "  ENDWHILE(expression)\n"
+      "See WHILE command.";
+    }
+  
+  cmTypeMacro(cmEndWhileCommand, cmCommand);
+};
+
+
+#endif

+ 99 - 0
Source/cmWhileCommand.cxx

@@ -0,0 +1,99 @@
+/*=========================================================================
+
+  Program:   CMake - Cross-Platform Makefile Generator
+  Module:    $RCSfile$
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+  Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
+  See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even 
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+     PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+#include "cmWhileCommand.h"
+
+bool cmWhileFunctionBlocker::
+IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf) 
+{
+  // Prevent recusion and don't let this blocker block its own
+  // commands.
+  if (m_Executing)
+    {
+    return false;
+    }
+  
+  // at end of for each execute recorded commands
+  if (lff.m_Name == "ENDWHILE")
+    {
+    char* errorString = 0;
+    
+    std::vector<std::string> expandedArguments;
+    mf.ExpandArguments(m_Args, expandedArguments);
+    bool isTrue = 
+      cmIfCommand::IsTrue(expandedArguments,&errorString,&mf);
+
+    m_Executing = true;
+    while (isTrue)
+      {      
+      // Invoke all the functions that were collected in the block.
+      for(unsigned int c = 0; c < m_Functions.size(); ++c)
+        {
+        mf.ExecuteCommand(m_Functions[c]);
+        }
+      expandedArguments.clear();
+      mf.ExpandArguments(m_Args, expandedArguments);
+      isTrue = 
+        cmIfCommand::IsTrue(expandedArguments,&errorString,&mf);
+      }
+    mf.RemoveFunctionBlocker(lff);
+    return true;
+    }
+
+  // record the command
+  m_Functions.push_back(lff);
+  
+  // always return true
+  return true;
+}
+
+bool cmWhileFunctionBlocker::
+ShouldRemove(const cmListFileFunction& lff, cmMakefile& mf)
+{
+  if(lff.m_Name == "ENDWHILE")
+    {
+    if (lff.m_Arguments == m_Args)
+      {
+      return true;
+      }
+    }
+  return false;
+}
+
+void cmWhileFunctionBlocker::
+ScopeEnded(cmMakefile &mf) 
+{
+  cmSystemTools::Error("The end of a CMakeLists file was reached with a WHILE statement that was not closed properly. Within the directory: ", 
+                       mf.GetCurrentDirectory());
+}
+
+bool cmWhileCommand::InvokeInitialPass(
+  const std::vector<cmListFileArgument>& args)
+{
+  if(args.size() < 1)
+    {
+    this->SetError("called with incorrect number of arguments");
+    return false;
+    }
+  
+  // create a function blocker
+  cmWhileFunctionBlocker *f = new cmWhileFunctionBlocker();
+  f->m_Args = args;
+  m_Makefile->AddFunctionBlocker(f);
+  
+  return true;
+}
+

+ 118 - 0
Source/cmWhileCommand.h

@@ -0,0 +1,118 @@
+/*=========================================================================
+
+  Program:   CMake - Cross-Platform Makefile Generator
+  Module:    $RCSfile$
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+  Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
+  See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even 
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+     PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+#ifndef cmWhileCommand_h
+#define cmWhileCommand_h
+
+#include "cmCommand.h"
+#include "cmFunctionBlocker.h"
+#include "cmListFileCache.h"
+
+/** \class cmWhileFunctionBlocker
+ * \brief subclass of function blocker
+ *
+ * 
+ */
+class cmWhileFunctionBlocker : public cmFunctionBlocker
+{
+public:
+  cmWhileFunctionBlocker() {m_Executing = false;}
+  virtual ~cmWhileFunctionBlocker() {}
+  virtual bool IsFunctionBlocked(const cmListFileFunction& lff,
+                                 cmMakefile &mf);
+  virtual bool ShouldRemove(const cmListFileFunction& lff, cmMakefile &mf);
+  virtual void ScopeEnded(cmMakefile &mf);
+  
+  std::vector<cmListFileArgument> m_Args;
+  std::vector<cmListFileFunction> m_Functions;
+  bool m_Executing;
+};
+
+/** \class cmWhileCommand
+ * \brief starts a while loop
+ *
+ * cmWhileCommand starts a while loop
+ */
+class cmWhileCommand : public cmCommand
+{
+public:
+  /**
+   * This is a virtual constructor for the command.
+   */
+  virtual cmCommand* Clone() 
+    {
+    return new cmWhileCommand;
+    }
+
+  /**
+   * This overrides the default InvokeInitialPass implementation.
+   * It records the arguments before expansion.
+   */
+  virtual bool InvokeInitialPass(const std::vector<cmListFileArgument>& args);
+    
+  /**
+   * This is called when the command is first encountered in
+   * the CMakeLists.txt file.
+   */
+  virtual bool InitialPass(std::vector<std::string> const&) { return false; }
+
+  /**
+   * This determines if the command gets propagated down
+   * to makefiles located in subdirectories.
+   */
+  virtual bool IsInherited() {return true;}
+
+  /**
+   * This determines if the command is invoked when in script mode.
+   */
+  virtual bool IsScriptable() { return true; }
+
+  /**
+   * The name of the command as specified in CMakeList.txt.
+   */
+  virtual const char* GetName() { return "WHILE";}
+
+  /**
+   * Succinct documentation.
+   */
+  virtual const char* GetTerseDocumentation() 
+    {
+    return "Evaluate a group of commands while a condition is true";
+    }
+  
+  /**
+   * More documentation.
+   */
+  virtual const char* GetFullDocumentation()
+    {
+    return
+      "  WHILE(condition)\n"
+      "    COMMAND1(ARGS ...)\n"
+      "    COMMAND2(ARGS ...)\n"
+      "    ...\n"
+      "  ENDWHILE(condition)\n"
+      "All commands between WHILE and the matching ENDWHILE are recorded "
+      "without being invoked.  Once the ENDWHILE is evaluated, the "
+      "recorded list of commands is invoked as long as the condition "
+      "is true. The condition is evaulated using the same logic as the "
+      "FOR command.";
+    }
+  
+  cmTypeMacro(cmWhileCommand, cmCommand);
+};
+
+
+#endif