summaryrefslogtreecommitdiffstats
path: root/Source/cmParseArgumentsCommand.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/cmParseArgumentsCommand.cxx')
-rw-r--r--Source/cmParseArgumentsCommand.cxx174
1 files changed, 174 insertions, 0 deletions
diff --git a/Source/cmParseArgumentsCommand.cxx b/Source/cmParseArgumentsCommand.cxx
new file mode 100644
index 0000000..8f524ec
--- /dev/null
+++ b/Source/cmParseArgumentsCommand.cxx
@@ -0,0 +1,174 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2015 Matthias Maennich <matthias@maennich.net>
+ Copyright 2010 Alexander Neundorf <neundorf@kde.org>
+
+ Distributed under the OSI-approved BSD License (the "License");
+ see accompanying file Copyright.txt for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License for more information.
+============================================================================*/
+
+#include "cmParseArgumentsCommand.h"
+
+#include "cmAlgorithms.h"
+
+bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
+{
+ // cmake_parse_arguments(prefix options single multi <ARGN>)
+ // 1 2 3 4
+ if (args.size() < 4) {
+ this->SetError("must be called with at least 4 arguments.");
+ return false;
+ }
+
+ std::vector<std::string>::const_iterator argIter = args.begin(),
+ argEnd = args.end();
+ // the first argument is the prefix
+ const std::string prefix = (*argIter++) + "_";
+
+ // define the result maps holding key/value pairs for
+ // options, single values and multi values
+ 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;
+ options_map options;
+ single_map single;
+ multi_map multi;
+
+ // 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: ";
+
+ // the second argument is a (cmake) list of options without argument
+ std::vector<std::string> list;
+ cmSystemTools::ExpandListArgument(*argIter++, list);
+ for (std::vector<std::string>::const_iterator iter = list.begin(),
+ end = list.end();
+ iter != end; ++iter) {
+ if (!used_keywords.insert(*iter).second) {
+ this->GetMakefile()->IssueMessage(cmake::WARNING, dup_warning + *iter);
+ }
+ options[*iter]; // default initialize
+ }
+
+ // the third argument is a (cmake) list of single argument options
+ list.clear();
+ cmSystemTools::ExpandListArgument(*argIter++, list);
+ for (std::vector<std::string>::const_iterator iter = list.begin(),
+ end = list.end();
+ iter != end; ++iter) {
+ if (!used_keywords.insert(*iter).second) {
+ this->GetMakefile()->IssueMessage(cmake::WARNING, dup_warning + *iter);
+ }
+ single[*iter]; // default initialize
+ }
+
+ // the fourth argument is a (cmake) list of multi argument options
+ list.clear();
+ cmSystemTools::ExpandListArgument(*argIter++, list);
+ for (std::vector<std::string>::const_iterator iter = list.begin(),
+ end = list.end();
+ iter != end; ++iter) {
+ if (!used_keywords.insert(*iter).second) {
+ this->GetMakefile()->IssueMessage(cmake::WARNING, dup_warning + *iter);
+ }
+ multi[*iter]; // default initialize
+ }
+
+ enum insideValues
+ {
+ NONE,
+ SINGLE,
+ MULTI
+ } insideValues = NONE;
+ std::string currentArgName;
+
+ // Flatten ;-lists in the arguments into a single list as was done
+ // by the original function(CMAKE_PARSE_ARGUMENTS).
+ list.clear();
+ for (; argIter != argEnd; ++argIter) {
+ cmSystemTools::ExpandListArgument(*argIter, list);
+ }
+
+ // iterate over the arguments list and fill in the values where applicable
+ for (argIter = list.begin(), argEnd = list.end(); argIter != argEnd;
+ ++argIter) {
+ const options_map::iterator optIter = options.find(*argIter);
+ if (optIter != options.end()) {
+ insideValues = NONE;
+ optIter->second = true;
+ continue;
+ }
+
+ const single_map::iterator singleIter = single.find(*argIter);
+ if (singleIter != single.end()) {
+ insideValues = SINGLE;
+ currentArgName = *argIter;
+ continue;
+ }
+
+ const multi_map::iterator multiIter = multi.find(*argIter);
+ if (multiIter != multi.end()) {
+ insideValues = MULTI;
+ currentArgName = *argIter;
+ continue;
+ }
+
+ switch (insideValues) {
+ case SINGLE:
+ single[currentArgName] = *argIter;
+ insideValues = NONE;
+ break;
+ case MULTI:
+ multi[currentArgName].push_back(*argIter);
+ break;
+ default:
+ unparsed.push_back(*argIter);
+ break;
+ }
+ }
+
+ // now iterate over the collected values and update their definition
+ // within the current scope. undefine if necessary.
+
+ for (options_map::const_iterator iter = options.begin(), end = options.end();
+ iter != end; ++iter) {
+ this->Makefile->AddDefinition(prefix + iter->first,
+ iter->second ? "TRUE" : "FALSE");
+ }
+ for (single_map::const_iterator iter = single.begin(), end = single.end();
+ iter != end; ++iter) {
+ if (!iter->second.empty()) {
+ this->Makefile->AddDefinition(prefix + iter->first,
+ iter->second.c_str());
+ } else {
+ this->Makefile->RemoveDefinition(prefix + iter->first);
+ }
+ }
+
+ for (multi_map::const_iterator iter = multi.begin(), end = multi.end();
+ iter != end; ++iter) {
+ if (!iter->second.empty()) {
+ this->Makefile->AddDefinition(
+ prefix + iter->first, cmJoin(cmMakeRange(iter->second), ";").c_str());
+ } else {
+ this->Makefile->RemoveDefinition(prefix + iter->first);
+ }
+ }
+
+ if (!unparsed.empty()) {
+ this->Makefile->AddDefinition(prefix + "UNPARSED_ARGUMENTS",
+ cmJoin(cmMakeRange(unparsed), ";").c_str());
+ } else {
+ this->Makefile->RemoveDefinition(prefix + "UNPARSED_ARGUMENTS");
+ }
+
+ return true;
+}