From 541e19ce1bdb0bba2b87b2003dfbc79f347cbd91 Mon Sep 17 00:00:00 2001 From: Don Hinton Date: Sat, 11 May 2019 20:27:01 +0000 Subject: [PATCH] [CommandLine] Add long option flag for cl::ParseCommandLineOptions . Part 5 of 5 Summary: If passed, the long option flag makes the CommandLine parser mimic the behavior or GNU getopt_long. Short options are a single character prefixed by a single dash, and long options are multiple characters prefixed by a double dash. This patch was motivated by the discussion in the following thread: http://lists.llvm.org/pipermail/llvm-dev/2019-April/131786.html Reviewed By: MaskRay Tags: #llvm Differential Revision: https://reviews.llvm.org/D61294 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@360532 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Support/CommandLine.h | 3 +- lib/Support/CommandLine.cpp | 60 ++++++++++++++-------- unittests/Support/CommandLineTest.cpp | 73 +++++++++++++++++++++++++++ 3 files changed, 115 insertions(+), 21 deletions(-) diff --git a/include/llvm/Support/CommandLine.h b/include/llvm/Support/CommandLine.h index 68cbebe5de8..d144c9b0f0f 100644 --- a/include/llvm/Support/CommandLine.h +++ b/include/llvm/Support/CommandLine.h @@ -66,7 +66,8 @@ namespace cl { bool ParseCommandLineOptions(int argc, const char *const *argv, StringRef Overview = "", raw_ostream *Errs = nullptr, - const char *EnvVar = nullptr); + const char *EnvVar = nullptr, + bool LongOptionsUseDoubleDash = false); //===----------------------------------------------------------------------===// // ParseEnvironmentOptions - Environment variable option processing alternate diff --git a/lib/Support/CommandLine.cpp b/lib/Support/CommandLine.cpp index 28516476d58..4e63a07673a 100644 --- a/lib/Support/CommandLine.cpp +++ b/lib/Support/CommandLine.cpp @@ -105,6 +105,16 @@ static StringRef argPrefix(StringRef ArgName) { return ArgPrefixLong; } +// Option predicates... +static inline bool isGrouping(const Option *O) { + return O->getMiscFlags() & cl::Grouping; +} +static inline bool isPrefixedOrGrouping(const Option *O) { + return isGrouping(O) || O->getFormattingFlag() == cl::Prefix || + O->getFormattingFlag() == cl::AlwaysPrefix; +} + + namespace { class PrintArg { @@ -148,7 +158,8 @@ public: void ResetAllOptionOccurrences(); bool ParseCommandLineOptions(int argc, const char *const *argv, - StringRef Overview, raw_ostream *Errs = nullptr); + StringRef Overview, raw_ostream *Errs = nullptr, + bool LongOptionsUseDoubleDash = false); void addLiteralOption(Option &Opt, SubCommand *SC, StringRef Name) { if (Opt.hasArgStr()) @@ -394,6 +405,13 @@ private: SubCommand *ActiveSubCommand; Option *LookupOption(SubCommand &Sub, StringRef &Arg, StringRef &Value); + Option *LookupLongOption(SubCommand &Sub, StringRef &Arg, StringRef &Value, + bool LongOptionsUseDoubleDash, bool HaveDoubleDash) { + Option *Opt = LookupOption(Sub, Arg, Value); + if (Opt && LongOptionsUseDoubleDash && !HaveDoubleDash && !isGrouping(Opt)) + return nullptr; + return Opt; + } SubCommand *LookupSubCommand(StringRef Name); }; @@ -679,15 +697,6 @@ static bool ProvidePositionalOption(Option *Handler, StringRef Arg, int i) { return ProvideOption(Handler, Handler->ArgStr, Arg, 0, nullptr, Dummy); } -// Option predicates... -static inline bool isGrouping(const Option *O) { - return O->getMiscFlags() & cl::Grouping; -} -static inline bool isPrefixedOrGrouping(const Option *O) { - return isGrouping(O) || O->getFormattingFlag() == cl::Prefix || - O->getFormattingFlag() == cl::AlwaysPrefix; -} - // getOptionPred - Check to see if there are any options that satisfy the // specified predicate with names that are the prefixes in Name. This is // checked by progressively stripping characters off of the name, checking to @@ -697,8 +706,9 @@ static inline bool isPrefixedOrGrouping(const Option *O) { static Option *getOptionPred(StringRef Name, size_t &Length, bool (*Pred)(const Option *), const StringMap