mirror of
https://github.com/Kitware/CMake.git
synced 2026-04-25 15:49:08 -05:00
cm*FunctionBlocker: Extract function Replay
This commit is contained in:
+48
-38
@@ -25,6 +25,8 @@ public:
|
|||||||
bool IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile& mf,
|
bool IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile& mf,
|
||||||
cmExecutionStatus&) override;
|
cmExecutionStatus&) override;
|
||||||
bool ShouldRemove(const cmListFileFunction& lff, cmMakefile& mf) 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<std::string> Args;
|
||||||
std::vector<cmListFileFunction> Functions;
|
std::vector<cmListFileFunction> Functions;
|
||||||
@@ -63,44 +65,7 @@ bool cmForEachFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// at end of for each execute recorded commands
|
return this->Replay(this->Functions, inStatus);
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
// close out a nested foreach
|
// close out a nested foreach
|
||||||
this->Depth--;
|
this->Depth--;
|
||||||
@@ -129,6 +94,51 @@ bool cmForEachFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
|
|||||||
return false;
|
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,
|
bool cmForEachCommand::InitialPass(std::vector<std::string> const& args,
|
||||||
cmExecutionStatus&)
|
cmExecutionStatus&)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -110,6 +110,8 @@ public:
|
|||||||
bool IsFunctionBlocked(const cmListFileFunction&, cmMakefile& mf,
|
bool IsFunctionBlocked(const cmListFileFunction&, cmMakefile& mf,
|
||||||
cmExecutionStatus&) override;
|
cmExecutionStatus&) override;
|
||||||
bool ShouldRemove(const cmListFileFunction&, cmMakefile& mf) override;
|
bool ShouldRemove(const cmListFileFunction&, cmMakefile& mf) override;
|
||||||
|
bool Replay(std::vector<cmListFileFunction> const& functions,
|
||||||
|
cmExecutionStatus& status);
|
||||||
|
|
||||||
std::vector<std::string> Args;
|
std::vector<std::string> Args;
|
||||||
std::vector<cmListFileFunction> Functions;
|
std::vector<cmListFileFunction> Functions;
|
||||||
@@ -117,7 +119,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
bool cmFunctionFunctionBlocker::IsFunctionBlocked(
|
bool cmFunctionFunctionBlocker::IsFunctionBlocked(
|
||||||
const cmListFileFunction& lff, cmMakefile& mf, cmExecutionStatus&)
|
const cmListFileFunction& lff, cmMakefile& mf, cmExecutionStatus& status)
|
||||||
{
|
{
|
||||||
// record commands until we hit the ENDFUNCTION
|
// record commands until we hit the ENDFUNCTION
|
||||||
// at the ENDFUNCTION call we shift gears and start looking for invocations
|
// 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") {
|
} else if (lff.Name.Lower == "endfunction") {
|
||||||
// if this is the endfunction for this function then execute
|
// if this is the endfunction for this function then execute
|
||||||
if (!this->Depth) {
|
if (!this->Depth) {
|
||||||
// create a new command and add it to cmake
|
auto self = mf.RemoveFunctionBlocker(this, lff);
|
||||||
cmFunctionHelperCommand f;
|
return this->Replay(this->Functions, status);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
// decrement for each nested function that ends
|
// decrement for each nested function that ends
|
||||||
this->Depth--;
|
this->Depth--;
|
||||||
@@ -165,6 +159,20 @@ bool cmFunctionFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
|
|||||||
return false;
|
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,
|
bool cmFunctionCommand::InitialPass(std::vector<std::string> const& args,
|
||||||
cmExecutionStatus&)
|
cmExecutionStatus&)
|
||||||
{
|
{
|
||||||
|
|||||||
+114
-104
@@ -36,6 +36,8 @@ public:
|
|||||||
bool IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile& mf,
|
bool IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile& mf,
|
||||||
cmExecutionStatus&) override;
|
cmExecutionStatus&) override;
|
||||||
bool ShouldRemove(const cmListFileFunction& lff, cmMakefile& mf) override;
|
bool ShouldRemove(const cmListFileFunction& lff, cmMakefile& mf) override;
|
||||||
|
bool Replay(std::vector<cmListFileFunction> const& functions,
|
||||||
|
cmExecutionStatus& inStatus);
|
||||||
|
|
||||||
std::vector<cmListFileArgument> Args;
|
std::vector<cmListFileArgument> Args;
|
||||||
std::vector<cmListFileFunction> Functions;
|
std::vector<cmListFileFunction> Functions;
|
||||||
@@ -64,110 +66,7 @@ bool cmIfFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// execute the functions for the true parts of the if statement
|
return this->Replay(this->Functions, inStatus);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,6 +92,117 @@ bool cmIfFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
|
|||||||
return false;
|
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,
|
bool cmIfCommand(std::vector<cmListFileArgument> const& args,
|
||||||
cmExecutionStatus& inStatus)
|
cmExecutionStatus& inStatus)
|
||||||
|
|||||||
+20
-12
@@ -144,6 +144,8 @@ public:
|
|||||||
bool IsFunctionBlocked(const cmListFileFunction&, cmMakefile& mf,
|
bool IsFunctionBlocked(const cmListFileFunction&, cmMakefile& mf,
|
||||||
cmExecutionStatus&) override;
|
cmExecutionStatus&) override;
|
||||||
bool ShouldRemove(const cmListFileFunction&, cmMakefile& mf) override;
|
bool ShouldRemove(const cmListFileFunction&, cmMakefile& mf) override;
|
||||||
|
bool Replay(std::vector<cmListFileFunction> const& functions,
|
||||||
|
cmExecutionStatus& status);
|
||||||
|
|
||||||
std::vector<std::string> Args;
|
std::vector<std::string> Args;
|
||||||
std::vector<cmListFileFunction> Functions;
|
std::vector<cmListFileFunction> Functions;
|
||||||
@@ -152,7 +154,7 @@ public:
|
|||||||
|
|
||||||
bool cmMacroFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
|
bool cmMacroFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
|
||||||
cmMakefile& mf,
|
cmMakefile& mf,
|
||||||
cmExecutionStatus&)
|
cmExecutionStatus& status)
|
||||||
{
|
{
|
||||||
// record commands until we hit the ENDMACRO
|
// record commands until we hit the ENDMACRO
|
||||||
// at the ENDMACRO call we shift gears and start looking for invocations
|
// 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") {
|
} else if (lff.Name.Lower == "endmacro") {
|
||||||
// if this is the endmacro for this macro then execute
|
// if this is the endmacro for this macro then execute
|
||||||
if (!this->Depth) {
|
if (!this->Depth) {
|
||||||
mf.AppendProperty("MACROS", this->Args[0].c_str());
|
auto self = mf.RemoveFunctionBlocker(this, lff);
|
||||||
// create a new command and add it to cmake
|
return this->Replay(this->Functions, status);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
// decrement for each nested macro that ends
|
// decrement for each nested macro that ends
|
||||||
this->Depth--;
|
this->Depth--;
|
||||||
@@ -201,6 +194,21 @@ bool cmMacroFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
|
|||||||
return false;
|
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,
|
bool cmMacroCommand::InitialPass(std::vector<std::string> const& args,
|
||||||
cmExecutionStatus&)
|
cmExecutionStatus&)
|
||||||
{
|
{
|
||||||
|
|||||||
+71
-62
@@ -24,6 +24,8 @@ public:
|
|||||||
bool IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile& mf,
|
bool IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile& mf,
|
||||||
cmExecutionStatus&) override;
|
cmExecutionStatus&) override;
|
||||||
bool ShouldRemove(const cmListFileFunction& lff, cmMakefile& mf) override;
|
bool ShouldRemove(const cmListFileFunction& lff, cmMakefile& mf) override;
|
||||||
|
bool Replay(std::vector<cmListFileFunction> const& functions,
|
||||||
|
cmExecutionStatus& inStatus);
|
||||||
|
|
||||||
std::vector<cmListFileArgument> Args;
|
std::vector<cmListFileArgument> Args;
|
||||||
std::vector<cmListFileFunction> Functions;
|
std::vector<cmListFileFunction> Functions;
|
||||||
@@ -62,68 +64,7 @@ bool cmWhileFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
|
|||||||
if (!fb) {
|
if (!fb) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
return this->Replay(this->Functions, inStatus);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
// decrement for each nested while that ends
|
// decrement for each nested while that ends
|
||||||
this->Depth--;
|
this->Depth--;
|
||||||
@@ -149,6 +90,74 @@ bool cmWhileFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
|
|||||||
return false;
|
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,
|
bool cmWhileCommand(std::vector<cmListFileArgument> const& args,
|
||||||
cmExecutionStatus& status)
|
cmExecutionStatus& status)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user