Browse Source

cm*FunctionBlocker: Extract function Replay

Regina Pfeifer 6 years ago
parent
commit
ef38ff22f7
5 changed files with 272 additions and 227 deletions
  1. 48 38
      Source/cmForEachCommand.cxx
  2. 19 11
      Source/cmFunctionCommand.cxx
  3. 114 104
      Source/cmIfCommand.cxx
  4. 20 12
      Source/cmMacroCommand.cxx
  5. 71 62
      Source/cmWhileCommand.cxx

+ 48 - 38
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&)
 {

+ 19 - 11
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&)
 {

+ 114 - 104
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)

+ 20 - 12
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&)
 {

+ 71 - 62
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)
 {