| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249 | 
							- /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
 
-    file Copyright.txt or https://cmake.org/licensing for details.  */
 
- #include "cmParseArgumentsCommand.h"
 
- #include <map>
 
- #include <set>
 
- #include <sstream>
 
- #include <utility>
 
- #include "cmAlgorithms.h"
 
- #include "cmMakefile.h"
 
- #include "cmMessageType.h"
 
- #include "cmSystemTools.h"
 
- class cmExecutionStatus;
 
- static std::string escape_arg(const std::string& arg)
 
- {
 
-   // replace ";" with "\;" so output argument lists will split correctly
 
-   std::string escapedArg;
 
-   for (char i : arg) {
 
-     if (i == ';') {
 
-       escapedArg += '\\';
 
-     }
 
-     escapedArg += i;
 
-   }
 
-   return escapedArg;
 
- }
 
- namespace {
 
- enum InsideValues
 
- {
 
-   NONE,
 
-   SINGLE,
 
-   MULTI
 
- };
 
- 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;
 
- }
 
- 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)
 
- {
 
-   for (auto const& iter : options) {
 
-     makefile.AddDefinition(prefix + iter.first,
 
-                            iter.second ? "TRUE" : "FALSE");
 
-   }
 
-   for (auto const& iter : singleValArgs) {
 
-     if (!iter.second.empty()) {
 
-       makefile.AddDefinition(prefix + iter.first, iter.second.c_str());
 
-     } else {
 
-       makefile.RemoveDefinition(prefix + iter.first);
 
-     }
 
-   }
 
-   for (auto const& iter : multiValArgs) {
 
-     if (!iter.second.empty()) {
 
-       makefile.AddDefinition(prefix + iter.first,
 
-                              cmJoin(cmMakeRange(iter.second), ";").c_str());
 
-     } else {
 
-       makefile.RemoveDefinition(prefix + iter.first);
 
-     }
 
-   }
 
-   if (!unparsed.empty()) {
 
-     makefile.AddDefinition(prefix + "UNPARSED_ARGUMENTS",
 
-                            cmJoin(cmMakeRange(unparsed), ";").c_str());
 
-   } else {
 
-     makefile.RemoveDefinition(prefix + "UNPARSED_ARGUMENTS");
 
-   }
 
- }
 
- bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args,
 
-                                           cmExecutionStatus&)
 
- {
 
-   // cmake_parse_arguments(prefix options single multi <ARGN>)
 
-   //                         1       2      3      4
 
-   // or
 
-   // cmake_parse_arguments(PARSE_ARGV N prefix options single multi)
 
-   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();
 
-   bool parseFromArgV = false;
 
-   unsigned long argvStart = 0;
 
-   if (*argIter == "PARSE_ARGV") {
 
-     if (args.size() != 6) {
 
-       this->Makefile->IssueMessage(
 
-         MessageType::FATAL_ERROR,
 
-         "PARSE_ARGV must be called with exactly 6 arguments.");
 
-       cmSystemTools::SetFatalErrorOccured();
 
-       return true;
 
-     }
 
-     parseFromArgV = true;
 
-     argIter++; // move past PARSE_ARGV
 
-     if (!cmSystemTools::StringToULong(argIter->c_str(), &argvStart)) {
 
-       this->Makefile->IssueMessage(MessageType::FATAL_ERROR,
 
-                                    "PARSE_ARGV index '" + *argIter +
 
-                                      "' is not an unsigned integer");
 
-       cmSystemTools::SetFatalErrorOccured();
 
-       return true;
 
-     }
 
-     argIter++; // move past N
 
-   }
 
-   // 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
 
-   options_map options;
 
-   single_map singleValArgs;
 
-   multi_map multiValArgs;
 
-   // 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::string const& iter : list) {
 
-     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
 
-   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
 
-   }
 
-   // 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;
 
-   list.clear();
 
-   if (!parseFromArgV) {
 
-     // Flatten ;-lists in the arguments into a single list as was done
 
-     // by the original function(CMAKE_PARSE_ARGUMENTS).
 
-     for (; argIter != argEnd; ++argIter) {
 
-       cmSystemTools::ExpandListArgument(*argIter, list);
 
-     }
 
-   } else {
 
-     // in the PARSE_ARGV move read the arguments from ARGC and ARGV#
 
-     std::string argc = this->Makefile->GetSafeDefinition("ARGC");
 
-     unsigned long count;
 
-     if (!cmSystemTools::StringToULong(argc.c_str(), &count)) {
 
-       this->Makefile->IssueMessage(MessageType::FATAL_ERROR,
 
-                                    "PARSE_ARGV called with ARGC='" + argc +
 
-                                      "' that is not an unsigned integer");
 
-       cmSystemTools::SetFatalErrorOccured();
 
-       return true;
 
-     }
 
-     for (unsigned long i = argvStart; i < count; ++i) {
 
-       std::ostringstream argName;
 
-       argName << "ARGV" << i;
 
-       const char* arg = this->Makefile->GetDefinition(argName.str());
 
-       if (!arg) {
 
-         this->Makefile->IssueMessage(MessageType::FATAL_ERROR,
 
-                                      "PARSE_ARGV called with " +
 
-                                        argName.str() + " not set");
 
-         cmSystemTools::SetFatalErrorOccured();
 
-         return true;
 
-       }
 
-       list.emplace_back(arg);
 
-     }
 
-   }
 
-   // 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()) {
 
-       insideValues = NONE;
 
-       optIter->second = true;
 
-       continue;
 
-     }
 
-     const single_map::iterator singleIter = singleValArgs.find(arg);
 
-     if (singleIter != singleValArgs.end()) {
 
-       insideValues = SINGLE;
 
-       currentArgName = arg;
 
-       continue;
 
-     }
 
-     const multi_map::iterator multiIter = multiValArgs.find(arg);
 
-     if (multiIter != multiValArgs.end()) {
 
-       insideValues = MULTI;
 
-       currentArgName = arg;
 
-       continue;
 
-     }
 
-     switch (insideValues) {
 
-       case SINGLE:
 
-         singleValArgs[currentArgName] = arg;
 
-         insideValues = NONE;
 
-         break;
 
-       case MULTI:
 
-         if (parseFromArgV) {
 
-           multiValArgs[currentArgName].push_back(escape_arg(arg));
 
-         } else {
 
-           multiValArgs[currentArgName].push_back(arg);
 
-         }
 
-         break;
 
-       default:
 
-         if (parseFromArgV) {
 
-           unparsed.push_back(escape_arg(arg));
 
-         } else {
 
-           unparsed.push_back(arg);
 
-         }
 
-         break;
 
-     }
 
-   }
 
-   PassParsedArguments(prefix, *this->Makefile, options, singleValArgs,
 
-                       multiValArgs, unparsed);
 
-   return true;
 
- }
 
 
  |