summaryrefslogtreecommitdiffstats
path: root/Source/cmIfCommand.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/cmIfCommand.cxx')
-rw-r--r--Source/cmIfCommand.cxx230
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;
+}