summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Source/cmArgumentParser.cxx14
-rw-r--r--Source/cmArgumentParser.h1
-rw-r--r--Source/cmArgumentParserTypes.h5
-rw-r--r--Source/cmCMakePathCommand.cxx44
-rw-r--r--Tests/CMakeLib/testArgumentParser.cxx16
-rw-r--r--Tests/RunCMake/cmake_path/OUTPUT_VARIABLE-empty-stderr.txt4
-rw-r--r--Tests/RunCMake/cmake_path/RunCMakeTest.cmake3
7 files changed, 48 insertions, 39 deletions
diff --git a/Source/cmArgumentParser.cxx b/Source/cmArgumentParser.cxx
index 05f8ce8..614d00d 100644
--- a/Source/cmArgumentParser.cxx
+++ b/Source/cmArgumentParser.cxx
@@ -76,6 +76,20 @@ void Instance::Bind(std::string& val)
ExpectAtLeast{ 1 });
}
+void Instance::Bind(NonEmpty<std::string>& val)
+{
+ this->Bind(
+ [this, &val](cm::string_view arg) -> Continue {
+ if (arg.empty() && this->ParseResults) {
+ this->ParseResults->AddKeywordError(this->Keyword,
+ " empty string not allowed\n");
+ }
+ val.assign(std::string(arg));
+ return Continue::No;
+ },
+ ExpectAtLeast{ 1 });
+}
+
void Instance::Bind(Maybe<std::string>& val)
{
this->Bind(
diff --git a/Source/cmArgumentParser.h b/Source/cmArgumentParser.h
index c25e2f6..ac78872 100644
--- a/Source/cmArgumentParser.h
+++ b/Source/cmArgumentParser.h
@@ -171,6 +171,7 @@ public:
void Bind(std::function<Continue(cm::string_view)> f, ExpectAtLeast expect);
void Bind(bool& val);
void Bind(std::string& val);
+ void Bind(NonEmpty<std::string>& val);
void Bind(Maybe<std::string>& val);
void Bind(MaybeEmpty<std::vector<std::string>>& val);
void Bind(NonEmpty<std::vector<std::string>>& val);
diff --git a/Source/cmArgumentParserTypes.h b/Source/cmArgumentParserTypes.h
index fe8e4ca..7daae09 100644
--- a/Source/cmArgumentParserTypes.h
+++ b/Source/cmArgumentParserTypes.h
@@ -34,6 +34,11 @@ struct NonEmpty<std::vector<T>> : public std::vector<T>
{
using std::vector<T>::vector;
};
+template <>
+struct NonEmpty<std::string> : public std::string
+{
+ using std::string::basic_string;
+};
} // namespace ArgumentParser
diff --git a/Source/cmCMakePathCommand.cxx b/Source/cmCMakePathCommand.cxx
index b955bcf..7755082 100644
--- a/Source/cmCMakePathCommand.cxx
+++ b/Source/cmCMakePathCommand.cxx
@@ -15,6 +15,7 @@
#include <cmext/string_view>
#include "cmArgumentParser.h"
+#include "cmArgumentParserTypes.h"
#include "cmCMakePath.h"
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
@@ -82,22 +83,11 @@ public:
return this->CMakePathArgumentParser<Result>::template Parse<Advance>(
args);
}
-
- bool checkOutputVariable(const Result& arguments,
- cmExecutionStatus& status) const
- {
- if (arguments.Output && arguments.Output->empty()) {
- status.SetError("Invalid name for output variable.");
- return false;
- }
-
- return true;
- }
};
struct OutputVariable : public ArgumentParser::ParseResult
{
- cm::optional<std::string> Output;
+ cm::optional<ArgumentParser::NonEmpty<std::string>> Output;
};
// Usable when OUTPUT_VARIABLE is the only option
class OutputVariableParser
@@ -270,9 +260,6 @@ bool HandleAppendCommand(std::vector<std::string> const& args,
if (arguments.MaybeReportError(status.GetMakefile())) {
return true;
}
- if (!parser.checkOutputVariable(arguments, status)) {
- return false;
- }
cmCMakePath path(status.GetMakefile().GetSafeDefinition(args[1]));
for (const auto& input : parser.GetInputs()) {
@@ -295,9 +282,6 @@ bool HandleAppendStringCommand(std::vector<std::string> const& args,
if (arguments.MaybeReportError(status.GetMakefile())) {
return true;
}
- if (!parser.checkOutputVariable(arguments, status)) {
- return false;
- }
std::string inputPath;
if (!getInputPath(args[1], status, inputPath)) {
@@ -325,9 +309,6 @@ bool HandleRemoveFilenameCommand(std::vector<std::string> const& args,
if (arguments.MaybeReportError(status.GetMakefile())) {
return true;
}
- if (!parser.checkOutputVariable(arguments, status)) {
- return false;
- }
if (!parser.GetInputs().empty()) {
status.SetError("REMOVE_FILENAME called with unexpected arguments.");
@@ -358,9 +339,6 @@ bool HandleReplaceFilenameCommand(std::vector<std::string> const& args,
if (arguments.MaybeReportError(status.GetMakefile())) {
return true;
}
- if (!parser.checkOutputVariable(arguments, status)) {
- return false;
- }
if (parser.GetInputs().size() > 1) {
status.SetError("REPLACE_FILENAME called with unexpected arguments.");
@@ -387,7 +365,7 @@ bool HandleRemoveExtensionCommand(std::vector<std::string> const& args,
{
struct Arguments : public ArgumentParser::ParseResult
{
- cm::optional<std::string> Output;
+ cm::optional<ArgumentParser::NonEmpty<std::string>> Output;
bool LastOnly = false;
};
@@ -400,9 +378,6 @@ bool HandleRemoveExtensionCommand(std::vector<std::string> const& args,
if (arguments.MaybeReportError(status.GetMakefile())) {
return true;
}
- if (!parser.checkOutputVariable(arguments, status)) {
- return false;
- }
if (!parser.GetInputs().empty()) {
status.SetError("REMOVE_EXTENSION called with unexpected arguments.");
@@ -433,7 +408,7 @@ bool HandleReplaceExtensionCommand(std::vector<std::string> const& args,
{
struct Arguments : public ArgumentParser::ParseResult
{
- cm::optional<std::string> Output;
+ cm::optional<ArgumentParser::NonEmpty<std::string>> Output;
bool LastOnly = false;
};
@@ -446,9 +421,6 @@ bool HandleReplaceExtensionCommand(std::vector<std::string> const& args,
if (arguments.MaybeReportError(status.GetMakefile())) {
return true;
}
- if (!parser.checkOutputVariable(arguments, status)) {
- return false;
- }
if (parser.GetInputs().size() > 1) {
status.SetError("REPLACE_EXTENSION called with unexpected arguments.");
@@ -486,9 +458,6 @@ bool HandleNormalPathCommand(std::vector<std::string> const& args,
if (arguments.MaybeReportError(status.GetMakefile())) {
return true;
}
- if (!parser.checkOutputVariable(arguments, status)) {
- return false;
- }
if (!parser.GetInputs().empty()) {
status.SetError("NORMAL_PATH called with unexpected arguments.");
@@ -516,7 +485,7 @@ bool HandleTransformPathCommand(
{
struct Arguments : public ArgumentParser::ParseResult
{
- cm::optional<std::string> Output;
+ cm::optional<ArgumentParser::NonEmpty<std::string>> Output;
cm::optional<std::string> BaseDirectory;
bool Normalize = false;
};
@@ -532,9 +501,6 @@ bool HandleTransformPathCommand(
if (arguments.MaybeReportError(status.GetMakefile())) {
return true;
}
- if (!parser.checkOutputVariable(arguments, status)) {
- return false;
- }
if (!parser.GetInputs().empty()) {
status.SetError(cmStrCat(args[0], " called with unexpected arguments."));
diff --git a/Tests/CMakeLib/testArgumentParser.cxx b/Tests/CMakeLib/testArgumentParser.cxx
index 496b873..58c0418 100644
--- a/Tests/CMakeLib/testArgumentParser.cxx
+++ b/Tests/CMakeLib/testArgumentParser.cxx
@@ -27,6 +27,8 @@ struct Result : public ArgumentParser::ParseResult
cm::optional<std::string> String2;
cm::optional<std::string> String3;
ArgumentParser::Maybe<std::string> String4;
+ ArgumentParser::NonEmpty<std::string> String5;
+ ArgumentParser::NonEmpty<std::string> String6;
ArgumentParser::NonEmpty<std::vector<std::string>> List1;
ArgumentParser::NonEmpty<std::vector<std::string>> List2;
@@ -87,6 +89,8 @@ struct Result : public ArgumentParser::ParseResult
ArgumentParser::NonEmpty<std::vector<std::string>> UnboundNonEmpty{
1, "unbound"
};
+ ArgumentParser::NonEmpty<std::string> UnboundNonEmptyStr{ 'u', 'n', 'b', 'o',
+ 'u', 'n', 'd' };
std::vector<cm::string_view> ParsedKeywords;
};
@@ -100,6 +104,8 @@ std::initializer_list<cm::string_view> const args = {
"STRING_2", "foo", "bar", // string arg + unparsed value, presence captured
// "STRING_3", // string arg that is not present
"STRING_4", // string arg allowed to be missing value
+ "STRING_5", "foo", // string arg that is not empty
+ "STRING_6", "", // string arg that is empty
"LIST_1", // list arg missing values
"LIST_2", "foo", "bar", // list arg with 2 elems
"LIST_3", "bar", // list arg ...
@@ -133,6 +139,8 @@ bool verifyResult(Result const& result,
"STRING_1",
"STRING_2",
"STRING_4",
+ "STRING_5",
+ "STRING_6",
"LIST_1",
"LIST_2",
"LIST_3",
@@ -159,6 +167,7 @@ bool verifyResult(Result const& result,
};
static std::map<cm::string_view, std::string> const keywordErrors = {
{ "STRING_1"_s, " missing required value\n" },
+ { "STRING_6"_s, " empty string not allowed\n" },
{ "LIST_1"_s, " missing required value\n" },
{ "LIST_4"_s, " missing required value\n" },
{ "FUNC_0"_s, " missing required value\n" }
@@ -184,6 +193,8 @@ bool verifyResult(Result const& result,
ASSERT_TRUE(*result.String2 == "foo");
ASSERT_TRUE(!result.String3);
ASSERT_TRUE(result.String4.empty());
+ ASSERT_TRUE(result.String5 == "foo");
+ ASSERT_TRUE(result.String6.empty());
ASSERT_TRUE(result.List1.empty());
ASSERT_TRUE(result.List2 == foobar);
@@ -217,6 +228,7 @@ bool verifyResult(Result const& result,
ASSERT_TRUE(result.UnboundMaybe == "unbound");
ASSERT_TRUE(result.UnboundMaybeEmpty == unbound);
ASSERT_TRUE(result.UnboundNonEmpty == unbound);
+ ASSERT_TRUE(result.UnboundNonEmptyStr == "unbound");
ASSERT_TRUE(result.ParsedKeywords == parsedKeywords);
@@ -249,6 +261,8 @@ bool testArgumentParserDynamic()
.Bind("STRING_2"_s, result.String2)
.Bind("STRING_3"_s, result.String3)
.Bind("STRING_4"_s, result.String4)
+ .Bind("STRING_5"_s, result.String5)
+ .Bind("STRING_6"_s, result.String6)
.Bind("LIST_1"_s, result.List1)
.Bind("LIST_2"_s, result.List2)
.Bind("LIST_3"_s, result.List3)
@@ -299,6 +313,8 @@ static auto const parserStatic = //
.Bind("STRING_2"_s, &Result::String2)
.Bind("STRING_3"_s, &Result::String3)
.Bind("STRING_4"_s, &Result::String4)
+ .Bind("STRING_5"_s, &Result::String5)
+ .Bind("STRING_6"_s, &Result::String6)
.Bind("LIST_1"_s, &Result::List1)
.Bind("LIST_2"_s, &Result::List2)
.Bind("LIST_3"_s, &Result::List3)
diff --git a/Tests/RunCMake/cmake_path/OUTPUT_VARIABLE-empty-stderr.txt b/Tests/RunCMake/cmake_path/OUTPUT_VARIABLE-empty-stderr.txt
new file mode 100644
index 0000000..f1b52cc
--- /dev/null
+++ b/Tests/RunCMake/cmake_path/OUTPUT_VARIABLE-empty-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at .+/call-cmake_path.cmake:[0-9]+ \(cmake_path\):
+ Error after keyword "OUTPUT_VARIABLE":
+
+ empty string not allowed
diff --git a/Tests/RunCMake/cmake_path/RunCMakeTest.cmake b/Tests/RunCMake/cmake_path/RunCMakeTest.cmake
index 8a2dd95..1742b06 100644
--- a/Tests/RunCMake/cmake_path/RunCMakeTest.cmake
+++ b/Tests/RunCMake/cmake_path/RunCMakeTest.cmake
@@ -114,6 +114,9 @@ foreach (command IN ITEMS NATIVE_PATH
run_cmake_command (${command}-invalid-output "${CMAKE_COMMAND}" "-DCMAKE_PATH_ARGUMENTS=${command} path ${extra_args}" -DCHECK_INVALID_OUTPUT=ON -P "${RunCMake_SOURCE_DIR}/call-cmake_path.cmake")
endforeach()
+# OUTPUT_VARIABLE empty name
+set (RunCMake-stderr-file "OUTPUT_VARIABLE-empty-stderr.txt")
+
foreach (command IN ITEMS APPEND APPEND_STRING REMOVE_FILENAME REPLACE_FILENAME
REMOVE_EXTENSION REPLACE_EXTENSION NORMAL_PATH
RELATIVE_PATH ABSOLUTE_PATH)