summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/CommandLine.html11
-rw-r--r--include/llvm/Support/CommandLine.h23
-rw-r--r--lib/Support/CommandLine.cpp44
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.</li>
+<li><a name="cl::multi_val">The <b><tt>cl::multi_val</tt></b></a>
+attribute specifies that this option takes has multiple values
+(example: <tt>-sectalign segname sectname sectvalue</tt>). This
+attribute takes one unsigned argument - the number of values for the
+option. This attribute is valid only on <tt>cl::list</tt> 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 <tt>cl::ValueDisallowed</tt>,
+obviously).</li>
+
+
</ol>
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<class M0t>
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 <typename D, typename S, typename P>
+ void apply(list<D, S, P> &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: