From 0c225eb5b969e4f4d93d12dc337927abb25e6878 Mon Sep 17 00:00:00 2001 From: Ken Martin Date: Fri, 21 Jan 2005 09:38:04 -0500 Subject: [PATCH] ENH: added while command --- Source/cmCommands.cxx | 4 ++ Source/cmEndWhileCommand.cxx | 24 +++++++ Source/cmEndWhileCommand.h | 88 ++++++++++++++++++++++++++ Source/cmWhileCommand.cxx | 99 +++++++++++++++++++++++++++++ Source/cmWhileCommand.h | 118 +++++++++++++++++++++++++++++++++++ 5 files changed, 333 insertions(+) create mode 100644 Source/cmEndWhileCommand.cxx create mode 100644 Source/cmEndWhileCommand.h create mode 100644 Source/cmWhileCommand.cxx create mode 100644 Source/cmWhileCommand.h diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx index 0898b0dbc..c91021fe3 100644 --- a/Source/cmCommands.cxx +++ b/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& 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& 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 } diff --git a/Source/cmEndWhileCommand.cxx b/Source/cmEndWhileCommand.cxx new file mode 100644 index 000000000..6d62e78a4 --- /dev/null +++ b/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 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; +} + diff --git a/Source/cmEndWhileCommand.h b/Source/cmEndWhileCommand.h new file mode 100644 index 000000000..1f8453e32 --- /dev/null +++ b/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 const&); + + /** + * This is called when the command is first encountered in + * the CMakeLists.txt file. + */ + virtual bool InitialPass(std::vector 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 diff --git a/Source/cmWhileCommand.cxx b/Source/cmWhileCommand.cxx new file mode 100644 index 000000000..352a19573 --- /dev/null +++ b/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 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& 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; +} + diff --git a/Source/cmWhileCommand.h b/Source/cmWhileCommand.h new file mode 100644 index 000000000..752867f5f --- /dev/null +++ b/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 m_Args; + std::vector 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& args); + + /** + * This is called when the command is first encountered in + * the CMakeLists.txt file. + */ + virtual bool InitialPass(std::vector 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