mirror of
https://github.com/Kitware/CMake.git
synced 2026-01-05 21:31:08 -06:00
cmParseArgumentsCommand: Port to cmArgumentParser
This commit is contained in:
committed by
Kyle Edwards
parent
45edf1ad66
commit
9bddb03f31
@@ -8,10 +8,12 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "cmAlgorithms.h"
|
#include "cmAlgorithms.h"
|
||||||
|
#include "cmArgumentParser.h"
|
||||||
#include "cmMakefile.h"
|
#include "cmMakefile.h"
|
||||||
#include "cmMessageType.h"
|
#include "cmMessageType.h"
|
||||||
#include "cmRange.h"
|
#include "cmRange.h"
|
||||||
#include "cmSystemTools.h"
|
#include "cmSystemTools.h"
|
||||||
|
#include "cm_string_view.hxx"
|
||||||
|
|
||||||
class cmExecutionStatus;
|
class cmExecutionStatus;
|
||||||
|
|
||||||
@@ -28,42 +30,43 @@ static std::string EscapeArg(const std::string& arg)
|
|||||||
return escapedArg;
|
return escapedArg;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
static std::string JoinList(std::vector<std::string> const& arg, bool escape)
|
||||||
enum insideValues
|
|
||||||
{
|
{
|
||||||
NONE,
|
return escape ? cmJoin(cmMakeRange(arg).transform(EscapeArg), ";")
|
||||||
SINGLE,
|
: cmJoin(cmMakeRange(arg), ";");
|
||||||
MULTI
|
}
|
||||||
};
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
typedef std::map<std::string, bool> options_map;
|
typedef std::map<std::string, bool> options_map;
|
||||||
typedef std::map<std::string, std::string> single_map;
|
typedef std::map<std::string, std::string> single_map;
|
||||||
typedef std::map<std::string, std::vector<std::string>> multi_map;
|
typedef std::map<std::string, std::vector<std::string>> multi_map;
|
||||||
typedef std::set<std::string> options_set;
|
typedef std::set<std::string> options_set;
|
||||||
}
|
|
||||||
|
|
||||||
// function to be called every time, a new key word was parsed or all
|
struct UserArgumentParser : public cmArgumentParser<void>
|
||||||
// parameters where parsed.
|
|
||||||
static void DetectKeywordsMissingValues(insideValues currentState,
|
|
||||||
const std::string& currentArgName,
|
|
||||||
int& argumentsFound,
|
|
||||||
options_set& keywordsMissingValues)
|
|
||||||
{
|
{
|
||||||
if (currentState == SINGLE ||
|
template <typename T, typename H>
|
||||||
(currentState == MULTI && argumentsFound == 0)) {
|
void Bind(std::vector<std::string> const& names,
|
||||||
keywordsMissingValues.insert(currentArgName);
|
std::map<std::string, T>& ref, H duplicateKey)
|
||||||
|
{
|
||||||
|
for (std::string const& key : names) {
|
||||||
|
auto const it = ref.emplace(key, T{}).first;
|
||||||
|
bool const inserted = this->cmArgumentParser<void>::Bind(
|
||||||
|
cm::string_view(it->first), it->second);
|
||||||
|
if (!inserted) {
|
||||||
|
duplicateKey(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
argumentsFound = 0;
|
} // namespace
|
||||||
}
|
|
||||||
|
|
||||||
static void PassParsedArguments(const std::string& prefix,
|
static void PassParsedArguments(
|
||||||
cmMakefile& makefile,
|
const std::string& prefix, cmMakefile& makefile, const options_map& options,
|
||||||
const options_map& options,
|
const single_map& singleValArgs, const multi_map& multiValArgs,
|
||||||
const single_map& singleValArgs,
|
const std::vector<std::string>& unparsed,
|
||||||
const multi_map& multiValArgs,
|
const options_set& keywordsMissingValues, bool parseFromArgV)
|
||||||
const std::vector<std::string>& unparsed,
|
|
||||||
const options_set& keywordsMissingValues)
|
|
||||||
{
|
{
|
||||||
for (auto const& iter : options) {
|
for (auto const& iter : options) {
|
||||||
makefile.AddDefinition(prefix + iter.first,
|
makefile.AddDefinition(prefix + iter.first,
|
||||||
@@ -81,7 +84,7 @@ static void PassParsedArguments(const std::string& prefix,
|
|||||||
for (auto const& iter : multiValArgs) {
|
for (auto const& iter : multiValArgs) {
|
||||||
if (!iter.second.empty()) {
|
if (!iter.second.empty()) {
|
||||||
makefile.AddDefinition(prefix + iter.first,
|
makefile.AddDefinition(prefix + iter.first,
|
||||||
cmJoin(cmMakeRange(iter.second), ";").c_str());
|
JoinList(iter.second, parseFromArgV).c_str());
|
||||||
} else {
|
} else {
|
||||||
makefile.RemoveDefinition(prefix + iter.first);
|
makefile.RemoveDefinition(prefix + iter.first);
|
||||||
}
|
}
|
||||||
@@ -89,7 +92,7 @@ static void PassParsedArguments(const std::string& prefix,
|
|||||||
|
|
||||||
if (!unparsed.empty()) {
|
if (!unparsed.empty()) {
|
||||||
makefile.AddDefinition(prefix + "UNPARSED_ARGUMENTS",
|
makefile.AddDefinition(prefix + "UNPARSED_ARGUMENTS",
|
||||||
cmJoin(cmMakeRange(unparsed), ";").c_str());
|
JoinList(unparsed, parseFromArgV).c_str());
|
||||||
} else {
|
} else {
|
||||||
makefile.RemoveDefinition(prefix + "UNPARSED_ARGUMENTS");
|
makefile.RemoveDefinition(prefix + "UNPARSED_ARGUMENTS");
|
||||||
}
|
}
|
||||||
@@ -141,6 +144,8 @@ bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args,
|
|||||||
// the first argument is the prefix
|
// the first argument is the prefix
|
||||||
const std::string prefix = (*argIter++) + "_";
|
const std::string prefix = (*argIter++) + "_";
|
||||||
|
|
||||||
|
UserArgumentParser parser;
|
||||||
|
|
||||||
// define the result maps holding key/value pairs for
|
// define the result maps holding key/value pairs for
|
||||||
// options, single values and multi values
|
// options, single values and multi values
|
||||||
options_map options;
|
options_map options;
|
||||||
@@ -150,45 +155,25 @@ bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args,
|
|||||||
// anything else is put into a vector of unparsed strings
|
// anything else is put into a vector of unparsed strings
|
||||||
std::vector<std::string> unparsed;
|
std::vector<std::string> unparsed;
|
||||||
|
|
||||||
// remember already defined keywords
|
auto const duplicateKey = [this](std::string const& key) {
|
||||||
std::set<std::string> used_keywords;
|
this->GetMakefile()->IssueMessage(
|
||||||
const std::string dup_warning = "keyword defined more than once: ";
|
MessageType::WARNING, "keyword defined more than once: " + key);
|
||||||
|
};
|
||||||
|
|
||||||
// the second argument is a (cmake) list of options without argument
|
// the second argument is a (cmake) list of options without argument
|
||||||
std::vector<std::string> list;
|
std::vector<std::string> list;
|
||||||
cmSystemTools::ExpandListArgument(*argIter++, list);
|
cmSystemTools::ExpandListArgument(*argIter++, list);
|
||||||
for (std::string const& iter : list) {
|
parser.Bind(list, options, duplicateKey);
|
||||||
if (!used_keywords.insert(iter).second) {
|
|
||||||
this->GetMakefile()->IssueMessage(MessageType::WARNING,
|
|
||||||
dup_warning + iter);
|
|
||||||
}
|
|
||||||
options[iter]; // default initialize
|
|
||||||
}
|
|
||||||
|
|
||||||
// the third argument is a (cmake) list of single argument options
|
// the third argument is a (cmake) list of single argument options
|
||||||
list.clear();
|
list.clear();
|
||||||
cmSystemTools::ExpandListArgument(*argIter++, list);
|
cmSystemTools::ExpandListArgument(*argIter++, list);
|
||||||
for (std::string const& iter : list) {
|
parser.Bind(list, singleValArgs, duplicateKey);
|
||||||
if (!used_keywords.insert(iter).second) {
|
|
||||||
this->GetMakefile()->IssueMessage(MessageType::WARNING,
|
|
||||||
dup_warning + iter);
|
|
||||||
}
|
|
||||||
singleValArgs[iter]; // default initialize
|
|
||||||
}
|
|
||||||
|
|
||||||
// the fourth argument is a (cmake) list of multi argument options
|
// the fourth argument is a (cmake) list of multi argument options
|
||||||
list.clear();
|
list.clear();
|
||||||
cmSystemTools::ExpandListArgument(*argIter++, list);
|
cmSystemTools::ExpandListArgument(*argIter++, list);
|
||||||
for (std::string const& iter : list) {
|
parser.Bind(list, multiValArgs, duplicateKey);
|
||||||
if (!used_keywords.insert(iter).second) {
|
|
||||||
this->GetMakefile()->IssueMessage(MessageType::WARNING,
|
|
||||||
dup_warning + iter);
|
|
||||||
}
|
|
||||||
multiValArgs[iter]; // default initialize
|
|
||||||
}
|
|
||||||
|
|
||||||
insideValues insideValues = NONE;
|
|
||||||
std::string currentArgName;
|
|
||||||
|
|
||||||
list.clear();
|
list.clear();
|
||||||
if (!parseFromArgV) {
|
if (!parseFromArgV) {
|
||||||
@@ -223,68 +208,14 @@ bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
options_set keywordsMissingValues;
|
std::vector<std::string> keywordsMissingValues;
|
||||||
int multiArgumentsFound = 0;
|
|
||||||
|
|
||||||
// iterate over the arguments list and fill in the values where applicable
|
parser.Parse(list, &unparsed, &keywordsMissingValues);
|
||||||
for (std::string const& arg : list) {
|
|
||||||
const options_map::iterator optIter = options.find(arg);
|
|
||||||
if (optIter != options.end()) {
|
|
||||||
DetectKeywordsMissingValues(insideValues, currentArgName,
|
|
||||||
multiArgumentsFound, keywordsMissingValues);
|
|
||||||
insideValues = NONE;
|
|
||||||
optIter->second = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const single_map::iterator singleIter = singleValArgs.find(arg);
|
PassParsedArguments(
|
||||||
if (singleIter != singleValArgs.end()) {
|
prefix, *this->Makefile, options, singleValArgs, multiValArgs, unparsed,
|
||||||
DetectKeywordsMissingValues(insideValues, currentArgName,
|
options_set(keywordsMissingValues.begin(), keywordsMissingValues.end()),
|
||||||
multiArgumentsFound, keywordsMissingValues);
|
parseFromArgV);
|
||||||
insideValues = SINGLE;
|
|
||||||
currentArgName = arg;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const multi_map::iterator multiIter = multiValArgs.find(arg);
|
|
||||||
if (multiIter != multiValArgs.end()) {
|
|
||||||
DetectKeywordsMissingValues(insideValues, currentArgName,
|
|
||||||
multiArgumentsFound, keywordsMissingValues);
|
|
||||||
insideValues = MULTI;
|
|
||||||
currentArgName = arg;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (insideValues) {
|
|
||||||
case SINGLE:
|
|
||||||
singleValArgs[currentArgName] = arg;
|
|
||||||
insideValues = NONE;
|
|
||||||
break;
|
|
||||||
case MULTI:
|
|
||||||
++multiArgumentsFound;
|
|
||||||
if (parseFromArgV) {
|
|
||||||
multiValArgs[currentArgName].push_back(EscapeArg(arg));
|
|
||||||
} else {
|
|
||||||
multiValArgs[currentArgName].push_back(arg);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
multiArgumentsFound = 0;
|
|
||||||
|
|
||||||
if (parseFromArgV) {
|
|
||||||
unparsed.push_back(EscapeArg(arg));
|
|
||||||
} else {
|
|
||||||
unparsed.push_back(arg);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DetectKeywordsMissingValues(insideValues, currentArgName,
|
|
||||||
multiArgumentsFound, keywordsMissingValues);
|
|
||||||
|
|
||||||
PassParsedArguments(prefix, *this->Makefile, options, singleValArgs,
|
|
||||||
multiValArgs, unparsed, keywordsMissingValues);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user