From 0fb78576b00aa9ca39112210d19ec53b0e6e975c Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Mon, 28 Dec 2020 16:41:18 -0500 Subject: cmake: Use shared parsing code for all cmake argv parsing --- Source/cmCommandLineArgument.h | 133 ++++++++++++++++++++++++++++++++++++++ Source/cmake.cxx | 125 ++---------------------------------- Source/cmakemain.cxx | 141 ++++++++++++++++++++++++++++------------- 3 files changed, 235 insertions(+), 164 deletions(-) create mode 100644 Source/cmCommandLineArgument.h diff --git a/Source/cmCommandLineArgument.h b/Source/cmCommandLineArgument.h new file mode 100644 index 0000000..aa96305 --- /dev/null +++ b/Source/cmCommandLineArgument.h @@ -0,0 +1,133 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#pragma once + +#include "cmStringAlgorithms.h" +#include "cmSystemTools.h" + +template +struct cmCommandLineArgument +{ + enum class Values + { + Zero, + One, + Two, + }; + + std::string InvalidSyntaxMessage; + std::string InvalidValueMessage; + std::string Name; + Values Type; + std::function StoreCall; + + template + cmCommandLineArgument(std::string n, Values t, FunctionType&& func) + : InvalidSyntaxMessage(cmStrCat("Invalid syntax used with ", n)) + , InvalidValueMessage(cmStrCat("Invalid value used with ", n)) + , Name(std::move(n)) + , Type(t) + , StoreCall(std::forward(func)) + { + } + + template + cmCommandLineArgument(std::string n, std::string failedMsg, Values t, + FunctionType&& func) + : InvalidSyntaxMessage(cmStrCat("Invalid syntax used with ", n)) + , InvalidValueMessage(std::move(failedMsg)) + , Name(std::move(n)) + , Type(t) + , StoreCall(std::forward(func)) + { + } + + bool matches(std::string const& input) const + { + return (this->Type == Values::Zero) ? (input == this->Name) + : cmHasPrefix(input, this->Name); + } + + template + bool parse(std::string const& input, T& index, + std::vector const& allArgs, + CallState&&... state) const + { + enum class ParseMode + { + Valid, + Invalid, + SyntaxError, + ValueError + }; + ParseMode parseState = ParseMode::Valid; + + if (this->Type == Values::Zero) { + if (input.size() == this->Name.size()) { + parseState = + this->StoreCall(std::string{}, std::forward(state)...) + ? ParseMode::Valid + : ParseMode::Invalid; + } else { + parseState = ParseMode::SyntaxError; + } + + } else if (this->Type == Values::One) { + if (input.size() == this->Name.size()) { + ++index; + if (index >= allArgs.size() || allArgs[index][0] == '-') { + parseState = ParseMode::ValueError; + } else { + parseState = + this->StoreCall(allArgs[index], std::forward(state)...) + ? ParseMode::Valid + : ParseMode::Invalid; + } + } else { + // parse the string to get the value + auto possible_value = cm::string_view(input).substr(this->Name.size()); + if (possible_value.empty()) { + parseState = ParseMode::SyntaxError; + parseState = ParseMode::ValueError; + } else if (possible_value[0] == '=') { + possible_value.remove_prefix(1); + if (possible_value.empty()) { + parseState = ParseMode::ValueError; + } else { + parseState = this->StoreCall(std::string(possible_value), + std::forward(state)...) + ? ParseMode::Valid + : ParseMode::Invalid; + } + } + if (parseState == ParseMode::Valid) { + parseState = this->StoreCall(std::string(possible_value), + std::forward(state)...) + ? ParseMode::Valid + : ParseMode::Invalid; + } + } + } else if (this->Type == Values::Two) { + if (input.size() == this->Name.size()) { + if (index + 2 >= allArgs.size() || allArgs[index + 1][0] == '-' || + allArgs[index + 2][0] == '-') { + parseState = ParseMode::ValueError; + } else { + index += 2; + parseState = + this->StoreCall(cmStrCat(allArgs[index - 1], ";", allArgs[index]), + std::forward(state)...) + ? ParseMode::Valid + : ParseMode::Invalid; + } + } + } + + if (parseState == ParseMode::SyntaxError) { + cmSystemTools::Error(this->InvalidSyntaxMessage); + } else if (parseState == ParseMode::ValueError) { + cmSystemTools::Error(this->InvalidValueMessage); + } + return (parseState == ParseMode::Valid); + } +}; diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 1691037..d6360a7 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -29,6 +29,7 @@ #include "cm_sys_stat.h" #include "cmCMakePresetsFile.h" +#include "cmCommandLineArgument.h" #include "cmCommands.h" #include "cmDocumentation.h" #include "cmDocumentationEntry.h" @@ -132,131 +133,13 @@ namespace { using JsonValueMapType = std::unordered_map; #endif -struct CommandArgument -{ - enum struct Values - { - Zero, - One, - Two, - }; - - std::string InvalidSyntaxMessage; - std::string InvalidValueMessage; - std::string Name; - CommandArgument::Values Type; - std::function StoreCall; - - template - CommandArgument(std::string n, CommandArgument::Values t, - FunctionType&& func) - : InvalidSyntaxMessage(cmStrCat("Invalid syntax used with ", n)) - , InvalidValueMessage(cmStrCat("Invalid value used with ", n)) - , Name(std::move(n)) - , Type(t) - , StoreCall(std::forward(func)) - { - } - - template - CommandArgument(std::string n, std::string failedMsg, - CommandArgument::Values t, FunctionType&& func) - : InvalidSyntaxMessage(cmStrCat("Invalid syntax used with ", n)) - , InvalidValueMessage(std::move(failedMsg)) - , Name(std::move(n)) - , Type(t) - , StoreCall(std::forward(func)) - { - } - - bool matches(std::string const& input) const - { - return cmHasPrefix(input, this->Name); - } - - template - bool parse(std::string const& input, T& index, - std::vector const& allArgs, cmake* state) const - { - enum struct ParseMode - { - Valid, - Invalid, - SyntaxError, - ValueError - }; - ParseMode parseState = ParseMode::Valid; - - // argument is the next parameter - if (this->Type == CommandArgument::Values::Zero) { - if (input.size() == this->Name.size()) { - parseState = this->StoreCall(input, state) ? ParseMode::Valid - : ParseMode::Invalid; - } else { - parseState = ParseMode::SyntaxError; - } - - } else if (this->Type == CommandArgument::Values::One) { - if (input.size() == this->Name.size()) { - ++index; - if (index >= allArgs.size() || allArgs[index][0] == '-') { - parseState = ParseMode::ValueError; - } else { - parseState = this->StoreCall(allArgs[index], state) - ? ParseMode::Valid - : ParseMode::Invalid; - } - } else { - // parse the string to get the value - auto possible_value = cm::string_view(input).substr(this->Name.size()); - if (possible_value.empty()) { - parseState = ParseMode::SyntaxError; - parseState = ParseMode::ValueError; - } else if (possible_value[0] == '=') { - possible_value.remove_prefix(1); - if (possible_value.empty()) { - parseState = ParseMode::ValueError; - } else { - parseState = this->StoreCall(std::string(possible_value), state) - ? ParseMode::Valid - : ParseMode::Invalid; - } - } - if (parseState == ParseMode::Valid) { - parseState = this->StoreCall(std::string(possible_value), state) - ? ParseMode::Valid - : ParseMode::Invalid; - } - } - } else if (this->Type == CommandArgument::Values::Two) { - if (input.size() == this->Name.size()) { - if (index + 2 >= allArgs.size() || allArgs[index + 1][0] == '-' || - allArgs[index + 2][0] == '-') { - parseState = ParseMode::ValueError; - } else { - index += 2; - parseState = - this->StoreCall(cmStrCat(allArgs[index - 1], ";", allArgs[index]), - state) - ? ParseMode::Valid - : ParseMode::Invalid; - } - } - } - - if (parseState == ParseMode::SyntaxError) { - cmSystemTools::Error(this->InvalidSyntaxMessage); - } else if (parseState == ParseMode::ValueError) { - cmSystemTools::Error(this->InvalidValueMessage); - } - return (parseState == ParseMode::Valid); - } -}; - auto IgnoreAndTrueLambda = [](std::string const&, cmake*) -> bool { return true; }; +using CommandArgument = + cmCommandLineArgument; + } // namespace static bool cmakeCheckStampFile(const std::string& stampName); diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index f7734a6..fc740a9 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -19,6 +19,7 @@ #include +#include "cmCommandLineArgument.h" #include "cmConsoleBuf.h" #include "cmDocumentationEntry.h" // IWYU pragma: keep #include "cmGlobalGenerator.h" @@ -213,61 +214,115 @@ int do_cmake(int ac, char const* const* av) } #endif + bool wizard_mode = false; bool sysinfo = false; bool list_cached = false; bool list_all_cached = false; bool list_help = false; bool view_only = false; cmake::WorkingMode workingMode = cmake::NORMAL_MODE; - std::vector args; - for (int i = 0; i < ac; ++i) { - if (strcmp(av[i], "-i") == 0) { - /* clang-format off */ - std::cerr << - "The \"cmake -i\" wizard mode is no longer supported.\n" - "Use the -D option to set cache values on the command line.\n" - "Use cmake-gui or ccmake for an interactive dialog.\n"; - /* clang-format on */ - return 1; - } - if (strcmp(av[i], "--system-information") == 0) { - sysinfo = true; - } else if (strcmp(av[i], "-N") == 0) { - view_only = true; - } else if (strcmp(av[i], "-L") == 0) { - list_cached = true; - } else if (strcmp(av[i], "-LA") == 0) { - list_all_cached = true; - } else if (strcmp(av[i], "-LH") == 0) { - list_cached = true; - list_help = true; - } else if (strcmp(av[i], "-LAH") == 0) { - list_all_cached = true; - list_help = true; - } else if (cmHasLiteralPrefix(av[i], "-P")) { - if (i == ac - 1) { - cmSystemTools::Error("No script specified for argument -P"); - return 1; + std::vector parsedArgs; + + using CommandArgument = + cmCommandLineArgument; + std::vector arguments = { + CommandArgument{ + "-i", CommandArgument::Values::Zero, + [&wizard_mode](std::string const&) -> bool { + /* clang-format off */ + std::cerr << + "The \"cmake -i\" wizard mode is no longer supported.\n" + "Use the -D option to set cache values on the command line.\n" + "Use cmake-gui or ccmake for an interactive dialog.\n"; + /* clang-format on */ + wizard_mode = true; + return true; + } }, + CommandArgument{ "--system-information", CommandArgument::Values::Zero, + [&](std::string const&) -> bool { + sysinfo = true; + return true; + } }, + CommandArgument{ "-N", CommandArgument::Values::Zero, + [&](std::string const&) -> bool { + view_only = true; + return true; + } }, + CommandArgument{ "-LAH", CommandArgument::Values::Zero, + [&](std::string const&) -> bool { + list_all_cached = true; + list_help = true; + return true; + } }, + CommandArgument{ "-LA", CommandArgument::Values::Zero, + [&](std::string const&) -> bool { + list_all_cached = true; + return true; + } }, + CommandArgument{ "-LH", CommandArgument::Values::Zero, + [&](std::string const&) -> bool { + list_cached = true; + list_help = true; + return true; + } }, + CommandArgument{ "-L", CommandArgument::Values::Zero, + [&](std::string const&) -> bool { + list_cached = true; + return true; + } }, + CommandArgument{ "-P", "No script specified for argument -P", + CommandArgument::Values::One, + [&](std::string const& value) -> bool { + workingMode = cmake::SCRIPT_MODE; + parsedArgs.emplace_back("-P"); + parsedArgs.push_back(std::move(value)); + return true; + } }, + CommandArgument{ "--find-package", CommandArgument::Values::Zero, + [&](std::string const&) -> bool { + workingMode = cmake::FIND_PACKAGE_MODE; + parsedArgs.emplace_back("--find-package"); + return true; + } }, + CommandArgument{ "--list-presets", CommandArgument::Values::Zero, + [&](std::string const&) -> bool { + workingMode = cmake::HELP_MODE; + parsedArgs.emplace_back("--list-presets"); + return true; + } }, + }; + + std::vector inputArgs; + inputArgs.reserve(ac); + cm::append(inputArgs, av, av + ac); + + for (decltype(inputArgs.size()) i = 0; i < inputArgs.size(); ++i) { + std::string const& arg = inputArgs[i]; + bool matched = false; + for (auto const& m : arguments) { + if (m.matches(arg)) { + matched = true; + if (m.parse(arg, i, inputArgs)) { + break; + } else { + return 1; + } } - workingMode = cmake::SCRIPT_MODE; - args.emplace_back(av[i]); - i++; - args.emplace_back(av[i]); - } else if (cmHasLiteralPrefix(av[i], "--find-package")) { - workingMode = cmake::FIND_PACKAGE_MODE; - args.emplace_back(av[i]); - } else if (strcmp(av[i], "--list-presets") == 0) { - workingMode = cmake::HELP_MODE; - args.emplace_back(av[i]); - } else { - args.emplace_back(av[i]); + } + if (!matched) { + parsedArgs.emplace_back(av[i]); } } + + if (wizard_mode) { + return 1; + } + if (sysinfo) { cmake cm(cmake::RoleProject, cmState::Project); cm.SetHomeDirectory(""); cm.SetHomeOutputDirectory(""); - int ret = cm.GetSystemInformation(args); + int ret = cm.GetSystemInformation(parsedArgs); return ret; } cmake::Role const role = @@ -297,7 +352,7 @@ int do_cmake(int ac, char const* const* av) }); cm.SetWorkingMode(workingMode); - int res = cm.Run(args, view_only); + int res = cm.Run(parsedArgs, view_only); if (list_cached || list_all_cached) { std::cout << "-- Cache values" << std::endl; std::vector keys = cm.GetState()->GetCacheEntryKeys(); -- cgit v0.12 From b34db1db69150b4a35b8c3a692b16ebf70cda89c Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Tue, 29 Dec 2020 14:02:08 -0500 Subject: cmCommandLineArgument supports ZeroOrOne arguments This allows us to parse command line arguments such as `-j` || `-j2` --- Source/cmCommandLineArgument.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Source/cmCommandLineArgument.h b/Source/cmCommandLineArgument.h index aa96305..16564dd 100644 --- a/Source/cmCommandLineArgument.h +++ b/Source/cmCommandLineArgument.h @@ -13,6 +13,7 @@ struct cmCommandLineArgument Zero, One, Two, + ZeroOrOne, }; std::string InvalidSyntaxMessage; @@ -72,11 +73,18 @@ struct cmCommandLineArgument parseState = ParseMode::SyntaxError; } - } else if (this->Type == Values::One) { + } else if (this->Type == Values::One || this->Type == Values::ZeroOrOne) { if (input.size() == this->Name.size()) { ++index; if (index >= allArgs.size() || allArgs[index][0] == '-') { - parseState = ParseMode::ValueError; + if (this->Type == Values::ZeroOrOne) { + parseState = + this->StoreCall(std::string{}, std::forward(state)...) + ? ParseMode::Valid + : ParseMode::Invalid; + } else { + parseState = ParseMode::ValueError; + } } else { parseState = this->StoreCall(allArgs[index], std::forward(state)...) -- cgit v0.12 From 5ab0b5448265355fcd1f88dfd49bfac075afd1c9 Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Wed, 30 Dec 2020 09:01:11 -0500 Subject: cmCommandLineArgument now supports OneOrMore argument type --- Source/cmCommandLineArgument.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Source/cmCommandLineArgument.h b/Source/cmCommandLineArgument.h index 16564dd..cbedf0a 100644 --- a/Source/cmCommandLineArgument.h +++ b/Source/cmCommandLineArgument.h @@ -14,6 +14,7 @@ struct cmCommandLineArgument One, Two, ZeroOrOne, + OneOrMore }; std::string InvalidSyntaxMessage; @@ -129,6 +130,23 @@ struct cmCommandLineArgument : ParseMode::Invalid; } } + } else if (this->Type == Values::OneOrMore) { + if (input.size() == this->Name.size()) { + auto nextValueIndex = index + 1; + if (nextValueIndex >= allArgs.size() || allArgs[index + 1][0] == '-') { + parseState = ParseMode::ValueError; + } else { + std::string buffer = allArgs[nextValueIndex++]; + while (nextValueIndex < allArgs.size() && + allArgs[nextValueIndex][0] != '-') { + buffer = cmStrCat(buffer, ";", allArgs[nextValueIndex++]); + } + parseState = + this->StoreCall(buffer, std::forward(state)...) + ? ParseMode::Valid + : ParseMode::Invalid; + } + } } if (parseState == ParseMode::SyntaxError) { -- cgit v0.12 From 75ac6dfbce50800e12ed165ca65e91be3d0a6182 Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Wed, 30 Dec 2020 09:05:14 -0500 Subject: cmake: --build now uses cmCommandLineArgument This makes `--build` use the same parsing rules as the rest of the the cmake executable --- Source/cmakemain.cxx | 178 +++++++++++++++++++++++++++------------------------ 1 file changed, 95 insertions(+), 83 deletions(-) diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index fc740a9..4934fce 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -387,16 +387,9 @@ int do_cmake(int ac, char const* const* av) } #ifndef CMAKE_BOOTSTRAP -int extract_job_number(int& index, char const* current, char const* next, - int len_of_flag) +int extract_job_number(std::string const& command, + std::string const& jobString) { - std::string command(current); - std::string jobString = command.substr(len_of_flag); - if (jobString.empty() && next && isdigit(next[0])) { - ++index; // skip parsing the job number - jobString = std::string(next); - } - int jobs = -1; unsigned long numJobs = 0; if (jobString.empty()) { @@ -411,8 +404,8 @@ int extract_job_number(int& index, char const* current, char const* next, jobs = int(numJobs); } } else { - std::cerr << "'" << command.substr(0, len_of_flag) << "' invalid number '" - << jobString << "' given.\n\n"; + std::cerr << "'" << command << "' invalid number '" << jobString + << "' given.\n\n"; } return jobs; } @@ -429,88 +422,107 @@ int do_build(int ac, char const* const* av) std::string config; std::string dir; std::vector nativeOptions; + bool nativeOptionsPassed = false; bool cleanFirst = false; bool foundClean = false; bool foundNonClean = false; bool verbose = cmSystemTools::HasEnv("VERBOSE"); - enum Doing - { - DoingNone, - DoingDir, - DoingTarget, - DoingConfig, - DoingNative + auto jLambda = [&](std::string const& value) -> bool { + jobs = extract_job_number("-j", value); + if (jobs < 0) { + dir.clear(); + } + return true; }; - Doing doing = DoingDir; - for (int i = 2; i < ac; ++i) { - if (doing == DoingNative) { - nativeOptions.emplace_back(av[i]); - } else if (cmHasLiteralPrefix(av[i], "-j")) { - const char* nextArg = ((i + 1 < ac) ? av[i + 1] : nullptr); - jobs = extract_job_number(i, av[i], nextArg, sizeof("-j") - 1); - if (jobs < 0) { - dir.clear(); - } - doing = DoingNone; - } else if (cmHasLiteralPrefix(av[i], "--parallel")) { - const char* nextArg = ((i + 1 < ac) ? av[i + 1] : nullptr); - jobs = extract_job_number(i, av[i], nextArg, sizeof("--parallel") - 1); - if (jobs < 0) { - dir.clear(); + auto parallelLambda = [&](std::string const& value) -> bool { + jobs = extract_job_number("--parallel", value); + if (jobs < 0) { + dir.clear(); + } + return true; + }; + auto targetLambda = [&](std::string const& value) -> bool { + if (!value.empty()) { + std::vector values = cmExpandedList(value); + for (auto const& v : values) { + targets.emplace_back(v); + if (v == "clean") { + foundClean = true; + } else { + foundNonClean = true; + } } - doing = DoingNone; - } else if ((strcmp(av[i], "--target") == 0) || - (strcmp(av[i], "-t") == 0)) { - doing = DoingTarget; - } else if (strcmp(av[i], "--config") == 0) { - doing = DoingConfig; - } else if (strcmp(av[i], "--clean-first") == 0) { - cleanFirst = true; - doing = DoingNone; - } else if ((strcmp(av[i], "--verbose") == 0) || - (strcmp(av[i], "-v") == 0)) { - verbose = true; - doing = DoingNone; - } else if (strcmp(av[i], "--use-stderr") == 0) { - /* tolerate legacy option */ - } else if (strcmp(av[i], "--") == 0) { - doing = DoingNative; - } else { - switch (doing) { - case DoingDir: - dir = cmSystemTools::CollapseFullPath(av[i]); - doing = DoingNone; - break; - case DoingTarget: - if (strlen(av[i]) == 0) { - std::cerr << "Warning: Argument number " << i - << " after --target option is empty." << std::endl; - } else { - targets.emplace_back(av[i]); - if (strcmp(av[i], "clean") == 0) { - foundClean = true; - } else { - foundNonClean = true; - } - } - if (foundClean && foundNonClean) { - std::cerr << "Error: Building 'clean' and other targets together " - "is not supported." - << std::endl; - dir.clear(); - } - break; - case DoingConfig: - config = av[i]; - doing = DoingNone; - break; - default: - std::cerr << "Unknown argument " << av[i] << std::endl; - dir.clear(); + return true; + } + return false; + }; + auto verboseLambda = [&](std::string const&) -> bool { + verbose = true; + return true; + }; + + using CommandArgument = + cmCommandLineArgument; + + std::vector arguments = { + CommandArgument{ "-j", CommandArgument::Values::ZeroOrOne, jLambda }, + CommandArgument{ "--parallel", CommandArgument::Values::ZeroOrOne, + parallelLambda }, + CommandArgument{ "-t", CommandArgument::Values::OneOrMore, targetLambda }, + CommandArgument{ "--target", CommandArgument::Values::OneOrMore, + targetLambda }, + CommandArgument{ "--config", CommandArgument::Values::One, + [&](std::string const& value) -> bool { + config = value; + return true; + } }, + CommandArgument{ "--clean-first", CommandArgument::Values::Zero, + [&](std::string const&) -> bool { + cleanFirst = true; + return true; + } }, + CommandArgument{ "-v", CommandArgument::Values::Zero, verboseLambda }, + CommandArgument{ "--verbose", CommandArgument::Values::Zero, + verboseLambda }, + /* legacy option no-op*/ + CommandArgument{ "--use-stderr", CommandArgument::Values::Zero, + [](std::string const&) -> bool { return true; } }, + CommandArgument{ "--", CommandArgument::Values::Zero, + [&](std::string const&) -> bool { + nativeOptionsPassed = true; + return true; + } }, + }; + + if (ac >= 3) { + dir = cmSystemTools::CollapseFullPath(av[2]); + + std::vector inputArgs; + inputArgs.reserve(ac - 3); + cm::append(inputArgs, av + 3, av + ac); + + decltype(inputArgs.size()) i = 0; + for (; i < inputArgs.size() && !nativeOptionsPassed; ++i) { + + std::string const& arg = inputArgs[i]; + for (auto const& m : arguments) { + if (m.matches(arg) && m.parse(arg, i, inputArgs)) { break; + } } } + + if (nativeOptionsPassed) { + cm::append(nativeOptions, inputArgs.begin() + i, inputArgs.end()); + } + } + + if (foundClean && foundNonClean) { + std::cerr << "Error: Building 'clean' and other targets together " + "is not supported." + << std::endl; + dir.clear(); } if (jobs == cmake::NO_BUILD_PARALLEL_LEVEL) { -- cgit v0.12 From 8c22c1964c63f902dcbf8505cfc40783e13b7455 Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Wed, 30 Dec 2020 09:05:30 -0500 Subject: cmake: --install now uses cmCommandLineArgument This makes `--install` use the same parsing rules as the rest of the the cmake executable --- Source/cmakemain.cxx | 105 +++++++++++++++++++++++++-------------------------- 1 file changed, 51 insertions(+), 54 deletions(-) diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index 4934fce..ba471b7 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -5,7 +5,6 @@ #include #include -#include #include #include #include @@ -275,7 +274,7 @@ int do_cmake(int ac, char const* const* av) [&](std::string const& value) -> bool { workingMode = cmake::SCRIPT_MODE; parsedArgs.emplace_back("-P"); - parsedArgs.push_back(std::move(value)); + parsedArgs.push_back(value); return true; } }, CommandArgument{ "--find-package", CommandArgument::Values::Zero, @@ -304,9 +303,8 @@ int do_cmake(int ac, char const* const* av) matched = true; if (m.parse(arg, i, inputArgs)) { break; - } else { - return 1; } + return 1; // failed to parse } } if (!matched) { @@ -725,60 +723,59 @@ int do_install(int ac, char const* const* av) bool strip = false; bool verbose = cmSystemTools::HasEnv("VERBOSE"); - enum Doing - { - DoingNone, - DoingDir, - DoingConfig, - DoingComponent, - DoingPrefix, - DoingDefaultDirectoryPermissions, + auto verboseLambda = [&](std::string const&) -> bool { + verbose = true; + return true; }; - Doing doing = DoingDir; + using CommandArgument = + cmCommandLineArgument; - for (int i = 2; i < ac; ++i) { - if (strcmp(av[i], "--config") == 0) { - doing = DoingConfig; - } else if (strcmp(av[i], "--component") == 0) { - doing = DoingComponent; - } else if (strcmp(av[i], "--prefix") == 0) { - doing = DoingPrefix; - } else if (strcmp(av[i], "--strip") == 0) { - strip = true; - doing = DoingNone; - } else if ((strcmp(av[i], "--verbose") == 0) || - (strcmp(av[i], "-v") == 0)) { - verbose = true; - doing = DoingNone; - } else if (strcmp(av[i], "--default-directory-permissions") == 0) { - doing = DoingDefaultDirectoryPermissions; - } else { - switch (doing) { - case DoingDir: - dir = cmSystemTools::CollapseFullPath(av[i]); - doing = DoingNone; - break; - case DoingConfig: - config = av[i]; - doing = DoingNone; - break; - case DoingComponent: - component = av[i]; - doing = DoingNone; - break; - case DoingPrefix: - prefix = av[i]; - doing = DoingNone; - break; - case DoingDefaultDirectoryPermissions: - defaultDirectoryPermissions = av[i]; - doing = DoingNone; - break; - default: - std::cerr << "Unknown argument " << av[i] << std::endl; - dir.clear(); + std::vector arguments = { + CommandArgument{ "--config", CommandArgument::Values::One, + [&](std::string const& value) -> bool { + config = value; + return true; + } }, + CommandArgument{ "--component", CommandArgument::Values::One, + [&](std::string const& value) -> bool { + component = value; + return true; + } }, + CommandArgument{ "--default-directory-permissions", + CommandArgument::Values::One, + [&](std::string const& value) -> bool { + defaultDirectoryPermissions = value; + return true; + } }, + CommandArgument{ "--prefix", CommandArgument::Values::One, + [&](std::string const& value) -> bool { + prefix = value; + return true; + } }, + CommandArgument{ "--strip", CommandArgument::Values::Zero, + [&](std::string const&) -> bool { + strip = true; + return true; + } }, + CommandArgument{ "-v", CommandArgument::Values::Zero, verboseLambda }, + CommandArgument{ "--verbose", CommandArgument::Values::Zero, + verboseLambda } + }; + + if (ac >= 3) { + dir = cmSystemTools::CollapseFullPath(av[2]); + + std::vector inputArgs; + inputArgs.reserve(ac - 3); + cm::append(inputArgs, av + 3, av + ac); + for (decltype(inputArgs.size()) i = 0; i < inputArgs.size(); ++i) { + + std::string const& arg = inputArgs[i]; + for (auto const& m : arguments) { + if (m.matches(arg) && m.parse(arg, i, inputArgs)) { break; + } } } } -- cgit v0.12