cmFunctionBlocker: Move common logic to base

This commit is contained in:
Regina Pfeifer 2019-07-30 18:15:13 +02:00
parent ef38ff22f7
commit af24e4ef6e
10 changed files with 78 additions and 169 deletions

View File

@ -531,6 +531,8 @@ set(SRCS
cmFindProgramCommand.h
cmForEachCommand.cxx
cmForEachCommand.h
cmFunctionBlocker.cxx
cmFunctionBlocker.h
cmFunctionCommand.cxx
cmFunctionCommand.h
cmGetCMakePropertyCommand.cxx

View File

@ -8,6 +8,8 @@
#include <utility>
#include "cm_memory.hxx"
#include "cm_static_string_view.hxx"
#include "cm_string_view.hxx"
#include "cmExecutionStatus.h"
#include "cmFunctionBlocker.h"
@ -22,23 +24,22 @@ class cmForEachFunctionBlocker : public cmFunctionBlocker
public:
cmForEachFunctionBlocker(cmMakefile* mf);
~cmForEachFunctionBlocker() override;
bool IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile& mf,
cmExecutionStatus&) override;
cm::string_view StartCommandName() const override { return "foreach"_s; }
cm::string_view EndCommandName() const override { return "endforeach"_s; }
bool ShouldRemove(const cmListFileFunction& lff, cmMakefile& mf) override;
bool Replay(std::vector<cmListFileFunction> const& functions,
cmExecutionStatus& inStatus);
cmExecutionStatus& inStatus) override;
std::vector<std::string> Args;
std::vector<cmListFileFunction> Functions;
private:
cmMakefile* Makefile;
int Depth;
};
cmForEachFunctionBlocker::cmForEachFunctionBlocker(cmMakefile* mf)
: Makefile(mf)
, Depth(0)
{
this->Makefile->PushLoopBlock();
}
@ -48,36 +49,6 @@ cmForEachFunctionBlocker::~cmForEachFunctionBlocker()
this->Makefile->PopLoopBlock();
}
bool cmForEachFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
cmMakefile& mf,
cmExecutionStatus& inStatus)
{
if (lff.Name.Lower == "foreach") {
// record the number of nested foreach commands
this->Depth++;
} else if (lff.Name.Lower == "endforeach") {
// if this is the endofreach for this statement
if (!this->Depth) {
// Remove the function blocker for this scope or bail.
std::unique_ptr<cmFunctionBlocker> fb(
mf.RemoveFunctionBlocker(this, lff));
if (!fb) {
return false;
}
return this->Replay(this->Functions, inStatus);
}
// close out a nested foreach
this->Depth--;
}
// record the command
this->Functions.push_back(lff);
// always return true
return true;
}
bool cmForEachFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
cmMakefile& mf)
{

View File

@ -0,0 +1,24 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmFunctionBlocker.h"
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
bool cmFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
cmExecutionStatus& status)
{
if (lff.Name.Lower == this->StartCommandName()) {
this->ScopeDepth++;
} else if (lff.Name.Lower == this->EndCommandName()) {
this->ScopeDepth--;
if (this->ScopeDepth == 0U) {
cmMakefile& mf = status.GetMakefile();
auto self = mf.RemoveFunctionBlocker(this, lff);
return this->Replay(this->Functions, status);
}
}
this->Functions.push_back(lff);
return true;
}

View File

@ -3,6 +3,12 @@
#ifndef cmFunctionBlocker_h
#define cmFunctionBlocker_h
#include "cmConfigure.h" // IWYU pragma: keep
#include <vector>
#include "cm_string_view.hxx"
#include "cmListFileCache.h"
class cmExecutionStatus;
@ -14,8 +20,8 @@ public:
/**
* should a function be blocked
*/
virtual bool IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile& mf,
cmExecutionStatus& status) = 0;
bool IsFunctionBlocked(cmListFileFunction const& lff,
cmExecutionStatus& status);
/**
* should this function blocker be removed, useful when one function adds a
@ -38,8 +44,17 @@ public:
return this->StartingContext;
}
private:
virtual cm::string_view StartCommandName() const = 0;
virtual cm::string_view EndCommandName() const = 0;
virtual bool Replay(std::vector<cmListFileFunction> const& functions,
cmExecutionStatus& status) = 0;
private:
cmListFileContext StartingContext;
std::vector<cmListFileFunction> Functions;
unsigned int ScopeDepth = 1;
};
#endif

View File

@ -5,6 +5,9 @@
#include <sstream>
#include <utility>
#include "cm_static_string_view.hxx"
#include "cm_string_view.hxx"
#include "cmAlgorithms.h"
#include "cmExecutionStatus.h"
#include "cmFunctionBlocker.h"
@ -107,40 +110,16 @@ bool cmFunctionHelperCommand::operator()(
class cmFunctionFunctionBlocker : public cmFunctionBlocker
{
public:
bool IsFunctionBlocked(const cmListFileFunction&, cmMakefile& mf,
cmExecutionStatus&) override;
cm::string_view StartCommandName() const override { return "function"_s; }
cm::string_view EndCommandName() const override { return "endfunction"_s; }
bool ShouldRemove(const cmListFileFunction&, cmMakefile& mf) override;
bool Replay(std::vector<cmListFileFunction> const& functions,
cmExecutionStatus& status);
cmExecutionStatus& status) override;
std::vector<std::string> Args;
std::vector<cmListFileFunction> Functions;
int Depth = 0;
};
bool cmFunctionFunctionBlocker::IsFunctionBlocked(
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
if (lff.Name.Lower == "function") {
this->Depth++;
} else if (lff.Name.Lower == "endfunction") {
// if this is the endfunction for this function then execute
if (!this->Depth) {
auto self = mf.RemoveFunctionBlocker(this, lff);
return this->Replay(this->Functions, status);
}
// decrement for each nested function that ends
this->Depth--;
}
// if it wasn't an endfunction and we are not executing then we must be
// recording
this->Functions.push_back(lff);
return true;
}
bool cmFunctionFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
cmMakefile& mf)
{

View File

@ -3,6 +3,8 @@
#include "cmIfCommand.h"
#include "cm_memory.hxx"
#include "cm_static_string_view.hxx"
#include "cm_string_view.hxx"
#include "cmConditionEvaluator.h"
#include "cmExecutionStatus.h"
@ -33,51 +35,19 @@ static std::string cmIfCommandError(
class cmIfFunctionBlocker : public cmFunctionBlocker
{
public:
bool IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile& mf,
cmExecutionStatus&) override;
cm::string_view StartCommandName() const override { return "if"_s; }
cm::string_view EndCommandName() const override { return "endif"_s; }
bool ShouldRemove(const cmListFileFunction& lff, cmMakefile& mf) override;
bool Replay(std::vector<cmListFileFunction> const& functions,
cmExecutionStatus& inStatus);
cmExecutionStatus& inStatus) override;
std::vector<cmListFileArgument> Args;
std::vector<cmListFileFunction> Functions;
bool IsBlocking;
bool HasRun = false;
bool ElseSeen = false;
unsigned int ScopeDepth = 0;
};
//=========================================================================
bool cmIfFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
cmMakefile& mf,
cmExecutionStatus& inStatus)
{
// we start by recording all the functions
if (lff.Name.Lower == "if") {
this->ScopeDepth++;
} else if (lff.Name.Lower == "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.
std::unique_ptr<cmFunctionBlocker> fb(
mf.RemoveFunctionBlocker(this, lff));
if (!fb) {
return false;
}
return this->Replay(this->Functions, inStatus);
}
}
// record the command
this->Functions.push_back(lff);
// always return true
return true;
}
//=========================================================================
bool cmIfFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
cmMakefile&)
{
@ -235,7 +205,6 @@ bool cmIfCommand(std::vector<cmListFileArgument> const& args,
{
auto fb = cm::make_unique<cmIfFunctionBlocker>();
// if is isn't true block the commands
fb->ScopeDepth = 1;
fb->IsBlocking = !isTrue;
if (isTrue) {
fb->HasRun = true;

View File

@ -7,6 +7,8 @@
#include <utility>
#include "cm_memory.hxx"
#include "cm_static_string_view.hxx"
#include "cm_string_view.hxx"
#include "cmAlgorithms.h"
#include "cmExecutionStatus.h"
@ -141,41 +143,16 @@ bool cmMacroHelperCommand::operator()(
class cmMacroFunctionBlocker : public cmFunctionBlocker
{
public:
bool IsFunctionBlocked(const cmListFileFunction&, cmMakefile& mf,
cmExecutionStatus&) override;
cm::string_view StartCommandName() const override { return "macro"_s; }
cm::string_view EndCommandName() const override { return "endmacro"_s; }
bool ShouldRemove(const cmListFileFunction&, cmMakefile& mf) override;
bool Replay(std::vector<cmListFileFunction> const& functions,
cmExecutionStatus& status);
cmExecutionStatus& status) override;
std::vector<std::string> Args;
std::vector<cmListFileFunction> Functions;
int Depth = 0;
};
bool cmMacroFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
cmMakefile& mf,
cmExecutionStatus& status)
{
// record commands until we hit the ENDMACRO
// at the ENDMACRO call we shift gears and start looking for invocations
if (lff.Name.Lower == "macro") {
this->Depth++;
} else if (lff.Name.Lower == "endmacro") {
// if this is the endmacro for this macro then execute
if (!this->Depth) {
auto self = mf.RemoveFunctionBlocker(this, lff);
return this->Replay(this->Functions, status);
}
// decrement for each nested macro that ends
this->Depth--;
}
// if it wasn't an endmacro and we are not executing then we must be
// recording
this->Functions.push_back(lff);
return true;
}
bool cmMacroFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
cmMakefile& mf)
{

View File

@ -3070,7 +3070,7 @@ bool cmMakefile::IsFunctionBlocked(const cmListFileFunction& lff,
return false;
}
return this->FunctionBlockers.top()->IsFunctionBlocked(lff, *this, status);
return this->FunctionBlockers.top()->IsFunctionBlocked(lff, status);
}
void cmMakefile::PushFunctionBlockerBarrier()

View File

@ -3,6 +3,8 @@
#include "cmWhileCommand.h"
#include "cm_memory.hxx"
#include "cm_static_string_view.hxx"
#include "cm_string_view.hxx"
#include "cmConditionEvaluator.h"
#include "cmExecutionStatus.h"
@ -21,23 +23,22 @@ class cmWhileFunctionBlocker : public cmFunctionBlocker
public:
cmWhileFunctionBlocker(cmMakefile* mf);
~cmWhileFunctionBlocker() override;
bool IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile& mf,
cmExecutionStatus&) override;
cm::string_view StartCommandName() const override { return "while"_s; }
cm::string_view EndCommandName() const override { return "endwhile"_s; }
bool ShouldRemove(const cmListFileFunction& lff, cmMakefile& mf) override;
bool Replay(std::vector<cmListFileFunction> const& functions,
cmExecutionStatus& inStatus);
cmExecutionStatus& inStatus) override;
std::vector<cmListFileArgument> Args;
std::vector<cmListFileFunction> Functions;
private:
cmMakefile* Makefile;
int Depth;
};
cmWhileFunctionBlocker::cmWhileFunctionBlocker(cmMakefile* mf)
: Makefile(mf)
, Depth(0)
{
this->Makefile->PushLoopBlock();
}
@ -47,36 +48,6 @@ cmWhileFunctionBlocker::~cmWhileFunctionBlocker()
this->Makefile->PopLoopBlock();
}
bool cmWhileFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
cmMakefile& mf,
cmExecutionStatus& inStatus)
{
// at end of for each execute recorded commands
if (lff.Name.Lower == "while") {
// record the number of while commands past this one
this->Depth++;
} else if (lff.Name.Lower == "endwhile") {
// if this is the endwhile for this while loop then execute
if (!this->Depth) {
// Remove the function blocker for this scope or bail.
std::unique_ptr<cmFunctionBlocker> fb(
mf.RemoveFunctionBlocker(this, lff));
if (!fb) {
return false;
}
return this->Replay(this->Functions, inStatus);
}
// decrement for each nested while that ends
this->Depth--;
}
// record the command
this->Functions.push_back(lff);
// always return true
return true;
}
bool cmWhileFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
cmMakefile&)
{

View File

@ -326,6 +326,7 @@ CMAKE_CXX_SOURCES="\
cmFindPathCommand \
cmFindProgramCommand \
cmForEachCommand \
cmFunctionBlocker \
cmFunctionCommand \
cmFSPermissions \
cmGeneratedFileStream \