diff options
Diffstat (limited to 'Source/cmIfCommand.cxx')
-rw-r--r-- | Source/cmIfCommand.cxx | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/Source/cmIfCommand.cxx b/Source/cmIfCommand.cxx new file mode 100644 index 0000000..f728c15 --- /dev/null +++ b/Source/cmIfCommand.cxx @@ -0,0 +1,230 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2009 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#include "cmIfCommand.h" +#include "cmStringCommand.h" + +#include "cmConditionEvaluator.h" + +#include <stdlib.h> // required for atof +#include <list> +#include <cmsys/RegularExpression.hxx> + + +static std::string cmIfCommandError( + cmMakefile* mf, std::vector<cmExpandedCommandArgument> const& args) +{ + cmLocalGenerator* lg = mf->GetLocalGenerator(); + std::string err = "given arguments:\n "; + for(std::vector<cmExpandedCommandArgument>::const_iterator i = args.begin(); + i != args.end(); ++i) + { + err += " "; + err += lg->EscapeForCMake(i->GetValue()); + } + err += "\n"; + return err; +} + +//========================================================================= +bool cmIfFunctionBlocker:: +IsFunctionBlocked(const cmListFileFunction& lff, + cmMakefile &mf, + cmExecutionStatus &inStatus) +{ + // we start by recording all the functions + if (!cmSystemTools::Strucmp(lff.Name.c_str(),"if")) + { + this->ScopeDepth++; + } + if (!cmSystemTools::Strucmp(lff.Name.c_str(),"endif")) + { + this->ScopeDepth--; + // if this is the endif for this if statement, then start executing + if (!this->ScopeDepth) + { + // Remove the function blocker for this scope or bail. + cmsys::auto_ptr<cmFunctionBlocker> + fb(mf.RemoveFunctionBlocker(this, lff)); + if(!fb.get()) { return false; } + + // execute the functions for the true parts of the if statement + cmExecutionStatus status; + int scopeDepth = 0; + for(unsigned int c = 0; c < this->Functions.size(); ++c) + { + // keep track of scope depth + if (!cmSystemTools::Strucmp(this->Functions[c].Name.c_str(),"if")) + { + scopeDepth++; + } + if (!cmSystemTools::Strucmp(this->Functions[c].Name.c_str(),"endif")) + { + scopeDepth--; + } + // watch for our state change + if (scopeDepth == 0 && + !cmSystemTools::Strucmp(this->Functions[c].Name.c_str(),"else")) + { + this->IsBlocking = this->HasRun; + this->HasRun = true; + + // if trace is enabled, print a (trivially) evaluated "else" + // statement + if(!this->IsBlocking && mf.GetCMakeInstance()->GetTrace()) + { + mf.PrintCommandTrace(this->Functions[c]); + } + } + else if (scopeDepth == 0 && !cmSystemTools::Strucmp + (this->Functions[c].Name.c_str(),"elseif")) + { + if (this->HasRun) + { + this->IsBlocking = true; + } + else + { + // Place this call on the call stack. + cmMakefileCall stack_manager(&mf, this->Functions[c], status); + static_cast<void>(stack_manager); + + // if trace is enabled, print the evaluated "elseif" statement + if(mf.GetCMakeInstance()->GetTrace()) + { + mf.PrintCommandTrace(this->Functions[c]); + } + + std::string errorString; + + std::vector<cmExpandedCommandArgument> expandedArguments; + mf.ExpandArguments(this->Functions[c].Arguments, + expandedArguments); + + cmake::MessageType messType; + + cmConditionEvaluator conditionEvaluator(mf); + + bool isTrue = conditionEvaluator.IsTrue( + expandedArguments, errorString, messType); + + if (errorString.size()) + { + std::string err = cmIfCommandError(&mf, expandedArguments); + err += errorString; + mf.IssueMessage(messType, err); + if (messType == cmake::FATAL_ERROR) + { + cmSystemTools::SetFatalErrorOccured(); + return true; + } + } + + if (isTrue) + { + this->IsBlocking = false; + this->HasRun = true; + } + } + } + + // should we execute? + else if (!this->IsBlocking) + { + status.Clear(); + mf.ExecuteCommand(this->Functions[c],status); + if (status.GetReturnInvoked()) + { + inStatus.SetReturnInvoked(true); + return true; + } + if (status.GetBreakInvoked()) + { + inStatus.SetBreakInvoked(true); + return true; + } + } + } + return true; + } + } + + // record the command + this->Functions.push_back(lff); + + // always return true + return true; +} + +//========================================================================= +bool cmIfFunctionBlocker::ShouldRemove(const cmListFileFunction& lff, + cmMakefile&) +{ + if (!cmSystemTools::Strucmp(lff.Name.c_str(),"endif")) + { + // if the endif has arguments, then make sure + // they match the arguments of the matching if + if (lff.Arguments.size() == 0 || + lff.Arguments == this->Args) + { + return true; + } + } + + return false; +} + +//========================================================================= +bool cmIfCommand +::InvokeInitialPass(const std::vector<cmListFileArgument>& args, + cmExecutionStatus &) +{ + std::string errorString; + + std::vector<cmExpandedCommandArgument> expandedArguments; + this->Makefile->ExpandArguments(args, expandedArguments); + + cmake::MessageType status; + + cmConditionEvaluator conditionEvaluator(*(this->Makefile)); + + bool isTrue = conditionEvaluator.IsTrue( + expandedArguments, errorString, status); + + if (errorString.size()) + { + std::string err = cmIfCommandError(this->Makefile, expandedArguments); + err += errorString; + if (status == cmake::FATAL_ERROR) + { + this->SetError(err); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + else + { + this->Makefile->IssueMessage(status, err); + } + } + + cmIfFunctionBlocker *f = new cmIfFunctionBlocker(); + // if is isn't true block the commands + f->ScopeDepth = 1; + f->IsBlocking = !isTrue; + if (isTrue) + { + f->HasRun = true; + } + f->Args = args; + this->Makefile->AddFunctionBlocker(f); + + return true; +} |