summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Source/cmForEachCommand.cxx86
-rw-r--r--Source/cmFunctionCommand.cxx30
-rw-r--r--Source/cmIfCommand.cxx218
-rw-r--r--Source/cmMacroCommand.cxx32
-rw-r--r--Source/cmWhileCommand.cxx133
5 files changed, 272 insertions, 227 deletions
diff --git a/Source/cmForEachCommand.cxx b/Source/cmForEachCommand.cxx
index b04f14c..af32040 100644
--- a/Source/cmForEachCommand.cxx
+++ b/Source/cmForEachCommand.cxx
@@ -25,6 +25,8 @@ public:
bool IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile& mf,
cmExecutionStatus&) override;
bool ShouldRemove(const cmListFileFunction& lff, cmMakefile& mf) override;
+ bool Replay(std::vector<cmListFileFunction> const& functions,
+ cmExecutionStatus& inStatus);
std::vector<std::string> Args;
std::vector<cmListFileFunction> Functions;
@@ -63,44 +65,7 @@ bool cmForEachFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
return false;
}
- // at end of for each execute recorded commands
- // store the old value
- std::string oldDef;
- if (mf.GetDefinition(this->Args[0])) {
- oldDef = mf.GetDefinition(this->Args[0]);
- }
-
- for (std::string const& arg : cmMakeRange(this->Args).advance(1)) {
- // set the variable to the loop value
- mf.AddDefinition(this->Args[0], arg);
- // Invoke all the functions that were collected in the block.
- cmExecutionStatus status(mf);
- for (cmListFileFunction const& func : this->Functions) {
- status.Clear();
- mf.ExecuteCommand(func, status);
- if (status.GetReturnInvoked()) {
- inStatus.SetReturnInvoked();
- // restore the variable to its prior value
- mf.AddDefinition(this->Args[0], oldDef);
- return true;
- }
- if (status.GetBreakInvoked()) {
- // restore the variable to its prior value
- mf.AddDefinition(this->Args[0], oldDef);
- return true;
- }
- if (status.GetContinueInvoked()) {
- break;
- }
- if (cmSystemTools::GetFatalErrorOccured()) {
- return true;
- }
- }
- }
-
- // restore the variable to its prior value
- mf.AddDefinition(this->Args[0], oldDef);
- return true;
+ return this->Replay(this->Functions, inStatus);
}
// close out a nested foreach
this->Depth--;
@@ -129,6 +94,51 @@ bool cmForEachFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
return false;
}
+bool cmForEachFunctionBlocker::Replay(
+ std::vector<cmListFileFunction> const& functions,
+ cmExecutionStatus& inStatus)
+{
+ cmMakefile& mf = inStatus.GetMakefile();
+ // at end of for each execute recorded commands
+ // store the old value
+ std::string oldDef;
+ if (mf.GetDefinition(this->Args[0])) {
+ oldDef = mf.GetDefinition(this->Args[0]);
+ }
+
+ for (std::string const& arg : cmMakeRange(this->Args).advance(1)) {
+ // set the variable to the loop value
+ mf.AddDefinition(this->Args[0], arg);
+ // Invoke all the functions that were collected in the block.
+ cmExecutionStatus status(mf);
+ for (cmListFileFunction const& func : functions) {
+ status.Clear();
+ mf.ExecuteCommand(func, status);
+ if (status.GetReturnInvoked()) {
+ inStatus.SetReturnInvoked();
+ // restore the variable to its prior value
+ mf.AddDefinition(this->Args[0], oldDef);
+ return true;
+ }
+ if (status.GetBreakInvoked()) {
+ // restore the variable to its prior value
+ mf.AddDefinition(this->Args[0], oldDef);
+ return true;
+ }
+ if (status.GetContinueInvoked()) {
+ break;
+ }
+ if (cmSystemTools::GetFatalErrorOccured()) {
+ return true;
+ }
+ }
+ }
+
+ // restore the variable to its prior value
+ mf.AddDefinition(this->Args[0], oldDef);
+ return true;
+}
+
bool cmForEachCommand::InitialPass(std::vector<std::string> const& args,
cmExecutionStatus&)
{
diff --git a/Source/cmFunctionCommand.cxx b/Source/cmFunctionCommand.cxx
index f8230f1..51b6970 100644
--- a/Source/cmFunctionCommand.cxx
+++ b/Source/cmFunctionCommand.cxx
@@ -110,6 +110,8 @@ public:
bool IsFunctionBlocked(const cmListFileFunction&, cmMakefile& mf,
cmExecutionStatus&) override;
bool ShouldRemove(const cmListFileFunction&, cmMakefile& mf) override;
+ bool Replay(std::vector<cmListFileFunction> const& functions,
+ cmExecutionStatus& status);
std::vector<std::string> Args;
std::vector<cmListFileFunction> Functions;
@@ -117,7 +119,7 @@ public:
};
bool cmFunctionFunctionBlocker::IsFunctionBlocked(
- const cmListFileFunction& lff, cmMakefile& mf, cmExecutionStatus&)
+ const cmListFileFunction& lff, cmMakefile& mf, cmExecutionStatus& status)
{
// record commands until we hit the ENDFUNCTION
// at the ENDFUNCTION call we shift gears and start looking for invocations
@@ -126,16 +128,8 @@ bool cmFunctionFunctionBlocker::IsFunctionBlocked(
} else if (lff.Name.Lower == "endfunction") {
// if this is the endfunction for this function then execute
if (!this->Depth) {
- // create a new command and add it to cmake
- cmFunctionHelperCommand f;
- f.Args = this->Args;
- f.Functions = this->Functions;
- f.FilePath = this->GetStartingContext().FilePath;
- mf.RecordPolicies(f.Policies);
- mf.GetState()->AddScriptedCommand(this->Args[0], std::move(f));
- // remove the function blocker now that the function is defined
- mf.RemoveFunctionBlocker(this, lff);
- return true;
+ auto self = mf.RemoveFunctionBlocker(this, lff);
+ return this->Replay(this->Functions, status);
}
// decrement for each nested function that ends
this->Depth--;
@@ -165,6 +159,20 @@ bool cmFunctionFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
return false;
}
+bool cmFunctionFunctionBlocker::Replay(
+ std::vector<cmListFileFunction> const& functions, cmExecutionStatus& status)
+{
+ cmMakefile& mf = status.GetMakefile();
+ // create a new command and add it to cmake
+ cmFunctionHelperCommand f;
+ f.Args = this->Args;
+ f.Functions = functions;
+ f.FilePath = this->GetStartingContext().FilePath;
+ mf.RecordPolicies(f.Policies);
+ mf.GetState()->AddScriptedCommand(this->Args[0], std::move(f));
+ return true;
+}
+
bool cmFunctionCommand::InitialPass(std::vector<std::string> const& args,
cmExecutionStatus&)
{
diff --git a/Source/cmIfCommand.cxx b/Source/cmIfCommand.cxx
index 20fe2f8..95f8177 100644
--- a/Source/cmIfCommand.cxx
+++ b/Source/cmIfCommand.cxx
@@ -36,6 +36,8 @@ public:
bool IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile& mf,
cmExecutionStatus&) override;
bool ShouldRemove(const cmListFileFunction& lff, cmMakefile& mf) override;
+ bool Replay(std::vector<cmListFileFunction> const& functions,
+ cmExecutionStatus& inStatus);
std::vector<cmListFileArgument> Args;
std::vector<cmListFileFunction> Functions;
@@ -64,110 +66,7 @@ bool cmIfFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
return false;
}
- // execute the functions for the true parts of the if statement
- cmExecutionStatus status(mf);
- int scopeDepth = 0;
- for (cmListFileFunction const& func : this->Functions) {
- // keep track of scope depth
- if (func.Name.Lower == "if") {
- scopeDepth++;
- }
- if (func.Name.Lower == "endif") {
- scopeDepth--;
- }
- // watch for our state change
- if (scopeDepth == 0 && func.Name.Lower == "else") {
-
- if (this->ElseSeen) {
- cmListFileBacktrace bt = mf.GetBacktrace(func);
- mf.GetCMakeInstance()->IssueMessage(
- MessageType::FATAL_ERROR,
- "A duplicate ELSE command was found inside an IF block.", bt);
- cmSystemTools::SetFatalErrorOccured();
- return true;
- }
-
- this->IsBlocking = this->HasRun;
- this->HasRun = true;
- this->ElseSeen = true;
-
- // if trace is enabled, print a (trivially) evaluated "else"
- // statement
- if (!this->IsBlocking && mf.GetCMakeInstance()->GetTrace()) {
- mf.PrintCommandTrace(func);
- }
- } else if (scopeDepth == 0 && func.Name.Lower == "elseif") {
- if (this->ElseSeen) {
- cmListFileBacktrace bt = mf.GetBacktrace(func);
- mf.GetCMakeInstance()->IssueMessage(
- MessageType::FATAL_ERROR,
- "An ELSEIF command was found after an ELSE command.", bt);
- cmSystemTools::SetFatalErrorOccured();
- return true;
- }
-
- if (this->HasRun) {
- this->IsBlocking = true;
- } else {
- // if trace is enabled, print the evaluated "elseif" statement
- if (mf.GetCMakeInstance()->GetTrace()) {
- mf.PrintCommandTrace(func);
- }
-
- std::string errorString;
-
- std::vector<cmExpandedCommandArgument> expandedArguments;
- mf.ExpandArguments(func.Arguments, expandedArguments);
-
- MessageType messType;
-
- cmListFileContext conditionContext =
- cmListFileContext::FromCommandContext(
- func, this->GetStartingContext().FilePath);
-
- cmConditionEvaluator conditionEvaluator(mf, conditionContext,
- mf.GetBacktrace(func));
-
- bool isTrue = conditionEvaluator.IsTrue(expandedArguments,
- errorString, messType);
-
- if (!errorString.empty()) {
- std::string err = cmIfCommandError(expandedArguments);
- err += errorString;
- cmListFileBacktrace bt = mf.GetBacktrace(func);
- mf.GetCMakeInstance()->IssueMessage(messType, err, bt);
- if (messType == MessageType::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(func, status);
- if (status.GetReturnInvoked()) {
- inStatus.SetReturnInvoked();
- return true;
- }
- if (status.GetBreakInvoked()) {
- inStatus.SetBreakInvoked();
- return true;
- }
- if (status.GetContinueInvoked()) {
- inStatus.SetContinueInvoked();
- return true;
- }
- }
- }
- return true;
+ return this->Replay(this->Functions, inStatus);
}
}
@@ -193,6 +92,117 @@ bool cmIfFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
return false;
}
+bool cmIfFunctionBlocker::Replay(
+ std::vector<cmListFileFunction> const& functions,
+ cmExecutionStatus& inStatus)
+{
+ cmMakefile& mf = inStatus.GetMakefile();
+ // execute the functions for the true parts of the if statement
+ cmExecutionStatus status(mf);
+ int scopeDepth = 0;
+ for (cmListFileFunction const& func : functions) {
+ // keep track of scope depth
+ if (func.Name.Lower == "if") {
+ scopeDepth++;
+ }
+ if (func.Name.Lower == "endif") {
+ scopeDepth--;
+ }
+ // watch for our state change
+ if (scopeDepth == 0 && func.Name.Lower == "else") {
+
+ if (this->ElseSeen) {
+ cmListFileBacktrace bt = mf.GetBacktrace(func);
+ mf.GetCMakeInstance()->IssueMessage(
+ MessageType::FATAL_ERROR,
+ "A duplicate ELSE command was found inside an IF block.", bt);
+ cmSystemTools::SetFatalErrorOccured();
+ return true;
+ }
+
+ this->IsBlocking = this->HasRun;
+ this->HasRun = true;
+ this->ElseSeen = true;
+
+ // if trace is enabled, print a (trivially) evaluated "else"
+ // statement
+ if (!this->IsBlocking && mf.GetCMakeInstance()->GetTrace()) {
+ mf.PrintCommandTrace(func);
+ }
+ } else if (scopeDepth == 0 && func.Name.Lower == "elseif") {
+ if (this->ElseSeen) {
+ cmListFileBacktrace bt = mf.GetBacktrace(func);
+ mf.GetCMakeInstance()->IssueMessage(
+ MessageType::FATAL_ERROR,
+ "An ELSEIF command was found after an ELSE command.", bt);
+ cmSystemTools::SetFatalErrorOccured();
+ return true;
+ }
+
+ if (this->HasRun) {
+ this->IsBlocking = true;
+ } else {
+ // if trace is enabled, print the evaluated "elseif" statement
+ if (mf.GetCMakeInstance()->GetTrace()) {
+ mf.PrintCommandTrace(func);
+ }
+
+ std::string errorString;
+
+ std::vector<cmExpandedCommandArgument> expandedArguments;
+ mf.ExpandArguments(func.Arguments, expandedArguments);
+
+ MessageType messType;
+
+ cmListFileContext conditionContext =
+ cmListFileContext::FromCommandContext(
+ func, this->GetStartingContext().FilePath);
+
+ cmConditionEvaluator conditionEvaluator(mf, conditionContext,
+ mf.GetBacktrace(func));
+
+ bool isTrue =
+ conditionEvaluator.IsTrue(expandedArguments, errorString, messType);
+
+ if (!errorString.empty()) {
+ std::string err = cmIfCommandError(expandedArguments);
+ err += errorString;
+ cmListFileBacktrace bt = mf.GetBacktrace(func);
+ mf.GetCMakeInstance()->IssueMessage(messType, err, bt);
+ if (messType == MessageType::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(func, status);
+ if (status.GetReturnInvoked()) {
+ inStatus.SetReturnInvoked();
+ return true;
+ }
+ if (status.GetBreakInvoked()) {
+ inStatus.SetBreakInvoked();
+ return true;
+ }
+ if (status.GetContinueInvoked()) {
+ inStatus.SetContinueInvoked();
+ return true;
+ }
+ }
+ }
+ return true;
+}
+
//=========================================================================
bool cmIfCommand(std::vector<cmListFileArgument> const& args,
cmExecutionStatus& inStatus)
diff --git a/Source/cmMacroCommand.cxx b/Source/cmMacroCommand.cxx
index a123f22..e82d6fa 100644
--- a/Source/cmMacroCommand.cxx
+++ b/Source/cmMacroCommand.cxx
@@ -144,6 +144,8 @@ public:
bool IsFunctionBlocked(const cmListFileFunction&, cmMakefile& mf,
cmExecutionStatus&) override;
bool ShouldRemove(const cmListFileFunction&, cmMakefile& mf) override;
+ bool Replay(std::vector<cmListFileFunction> const& functions,
+ cmExecutionStatus& status);
std::vector<std::string> Args;
std::vector<cmListFileFunction> Functions;
@@ -152,7 +154,7 @@ public:
bool cmMacroFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
cmMakefile& mf,
- cmExecutionStatus&)
+ cmExecutionStatus& status)
{
// record commands until we hit the ENDMACRO
// at the ENDMACRO call we shift gears and start looking for invocations
@@ -161,17 +163,8 @@ bool cmMacroFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
} else if (lff.Name.Lower == "endmacro") {
// if this is the endmacro for this macro then execute
if (!this->Depth) {
- mf.AppendProperty("MACROS", this->Args[0].c_str());
- // create a new command and add it to cmake
- cmMacroHelperCommand f;
- f.Args = this->Args;
- f.Functions = this->Functions;
- f.FilePath = this->GetStartingContext().FilePath;
- mf.RecordPolicies(f.Policies);
- mf.GetState()->AddScriptedCommand(this->Args[0], std::move(f));
- // remove the function blocker now that the macro is defined
- mf.RemoveFunctionBlocker(this, lff);
- return true;
+ auto self = mf.RemoveFunctionBlocker(this, lff);
+ return this->Replay(this->Functions, status);
}
// decrement for each nested macro that ends
this->Depth--;
@@ -201,6 +194,21 @@ bool cmMacroFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
return false;
}
+bool cmMacroFunctionBlocker::Replay(
+ std::vector<cmListFileFunction> const& functions, cmExecutionStatus& status)
+{
+ cmMakefile& mf = status.GetMakefile();
+ mf.AppendProperty("MACROS", this->Args[0].c_str());
+ // create a new command and add it to cmake
+ cmMacroHelperCommand f;
+ f.Args = this->Args;
+ f.Functions = functions;
+ f.FilePath = this->GetStartingContext().FilePath;
+ mf.RecordPolicies(f.Policies);
+ mf.GetState()->AddScriptedCommand(this->Args[0], std::move(f));
+ return true;
+}
+
bool cmMacroCommand::InitialPass(std::vector<std::string> const& args,
cmExecutionStatus&)
{
diff --git a/Source/cmWhileCommand.cxx b/Source/cmWhileCommand.cxx
index 914860c..025d14a 100644
--- a/Source/cmWhileCommand.cxx
+++ b/Source/cmWhileCommand.cxx
@@ -24,6 +24,8 @@ public:
bool IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile& mf,
cmExecutionStatus&) override;
bool ShouldRemove(const cmListFileFunction& lff, cmMakefile& mf) override;
+ bool Replay(std::vector<cmListFileFunction> const& functions,
+ cmExecutionStatus& inStatus);
std::vector<cmListFileArgument> Args;
std::vector<cmListFileFunction> Functions;
@@ -62,68 +64,7 @@ bool cmWhileFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
if (!fb) {
return false;
}
-
- std::string errorString;
-
- std::vector<cmExpandedCommandArgument> expandedArguments;
- mf.ExpandArguments(this->Args, expandedArguments);
- MessageType messageType;
-
- cmListFileContext execContext = this->GetStartingContext();
-
- cmCommandContext commandContext;
- commandContext.Line = execContext.Line;
- commandContext.Name = execContext.Name;
-
- cmConditionEvaluator conditionEvaluator(mf, this->GetStartingContext(),
- mf.GetBacktrace(commandContext));
-
- bool isTrue =
- conditionEvaluator.IsTrue(expandedArguments, errorString, messageType);
-
- while (isTrue) {
- if (!errorString.empty()) {
- std::string err = "had incorrect arguments: ";
- for (cmListFileArgument const& arg : this->Args) {
- err += (arg.Delim ? "\"" : "");
- err += arg.Value;
- err += (arg.Delim ? "\"" : "");
- err += " ";
- }
- err += "(";
- err += errorString;
- err += ").";
- mf.IssueMessage(messageType, err);
- if (messageType == MessageType::FATAL_ERROR) {
- cmSystemTools::SetFatalErrorOccured();
- return true;
- }
- }
-
- // Invoke all the functions that were collected in the block.
- for (cmListFileFunction const& fn : this->Functions) {
- cmExecutionStatus status(mf);
- mf.ExecuteCommand(fn, status);
- if (status.GetReturnInvoked()) {
- inStatus.SetReturnInvoked();
- return true;
- }
- if (status.GetBreakInvoked()) {
- return true;
- }
- if (status.GetContinueInvoked()) {
- break;
- }
- if (cmSystemTools::GetFatalErrorOccured()) {
- return true;
- }
- }
- expandedArguments.clear();
- mf.ExpandArguments(this->Args, expandedArguments);
- isTrue = conditionEvaluator.IsTrue(expandedArguments, errorString,
- messageType);
- }
- return true;
+ return this->Replay(this->Functions, inStatus);
}
// decrement for each nested while that ends
this->Depth--;
@@ -149,6 +90,74 @@ bool cmWhileFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
return false;
}
+bool cmWhileFunctionBlocker::Replay(
+ std::vector<cmListFileFunction> const& functions,
+ cmExecutionStatus& inStatus)
+{
+ cmMakefile& mf = inStatus.GetMakefile();
+ std::string errorString;
+
+ std::vector<cmExpandedCommandArgument> expandedArguments;
+ mf.ExpandArguments(this->Args, expandedArguments);
+ MessageType messageType;
+
+ cmListFileContext execContext = this->GetStartingContext();
+
+ cmCommandContext commandContext;
+ commandContext.Line = execContext.Line;
+ commandContext.Name = execContext.Name;
+
+ cmConditionEvaluator conditionEvaluator(mf, this->GetStartingContext(),
+ mf.GetBacktrace(commandContext));
+
+ bool isTrue =
+ conditionEvaluator.IsTrue(expandedArguments, errorString, messageType);
+
+ while (isTrue) {
+ if (!errorString.empty()) {
+ std::string err = "had incorrect arguments: ";
+ for (cmListFileArgument const& arg : this->Args) {
+ err += (arg.Delim ? "\"" : "");
+ err += arg.Value;
+ err += (arg.Delim ? "\"" : "");
+ err += " ";
+ }
+ err += "(";
+ err += errorString;
+ err += ").";
+ mf.IssueMessage(messageType, err);
+ if (messageType == MessageType::FATAL_ERROR) {
+ cmSystemTools::SetFatalErrorOccured();
+ return true;
+ }
+ }
+
+ // Invoke all the functions that were collected in the block.
+ for (cmListFileFunction const& fn : functions) {
+ cmExecutionStatus status(mf);
+ mf.ExecuteCommand(fn, status);
+ if (status.GetReturnInvoked()) {
+ inStatus.SetReturnInvoked();
+ return true;
+ }
+ if (status.GetBreakInvoked()) {
+ return true;
+ }
+ if (status.GetContinueInvoked()) {
+ break;
+ }
+ if (cmSystemTools::GetFatalErrorOccured()) {
+ return true;
+ }
+ }
+ expandedArguments.clear();
+ mf.ExpandArguments(this->Args, expandedArguments);
+ isTrue =
+ conditionEvaluator.IsTrue(expandedArguments, errorString, messageType);
+ }
+ return true;
+}
+
bool cmWhileCommand(std::vector<cmListFileArgument> const& args,
cmExecutionStatus& status)
{