From 7059d47a6e1a378232dce3e47b51434dec0ea608 Mon Sep 17 00:00:00 2001 From: Mikhail Glushenkov Date: Fri, 16 Jan 2009 22:54:19 +0000 Subject: Support for multi-valued options in CommandLine Makes possible to specify options that take multiple arguments (a-la -sectalign on Darwin). See documentation for details. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@62372 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/CommandLine.html | 11 ++++++++++ include/llvm/Support/CommandLine.h | 23 ++++++++++++++++++-- lib/Support/CommandLine.cpp | 44 ++++++++++++++++++++++++++++++++++---- 3 files changed, 72 insertions(+), 6 deletions(-) diff --git a/docs/CommandLine.html b/docs/CommandLine.html index 7fcd66c..97df9f7 100644 --- a/docs/CommandLine.html +++ b/docs/CommandLine.html @@ -1146,6 +1146,17 @@ specify macro options where the option name doesn't equal the enum name. For this macro, the first argument is the enum value, the second is the flag name, and the second is the description. +
  • The cl::multi_val +attribute specifies that this option takes has multiple values +(example: -sectalign segname sectname sectvalue). This +attribute takes one unsigned argument - the number of values for the +option. This attribute is valid only on cl::list options (and +will fail with compile error if you try to use it with other option +types). It is allowed to use all of the usual modifiers on +multi-valued options (besides cl::ValueDisallowed, +obviously).
  • + + You will get a compile time error if you try to use cl::values with a parser diff --git a/include/llvm/Support/CommandLine.h b/include/llvm/Support/CommandLine.h index b7de038..e7f5a02 100644 --- a/include/llvm/Support/CommandLine.h +++ b/include/llvm/Support/CommandLine.h @@ -155,6 +155,7 @@ class Option { int NumOccurrences; // The number of times specified int Flags; // Flags for the argument unsigned Position; // Position of last occurrence of the option + unsigned AdditionalVals;// Greater than 0 for multi-valued option. Option *NextRegistered; // Singly linked list of registered options. public: const char *ArgStr; // The argument string itself (ex: "help", "o") @@ -179,6 +180,7 @@ public: return Flags & MiscMask; } inline unsigned getPosition() const { return Position; } + inline unsigned getNumAdditionalVals() const { return AdditionalVals; } // hasArgStr - Return true if the argstr != "" bool hasArgStr() const { return ArgStr[0] != 0; } @@ -206,11 +208,14 @@ public: protected: explicit Option(unsigned DefaultFlags) : NumOccurrences(0), Flags(DefaultFlags | NormalFormatting), Position(0), - NextRegistered(0), ArgStr(""), HelpStr(""), ValueStr("") { + AdditionalVals(0), NextRegistered(0), + ArgStr(""), HelpStr(""), ValueStr("") { assert(getNumOccurrencesFlag() != 0 && getOptionHiddenFlag() != 0 && "Not all default flags specified!"); } + inline void setNumAdditionalVals(unsigned n) + { AdditionalVals = n; } public: // addArgument - Register this argument with the commandline system. // @@ -231,7 +236,7 @@ public: // addOccurrence - Wrapper around handleOccurrence that enforces Flags // bool addOccurrence(unsigned pos, const char *ArgName, - const std::string &Value); + const std::string &Value, bool MultiArg = false); // Prints option name followed by message. Always returns true. bool error(std::string Message, const char *ArgName = 0); @@ -1000,6 +1005,10 @@ public: return Positions[optnum]; } + void setNumAdditionalVals(unsigned n) { + Option::setNumAdditionalVals(n); + } + // One option... template explicit list(const M0t &M0) : Option(ZeroOrMore | NotHidden) { @@ -1065,6 +1074,16 @@ public: } }; +// multi_arg - Modifier to set the number of additional values. +struct multi_val { + unsigned AdditionalVals; + explicit multi_val(unsigned N) : AdditionalVals(N) {} + + template + void apply(list &L) const { L.setNumAdditionalVals(AdditionalVals); } +}; + + //===----------------------------------------------------------------------===// // bits_storage class diff --git a/lib/Support/CommandLine.cpp b/lib/Support/CommandLine.cpp index 20c2b8e..87dfc5a 100644 --- a/lib/Support/CommandLine.cpp +++ b/lib/Support/CommandLine.cpp @@ -172,6 +172,9 @@ static Option *LookupOption(const char *&Arg, const char *&Value, static inline bool ProvideOption(Option *Handler, const char *ArgName, const char *Value, int argc, char **argv, int &i) { + // Is this a multi-argument option? + unsigned NumAdditionalVals = Handler->getNumAdditionalVals(); + // Enforce value requirements switch (Handler->getValueExpectedFlag()) { case ValueRequired: @@ -184,6 +187,10 @@ static inline bool ProvideOption(Option *Handler, const char *ArgName, } break; case ValueDisallowed: + if (NumAdditionalVals > 0) + return Handler->error(": multi-valued option specified" + " with ValueDisallowed modifier!"); + if (Value) return Handler->error(" does not allow a value! '" + std::string(Value) + "' specified."); @@ -198,8 +205,35 @@ static inline bool ProvideOption(Option *Handler, const char *ArgName, break; } - // Run the handler now! - return Handler->addOccurrence(i, ArgName, Value ? Value : ""); + // If this isn't a multi-arg option, just run the handler. + if (NumAdditionalVals == 0) { + return Handler->addOccurrence(i, ArgName, Value ? Value : ""); + } + // If it is, run the handle several times. + else { + bool MultiArg = false; + + if (Value) { + if (Handler->addOccurrence(i, ArgName, Value, MultiArg)) + return true; + --NumAdditionalVals; + MultiArg = true; + } + + while (NumAdditionalVals > 0) { + + if (i+1 < argc) { + Value = argv[++i]; + } else { + return Handler->error(": not enough values!"); + } + if (Handler->addOccurrence(i, ArgName, Value, MultiArg)) + return true; + MultiArg = true; + --NumAdditionalVals; + } + return false; + } } static bool ProvidePositionalOption(Option *Handler, const std::string &Arg, @@ -738,8 +772,10 @@ bool Option::error(std::string Message, const char *ArgName) { } bool Option::addOccurrence(unsigned pos, const char *ArgName, - const std::string &Value) { - NumOccurrences++; // Increment the number of times we have been seen + const std::string &Value, + bool MultiArg) { + if (!MultiArg) + NumOccurrences++; // Increment the number of times we have been seen switch (getNumOccurrencesFlag()) { case Optional: -- cgit v1.1