浏览代码

cmParseArgumentsCommand: Port to cmArgumentParser

Regina Pfeifer 6 年之前
父节点
当前提交
9bddb03f31
共有 1 个文件被更改,包括 45 次插入114 次删除
  1. 45 114
      Source/cmParseArgumentsCommand.cxx

+ 45 - 114
Source/cmParseArgumentsCommand.cxx

@@ -8,10 +8,12 @@
 #include <utility>
 
 #include "cmAlgorithms.h"
+#include "cmArgumentParser.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
 #include "cmRange.h"
 #include "cmSystemTools.h"
+#include "cm_string_view.hxx"
 
 class cmExecutionStatus;
 
@@ -28,42 +30,43 @@ static std::string EscapeArg(const std::string& arg)
   return escapedArg;
 }
 
-namespace {
-enum insideValues
+static std::string JoinList(std::vector<std::string> const& arg, bool escape)
 {
-  NONE,
-  SINGLE,
-  MULTI
-};
+  return escape ? cmJoin(cmMakeRange(arg).transform(EscapeArg), ";")
+                : cmJoin(cmMakeRange(arg), ";");
+}
+
+namespace {
 
 typedef std::map<std::string, bool> options_map;
 typedef std::map<std::string, std::string> single_map;
 typedef std::map<std::string, std::vector<std::string>> multi_map;
 typedef std::set<std::string> options_set;
-}
 
-// function to be called every time, a new key word was parsed or all
-// parameters where parsed.
-static void DetectKeywordsMissingValues(insideValues currentState,
-                                        const std::string& currentArgName,
-                                        int& argumentsFound,
-                                        options_set& keywordsMissingValues)
+struct UserArgumentParser : public cmArgumentParser<void>
 {
-  if (currentState == SINGLE ||
-      (currentState == MULTI && argumentsFound == 0)) {
-    keywordsMissingValues.insert(currentArgName);
+  template <typename T, typename H>
+  void Bind(std::vector<std::string> const& names,
+            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,
-                                cmMakefile& makefile,
-                                const options_map& options,
-                                const single_map& singleValArgs,
-                                const multi_map& multiValArgs,
-                                const std::vector<std::string>& unparsed,
-                                const options_set& keywordsMissingValues)
+static void PassParsedArguments(
+  const std::string& prefix, cmMakefile& makefile, const options_map& options,
+  const single_map& singleValArgs, const multi_map& multiValArgs,
+  const std::vector<std::string>& unparsed,
+  const options_set& keywordsMissingValues, bool parseFromArgV)
 {
   for (auto const& iter : options) {
     makefile.AddDefinition(prefix + iter.first,
@@ -81,7 +84,7 @@ static void PassParsedArguments(const std::string& prefix,
   for (auto const& iter : multiValArgs) {
     if (!iter.second.empty()) {
       makefile.AddDefinition(prefix + iter.first,
-                             cmJoin(cmMakeRange(iter.second), ";").c_str());
+                             JoinList(iter.second, parseFromArgV).c_str());
     } else {
       makefile.RemoveDefinition(prefix + iter.first);
     }
@@ -89,7 +92,7 @@ static void PassParsedArguments(const std::string& prefix,
 
   if (!unparsed.empty()) {
     makefile.AddDefinition(prefix + "UNPARSED_ARGUMENTS",
-                           cmJoin(cmMakeRange(unparsed), ";").c_str());
+                           JoinList(unparsed, parseFromArgV).c_str());
   } else {
     makefile.RemoveDefinition(prefix + "UNPARSED_ARGUMENTS");
   }
@@ -141,6 +144,8 @@ bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args,
   // the first argument is the prefix
   const std::string prefix = (*argIter++) + "_";
 
+  UserArgumentParser parser;
+
   // define the result maps holding key/value pairs for
   // options, single values and multi values
   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
   std::vector<std::string> unparsed;
 
-  // remember already defined keywords
-  std::set<std::string> used_keywords;
-  const std::string dup_warning = "keyword defined more than once: ";
+  auto const duplicateKey = [this](std::string const& key) {
+    this->GetMakefile()->IssueMessage(
+      MessageType::WARNING, "keyword defined more than once: " + key);
+  };
 
   // the second argument is a (cmake) list of options without argument
   std::vector<std::string> list;
   cmSystemTools::ExpandListArgument(*argIter++, list);
-  for (std::string const& iter : list) {
-    if (!used_keywords.insert(iter).second) {
-      this->GetMakefile()->IssueMessage(MessageType::WARNING,
-                                        dup_warning + iter);
-    }
-    options[iter]; // default initialize
-  }
+  parser.Bind(list, options, duplicateKey);
 
   // the third argument is a (cmake) list of single argument options
   list.clear();
   cmSystemTools::ExpandListArgument(*argIter++, list);
-  for (std::string const& iter : list) {
-    if (!used_keywords.insert(iter).second) {
-      this->GetMakefile()->IssueMessage(MessageType::WARNING,
-                                        dup_warning + iter);
-    }
-    singleValArgs[iter]; // default initialize
-  }
+  parser.Bind(list, singleValArgs, duplicateKey);
 
   // the fourth argument is a (cmake) list of multi argument options
   list.clear();
   cmSystemTools::ExpandListArgument(*argIter++, list);
-  for (std::string const& iter : list) {
-    if (!used_keywords.insert(iter).second) {
-      this->GetMakefile()->IssueMessage(MessageType::WARNING,
-                                        dup_warning + iter);
-    }
-    multiValArgs[iter]; // default initialize
-  }
-
-  insideValues insideValues = NONE;
-  std::string currentArgName;
+  parser.Bind(list, multiValArgs, duplicateKey);
 
   list.clear();
   if (!parseFromArgV) {
@@ -223,68 +208,14 @@ bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args,
     }
   }
 
-  options_set keywordsMissingValues;
-  int multiArgumentsFound = 0;
-
-  // iterate over the arguments list and fill in the values where applicable
-  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);
-    if (singleIter != singleValArgs.end()) {
-      DetectKeywordsMissingValues(insideValues, currentArgName,
-                                  multiArgumentsFound, keywordsMissingValues);
-      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;
-    }
-  }
+  std::vector<std::string> keywordsMissingValues;
 
-  DetectKeywordsMissingValues(insideValues, currentArgName,
-                              multiArgumentsFound, keywordsMissingValues);
+  parser.Parse(list, &unparsed, &keywordsMissingValues);
 
-  PassParsedArguments(prefix, *this->Makefile, options, singleValArgs,
-                      multiValArgs, unparsed, keywordsMissingValues);
+  PassParsedArguments(
+    prefix, *this->Makefile, options, singleValArgs, multiValArgs, unparsed,
+    options_set(keywordsMissingValues.begin(), keywordsMissingValues.end()),
+    parseFromArgV);
 
   return true;
 }