Coverage Report

Created: 2026-10-28 06:38

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Source/cmCMakePathCommand.cxx
Line
Count
Source
1
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2
   file LICENSE.rst or https://cmake.org/licensing for details.  */
3
#include "cmCMakePathCommand.h"
4
5
#include <functional>
6
#include <iomanip>
7
#include <map>
8
#include <sstream>
9
#include <string>
10
#include <utility>
11
#include <vector>
12
13
#include <cm/optional>
14
#include <cm/string_view>
15
#include <cmext/string_view>
16
17
#include "cmArgumentParser.h"
18
#include "cmArgumentParserTypes.h"
19
#include "cmCMakePath.h"
20
#include "cmExecutionStatus.h"
21
#include "cmList.h"
22
#include "cmMakefile.h"
23
#include "cmPolicies.h"
24
#include "cmRange.h"
25
#include "cmStringAlgorithms.h"
26
#include "cmSubcommandTable.h"
27
#include "cmSystemTools.h"
28
#include "cmValue.h"
29
30
namespace {
31
// Helper classes for argument parsing
32
template <typename Result>
33
class CMakePathArgumentParser : public cmArgumentParser<Result>
34
{
35
public:
36
  CMakePathArgumentParser()
37
0
    : cmArgumentParser<Result>()
38
0
  {
39
0
  }
Unexecuted instantiation: cmCMakePathCommand.cxx:(anonymous namespace)::CMakePathArgumentParser<(anonymous namespace)::HandleGetCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&)::Arguments>::CMakePathArgumentParser()
Unexecuted instantiation: cmCMakePathCommand.cxx:(anonymous namespace)::CMakePathArgumentParser<(anonymous namespace)::NormalizeOption>::CMakePathArgumentParser()
Unexecuted instantiation: cmCMakePathCommand.cxx:(anonymous namespace)::CMakePathArgumentParser<(anonymous namespace)::OutputVariable>::CMakePathArgumentParser()
Unexecuted instantiation: cmCMakePathCommand.cxx:(anonymous namespace)::CMakePathArgumentParser<(anonymous namespace)::HandleRemoveExtensionCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&)::Arguments>::CMakePathArgumentParser()
Unexecuted instantiation: cmCMakePathCommand.cxx:(anonymous namespace)::CMakePathArgumentParser<(anonymous namespace)::HandleReplaceExtensionCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&)::Arguments>::CMakePathArgumentParser()
Unexecuted instantiation: cmCMakePathCommand.cxx:(anonymous namespace)::CMakePathArgumentParser<(anonymous namespace)::HandleTransformPathCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&, std::__1::function<cmCMakePath (cmCMakePath const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)> const&, bool)::Arguments>::CMakePathArgumentParser()
40
41
  template <typename T>
42
  CMakePathArgumentParser& Bind(cm::static_string_view name, T Result::*member)
43
0
  {
44
0
    this->cmArgumentParser<Result>::Bind(name, member);
45
0
    return *this;
46
0
  }
Unexecuted instantiation: cmCMakePathCommand.cxx:(anonymous namespace)::CMakePathArgumentParser<(anonymous namespace)::HandleGetCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&)::Arguments>& (anonymous namespace)::CMakePathArgumentParser<(anonymous namespace)::HandleGetCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&)::Arguments>::Bind<bool>(cm::static_string_view, bool (anonymous namespace)::HandleGetCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&)::Arguments::*)
Unexecuted instantiation: cmCMakePathCommand.cxx:(anonymous namespace)::CMakePathArgumentParser<(anonymous namespace)::NormalizeOption>& (anonymous namespace)::CMakePathArgumentParser<(anonymous namespace)::NormalizeOption>::Bind<bool>(cm::static_string_view, bool (anonymous namespace)::NormalizeOption::*)
47
48
  template <int Advance = 2>
49
  Result Parse(std::vector<std::string> const& args) const
50
0
  {
51
0
    this->Inputs.clear();
52
53
0
    return this->cmArgumentParser<Result>::Parse(
54
0
      cmMakeRange(args).advance(Advance), &this->Inputs);
55
0
  }
Unexecuted instantiation: cmCMakePathCommand.cxx:(anonymous namespace)::HandleGetCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&)::Arguments (anonymous namespace)::CMakePathArgumentParser<(anonymous namespace)::HandleGetCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&)::Arguments>::Parse<3>(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&) const
Unexecuted instantiation: cmCMakePathCommand.cxx:(anonymous namespace)::NormalizeOption (anonymous namespace)::CMakePathArgumentParser<(anonymous namespace)::NormalizeOption>::Parse<2>(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&) const
Unexecuted instantiation: cmCMakePathCommand.cxx:(anonymous namespace)::OutputVariable (anonymous namespace)::CMakePathArgumentParser<(anonymous namespace)::OutputVariable>::Parse<2>(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&) const
Unexecuted instantiation: cmCMakePathCommand.cxx:(anonymous namespace)::HandleRemoveExtensionCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&)::Arguments (anonymous namespace)::CMakePathArgumentParser<(anonymous namespace)::HandleRemoveExtensionCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&)::Arguments>::Parse<2>(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&) const
Unexecuted instantiation: cmCMakePathCommand.cxx:(anonymous namespace)::HandleReplaceExtensionCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&)::Arguments (anonymous namespace)::CMakePathArgumentParser<(anonymous namespace)::HandleReplaceExtensionCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&)::Arguments>::Parse<2>(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&) const
Unexecuted instantiation: cmCMakePathCommand.cxx:(anonymous namespace)::HandleTransformPathCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&, std::__1::function<cmCMakePath (cmCMakePath const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)> const&, bool)::Arguments (anonymous namespace)::CMakePathArgumentParser<(anonymous namespace)::HandleTransformPathCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&, std::__1::function<cmCMakePath (cmCMakePath const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)> const&, bool)::Arguments>::Parse<2>(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&) const
Unexecuted instantiation: cmCMakePathCommand.cxx:(anonymous namespace)::NormalizeOption (anonymous namespace)::CMakePathArgumentParser<(anonymous namespace)::NormalizeOption>::Parse<4>(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&) const
56
57
0
  std::vector<std::string> const& GetInputs() const { return this->Inputs; }
Unexecuted instantiation: cmCMakePathCommand.cxx:(anonymous namespace)::CMakePathArgumentParser<(anonymous namespace)::HandleGetCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&)::Arguments>::GetInputs() const
Unexecuted instantiation: cmCMakePathCommand.cxx:(anonymous namespace)::CMakePathArgumentParser<(anonymous namespace)::NormalizeOption>::GetInputs() const
Unexecuted instantiation: cmCMakePathCommand.cxx:(anonymous namespace)::CMakePathArgumentParser<(anonymous namespace)::OutputVariable>::GetInputs() const
Unexecuted instantiation: cmCMakePathCommand.cxx:(anonymous namespace)::CMakePathArgumentParser<(anonymous namespace)::HandleRemoveExtensionCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&)::Arguments>::GetInputs() const
Unexecuted instantiation: cmCMakePathCommand.cxx:(anonymous namespace)::CMakePathArgumentParser<(anonymous namespace)::HandleReplaceExtensionCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&)::Arguments>::GetInputs() const
Unexecuted instantiation: cmCMakePathCommand.cxx:(anonymous namespace)::CMakePathArgumentParser<(anonymous namespace)::HandleTransformPathCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&, std::__1::function<cmCMakePath (cmCMakePath const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)> const&, bool)::Arguments>::GetInputs() const
58
59
protected:
60
  mutable std::vector<std::string> Inputs;
61
};
62
63
// OUTPUT_VARIABLE is expected
64
template <typename Result>
65
class ArgumentParserWithOutputVariable : public CMakePathArgumentParser<Result>
66
{
67
public:
68
  ArgumentParserWithOutputVariable()
69
0
    : CMakePathArgumentParser<Result>()
70
0
  {
71
0
    this->Bind("OUTPUT_VARIABLE"_s, &Result::Output);
72
0
  }
Unexecuted instantiation: cmCMakePathCommand.cxx:(anonymous namespace)::ArgumentParserWithOutputVariable<(anonymous namespace)::OutputVariable>::ArgumentParserWithOutputVariable()
Unexecuted instantiation: cmCMakePathCommand.cxx:(anonymous namespace)::ArgumentParserWithOutputVariable<(anonymous namespace)::HandleRemoveExtensionCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&)::Arguments>::ArgumentParserWithOutputVariable()
Unexecuted instantiation: cmCMakePathCommand.cxx:(anonymous namespace)::ArgumentParserWithOutputVariable<(anonymous namespace)::HandleReplaceExtensionCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&)::Arguments>::ArgumentParserWithOutputVariable()
Unexecuted instantiation: cmCMakePathCommand.cxx:(anonymous namespace)::ArgumentParserWithOutputVariable<(anonymous namespace)::HandleTransformPathCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&, std::__1::function<cmCMakePath (cmCMakePath const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)> const&, bool)::Arguments>::ArgumentParserWithOutputVariable()
73
74
  template <typename T>
75
  ArgumentParserWithOutputVariable& Bind(cm::static_string_view name,
76
                                         T Result::*member)
77
0
  {
78
0
    this->cmArgumentParser<Result>::Bind(name, member);
79
0
    return *this;
80
0
  }
Unexecuted instantiation: cmCMakePathCommand.cxx:(anonymous namespace)::ArgumentParserWithOutputVariable<(anonymous namespace)::OutputVariable>& (anonymous namespace)::ArgumentParserWithOutputVariable<(anonymous namespace)::OutputVariable>::Bind<std::__1::optional<ArgumentParser::NonEmpty<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >(cm::static_string_view, std::__1::optional<ArgumentParser::NonEmpty<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > (anonymous namespace)::OutputVariable::*)
Unexecuted instantiation: cmCMakePathCommand.cxx:(anonymous namespace)::ArgumentParserWithOutputVariable<(anonymous namespace)::HandleRemoveExtensionCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&)::Arguments>& (anonymous namespace)::ArgumentParserWithOutputVariable<(anonymous namespace)::HandleRemoveExtensionCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&)::Arguments>::Bind<std::__1::optional<ArgumentParser::NonEmpty<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >(cm::static_string_view, std::__1::optional<ArgumentParser::NonEmpty<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > (anonymous namespace)::HandleRemoveExtensionCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&)::Arguments::*)
Unexecuted instantiation: cmCMakePathCommand.cxx:(anonymous namespace)::ArgumentParserWithOutputVariable<(anonymous namespace)::HandleRemoveExtensionCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&)::Arguments>& (anonymous namespace)::ArgumentParserWithOutputVariable<(anonymous namespace)::HandleRemoveExtensionCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&)::Arguments>::Bind<bool>(cm::static_string_view, bool (anonymous namespace)::HandleRemoveExtensionCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&)::Arguments::*)
Unexecuted instantiation: cmCMakePathCommand.cxx:(anonymous namespace)::ArgumentParserWithOutputVariable<(anonymous namespace)::HandleReplaceExtensionCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&)::Arguments>& (anonymous namespace)::ArgumentParserWithOutputVariable<(anonymous namespace)::HandleReplaceExtensionCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&)::Arguments>::Bind<std::__1::optional<ArgumentParser::NonEmpty<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >(cm::static_string_view, std::__1::optional<ArgumentParser::NonEmpty<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > (anonymous namespace)::HandleReplaceExtensionCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&)::Arguments::*)
Unexecuted instantiation: cmCMakePathCommand.cxx:(anonymous namespace)::ArgumentParserWithOutputVariable<(anonymous namespace)::HandleReplaceExtensionCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&)::Arguments>& (anonymous namespace)::ArgumentParserWithOutputVariable<(anonymous namespace)::HandleReplaceExtensionCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&)::Arguments>::Bind<bool>(cm::static_string_view, bool (anonymous namespace)::HandleReplaceExtensionCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&)::Arguments::*)
Unexecuted instantiation: cmCMakePathCommand.cxx:(anonymous namespace)::ArgumentParserWithOutputVariable<(anonymous namespace)::HandleTransformPathCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&, std::__1::function<cmCMakePath (cmCMakePath const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)> const&, bool)::Arguments>& (anonymous namespace)::ArgumentParserWithOutputVariable<(anonymous namespace)::HandleTransformPathCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&, std::__1::function<cmCMakePath (cmCMakePath const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)> const&, bool)::Arguments>::Bind<std::__1::optional<ArgumentParser::NonEmpty<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >(cm::static_string_view, std::__1::optional<ArgumentParser::NonEmpty<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > (anonymous namespace)::HandleTransformPathCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&, std::__1::function<cmCMakePath (cmCMakePath const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)> const&, bool)::Arguments::*)
Unexecuted instantiation: cmCMakePathCommand.cxx:(anonymous namespace)::ArgumentParserWithOutputVariable<(anonymous namespace)::HandleTransformPathCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&, std::__1::function<cmCMakePath (cmCMakePath const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)> const&, bool)::Arguments>& (anonymous namespace)::ArgumentParserWithOutputVariable<(anonymous namespace)::HandleTransformPathCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&, std::__1::function<cmCMakePath (cmCMakePath const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)> const&, bool)::Arguments>::Bind<std::__1::optional<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >(cm::static_string_view, std::__1::optional<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > (anonymous namespace)::HandleTransformPathCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&, std::__1::function<cmCMakePath (cmCMakePath const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)> const&, bool)::Arguments::*)
Unexecuted instantiation: cmCMakePathCommand.cxx:(anonymous namespace)::ArgumentParserWithOutputVariable<(anonymous namespace)::HandleTransformPathCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&, std::__1::function<cmCMakePath (cmCMakePath const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)> const&, bool)::Arguments>& (anonymous namespace)::ArgumentParserWithOutputVariable<(anonymous namespace)::HandleTransformPathCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&, std::__1::function<cmCMakePath (cmCMakePath const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)> const&, bool)::Arguments>::Bind<bool>(cm::static_string_view, bool (anonymous namespace)::HandleTransformPathCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&, std::__1::function<cmCMakePath (cmCMakePath const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)> const&, bool)::Arguments::*)
81
82
  template <int Advance = 2>
83
  Result Parse(std::vector<std::string> const& args) const
84
0
  {
85
0
    return this->CMakePathArgumentParser<Result>::template Parse<Advance>(
86
0
      args);
87
0
  }
Unexecuted instantiation: cmCMakePathCommand.cxx:(anonymous namespace)::OutputVariable (anonymous namespace)::ArgumentParserWithOutputVariable<(anonymous namespace)::OutputVariable>::Parse<2>(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&) const
Unexecuted instantiation: cmCMakePathCommand.cxx:(anonymous namespace)::HandleRemoveExtensionCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&)::Arguments (anonymous namespace)::ArgumentParserWithOutputVariable<(anonymous namespace)::HandleRemoveExtensionCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&)::Arguments>::Parse<2>(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&) const
Unexecuted instantiation: cmCMakePathCommand.cxx:(anonymous namespace)::HandleReplaceExtensionCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&)::Arguments (anonymous namespace)::ArgumentParserWithOutputVariable<(anonymous namespace)::HandleReplaceExtensionCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&)::Arguments>::Parse<2>(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&) const
Unexecuted instantiation: cmCMakePathCommand.cxx:(anonymous namespace)::HandleTransformPathCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&, std::__1::function<cmCMakePath (cmCMakePath const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)> const&, bool)::Arguments (anonymous namespace)::ArgumentParserWithOutputVariable<(anonymous namespace)::HandleTransformPathCommand(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmExecutionStatus&, std::__1::function<cmCMakePath (cmCMakePath const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)> const&, bool)::Arguments>::Parse<2>(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&) const
88
};
89
90
struct OutputVariable : public ArgumentParser::ParseResult
91
{
92
  cm::optional<ArgumentParser::NonEmpty<std::string>> Output;
93
};
94
// Usable when OUTPUT_VARIABLE is the only option
95
class OutputVariableParser
96
  : public ArgumentParserWithOutputVariable<OutputVariable>
97
{
98
};
99
100
struct NormalizeOption
101
{
102
  bool Normalize = false;
103
};
104
// Usable when NORMALIZE is the only option
105
class NormalizeParser : public CMakePathArgumentParser<NormalizeOption>
106
{
107
public:
108
0
  NormalizeParser() { this->Bind("NORMALIZE"_s, &NormalizeOption::Normalize); }
109
};
110
111
// retrieve value of input path from specified variable
112
bool getInputPath(std::string const& arg, cmExecutionStatus& status,
113
                  std::string& path)
114
0
{
115
0
  cmValue def = status.GetMakefile().GetDefinition(arg);
116
0
  if (!def) {
117
0
    status.SetError("undefined variable for input path.");
118
0
    return false;
119
0
  }
120
121
0
  path = *def;
122
0
  return true;
123
0
}
124
125
bool HandleGetCommand(std::vector<std::string> const& args,
126
                      cmExecutionStatus& status)
127
0
{
128
0
  static std::map<cm::string_view,
129
0
                  std::function<cmCMakePath(cmCMakePath const&, bool)>> const
130
0
    actions{ { "ROOT_NAME"_s,
131
0
               [](cmCMakePath const& path, bool) -> cmCMakePath {
132
0
                 return path.GetRootName();
133
0
               } },
134
0
             { "ROOT_DIRECTORY"_s,
135
0
               [](cmCMakePath const& path, bool) -> cmCMakePath {
136
0
                 return path.GetRootDirectory();
137
0
               } },
138
0
             { "ROOT_PATH"_s,
139
0
               [](cmCMakePath const& path, bool) -> cmCMakePath {
140
0
                 return path.GetRootPath();
141
0
               } },
142
0
             { "FILENAME"_s,
143
0
               [](cmCMakePath const& path, bool) -> cmCMakePath {
144
0
                 return path.GetFileName();
145
0
               } },
146
0
             { "EXTENSION"_s,
147
0
               [](cmCMakePath const& path, bool last_only) -> cmCMakePath {
148
0
                 if (last_only) {
149
0
                   return path.GetExtension();
150
0
                 }
151
0
                 return path.GetWideExtension();
152
0
               } },
153
0
             { "STEM"_s,
154
0
               [](cmCMakePath const& path, bool last_only) -> cmCMakePath {
155
0
                 if (last_only) {
156
0
                   return path.GetStem();
157
0
                 }
158
0
                 return path.GetNarrowStem();
159
0
               } },
160
0
             { "RELATIVE_PART"_s,
161
0
               [](cmCMakePath const& path, bool) -> cmCMakePath {
162
0
                 return path.GetRelativePath();
163
0
               } },
164
0
             { "PARENT_PATH"_s,
165
0
               [](cmCMakePath const& path, bool) -> cmCMakePath {
166
0
                 return path.GetParentPath();
167
0
               } } };
168
169
0
  if (args.size() < 4) {
170
0
    status.SetError("GET must be called with at least three arguments.");
171
0
    return false;
172
0
  }
173
174
0
  auto const& action = args[2];
175
176
0
  if (actions.find(action) == actions.end()) {
177
0
    status.SetError(
178
0
      cmStrCat("GET called with an unknown action: ", action, '.'));
179
0
    return false;
180
0
  }
181
182
0
  struct Arguments
183
0
  {
184
0
    bool LastOnly = false;
185
0
  };
186
187
0
  CMakePathArgumentParser<Arguments> parser;
188
0
  if ((action == "EXTENSION"_s || action == "STEM"_s)) {
189
0
    parser.Bind("LAST_ONLY"_s, &Arguments::LastOnly);
190
0
  }
191
192
0
  Arguments const arguments = parser.Parse<3>(args);
193
194
0
  if (parser.GetInputs().size() != 1) {
195
0
    status.SetError("GET called with unexpected arguments.");
196
0
    return false;
197
0
  }
198
0
  if (parser.GetInputs().front().empty()) {
199
0
    status.SetError("Invalid name for output variable.");
200
0
    return false;
201
0
  }
202
203
0
  std::string path;
204
0
  if (!getInputPath(args[1], status, path)) {
205
0
    return false;
206
0
  }
207
208
0
  auto result = actions.at(action)(path, arguments.LastOnly);
209
210
0
  status.GetMakefile().AddDefinition(parser.GetInputs().front(),
211
0
                                     result.String());
212
213
0
  return true;
214
0
}
215
216
bool HandleSetCommand(std::vector<std::string> const& args,
217
                      cmExecutionStatus& status)
218
0
{
219
0
  if (args.size() < 3 || args.size() > 4) {
220
0
    status.SetError("SET must be called with two or three arguments.");
221
0
    return false;
222
0
  }
223
224
0
  if (args[1].empty()) {
225
0
    status.SetError("Invalid name for path variable.");
226
0
    return false;
227
0
  }
228
229
0
  static NormalizeParser const parser;
230
231
0
  auto const arguments = parser.Parse(args);
232
233
0
  if (parser.GetInputs().size() != 1) {
234
0
    status.SetError("SET called with unexpected arguments.");
235
0
    return false;
236
0
  }
237
238
0
  auto path =
239
0
    cmCMakePath(parser.GetInputs().front(), cmCMakePath::native_format);
240
241
0
  if (arguments.Normalize) {
242
0
    path = path.Normal();
243
0
  }
244
245
0
  status.GetMakefile().AddDefinition(args[1], path.GenericString());
246
247
0
  return true;
248
0
}
249
250
bool HandleAppendCommand(std::vector<std::string> const& args,
251
                         cmExecutionStatus& status)
252
0
{
253
0
  if (args[1].empty()) {
254
0
    status.SetError("Invalid name for path variable.");
255
0
    return false;
256
0
  }
257
258
0
  static OutputVariableParser const parser{};
259
260
0
  auto const arguments = parser.Parse(args);
261
262
0
  if (arguments.MaybeReportError(status.GetMakefile())) {
263
0
    return true;
264
0
  }
265
266
0
  cmCMakePath path(status.GetMakefile().GetSafeDefinition(args[1]));
267
0
  for (auto const& input : parser.GetInputs()) {
268
0
    path /= input;
269
0
  }
270
271
0
  status.GetMakefile().AddDefinition(
272
0
    arguments.Output ? *arguments.Output : args[1], path.String());
273
274
0
  return true;
275
0
}
276
277
bool HandleAppendStringCommand(std::vector<std::string> const& args,
278
                               cmExecutionStatus& status)
279
0
{
280
0
  static OutputVariableParser const parser{};
281
282
0
  auto const arguments = parser.Parse(args);
283
284
0
  if (arguments.MaybeReportError(status.GetMakefile())) {
285
0
    return true;
286
0
  }
287
288
0
  std::string inputPath;
289
0
  if (!getInputPath(args[1], status, inputPath)) {
290
0
    return false;
291
0
  }
292
293
0
  cmCMakePath path(inputPath);
294
0
  for (auto const& input : parser.GetInputs()) {
295
0
    path += input;
296
0
  }
297
298
0
  status.GetMakefile().AddDefinition(
299
0
    arguments.Output ? *arguments.Output : args[1], path.String());
300
301
0
  return true;
302
0
}
303
304
bool HandleRemoveFilenameCommand(std::vector<std::string> const& args,
305
                                 cmExecutionStatus& status)
306
0
{
307
0
  static OutputVariableParser const parser{};
308
309
0
  auto const arguments = parser.Parse(args);
310
311
0
  if (arguments.MaybeReportError(status.GetMakefile())) {
312
0
    return true;
313
0
  }
314
315
0
  if (!parser.GetInputs().empty()) {
316
0
    status.SetError("REMOVE_FILENAME called with unexpected arguments.");
317
0
    return false;
318
0
  }
319
320
0
  std::string inputPath;
321
0
  if (!getInputPath(args[1], status, inputPath)) {
322
0
    return false;
323
0
  }
324
325
0
  cmCMakePath path(inputPath);
326
0
  path.RemoveFileName();
327
328
0
  status.GetMakefile().AddDefinition(
329
0
    arguments.Output ? *arguments.Output : args[1], path.String());
330
331
0
  return true;
332
0
}
333
334
bool HandleReplaceFilenameCommand(std::vector<std::string> const& args,
335
                                  cmExecutionStatus& status)
336
0
{
337
0
  static OutputVariableParser const parser{};
338
339
0
  auto const arguments = parser.Parse(args);
340
341
0
  if (arguments.MaybeReportError(status.GetMakefile())) {
342
0
    return true;
343
0
  }
344
345
0
  if (parser.GetInputs().size() > 1) {
346
0
    status.SetError("REPLACE_FILENAME called with unexpected arguments.");
347
0
    return false;
348
0
  }
349
350
0
  std::string inputPath;
351
0
  if (!getInputPath(args[1], status, inputPath)) {
352
0
    return false;
353
0
  }
354
355
0
  cmCMakePath path(inputPath);
356
0
  path.ReplaceFileName(
357
0
    parser.GetInputs().empty() ? "" : parser.GetInputs().front());
358
359
0
  status.GetMakefile().AddDefinition(
360
0
    arguments.Output ? *arguments.Output : args[1], path.String());
361
362
0
  return true;
363
0
}
364
365
bool HandleRemoveExtensionCommand(std::vector<std::string> const& args,
366
                                  cmExecutionStatus& status)
367
0
{
368
0
  struct Arguments : public ArgumentParser::ParseResult
369
0
  {
370
0
    cm::optional<ArgumentParser::NonEmpty<std::string>> Output;
371
0
    bool LastOnly = false;
372
0
  };
373
374
0
  static auto const parser =
375
0
    ArgumentParserWithOutputVariable<Arguments>{}.Bind("LAST_ONLY"_s,
376
0
                                                       &Arguments::LastOnly);
377
378
0
  Arguments const arguments = parser.Parse(args);
379
380
0
  if (arguments.MaybeReportError(status.GetMakefile())) {
381
0
    return true;
382
0
  }
383
384
0
  if (!parser.GetInputs().empty()) {
385
0
    status.SetError("REMOVE_EXTENSION called with unexpected arguments.");
386
0
    return false;
387
0
  }
388
389
0
  std::string inputPath;
390
0
  if (!getInputPath(args[1], status, inputPath)) {
391
0
    return false;
392
0
  }
393
394
0
  cmCMakePath path(inputPath);
395
396
0
  if (arguments.LastOnly) {
397
0
    path.RemoveExtension();
398
0
  } else {
399
0
    path.RemoveWideExtension();
400
0
  }
401
402
0
  status.GetMakefile().AddDefinition(
403
0
    arguments.Output ? *arguments.Output : args[1], path.String());
404
405
0
  return true;
406
0
}
407
408
bool HandleReplaceExtensionCommand(std::vector<std::string> const& args,
409
                                   cmExecutionStatus& status)
410
0
{
411
0
  struct Arguments : public ArgumentParser::ParseResult
412
0
  {
413
0
    cm::optional<ArgumentParser::NonEmpty<std::string>> Output;
414
0
    bool LastOnly = false;
415
0
  };
416
417
0
  static auto const parser =
418
0
    ArgumentParserWithOutputVariable<Arguments>{}.Bind("LAST_ONLY"_s,
419
0
                                                       &Arguments::LastOnly);
420
421
0
  Arguments const arguments = parser.Parse(args);
422
423
0
  if (arguments.MaybeReportError(status.GetMakefile())) {
424
0
    return true;
425
0
  }
426
427
0
  if (parser.GetInputs().size() > 1) {
428
0
    status.SetError("REPLACE_EXTENSION called with unexpected arguments.");
429
0
    return false;
430
0
  }
431
432
0
  std::string inputPath;
433
0
  if (!getInputPath(args[1], status, inputPath)) {
434
0
    return false;
435
0
  }
436
437
0
  cmCMakePath path(inputPath);
438
0
  cmCMakePath extension(
439
0
    parser.GetInputs().empty() ? "" : parser.GetInputs().front());
440
441
0
  if (arguments.LastOnly) {
442
0
    path.ReplaceExtension(extension);
443
0
  } else {
444
0
    path.ReplaceWideExtension(extension);
445
0
  }
446
447
0
  status.GetMakefile().AddDefinition(
448
0
    arguments.Output ? *arguments.Output : args[1], path.String());
449
450
0
  return true;
451
0
}
452
453
bool HandleNormalPathCommand(std::vector<std::string> const& args,
454
                             cmExecutionStatus& status)
455
0
{
456
0
  static OutputVariableParser const parser{};
457
458
0
  auto const arguments = parser.Parse(args);
459
460
0
  if (arguments.MaybeReportError(status.GetMakefile())) {
461
0
    return true;
462
0
  }
463
464
0
  if (!parser.GetInputs().empty()) {
465
0
    status.SetError("NORMAL_PATH called with unexpected arguments.");
466
0
    return false;
467
0
  }
468
469
0
  std::string inputPath;
470
0
  if (!getInputPath(args[1], status, inputPath)) {
471
0
    return false;
472
0
  }
473
474
0
  auto path = cmCMakePath(inputPath).Normal();
475
476
0
  status.GetMakefile().AddDefinition(
477
0
    arguments.Output ? *arguments.Output : args[1], path.String());
478
479
0
  return true;
480
0
}
481
482
bool HandleTransformPathCommand(
483
  std::vector<std::string> const& args, cmExecutionStatus& status,
484
  std::function<cmCMakePath(cmCMakePath const&,
485
                            std::string const& base)> const& transform,
486
  bool normalizeOption = false)
487
0
{
488
0
  struct Arguments : public ArgumentParser::ParseResult
489
0
  {
490
0
    cm::optional<ArgumentParser::NonEmpty<std::string>> Output;
491
0
    cm::optional<std::string> BaseDirectory;
492
0
    bool Normalize = false;
493
0
  };
494
495
0
  auto parser = ArgumentParserWithOutputVariable<Arguments>{}.Bind(
496
0
    "BASE_DIRECTORY"_s, &Arguments::BaseDirectory);
497
0
  if (normalizeOption) {
498
0
    parser.Bind("NORMALIZE"_s, &Arguments::Normalize);
499
0
  }
500
501
0
  Arguments arguments = parser.Parse(args);
502
503
0
  if (arguments.MaybeReportError(status.GetMakefile())) {
504
0
    return true;
505
0
  }
506
507
0
  if (!parser.GetInputs().empty()) {
508
0
    status.SetError(cmStrCat(args[0], " called with unexpected arguments."));
509
0
    return false;
510
0
  }
511
512
0
  std::string baseDirectory;
513
0
  if (arguments.BaseDirectory) {
514
0
    baseDirectory = *arguments.BaseDirectory;
515
0
  } else {
516
0
    baseDirectory = status.GetMakefile().GetCurrentSourceDirectory();
517
0
  }
518
519
0
  std::string inputPath;
520
0
  if (!getInputPath(args[1], status, inputPath)) {
521
0
    return false;
522
0
  }
523
524
0
  auto path = transform(cmCMakePath(inputPath), baseDirectory);
525
0
  if (arguments.Normalize) {
526
0
    path = path.Normal();
527
0
  }
528
529
0
  status.GetMakefile().AddDefinition(
530
0
    arguments.Output ? *arguments.Output : args[1], path.String());
531
532
0
  return true;
533
0
}
534
535
bool HandleRelativePathCommand(std::vector<std::string> const& args,
536
                               cmExecutionStatus& status)
537
0
{
538
0
  return HandleTransformPathCommand(
539
0
    args, status,
540
0
    [](cmCMakePath const& path, std::string const& base) -> cmCMakePath {
541
0
      return path.Relative(base);
542
0
    });
543
0
}
544
545
bool HandleAbsolutePathCommand(std::vector<std::string> const& args,
546
                               cmExecutionStatus& status)
547
0
{
548
0
  return HandleTransformPathCommand(
549
0
    args, status,
550
0
    [](cmCMakePath const& path, std::string const& base) -> cmCMakePath {
551
0
      return path.Absolute(base);
552
0
    },
553
0
    true);
554
0
}
555
556
bool HandleNativePathCommand(std::vector<std::string> const& args,
557
                             cmExecutionStatus& status)
558
0
{
559
0
  if (args.size() < 3 || args.size() > 4) {
560
0
    status.SetError("NATIVE_PATH must be called with two or three arguments.");
561
0
    return false;
562
0
  }
563
564
0
  static NormalizeParser const parser;
565
566
0
  auto const arguments = parser.Parse(args);
567
568
0
  if (parser.GetInputs().size() != 1) {
569
0
    status.SetError("NATIVE_PATH called with unexpected arguments.");
570
0
    return false;
571
0
  }
572
0
  if (parser.GetInputs().front().empty()) {
573
0
    status.SetError("Invalid name for output variable.");
574
0
    return false;
575
0
  }
576
577
0
  std::string inputPath;
578
0
  if (!getInputPath(args[1], status, inputPath)) {
579
0
    return false;
580
0
  }
581
582
0
  cmCMakePath path(inputPath);
583
0
  if (arguments.Normalize) {
584
0
    path = path.Normal();
585
0
  }
586
587
0
  status.GetMakefile().AddDefinition(parser.GetInputs().front(),
588
0
                                     path.NativeString());
589
590
0
  return true;
591
0
}
592
593
bool HandleConvertCommand(std::vector<std::string> const& args,
594
                          cmExecutionStatus& status)
595
0
{
596
#if defined(_WIN32) && !defined(__CYGWIN__)
597
  auto const pathSep = ";"_s;
598
#else
599
0
  auto const pathSep = ":"_s;
600
0
#endif
601
0
  auto const cmakePath = "TO_CMAKE_PATH_LIST"_s;
602
0
  auto const nativePath = "TO_NATIVE_PATH_LIST"_s;
603
604
0
  if (args.size() < 4 || args.size() > 5) {
605
0
    status.SetError("CONVERT must be called with three or four arguments.");
606
0
    return false;
607
0
  }
608
609
0
  auto const& action = args[2];
610
611
0
  if (action != cmakePath && action != nativePath) {
612
0
    status.SetError(
613
0
      cmStrCat("CONVERT called with an unknown action: ", action, '.'));
614
0
    return false;
615
0
  }
616
617
0
  if (args[3].empty()) {
618
0
    status.SetError("Invalid name for output variable.");
619
0
    return false;
620
0
  }
621
622
0
  static NormalizeParser const parser;
623
624
0
  auto const arguments = parser.Parse<4>(args);
625
626
0
  if (!parser.GetInputs().empty()) {
627
0
    status.SetError("CONVERT called with unexpected arguments.");
628
0
    return false;
629
0
  }
630
631
0
  cmList paths;
632
633
0
  if (action == cmakePath) {
634
0
    paths = cmSystemTools::SplitString(args[1], pathSep.front());
635
0
  } else {
636
0
    paths.assign(args[1]);
637
0
  }
638
639
0
  for (auto& path : paths) {
640
0
    auto p = cmCMakePath(path,
641
0
                         action == cmakePath ? cmCMakePath::native_format
642
0
                                             : cmCMakePath::generic_format);
643
0
    if (arguments.Normalize) {
644
0
      p = p.Normal();
645
0
    }
646
0
    if (action == cmakePath) {
647
0
      path = p.GenericString();
648
0
    } else {
649
0
      path = p.NativeString();
650
0
    }
651
0
  }
652
653
0
  auto value = action == cmakePath ? paths.to_string() : paths.join(pathSep);
654
0
  status.GetMakefile().AddDefinition(args[3], value);
655
656
0
  return true;
657
0
}
658
659
bool HandleCompareCommand(std::vector<std::string> const& args,
660
                          cmExecutionStatus& status)
661
0
{
662
0
  if (args.size() != 5) {
663
0
    status.SetError("COMPARE must be called with four arguments.");
664
0
    return false;
665
0
  }
666
667
0
  static std::map<cm::string_view,
668
0
                  std::function<bool(cmCMakePath const&,
669
0
                                     cmCMakePath const&)>> const operators{
670
0
    { "EQUAL"_s,
671
0
      [](cmCMakePath const& path1, cmCMakePath const& path2) -> bool {
672
0
        return path1 == path2;
673
0
      } },
674
0
    { "NOT_EQUAL"_s,
675
0
      [](cmCMakePath const& path1, cmCMakePath const& path2) -> bool {
676
0
        return path1 != path2;
677
0
      } }
678
0
  };
679
680
0
  auto const op = operators.find(args[2]);
681
0
  if (op == operators.end()) {
682
0
    status.SetError(cmStrCat(
683
0
      "COMPARE called with an unknown comparison operator: ", args[2], '.'));
684
0
    return false;
685
0
  }
686
687
0
  if (args[4].empty()) {
688
0
    status.SetError("Invalid name for output variable.");
689
0
    return false;
690
0
  }
691
692
0
  cmCMakePath path1(args[1]);
693
0
  cmCMakePath path2(args[3]);
694
0
  auto result = op->second(path1, path2);
695
696
0
  status.GetMakefile().AddDefinitionBool(args[4], result);
697
698
0
  return true;
699
0
}
700
701
bool HandleHasItemCommand(
702
  std::vector<std::string> const& args, cmExecutionStatus& status,
703
  std::function<bool(cmCMakePath const&)> const& has_item)
704
0
{
705
0
  if (args.size() != 3) {
706
0
    status.SetError(
707
0
      cmStrCat(args.front(), " must be called with two arguments."));
708
0
    return false;
709
0
  }
710
711
0
  std::string inputPath;
712
0
  if (!getInputPath(args[1], status, inputPath)) {
713
0
    return false;
714
0
  }
715
716
0
  if (args[2].empty()) {
717
0
    status.SetError("Invalid name for output variable.");
718
0
    return false;
719
0
  }
720
721
0
  cmCMakePath path(inputPath);
722
0
  auto result = has_item(path);
723
724
0
  status.GetMakefile().AddDefinitionBool(args[2], result);
725
726
0
  return true;
727
0
}
728
729
bool HandleHasRootNameCommand(std::vector<std::string> const& args,
730
                              cmExecutionStatus& status)
731
0
{
732
0
  return HandleHasItemCommand(
733
0
    args, status,
734
0
    [](cmCMakePath const& path) -> bool { return path.HasRootName(); });
735
0
}
736
737
bool HandleHasRootDirectoryCommand(std::vector<std::string> const& args,
738
                                   cmExecutionStatus& status)
739
0
{
740
0
  return HandleHasItemCommand(
741
0
    args, status,
742
0
    [](cmCMakePath const& path) -> bool { return path.HasRootDirectory(); });
743
0
}
744
745
bool HandleHasRootPathCommand(std::vector<std::string> const& args,
746
                              cmExecutionStatus& status)
747
0
{
748
0
  return HandleHasItemCommand(
749
0
    args, status,
750
0
    [](cmCMakePath const& path) -> bool { return path.HasRootPath(); });
751
0
}
752
753
bool HandleHasFilenameCommand(std::vector<std::string> const& args,
754
                              cmExecutionStatus& status)
755
0
{
756
0
  return HandleHasItemCommand(
757
0
    args, status,
758
0
    [](cmCMakePath const& path) -> bool { return path.HasFileName(); });
759
0
}
760
761
bool HandleHasExtensionCommand(std::vector<std::string> const& args,
762
                               cmExecutionStatus& status)
763
0
{
764
0
  return HandleHasItemCommand(
765
0
    args, status,
766
0
    [](cmCMakePath const& path) -> bool { return path.HasExtension(); });
767
0
}
768
769
bool HandleHasStemCommand(std::vector<std::string> const& args,
770
                          cmExecutionStatus& status)
771
0
{
772
0
  return HandleHasItemCommand(
773
0
    args, status,
774
0
    [](cmCMakePath const& path) -> bool { return path.HasStem(); });
775
0
}
776
777
bool HandleHasRelativePartCommand(std::vector<std::string> const& args,
778
                                  cmExecutionStatus& status)
779
0
{
780
0
  return HandleHasItemCommand(
781
0
    args, status,
782
0
    [](cmCMakePath const& path) -> bool { return path.HasRelativePath(); });
783
0
}
784
785
bool HandleHasParentPathCommand(std::vector<std::string> const& args,
786
                                cmExecutionStatus& status)
787
0
{
788
0
  return HandleHasItemCommand(
789
0
    args, status,
790
0
    [](cmCMakePath const& path) -> bool { return path.HasParentPath(); });
791
0
}
792
793
bool HandleIsAbsoluteCommand(std::vector<std::string> const& args,
794
                             cmExecutionStatus& status)
795
0
{
796
0
  if (args.size() != 3) {
797
0
    status.SetError("IS_ABSOLUTE must be called with two arguments.");
798
0
    return false;
799
0
  }
800
801
0
  std::string inputPath;
802
0
  if (!getInputPath(args[1], status, inputPath)) {
803
0
    return false;
804
0
  }
805
806
0
  if (args[2].empty()) {
807
0
    status.SetError("Invalid name for output variable.");
808
0
    return false;
809
0
  }
810
811
0
  bool isAbsolute = cmCMakePath(inputPath).IsAbsolute();
812
813
0
  status.GetMakefile().AddDefinitionBool(args[2], isAbsolute);
814
815
0
  return true;
816
0
}
817
818
bool HandleIsRelativeCommand(std::vector<std::string> const& args,
819
                             cmExecutionStatus& status)
820
0
{
821
0
  if (args.size() != 3) {
822
0
    status.SetError("IS_RELATIVE must be called with two arguments.");
823
0
    return false;
824
0
  }
825
826
0
  std::string inputPath;
827
0
  if (!getInputPath(args[1], status, inputPath)) {
828
0
    return false;
829
0
  }
830
831
0
  if (args[2].empty()) {
832
0
    status.SetError("Invalid name for output variable.");
833
0
    return false;
834
0
  }
835
836
0
  bool isRelative = cmCMakePath(inputPath).IsRelative();
837
838
0
  status.GetMakefile().AddDefinitionBool(args[2], isRelative);
839
840
0
  return true;
841
0
}
842
843
// CMP0223: an empty path used to be a prefix of every path.
844
bool IsPrefixCMP0223(cmCMakePath const& prefix, cmMakefile& mf)
845
0
{
846
0
  if (!prefix.IsEmpty()) {
847
0
    return false;
848
0
  }
849
0
  switch (mf.GetPolicyStatus(cmPolicies::CMP0223)) {
850
0
    case cmPolicies::WARN:
851
0
      mf.IssuePolicyWarning(cmPolicies::CMP0223);
852
0
      CM_FALLTHROUGH;
853
0
    case cmPolicies::OLD:
854
0
      return true;
855
0
    case cmPolicies::NEW:
856
0
      break;
857
0
  }
858
0
  return false;
859
0
}
860
861
bool HandleIsPrefixCommand(std::vector<std::string> const& args,
862
                           cmExecutionStatus& status)
863
0
{
864
0
  if (args.size() < 4 || args.size() > 5) {
865
0
    status.SetError("IS_PREFIX must be called with three or four arguments.");
866
0
    return false;
867
0
  }
868
869
0
  static NormalizeParser const parser;
870
871
0
  auto const arguments = parser.Parse(args);
872
873
0
  if (parser.GetInputs().size() != 2) {
874
0
    status.SetError("IS_PREFIX called with unexpected arguments.");
875
0
    return false;
876
0
  }
877
878
0
  std::string inputPath;
879
0
  if (!getInputPath(args[1], status, inputPath)) {
880
0
    return false;
881
0
  }
882
883
0
  auto const& input = parser.GetInputs().front();
884
0
  auto const& output = parser.GetInputs().back();
885
886
0
  if (output.empty()) {
887
0
    status.SetError("Invalid name for output variable.");
888
0
    return false;
889
0
  }
890
891
0
  cmCMakePath prefix{ inputPath };
892
0
  cmCMakePath value{ input };
893
0
  if (arguments.Normalize) {
894
0
    prefix = prefix.Normal();
895
0
    value = value.Normal();
896
0
  }
897
898
0
  bool const isPrefix =
899
0
    prefix.IsPrefix(value) || IsPrefixCMP0223(prefix, status.GetMakefile());
900
901
0
  status.GetMakefile().AddDefinitionBool(output, isPrefix);
902
903
0
  return true;
904
0
}
905
906
bool HandleHashCommand(std::vector<std::string> const& args,
907
                       cmExecutionStatus& status)
908
0
{
909
0
  if (args.size() != 3) {
910
0
    status.SetError("HASH must be called with two arguments.");
911
0
    return false;
912
0
  }
913
914
0
  std::string inputPath;
915
0
  if (!getInputPath(args[1], status, inputPath)) {
916
0
    return false;
917
0
  }
918
919
0
  auto const& output = args[2];
920
921
0
  if (output.empty()) {
922
0
    status.SetError("Invalid name for output variable.");
923
0
    return false;
924
0
  }
925
926
0
  auto hash = hash_value(cmCMakePath(inputPath).Normal());
927
928
0
  std::ostringstream out;
929
0
  out << std::setbase(16) << hash;
930
931
0
  status.GetMakefile().AddDefinition(output, out.str());
932
933
0
  return true;
934
0
}
935
} // anonymous namespace
936
937
bool cmCMakePathCommand(std::vector<std::string> const& args,
938
                        cmExecutionStatus& status)
939
0
{
940
0
  if (args.size() < 2) {
941
0
    status.SetError("must be called with at least two arguments.");
942
0
    return false;
943
0
  }
944
945
0
  static cmSubcommandTable const subcommand{
946
0
    { "GET"_s, HandleGetCommand },
947
0
    { "SET"_s, HandleSetCommand },
948
0
    { "APPEND"_s, HandleAppendCommand },
949
0
    { "APPEND_STRING"_s, HandleAppendStringCommand },
950
0
    { "REMOVE_FILENAME"_s, HandleRemoveFilenameCommand },
951
0
    { "REPLACE_FILENAME"_s, HandleReplaceFilenameCommand },
952
0
    { "REMOVE_EXTENSION"_s, HandleRemoveExtensionCommand },
953
0
    { "REPLACE_EXTENSION"_s, HandleReplaceExtensionCommand },
954
0
    { "NORMAL_PATH"_s, HandleNormalPathCommand },
955
0
    { "RELATIVE_PATH"_s, HandleRelativePathCommand },
956
0
    { "ABSOLUTE_PATH"_s, HandleAbsolutePathCommand },
957
0
    { "NATIVE_PATH"_s, HandleNativePathCommand },
958
0
    { "CONVERT"_s, HandleConvertCommand },
959
0
    { "COMPARE"_s, HandleCompareCommand },
960
0
    { "HAS_ROOT_NAME"_s, HandleHasRootNameCommand },
961
0
    { "HAS_ROOT_DIRECTORY"_s, HandleHasRootDirectoryCommand },
962
0
    { "HAS_ROOT_PATH"_s, HandleHasRootPathCommand },
963
0
    { "HAS_FILENAME"_s, HandleHasFilenameCommand },
964
0
    { "HAS_EXTENSION"_s, HandleHasExtensionCommand },
965
0
    { "HAS_STEM"_s, HandleHasStemCommand },
966
0
    { "HAS_RELATIVE_PART"_s, HandleHasRelativePartCommand },
967
0
    { "HAS_PARENT_PATH"_s, HandleHasParentPathCommand },
968
0
    { "IS_ABSOLUTE"_s, HandleIsAbsoluteCommand },
969
0
    { "IS_RELATIVE"_s, HandleIsRelativeCommand },
970
0
    { "IS_PREFIX"_s, HandleIsPrefixCommand },
971
0
    { "HASH"_s, HandleHashCommand }
972
0
  };
973
974
0
  return subcommand(args[0], args, status);
975
0
}