| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713 | 
							- /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
 
-    file Copyright.txt or https://cmake.org/licensing for details.  */
 
- #include "cmCMakeHostSystemInformationCommand.h"
 
- #include <algorithm>
 
- #include <cassert>
 
- #include <cctype>
 
- #include <cstddef>
 
- #include <initializer_list>
 
- #include <map>
 
- #include <string>
 
- #include <utility>
 
- #include <cm/optional>
 
- #include <cm/string_view>
 
- #include <cmext/string_view>
 
- #include "cmsys/FStream.hxx"
 
- #include "cmsys/Glob.hxx"
 
- #include "cmsys/SystemInformation.hxx"
 
- #include "cmArgumentParser.h"
 
- #include "cmExecutionStatus.h"
 
- #include "cmList.h"
 
- #include "cmMakefile.h"
 
- #include "cmRange.h"
 
- #include "cmStringAlgorithms.h"
 
- #include "cmSystemTools.h"
 
- #include "cmValue.h"
 
- #include "cmWindowsRegistry.h"
 
- #ifdef _WIN32
 
- #  include "cmAlgorithms.h"
 
- #  include "cmGlobalGenerator.h"
 
- #  include "cmGlobalVisualStudio10Generator.h"
 
- #  include "cmGlobalVisualStudioVersionedGenerator.h"
 
- #  include "cmVSSetupHelper.h"
 
- #endif
 
- namespace {
 
- std::string const DELIM[2] = { {}, ";" };
 
- // BEGIN Private functions
 
- std::string ValueToString(std::size_t const value)
 
- {
 
-   return std::to_string(value);
 
- }
 
- std::string ValueToString(const char* const value)
 
- {
 
-   return value ? value : std::string{};
 
- }
 
- std::string ValueToString(std::string const& value)
 
- {
 
-   return value;
 
- }
 
- cm::optional<std::string> GetValue(cmsys::SystemInformation& info,
 
-                                    std::string const& key)
 
- {
 
-   if (key == "NUMBER_OF_LOGICAL_CORES"_s) {
 
-     return ValueToString(info.GetNumberOfLogicalCPU());
 
-   }
 
-   if (key == "NUMBER_OF_PHYSICAL_CORES"_s) {
 
-     return ValueToString(info.GetNumberOfPhysicalCPU());
 
-   }
 
-   if (key == "HOSTNAME"_s) {
 
-     return ValueToString(info.GetHostname());
 
-   }
 
-   if (key == "FQDN"_s) {
 
-     return ValueToString(info.GetFullyQualifiedDomainName());
 
-   }
 
-   if (key == "TOTAL_VIRTUAL_MEMORY"_s) {
 
-     return ValueToString(info.GetTotalVirtualMemory());
 
-   }
 
-   if (key == "AVAILABLE_VIRTUAL_MEMORY"_s) {
 
-     return ValueToString(info.GetAvailableVirtualMemory());
 
-   }
 
-   if (key == "TOTAL_PHYSICAL_MEMORY"_s) {
 
-     return ValueToString(info.GetTotalPhysicalMemory());
 
-   }
 
-   if (key == "AVAILABLE_PHYSICAL_MEMORY"_s) {
 
-     return ValueToString(info.GetAvailablePhysicalMemory());
 
-   }
 
-   if (key == "IS_64BIT"_s) {
 
-     return ValueToString(info.Is64Bits());
 
-   }
 
-   if (key == "HAS_FPU"_s) {
 
-     return ValueToString(
 
-       info.DoesCPUSupportFeature(cmsys::SystemInformation::CPU_FEATURE_FPU));
 
-   }
 
-   if (key == "HAS_MMX"_s) {
 
-     return ValueToString(
 
-       info.DoesCPUSupportFeature(cmsys::SystemInformation::CPU_FEATURE_MMX));
 
-   }
 
-   if (key == "HAS_MMX_PLUS"_s) {
 
-     return ValueToString(info.DoesCPUSupportFeature(
 
-       cmsys::SystemInformation::CPU_FEATURE_MMX_PLUS));
 
-   }
 
-   if (key == "HAS_SSE"_s) {
 
-     return ValueToString(
 
-       info.DoesCPUSupportFeature(cmsys::SystemInformation::CPU_FEATURE_SSE));
 
-   }
 
-   if (key == "HAS_SSE2"_s) {
 
-     return ValueToString(
 
-       info.DoesCPUSupportFeature(cmsys::SystemInformation::CPU_FEATURE_SSE2));
 
-   }
 
-   if (key == "HAS_SSE_FP"_s) {
 
-     return ValueToString(info.DoesCPUSupportFeature(
 
-       cmsys::SystemInformation::CPU_FEATURE_SSE_FP));
 
-   }
 
-   if (key == "HAS_SSE_MMX"_s) {
 
-     return ValueToString(info.DoesCPUSupportFeature(
 
-       cmsys::SystemInformation::CPU_FEATURE_SSE_MMX));
 
-   }
 
-   if (key == "HAS_AMD_3DNOW"_s) {
 
-     return ValueToString(info.DoesCPUSupportFeature(
 
-       cmsys::SystemInformation::CPU_FEATURE_AMD_3DNOW));
 
-   }
 
-   if (key == "HAS_AMD_3DNOW_PLUS"_s) {
 
-     return ValueToString(info.DoesCPUSupportFeature(
 
-       cmsys::SystemInformation::CPU_FEATURE_AMD_3DNOW_PLUS));
 
-   }
 
-   if (key == "HAS_IA64"_s) {
 
-     return ValueToString(
 
-       info.DoesCPUSupportFeature(cmsys::SystemInformation::CPU_FEATURE_IA64));
 
-   }
 
-   if (key == "HAS_SERIAL_NUMBER"_s) {
 
-     return ValueToString(info.DoesCPUSupportFeature(
 
-       cmsys::SystemInformation::CPU_FEATURE_SERIALNUMBER));
 
-   }
 
-   if (key == "PROCESSOR_NAME"_s) {
 
-     return ValueToString(info.GetExtendedProcessorName());
 
-   }
 
-   if (key == "PROCESSOR_DESCRIPTION"_s) {
 
-     return info.GetCPUDescription();
 
-   }
 
-   if (key == "PROCESSOR_SERIAL_NUMBER"_s) {
 
-     return ValueToString(info.GetProcessorSerialNumber());
 
-   }
 
-   if (key == "OS_NAME"_s) {
 
-     return ValueToString(info.GetOSName());
 
-   }
 
-   if (key == "OS_RELEASE"_s) {
 
-     return ValueToString(info.GetOSRelease());
 
-   }
 
-   if (key == "OS_VERSION"_s) {
 
-     return ValueToString(info.GetOSVersion());
 
-   }
 
-   if (key == "OS_PLATFORM"_s) {
 
-     return ValueToString(info.GetOSPlatform());
 
-   }
 
-   return {};
 
- }
 
- cm::optional<std::pair<std::string, std::string>> ParseOSReleaseLine(
 
-   std::string const& line)
 
- {
 
-   std::string key;
 
-   std::string value;
 
-   char prev = 0;
 
-   enum ParserState
 
-   {
 
-     PARSE_KEY_1ST,
 
-     PARSE_KEY,
 
-     FOUND_EQ,
 
-     PARSE_SINGLE_QUOTE_VALUE,
 
-     PARSE_DBL_QUOTE_VALUE,
 
-     PARSE_VALUE,
 
-     IGNORE_REST
 
-   } state = PARSE_KEY_1ST;
 
-   for (auto ch : line) {
 
-     switch (state) {
 
-       case PARSE_KEY_1ST:
 
-         if (std::isalpha(ch) || ch == '_') {
 
-           key += ch;
 
-           state = PARSE_KEY;
 
-         } else if (!cmIsSpace(ch)) {
 
-           state = IGNORE_REST;
 
-         }
 
-         break;
 
-       case PARSE_KEY:
 
-         if (ch == '=') {
 
-           state = FOUND_EQ;
 
-         } else if (std::isalnum(ch) || ch == '_') {
 
-           key += ch;
 
-         } else {
 
-           state = IGNORE_REST;
 
-         }
 
-         break;
 
-       case FOUND_EQ:
 
-         switch (ch) {
 
-           case '\'':
 
-             state = PARSE_SINGLE_QUOTE_VALUE;
 
-             break;
 
-           case '"':
 
-             state = PARSE_DBL_QUOTE_VALUE;
 
-             break;
 
-           case '#':
 
-           case '\\':
 
-             state = IGNORE_REST;
 
-             break;
 
-           default:
 
-             value += ch;
 
-             state = PARSE_VALUE;
 
-         }
 
-         break;
 
-       case PARSE_SINGLE_QUOTE_VALUE:
 
-         if (ch == '\'') {
 
-           if (prev != '\\') {
 
-             state = IGNORE_REST;
 
-           } else {
 
-             assert(!value.empty());
 
-             value[value.size() - 1] = ch;
 
-           }
 
-         } else {
 
-           value += ch;
 
-         }
 
-         break;
 
-       case PARSE_DBL_QUOTE_VALUE:
 
-         if (ch == '"') {
 
-           if (prev != '\\') {
 
-             state = IGNORE_REST;
 
-           } else {
 
-             assert(!value.empty());
 
-             value[value.size() - 1] = ch;
 
-           }
 
-         } else {
 
-           value += ch;
 
-         }
 
-         break;
 
-       case PARSE_VALUE:
 
-         if (ch == '#' || cmIsSpace(ch)) {
 
-           state = IGNORE_REST;
 
-         } else {
 
-           value += ch;
 
-         }
 
-         break;
 
-       default:
 
-         // Unexpected os-release parser state!
 
-         state = IGNORE_REST;
 
-         break;
 
-     }
 
-     if (state == IGNORE_REST) {
 
-       break;
 
-     }
 
-     prev = ch;
 
-   }
 
-   if (!(key.empty() || value.empty())) {
 
-     return std::make_pair(key, value);
 
-   }
 
-   return {};
 
- }
 
- std::map<std::string, std::string> GetOSReleaseVariables(
 
-   cmExecutionStatus& status)
 
- {
 
-   auto& makefile = status.GetMakefile();
 
-   const auto& sysroot = makefile.GetSafeDefinition("CMAKE_SYSROOT");
 
-   std::map<std::string, std::string> data;
 
-   // Based on
 
-   // https://www.freedesktop.org/software/systemd/man/latest/os-release.html
 
-   for (auto name : { "/etc/os-release"_s, "/usr/lib/os-release"_s }) {
 
-     const auto& filename = cmStrCat(sysroot, name);
 
-     if (cmSystemTools::FileExists(filename)) {
 
-       cmsys::ifstream fin(filename.c_str());
 
-       for (std::string line; !std::getline(fin, line).fail();) {
 
-         auto kv = ParseOSReleaseLine(line);
 
-         if (kv.has_value()) {
 
-           data.emplace(kv.value());
 
-         }
 
-       }
 
-       break;
 
-     }
 
-   }
 
-   // Got smth?
 
-   if (!data.empty()) {
 
-     return data;
 
-   }
 
-   // Ugh, it could be some pre-os-release distro.
 
-   // Lets try some fallback getters.
 
-   // See also:
 
-   //  - http://linuxmafia.com/faq/Admin/release-files.html
 
-   // 1. CMake provided
 
-   cmsys::Glob gl;
 
-   std::vector<std::string> scripts;
 
-   auto const findExpr = cmStrCat(cmSystemTools::GetCMakeRoot(),
 
-                                  "/Modules/Internal/OSRelease/*.cmake");
 
-   if (gl.FindFiles(findExpr)) {
 
-     scripts = gl.GetFiles();
 
-   }
 
-   // 2. User provided (append to the CMake prvided)
 
-   cmList::append(
 
-     scripts, makefile.GetDefinition("CMAKE_GET_OS_RELEASE_FALLBACK_SCRIPTS"));
 
-   // Filter out files that are not in format `NNN-name.cmake`
 
-   auto checkName = [](std::string const& filepath) -> bool {
 
-     auto const& filename = cmSystemTools::GetFilenameName(filepath);
 
-     // NOTE Minimum filename length expected:
 
-     //   NNN-<at-least-one-char-name>.cmake  --> 11
 
-     return (filename.size() < 11) || !std::isdigit(filename[0]) ||
 
-       !std::isdigit(filename[1]) || !std::isdigit(filename[2]) ||
 
-       filename[3] != '-';
 
-   };
 
-   scripts.erase(std::remove_if(scripts.begin(), scripts.end(), checkName),
 
-                 scripts.end());
 
-   // Make sure scripts are running in desired order
 
-   std::sort(scripts.begin(), scripts.end(),
 
-             [](std::string const& lhs, std::string const& rhs) -> bool {
 
-               long lhs_order;
 
-               cmStrToLong(cmSystemTools::GetFilenameName(lhs).substr(0u, 3u),
 
-                           &lhs_order);
 
-               long rhs_order;
 
-               cmStrToLong(cmSystemTools::GetFilenameName(rhs).substr(0u, 3u),
 
-                           &rhs_order);
 
-               return lhs_order < rhs_order;
 
-             });
 
-   // Name of the variable to put the results
 
-   std::string const result_variable{ "CMAKE_GET_OS_RELEASE_FALLBACK_RESULT" };
 
-   for (auto const& script : scripts) {
 
-     // Unset the result variable
 
-     makefile.RemoveDefinition(result_variable);
 
-     // include FATAL_ERROR and ERROR in the return status
 
-     if (!makefile.ReadListFile(script) ||
 
-         cmSystemTools::GetErrorOccurredFlag()) {
 
-       // Ok, no worries... go try the next script.
 
-       continue;
 
-     }
 
-     cmList variables{ makefile.GetDefinition(result_variable) };
 
-     if (variables.empty()) {
 
-       // Heh, this script didn't found anything... go try the next one.
 
-       continue;
 
-     }
 
-     for (auto const& variable : variables) {
 
-       auto value = makefile.GetSafeDefinition(variable);
 
-       makefile.RemoveDefinition(variable);
 
-       if (!cmHasPrefix(variable, cmStrCat(result_variable, '_'))) {
 
-         // Ignore unknown variable set by the script
 
-         continue;
 
-       }
 
-       auto key = variable.substr(result_variable.size() + 1,
 
-                                  variable.size() - result_variable.size() - 1);
 
-       data.emplace(std::move(key), std::move(value));
 
-     }
 
-     // Try 'till some script can get anything
 
-     if (!data.empty()) {
 
-       data.emplace("USED_FALLBACK_SCRIPT", script);
 
-       break;
 
-     }
 
-   }
 
-   makefile.RemoveDefinition(result_variable);
 
-   return data;
 
- }
 
- cm::optional<std::string> GetDistribValue(cmExecutionStatus& status,
 
-                                           std::string const& key,
 
-                                           std::string const& variable)
 
- {
 
-   const auto prefix = "DISTRIB_"_s;
 
-   if (!cmHasPrefix(key, prefix)) {
 
-     return {};
 
-   }
 
-   static const std::map<std::string, std::string> s_os_release =
 
-     GetOSReleaseVariables(status);
 
-   auto& makefile = status.GetMakefile();
 
-   const std::string subkey =
 
-     key.substr(prefix.size(), key.size() - prefix.size());
 
-   if (subkey == "INFO"_s) {
 
-     std::string vars;
 
-     for (const auto& kv : s_os_release) {
 
-       auto cmake_var_name = cmStrCat(variable, '_', kv.first);
 
-       vars += DELIM[!vars.empty()] + cmake_var_name;
 
-       makefile.AddDefinition(cmake_var_name, kv.second);
 
-     }
 
-     return cm::optional<std::string>(std::move(vars));
 
-   }
 
-   // Query individual variable
 
-   const auto it = s_os_release.find(subkey);
 
-   if (it != s_os_release.cend()) {
 
-     return it->second;
 
-   }
 
-   // NOTE Empty string means requested variable not set
 
-   return std::string{};
 
- }
 
- #ifdef _WIN32
 
- std::string FindMSYSTEM_PREFIX(std::vector<std::string> prefixes)
 
- {
 
-   for (std::string const& prefix : prefixes) {
 
-     std::string out;
 
-     std::string err;
 
-     int ret;
 
-     // In a modern MSYSTEM environment we expect cygpath to be in PATH.
 
-     std::vector<std::string> cygpath_cmd{ "cygpath", "-w", prefix };
 
-     if (cmSystemTools::RunSingleCommand(cygpath_cmd, &out, &err, &ret, nullptr,
 
-                                         cmSystemTools::OUTPUT_NONE)) {
 
-       if (ret == 0) {
 
-         out = cmTrimWhitespace(out);
 
-         cmSystemTools::ConvertToUnixSlashes(out);
 
-         if (cmSystemTools::FileIsDirectory(out)) {
 
-           return out;
 
-         }
 
-       }
 
-     } else {
 
-       // In a legacy MSYSTEM environment (MinGW/MSYS 1.0) there is no
 
-       // cygpath but we expect 'sh' to be in PATH.
 
-       std::vector<std::string> sh_cmd{
 
-         "sh", "-c", cmStrCat("cd \"", prefix, "\" && cmd //c cd")
 
-       };
 
-       if (cmSystemTools::RunSingleCommand(sh_cmd, &out, &err, &ret, nullptr,
 
-                                           cmSystemTools::OUTPUT_NONE)) {
 
-         if (ret == 0) {
 
-           out = cmTrimWhitespace(out);
 
-           cmSystemTools::ConvertToUnixSlashes(out);
 
-           if (cmSystemTools::FileIsDirectory(out)) {
 
-             return out;
 
-           }
 
-         }
 
-       }
 
-     }
 
-   }
 
-   return {};
 
- }
 
- std::string FallbackMSYSTEM_PREFIX(cm::string_view msystem)
 
- {
 
-   // These layouts are used by distributions such as
 
-   // * MSYS2: https://www.msys2.org/docs/environments/
 
-   // * MinGW/MSYS 1.0: http://mingw.osdn.io/
 
-   if (msystem == "MSYS"_s) {
 
-     static std::string const msystem_msys = FindMSYSTEM_PREFIX({ "/usr" });
 
-     return msystem_msys;
 
-   }
 
-   if (msystem == "MINGW32"_s) {
 
-     static std::string const msystem_mingw32 =
 
-       FindMSYSTEM_PREFIX({ "/mingw32", "/mingw" });
 
-     return msystem_mingw32;
 
-   }
 
-   if (msystem == "MINGW64"_s) {
 
-     static std::string const msystem_mingw64 =
 
-       FindMSYSTEM_PREFIX({ "/mingw64" });
 
-     return msystem_mingw64;
 
-   }
 
-   if (msystem == "UCRT64"_s) {
 
-     static std::string const msystem_ucrt64 =
 
-       FindMSYSTEM_PREFIX({ "/ucrt64" });
 
-     return msystem_ucrt64;
 
-   }
 
-   if (msystem == "CLANG32"_s) {
 
-     static std::string const msystem_clang32 =
 
-       FindMSYSTEM_PREFIX({ "/clang32" });
 
-     return msystem_clang32;
 
-   }
 
-   if (msystem == "CLANG64"_s) {
 
-     static std::string const msystem_clang64 =
 
-       FindMSYSTEM_PREFIX({ "/clang64" });
 
-     return msystem_clang64;
 
-   }
 
-   if (msystem == "CLANGARM64"_s) {
 
-     static std::string const msystem_clangarm64 =
 
-       FindMSYSTEM_PREFIX({ "/clangarm64" });
 
-     return msystem_clangarm64;
 
-   }
 
-   return {};
 
- }
 
- cm::optional<std::string> GetWindowsValue(cmExecutionStatus& status,
 
-                                           std::string const& key)
 
- {
 
-   auto* const gg = status.GetMakefile().GetGlobalGenerator();
 
-   for (auto vs : { 15, 16, 17 }) {
 
-     if (key == cmStrCat("VS_"_s, vs, "_DIR"_s)) {
 
-       std::string value;
 
-       // If generating for the VS nn IDE, use the same instance.
 
-       if (cmHasPrefix(gg->GetName(), cmStrCat("Visual Studio "_s, vs, ' '))) {
 
-         cmGlobalVisualStudioVersionedGenerator* vsNNgen =
 
-           static_cast<cmGlobalVisualStudioVersionedGenerator*>(gg);
 
-         if (vsNNgen->GetVSInstance(value)) {
 
-           return value;
 
-         }
 
-       }
 
-       // Otherwise, find a VS nn instance ourselves.
 
-       cmVSSetupAPIHelper vsSetupAPIHelper(vs);
 
-       if (vsSetupAPIHelper.GetVSInstanceInfo(value)) {
 
-         cmSystemTools::ConvertToUnixSlashes(value);
 
-       }
 
-       return value;
 
-     }
 
-   }
 
-   if (key == "VS_MSBUILD_COMMAND"_s && gg->IsVisualStudioAtLeast10()) {
 
-     cmGlobalVisualStudio10Generator* vs10gen =
 
-       static_cast<cmGlobalVisualStudio10Generator*>(gg);
 
-     return vs10gen->FindMSBuildCommandEarly(&status.GetMakefile());
 
-   }
 
-   if (key == "MSYSTEM_PREFIX") {
 
-     // MSYSTEM_PREFIX is meaningful only under a MSYSTEM environment.
 
-     cm::optional<std::string> ms = cmSystemTools::GetEnvVar("MSYSTEM");
 
-     if (!ms || ms->empty()) {
 
-       return std::string();
 
-     }
 
-     // Prefer the MSYSTEM_PREFIX environment variable.
 
-     if (cm::optional<std::string> msp =
 
-           cmSystemTools::GetEnvVar("MSYSTEM_PREFIX")) {
 
-       cmSystemTools::ConvertToUnixSlashes(*msp);
 
-       if (cmSystemTools::FileIsDirectory(*msp)) {
 
-         return msp;
 
-       }
 
-     }
 
-     // Fall back to known distribution layouts.
 
-     return FallbackMSYSTEM_PREFIX(*ms);
 
-   }
 
-   return {};
 
- }
 
- #endif
 
- cm::optional<std::string> GetValueChained()
 
- {
 
-   return {};
 
- }
 
- template <typename GetterFn, typename... Next>
 
- cm::optional<std::string> GetValueChained(GetterFn current, Next... chain)
 
- {
 
-   auto value = current();
 
-   if (value.has_value()) {
 
-     return value;
 
-   }
 
-   return GetValueChained(chain...);
 
- }
 
- template <typename Range>
 
- bool QueryWindowsRegistry(Range args, cmExecutionStatus& status,
 
-                           std::string const& variable)
 
- {
 
-   using View = cmWindowsRegistry::View;
 
-   if (args.empty()) {
 
-     status.SetError("missing <key> specification.");
 
-     return false;
 
-   }
 
-   std::string const& key = *args.begin();
 
-   struct Arguments : public ArgumentParser::ParseResult
 
-   {
 
-     std::string ValueName;
 
-     bool ValueNames = false;
 
-     bool SubKeys = false;
 
-     std::string View;
 
-     std::string Separator;
 
-     std::string ErrorVariable;
 
-   };
 
-   cmArgumentParser<Arguments> parser;
 
-   parser.Bind("VALUE"_s, &Arguments::ValueName)
 
-     .Bind("VALUE_NAMES"_s, &Arguments::ValueNames)
 
-     .Bind("SUBKEYS"_s, &Arguments::SubKeys)
 
-     .Bind("VIEW"_s, &Arguments::View)
 
-     .Bind("SEPARATOR"_s, &Arguments::Separator)
 
-     .Bind("ERROR_VARIABLE"_s, &Arguments::ErrorVariable);
 
-   std::vector<std::string> invalidArgs;
 
-   Arguments const arguments = parser.Parse(args.advance(1), &invalidArgs);
 
-   if (!invalidArgs.empty()) {
 
-     status.SetError(cmStrCat("given invalid argument(s) \"",
 
-                              cmJoin(invalidArgs, ", "_s), "\"."));
 
-     return false;
 
-   }
 
-   if (arguments.MaybeReportError(status.GetMakefile())) {
 
-     return true;
 
-   }
 
-   if ((!arguments.ValueName.empty() &&
 
-        (arguments.ValueNames || arguments.SubKeys)) ||
 
-       (arguments.ValueName.empty() && arguments.ValueNames &&
 
-        arguments.SubKeys)) {
 
-     status.SetError("given mutually exclusive sub-options \"VALUE\", "
 
-                     "\"VALUE_NAMES\" or \"SUBKEYS\".");
 
-     return false;
 
-   }
 
-   if (!arguments.View.empty() && !cmWindowsRegistry::ToView(arguments.View)) {
 
-     status.SetError(
 
-       cmStrCat("given invalid value for \"VIEW\": ", arguments.View, '.'));
 
-     return false;
 
-   }
 
-   auto& makefile = status.GetMakefile();
 
-   makefile.AddDefinition(variable, ""_s);
 
-   auto view = arguments.View.empty()
 
-     ? View::Both
 
-     : *cmWindowsRegistry::ToView(arguments.View);
 
-   cmWindowsRegistry registry(makefile);
 
-   if (arguments.ValueNames) {
 
-     auto result = registry.GetValueNames(key, view);
 
-     if (result) {
 
-       makefile.AddDefinition(variable, cmList::to_string(*result));
 
-     }
 
-   } else if (arguments.SubKeys) {
 
-     auto result = registry.GetSubKeys(key, view);
 
-     if (result) {
 
-       makefile.AddDefinition(variable, cmList::to_string(*result));
 
-     }
 
-   } else {
 
-     auto result =
 
-       registry.ReadValue(key, arguments.ValueName, view, arguments.Separator);
 
-     if (result) {
 
-       makefile.AddDefinition(variable, *result);
 
-     }
 
-   }
 
-   // return error message if requested
 
-   if (!arguments.ErrorVariable.empty()) {
 
-     makefile.AddDefinition(arguments.ErrorVariable, registry.GetLastError());
 
-   }
 
-   return true;
 
- }
 
- // END Private functions
 
- } // anonymous namespace
 
- // cmCMakeHostSystemInformation
 
- bool cmCMakeHostSystemInformationCommand(std::vector<std::string> const& args,
 
-                                          cmExecutionStatus& status)
 
- {
 
-   std::size_t current_index = 0;
 
-   if (args.size() < (current_index + 2) || args[current_index] != "RESULT"_s) {
 
-     status.SetError("missing RESULT specification.");
 
-     return false;
 
-   }
 
-   auto const& variable = args[current_index + 1];
 
-   current_index += 2;
 
-   if (args.size() < (current_index + 2) || args[current_index] != "QUERY"_s) {
 
-     status.SetError("missing QUERY specification");
 
-     return false;
 
-   }
 
-   if (args[current_index + 1] == "WINDOWS_REGISTRY"_s) {
 
-     return QueryWindowsRegistry(cmMakeRange(args).advance(current_index + 2),
 
-                                 status, variable);
 
-   }
 
-   static cmsys::SystemInformation info;
 
-   static auto initialized = false;
 
-   if (!initialized) {
 
-     info.RunCPUCheck();
 
-     info.RunOSCheck();
 
-     info.RunMemoryCheck();
 
-     initialized = true;
 
-   }
 
-   std::string result_list;
 
-   for (auto i = current_index + 1; i < args.size(); ++i) {
 
-     result_list += DELIM[!result_list.empty()];
 
-     auto const& key = args[i];
 
-     // clang-format off
 
-     auto value =
 
-       GetValueChained(
 
-           [&]() { return GetValue(info, key); }
 
-         , [&]() { return GetDistribValue(status, key, variable); }
 
- #ifdef _WIN32
 
-         , [&]() { return GetWindowsValue(status, key); }
 
- #endif
 
-         );
 
-     // clang-format on
 
-     if (!value) {
 
-       status.SetError("does not recognize <key> " + key);
 
-       return false;
 
-     }
 
-     result_list += value.value();
 
-   }
 
-   status.GetMakefile().AddDefinition(variable, result_list);
 
-   return true;
 
- }
 
 
  |