| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999 | 
							- /* 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 "cmProperty.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)
 
- {
 
-   cmProp def = status.GetMakefile().GetDefinition(arg);
 
-   if (!def) {
 
-     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);
 
- }
 
 
  |