/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
#include "cmFunctionCommand.h"

#include <sstream>

#include "cmAlgorithms.h"
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmPolicies.h"
#include "cmRange.h"
#include "cmState.h"

// define the class for function commands
class cmFunctionHelperCommand : public cmCommand
{
public:
  /**
   * This is a virtual constructor for the command.
   */
  cmCommand* Clone() override
  {
    cmFunctionHelperCommand* newC = new cmFunctionHelperCommand;
    // we must copy when we clone
    newC->Args = this->Args;
    newC->Functions = this->Functions;
    newC->Policies = this->Policies;
    newC->FilePath = this->FilePath;
    return newC;
  }

  /**
   * This is called when the command is first encountered in
   * the CMakeLists.txt file.
   */
  bool InvokeInitialPass(const std::vector<cmListFileArgument>& args,
                         cmExecutionStatus&) override;

  bool InitialPass(std::vector<std::string> const&,
                   cmExecutionStatus&) override
  {
    return false;
  }

  std::vector<std::string> Args;
  std::vector<cmListFileFunction> Functions;
  cmPolicies::PolicyMap Policies;
  std::string FilePath;
};

bool cmFunctionHelperCommand::InvokeInitialPass(
  const std::vector<cmListFileArgument>& args, cmExecutionStatus& inStatus)
{
  // Expand the argument list to the function.
  std::vector<std::string> expandedArgs;
  this->Makefile->ExpandArguments(args, expandedArgs);

  // make sure the number of arguments passed is at least the number
  // required by the signature
  if (expandedArgs.size() < this->Args.size() - 1) {
    std::string errorMsg =
      "Function invoked with incorrect arguments for function named: ";
    errorMsg += this->Args[0];
    this->SetError(errorMsg);
    return false;
  }

  cmMakefile::FunctionPushPop functionScope(this->Makefile, this->FilePath,
                                            this->Policies);

  // set the value of argc
  std::ostringstream strStream;
  strStream << expandedArgs.size();
  this->Makefile->AddDefinition("ARGC", strStream.str().c_str());
  this->Makefile->MarkVariableAsUsed("ARGC");

  // set the values for ARGV0 ARGV1 ...
  for (unsigned int t = 0; t < expandedArgs.size(); ++t) {
    std::ostringstream tmpStream;
    tmpStream << "ARGV" << t;
    this->Makefile->AddDefinition(tmpStream.str(), expandedArgs[t].c_str());
    this->Makefile->MarkVariableAsUsed(tmpStream.str());
  }

  // define the formal arguments
  for (unsigned int j = 1; j < this->Args.size(); ++j) {
    this->Makefile->AddDefinition(this->Args[j], expandedArgs[j - 1].c_str());
  }

  // define ARGV and ARGN
  std::string argvDef = cmJoin(expandedArgs, ";");
  std::vector<std::string>::const_iterator eit =
    expandedArgs.begin() + (this->Args.size() - 1);
  std::string argnDef = cmJoin(cmMakeRange(eit, expandedArgs.end()), ";");
  this->Makefile->AddDefinition("ARGV", argvDef.c_str());
  this->Makefile->MarkVariableAsUsed("ARGV");
  this->Makefile->AddDefinition("ARGN", argnDef.c_str());
  this->Makefile->MarkVariableAsUsed("ARGN");

  // Invoke all the functions that were collected in the block.
  // for each function
  for (cmListFileFunction const& func : this->Functions) {
    cmExecutionStatus status;
    if (!this->Makefile->ExecuteCommand(func, status) ||
        status.GetNestedError()) {
      // The error message should have already included the call stack
      // so we do not need to report an error here.
      functionScope.Quiet();
      inStatus.SetNestedError();
      return false;
    }
    if (status.GetReturnInvoked()) {
      return true;
    }
  }

  // pop scope on the makefile
  return true;
}

bool cmFunctionFunctionBlocker::IsFunctionBlocked(
  const cmListFileFunction& lff, cmMakefile& mf, cmExecutionStatus&)
{
  // 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) {
      // create a new command and add it to cmake
      cmFunctionHelperCommand* f = new cmFunctionHelperCommand();
      f->Args = this->Args;
      f->Functions = this->Functions;
      f->FilePath = this->GetStartingContext().FilePath;
      mf.RecordPolicies(f->Policies);
      mf.GetState()->AddScriptedCommand(this->Args[0], f);
      // remove the function blocker now that the function is defined
      mf.RemoveFunctionBlocker(this, lff);
      return true;
    }
    // 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)
{
  if (lff.Name.Lower == "endfunction") {
    std::vector<std::string> expandedArguments;
    mf.ExpandArguments(lff.Arguments, expandedArguments,
                       this->GetStartingContext().FilePath.c_str());
    // if the endfunction has arguments then make sure
    // they match the ones in the opening function command
    if ((expandedArguments.empty() ||
         (expandedArguments[0] == this->Args[0]))) {
      return true;
    }
  }

  return false;
}

bool cmFunctionCommand::InitialPass(std::vector<std::string> const& args,
                                    cmExecutionStatus&)
{
  if (args.empty()) {
    this->SetError("called with incorrect number of arguments");
    return false;
  }

  // create a function blocker
  cmFunctionFunctionBlocker* f = new cmFunctionFunctionBlocker();
  cmAppend(f->Args, args);
  this->Makefile->AddFunctionBlocker(f);
  return true;
}
