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

#include <algorithm>
#include <functional>
#include <iomanip>
#include <map>
#include <sstream>
#include <string>
#include <utility>
#include <vector>

#include <cm/string_view>
#include <cmext/string_view>

#include "cmArgumentParser.h"
#include "cmCMakePath.h"
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmRange.h"
#include "cmStringAlgorithms.h"
#include "cmSubcommandTable.h"
#include "cmSystemTools.h"

namespace {
// Helper classes for argument parsing
template <typename Result>
class CMakePathArgumentParser : public cmArgumentParser<Result>
{
public:
  CMakePathArgumentParser()
    : cmArgumentParser<Result>()
  {
  }

  template <typename T>
  CMakePathArgumentParser& Bind(cm::static_string_view name, T Result::*member)
  {
    this->cmArgumentParser<Result>::Bind(name, member);
    return *this;
  }

  template <int Advance = 2>
  Result Parse(std::vector<std::string> const& args,
               std::vector<std::string>* keywordsMissingValue = nullptr,
               std::vector<std::string>* parsedKeywords = nullptr) const
  {
    this->Inputs.clear();

    return this->cmArgumentParser<Result>::Parse(
      cmMakeRange(args).advance(Advance), &this->Inputs, keywordsMissingValue,
      parsedKeywords);
  }

  const std::vector<std::string>& GetInputs() const { return this->Inputs; }

protected:
  mutable std::vector<std::string> Inputs;
};

// OUTPUT_VARIABLE is expected
template <typename Result>
class ArgumentParserWithOutputVariable : public CMakePathArgumentParser<Result>
{
public:
  ArgumentParserWithOutputVariable()
    : CMakePathArgumentParser<Result>()
  {
    this->Bind("OUTPUT_VARIABLE"_s, &Result::Output);
  }

  template <typename T>
  ArgumentParserWithOutputVariable& Bind(cm::static_string_view name,
                                         T Result::*member)
  {
    this->cmArgumentParser<Result>::Bind(name, member);
    return *this;
  }

  template <int Advance = 2>
  Result Parse(std::vector<std::string> const& args) const
  {
    this->KeywordsMissingValue.clear();
    this->ParsedKeywords.clear();

    return this->CMakePathArgumentParser<Result>::template Parse<Advance>(
      args, &this->KeywordsMissingValue, &this->ParsedKeywords);
  }

  const std::vector<std::string>& GetKeywordsMissingValue() const
  {
    return this->KeywordsMissingValue;
  }
  const std::vector<std::string>& GetParsedKeywords() const
  {
    return this->ParsedKeywords;
  }

  bool checkOutputVariable(const Result& arguments,
                           cmExecutionStatus& status) const
  {
    if (std::find(this->GetKeywordsMissingValue().begin(),
                  this->GetKeywordsMissingValue().end(),
                  "OUTPUT_VARIABLE"_s) !=
        this->GetKeywordsMissingValue().end()) {
      status.SetError("OUTPUT_VARIABLE requires an argument.");
      return false;
    }

    if (std::find(this->GetParsedKeywords().begin(),
                  this->GetParsedKeywords().end(),
                  "OUTPUT_VARIABLE"_s) != this->GetParsedKeywords().end() &&
        arguments.Output.empty()) {
      status.SetError("Invalid name for output variable.");
      return false;
    }

    return true;
  }

private:
  mutable std::vector<std::string> KeywordsMissingValue;
  mutable std::vector<std::string> ParsedKeywords;
};

struct OutputVariable
{
  std::string Output;
};
// Usable when OUTPUT_VARIABLE is the only option
class OutputVariableParser
  : public ArgumentParserWithOutputVariable<OutputVariable>
{
};

struct NormalizeOption
{
  bool Normalize = false;
};
// Usable when NORMALIZE is the only option
class NormalizeParser : public CMakePathArgumentParser<NormalizeOption>
{
public:
  NormalizeParser() { this->Bind("NORMALIZE"_s, &NormalizeOption::Normalize); }
};

// retrieve value of input path from specified variable
bool getInputPath(const std::string& arg, cmExecutionStatus& status,
                  std::string& path)
{
  const auto* def = status.GetMakefile().GetDefinition(arg);
  if (def == nullptr) {
    status.SetError("undefined variable for input path.");
    return false;
  }

  path = *def;
  return true;
}

bool HandleGetCommand(std::vector<std::string> const& args,
                      cmExecutionStatus& status)
{
  static std::map<cm::string_view,
                  std::function<cmCMakePath(const cmCMakePath&, bool)>> const
    actions{ { "ROOT_NAME"_s,
               [](const cmCMakePath& path, bool) -> cmCMakePath {
                 return path.GetRootName();
               } },
             { "ROOT_DIRECTORY"_s,
               [](const cmCMakePath& path, bool) -> cmCMakePath {
                 return path.GetRootDirectory();
               } },
             { "ROOT_PATH"_s,
               [](const cmCMakePath& path, bool) -> cmCMakePath {
                 return path.GetRootPath();
               } },
             { "FILENAME"_s,
               [](const cmCMakePath& path, bool) -> cmCMakePath {
                 return path.GetFileName();
               } },
             { "EXTENSION"_s,
               [](const cmCMakePath& path, bool last_only) -> cmCMakePath {
                 if (last_only) {
                   return path.GetExtension();
                 }
                 return path.GetWideExtension();
               } },
             { "STEM"_s,
               [](const cmCMakePath& path, bool last_only) -> cmCMakePath {
                 if (last_only) {
                   return path.GetStem();
                 }
                 return path.GetNarrowStem();
               } },
             { "RELATIVE_PART"_s,
               [](const cmCMakePath& path, bool) -> cmCMakePath {
                 return path.GetRelativePath();
               } },
             { "PARENT_PATH"_s,
               [](const cmCMakePath& path, bool) -> cmCMakePath {
                 return path.GetParentPath();
               } } };

  if (args.size() < 4) {
    status.SetError("GET must be called with at least three arguments.");
    return false;
  }

  const auto& action = args[2];

  if (actions.find(action) == actions.end()) {
    status.SetError(
      cmStrCat("GET called with an unknown action: ", action, "."));
    return false;
  }

  struct Arguments
  {
    bool LastOnly = false;
  };

  CMakePathArgumentParser<Arguments> parser;
  if ((action == "EXTENSION"_s || action == "STEM"_s)) {
    parser.Bind("LAST_ONLY"_s, &Arguments::LastOnly);
  }

  Arguments const arguments = parser.Parse<3>(args);

  if (parser.GetInputs().size() != 1) {
    status.SetError("GET called with unexpected arguments.");
    return false;
  }
  if (parser.GetInputs().front().empty()) {
    status.SetError("Invalid name for output variable.");
    return false;
  }

  std::string path;
  if (!getInputPath(args[1], status, path)) {
    return false;
  }

  auto result = actions.at(action)(path, arguments.LastOnly);

  status.GetMakefile().AddDefinition(parser.GetInputs().front(),
                                     result.String());

  return true;
}

bool HandleSetCommand(std::vector<std::string> const& args,
                      cmExecutionStatus& status)
{
  if (args.size() < 3 || args.size() > 4) {
    status.SetError("SET must be called with two or three arguments.");
    return false;
  }

  if (args[1].empty()) {
    status.SetError("Invalid name for path variable.");
    return false;
  }

  static NormalizeParser const parser;

  const auto arguments = parser.Parse(args);

  if (parser.GetInputs().size() != 1) {
    status.SetError("SET called with unexpected arguments.");
    return false;
  }

  auto path =
    cmCMakePath(parser.GetInputs().front(), cmCMakePath::native_format);

  if (arguments.Normalize) {
    path = path.Normal();
  }

  status.GetMakefile().AddDefinition(args[1], path.GenericString());

  return true;
}

bool HandleAppendCommand(std::vector<std::string> const& args,
                         cmExecutionStatus& status)
{
  if (args[1].empty()) {
    status.SetError("Invalid name for path variable.");
    return false;
  }

  static OutputVariableParser const parser{};

  const auto arguments = parser.Parse(args);

  if (!parser.checkOutputVariable(arguments, status)) {
    return false;
  }

  cmCMakePath path(status.GetMakefile().GetSafeDefinition(args[1]));
  for (const auto& input : parser.GetInputs()) {
    path /= input;
  }

  status.GetMakefile().AddDefinition(
    arguments.Output.empty() ? args[1] : arguments.Output, path.String());

  return true;
}

bool HandleAppendStringCommand(std::vector<std::string> const& args,
                               cmExecutionStatus& status)
{
  static OutputVariableParser const parser{};

  const auto arguments = parser.Parse(args);

  if (!parser.checkOutputVariable(arguments, status)) {
    return false;
  }

  std::string inputPath;
  if (!getInputPath(args[1], status, inputPath)) {
    return false;
  }

  cmCMakePath path(inputPath);
  for (const auto& input : parser.GetInputs()) {
    path += input;
  }

  status.GetMakefile().AddDefinition(
    arguments.Output.empty() ? args[1] : arguments.Output, path.String());

  return true;
}

bool HandleRemoveFilenameCommand(std::vector<std::string> const& args,
                                 cmExecutionStatus& status)
{
  static OutputVariableParser const parser{};

  const auto arguments = parser.Parse(args);

  if (!parser.checkOutputVariable(arguments, status)) {
    return false;
  }

  if (!parser.GetInputs().empty()) {
    status.SetError("REMOVE_FILENAME called with unexpected arguments.");
    return false;
  }

  std::string inputPath;
  if (!getInputPath(args[1], status, inputPath)) {
    return false;
  }

  cmCMakePath path(inputPath);
  path.RemoveFileName();

  status.GetMakefile().AddDefinition(
    arguments.Output.empty() ? args[1] : arguments.Output, path.String());

  return true;
}

bool HandleReplaceFilenameCommand(std::vector<std::string> const& args,
                                  cmExecutionStatus& status)
{
  static OutputVariableParser const parser{};

  const auto arguments = parser.Parse(args);

  if (!parser.checkOutputVariable(arguments, status)) {
    return false;
  }

  if (parser.GetInputs().size() > 1) {
    status.SetError("REPLACE_FILENAME called with unexpected arguments.");
    return false;
  }

  std::string inputPath;
  if (!getInputPath(args[1], status, inputPath)) {
    return false;
  }

  cmCMakePath path(inputPath);
  path.ReplaceFileName(
    parser.GetInputs().empty() ? "" : parser.GetInputs().front());

  status.GetMakefile().AddDefinition(
    arguments.Output.empty() ? args[1] : arguments.Output, path.String());

  return true;
}

bool HandleRemoveExtensionCommand(std::vector<std::string> const& args,
                                  cmExecutionStatus& status)
{
  struct Arguments
  {
    std::string Output;
    bool LastOnly = false;
  };

  static auto const parser =
    ArgumentParserWithOutputVariable<Arguments>{}.Bind("LAST_ONLY"_s,
                                                       &Arguments::LastOnly);

  Arguments const arguments = parser.Parse(args);

  if (!parser.checkOutputVariable(arguments, status)) {
    return false;
  }

  if (!parser.GetInputs().empty()) {
    status.SetError("REMOVE_EXTENSION called with unexpected arguments.");
    return false;
  }

  std::string inputPath;
  if (!getInputPath(args[1], status, inputPath)) {
    return false;
  }

  cmCMakePath path(inputPath);

  if (arguments.LastOnly) {
    path.RemoveExtension();
  } else {
    path.RemoveWideExtension();
  }

  status.GetMakefile().AddDefinition(
    arguments.Output.empty() ? args[1] : arguments.Output, path.String());

  return true;
}

bool HandleReplaceExtensionCommand(std::vector<std::string> const& args,
                                   cmExecutionStatus& status)
{
  struct Arguments
  {
    std::string Output;
    bool LastOnly = false;
  };

  static auto const parser =
    ArgumentParserWithOutputVariable<Arguments>{}.Bind("LAST_ONLY"_s,
                                                       &Arguments::LastOnly);

  Arguments const arguments = parser.Parse(args);

  if (!parser.checkOutputVariable(arguments, status)) {
    return false;
  }

  if (parser.GetInputs().size() > 1) {
    status.SetError("REPLACE_EXTENSION called with unexpected arguments.");
    return false;
  }

  std::string inputPath;
  if (!getInputPath(args[1], status, inputPath)) {
    return false;
  }

  cmCMakePath path(inputPath);
  cmCMakePath extension(
    parser.GetInputs().empty() ? "" : parser.GetInputs().front());

  if (arguments.LastOnly) {
    path.ReplaceExtension(extension);
  } else {
    path.ReplaceWideExtension(extension);
  }

  status.GetMakefile().AddDefinition(
    arguments.Output.empty() ? args[1] : arguments.Output, path.String());

  return true;
}

bool HandleNormalPathCommand(std::vector<std::string> const& args,
                             cmExecutionStatus& status)
{
  static OutputVariableParser const parser{};

  const auto arguments = parser.Parse(args);

  if (!parser.checkOutputVariable(arguments, status)) {
    return false;
  }

  if (!parser.GetInputs().empty()) {
    status.SetError("NORMAL_PATH called with unexpected arguments.");
    return false;
  }

  std::string inputPath;
  if (!getInputPath(args[1], status, inputPath)) {
    return false;
  }

  auto path = cmCMakePath(inputPath).Normal();

  status.GetMakefile().AddDefinition(
    arguments.Output.empty() ? args[1] : arguments.Output, path.String());

  return true;
}

bool HandleTransformPathCommand(
  std::vector<std::string> const& args, cmExecutionStatus& status,
  const std::function<cmCMakePath(const cmCMakePath&,
                                  const std::string& base)>& transform,
  bool normalizeOption = false)
{
  struct Arguments
  {
    std::string Output;
    std::string BaseDirectory;
    bool Normalize = false;
  };

  auto parser = ArgumentParserWithOutputVariable<Arguments>{}.Bind(
    "BASE_DIRECTORY"_s, &Arguments::BaseDirectory);
  if (normalizeOption) {
    parser.Bind("NORMALIZE"_s, &Arguments::Normalize);
  }

  Arguments arguments = parser.Parse(args);

  if (!parser.checkOutputVariable(arguments, status)) {
    return false;
  }

  if (!parser.GetInputs().empty()) {
    status.SetError(cmStrCat(args[0], " called with unexpected arguments."));
    return false;
  }

  if (std::find(parser.GetKeywordsMissingValue().begin(),
                parser.GetKeywordsMissingValue().end(), "BASE_DIRECTORY"_s) !=
      parser.GetKeywordsMissingValue().end()) {
    status.SetError("BASE_DIRECTORY requires an argument.");
    return false;
  }

  if (std::find(parser.GetParsedKeywords().begin(),
                parser.GetParsedKeywords().end(),
                "BASE_DIRECTORY"_s) == parser.GetParsedKeywords().end()) {
    arguments.BaseDirectory = status.GetMakefile().GetCurrentSourceDirectory();
  }

  std::string inputPath;
  if (!getInputPath(args[1], status, inputPath)) {
    return false;
  }

  auto path = transform(cmCMakePath(inputPath), arguments.BaseDirectory);
  if (arguments.Normalize) {
    path = path.Normal();
  }

  status.GetMakefile().AddDefinition(
    arguments.Output.empty() ? args[1] : arguments.Output, path.String());

  return true;
}

bool HandleRelativePathCommand(std::vector<std::string> const& args,
                               cmExecutionStatus& status)
{
  return HandleTransformPathCommand(
    args, status,
    [](const cmCMakePath& path, const std::string& base) -> cmCMakePath {
      return path.Relative(base);
    });
}

bool HandleAbsolutePathCommand(std::vector<std::string> const& args,
                               cmExecutionStatus& status)
{
  return HandleTransformPathCommand(
    args, status,
    [](const cmCMakePath& path, const std::string& base) -> cmCMakePath {
      return path.Absolute(base);
    },
    true);
}

bool HandleNativePathCommand(std::vector<std::string> const& args,
                             cmExecutionStatus& status)
{
  if (args.size() < 3 || args.size() > 4) {
    status.SetError("NATIVE_PATH must be called with two or three arguments.");
    return false;
  }

  static NormalizeParser const parser;

  const auto arguments = parser.Parse(args);

  if (parser.GetInputs().size() != 1) {
    status.SetError("NATIVE_PATH called with unexpected arguments.");
    return false;
  }
  if (parser.GetInputs().front().empty()) {
    status.SetError("Invalid name for output variable.");
    return false;
  }

  std::string inputPath;
  if (!getInputPath(args[1], status, inputPath)) {
    return false;
  }

  cmCMakePath path(inputPath);
  if (arguments.Normalize) {
    path = path.Normal();
  }

  status.GetMakefile().AddDefinition(parser.GetInputs().front(),
                                     path.NativeString());

  return true;
}

bool HandleConvertCommand(std::vector<std::string> const& args,
                          cmExecutionStatus& status)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
  const auto pathSep = ";"_s;
#else
  const auto pathSep = ":"_s;
#endif
  const auto cmakePath = "TO_CMAKE_PATH_LIST"_s;
  const auto nativePath = "TO_NATIVE_PATH_LIST"_s;

  if (args.size() < 4 || args.size() > 5) {
    status.SetError("CONVERT must be called with three or four arguments.");
    return false;
  }

  const auto& action = args[2];

  if (action != cmakePath && action != nativePath) {
    status.SetError(
      cmStrCat("CONVERT called with an unknown action: ", action, "."));
    return false;
  }

  if (args[3].empty()) {
    status.SetError("Invalid name for output variable.");
    return false;
  }

  static NormalizeParser const parser;

  const auto arguments = parser.Parse<4>(args);

  if (!parser.GetInputs().empty()) {
    status.SetError("CONVERT called with unexpected arguments.");
    return false;
  }

  std::vector<std::string> paths;

  if (action == cmakePath) {
    paths = cmSystemTools::SplitString(args[1], pathSep.front());
  } else {
    cmExpandList(args[1], paths);
  }

  for (auto& path : paths) {
    auto p = cmCMakePath(path,
                         action == cmakePath ? cmCMakePath::native_format
                                             : cmCMakePath::generic_format);
    if (arguments.Normalize) {
      p = p.Normal();
    }
    if (action == cmakePath) {
      path = p.GenericString();
    } else {
      path = p.NativeString();
    }
  }

  auto value = cmJoin(paths, action == cmakePath ? ";"_s : pathSep);
  status.GetMakefile().AddDefinition(args[3], value);

  return true;
}

bool HandleCompareCommand(std::vector<std::string> const& args,
                          cmExecutionStatus& status)
{
  if (args.size() != 5) {
    status.SetError("COMPARE must be called with four arguments.");
    return false;
  }

  static std::map<cm::string_view,
                  std::function<bool(const cmCMakePath&,
                                     const cmCMakePath&)>> const operators{
    { "EQUAL"_s,
      [](const cmCMakePath& path1, const cmCMakePath& path2) -> bool {
        return path1 == path2;
      } },
    { "NOT_EQUAL"_s,
      [](const cmCMakePath& path1, const cmCMakePath& path2) -> bool {
        return path1 != path2;
      } }
  };

  const auto op = operators.find(args[2]);
  if (op == operators.end()) {
    status.SetError(cmStrCat(
      "COMPARE called with an unknown comparison operator: ", args[2], "."));
    return false;
  }

  if (args[4].empty()) {
    status.SetError("Invalid name for output variable.");
    return false;
  }

  cmCMakePath path1(args[1]);
  cmCMakePath path2(args[3]);
  auto result = op->second(path1, path2);

  status.GetMakefile().AddDefinitionBool(args[4], result);

  return true;
}

bool HandleHasItemCommand(
  std::vector<std::string> const& args, cmExecutionStatus& status,
  const std::function<bool(const cmCMakePath&)>& has_item)
{
  if (args.size() != 3) {
    status.SetError(
      cmStrCat(args.front(), " must be called with two arguments."));
    return false;
  }

  std::string inputPath;
  if (!getInputPath(args[1], status, inputPath)) {
    return false;
  }

  if (args[2].empty()) {
    status.SetError("Invalid name for output variable.");
    return false;
  }

  cmCMakePath path(inputPath);
  auto result = has_item(path);

  status.GetMakefile().AddDefinitionBool(args[2], result);

  return true;
}

bool HandleHasRootNameCommand(std::vector<std::string> const& args,
                              cmExecutionStatus& status)
{
  return HandleHasItemCommand(
    args, status,
    [](const cmCMakePath& path) -> bool { return path.HasRootName(); });
}

bool HandleHasRootDirectoryCommand(std::vector<std::string> const& args,
                                   cmExecutionStatus& status)
{
  return HandleHasItemCommand(
    args, status,
    [](const cmCMakePath& path) -> bool { return path.HasRootDirectory(); });
}

bool HandleHasRootPathCommand(std::vector<std::string> const& args,
                              cmExecutionStatus& status)
{
  return HandleHasItemCommand(
    args, status,
    [](const cmCMakePath& path) -> bool { return path.HasRootPath(); });
}

bool HandleHasFilenameCommand(std::vector<std::string> const& args,
                              cmExecutionStatus& status)
{
  return HandleHasItemCommand(
    args, status,
    [](const cmCMakePath& path) -> bool { return path.HasFileName(); });
}

bool HandleHasExtensionCommand(std::vector<std::string> const& args,
                               cmExecutionStatus& status)
{
  return HandleHasItemCommand(
    args, status,
    [](const cmCMakePath& path) -> bool { return path.HasExtension(); });
}

bool HandleHasStemCommand(std::vector<std::string> const& args,
                          cmExecutionStatus& status)
{
  return HandleHasItemCommand(
    args, status,
    [](const cmCMakePath& path) -> bool { return path.HasStem(); });
}

bool HandleHasRelativePartCommand(std::vector<std::string> const& args,
                                  cmExecutionStatus& status)
{
  return HandleHasItemCommand(
    args, status,
    [](const cmCMakePath& path) -> bool { return path.HasRelativePath(); });
}

bool HandleHasParentPathCommand(std::vector<std::string> const& args,
                                cmExecutionStatus& status)
{
  return HandleHasItemCommand(
    args, status,
    [](const cmCMakePath& path) -> bool { return path.HasParentPath(); });
}

bool HandleIsAbsoluteCommand(std::vector<std::string> const& args,
                             cmExecutionStatus& status)
{
  if (args.size() != 3) {
    status.SetError("IS_ABSOLUTE must be called with two arguments.");
    return false;
  }

  std::string inputPath;
  if (!getInputPath(args[1], status, inputPath)) {
    return false;
  }

  if (args[2].empty()) {
    status.SetError("Invalid name for output variable.");
    return false;
  }

  bool isAbsolute = cmCMakePath(inputPath).IsAbsolute();

  status.GetMakefile().AddDefinitionBool(args[2], isAbsolute);

  return true;
}

bool HandleIsRelativeCommand(std::vector<std::string> const& args,
                             cmExecutionStatus& status)
{
  if (args.size() != 3) {
    status.SetError("IS_RELATIVE must be called with two arguments.");
    return false;
  }

  std::string inputPath;
  if (!getInputPath(args[1], status, inputPath)) {
    return false;
  }

  if (args[2].empty()) {
    status.SetError("Invalid name for output variable.");
    return false;
  }

  bool isRelative = cmCMakePath(inputPath).IsRelative();

  status.GetMakefile().AddDefinitionBool(args[2], isRelative);

  return true;
}

bool HandleIsPrefixCommand(std::vector<std::string> const& args,
                           cmExecutionStatus& status)
{
  if (args.size() < 4 || args.size() > 5) {
    status.SetError("IS_PREFIX must be called with three or four arguments.");
    return false;
  }

  static NormalizeParser const parser;

  const auto arguments = parser.Parse(args);

  if (parser.GetInputs().size() != 2) {
    status.SetError("IS_PREFIX called with unexpected arguments.");
    return false;
  }

  std::string inputPath;
  if (!getInputPath(args[1], status, inputPath)) {
    return false;
  }

  const auto& input = parser.GetInputs().front();
  const auto& output = parser.GetInputs().back();

  if (output.empty()) {
    status.SetError("Invalid name for output variable.");
    return false;
  }

  bool isPrefix;
  if (arguments.Normalize) {
    isPrefix =
      cmCMakePath(inputPath).Normal().IsPrefix(cmCMakePath(input).Normal());
  } else {
    isPrefix = cmCMakePath(inputPath).IsPrefix(input);
  }

  status.GetMakefile().AddDefinitionBool(output, isPrefix);

  return true;
}

bool HandleHashCommand(std::vector<std::string> const& args,
                       cmExecutionStatus& status)
{
  if (args.size() != 3) {
    status.SetError("HASH must be called with two arguments.");
    return false;
  }

  std::string inputPath;
  if (!getInputPath(args[1], status, inputPath)) {
    return false;
  }

  const auto& output = args[2];

  if (output.empty()) {
    status.SetError("Invalid name for output variable.");
    return false;
  }

  auto hash = hash_value(cmCMakePath(inputPath).Normal());

  std::ostringstream out;
  out << std::setbase(16) << hash;

  status.GetMakefile().AddDefinition(output, out.str());

  return true;
}
} // anonymous namespace

bool cmCMakePathCommand(std::vector<std::string> const& args,
                        cmExecutionStatus& status)
{
  if (args.size() < 2) {
    status.SetError("must be called with at least two arguments.");
    return false;
  }

  static cmSubcommandTable const subcommand{
    { "GET"_s, HandleGetCommand },
    { "SET"_s, HandleSetCommand },
    { "APPEND"_s, HandleAppendCommand },
    { "APPEND_STRING"_s, HandleAppendStringCommand },
    { "REMOVE_FILENAME"_s, HandleRemoveFilenameCommand },
    { "REPLACE_FILENAME"_s, HandleReplaceFilenameCommand },
    { "REMOVE_EXTENSION"_s, HandleRemoveExtensionCommand },
    { "REPLACE_EXTENSION"_s, HandleReplaceExtensionCommand },
    { "NORMAL_PATH"_s, HandleNormalPathCommand },
    { "RELATIVE_PATH"_s, HandleRelativePathCommand },
    { "ABSOLUTE_PATH"_s, HandleAbsolutePathCommand },
    { "NATIVE_PATH"_s, HandleNativePathCommand },
    { "CONVERT"_s, HandleConvertCommand },
    { "COMPARE"_s, HandleCompareCommand },
    { "HAS_ROOT_NAME"_s, HandleHasRootNameCommand },
    { "HAS_ROOT_DIRECTORY"_s, HandleHasRootDirectoryCommand },
    { "HAS_ROOT_PATH"_s, HandleHasRootPathCommand },
    { "HAS_FILENAME"_s, HandleHasFilenameCommand },
    { "HAS_EXTENSION"_s, HandleHasExtensionCommand },
    { "HAS_STEM"_s, HandleHasStemCommand },
    { "HAS_RELATIVE_PART"_s, HandleHasRelativePartCommand },
    { "HAS_PARENT_PATH"_s, HandleHasParentPathCommand },
    { "IS_ABSOLUTE"_s, HandleIsAbsoluteCommand },
    { "IS_RELATIVE"_s, HandleIsRelativeCommand },
    { "IS_PREFIX"_s, HandleIsPrefixCommand },
    { "HASH"_s, HandleHashCommand }
  };

  return subcommand(args[0], args, status);
}
