[PATCH] Option parsing: support case-insensitive option matching.
Rui Ueyama
ruiu at google.com
Fri Aug 23 09:33:13 PDT 2013
The previous patch was incomplete so I'm sending the complete one for
completeness. Ignore this patch because I'm still addressing your comment.
Hi hans,
http://llvm-reviews.chandlerc.com/D1485
CHANGE SINCE LAST DIFF
http://llvm-reviews.chandlerc.com/D1485?vs=3693&id=3699#toc
Files:
include/llvm/Option/OptParser.td
include/llvm/Option/OptTable.h
lib/Option/OptTable.cpp
unittests/Option/OptionParsingTest.cpp
unittests/Option/Opts.td
utils/TableGen/OptParserEmitter.cpp
Index: include/llvm/Option/OptParser.td
===================================================================
--- include/llvm/Option/OptParser.td
+++ include/llvm/Option/OptParser.td
@@ -92,6 +92,7 @@
OptionGroup Group = ?;
Option Alias = ?;
list<string> AliasArgs = [];
+ bit IgnoreCase = ?;
}
// Helpers for defining options.
@@ -122,6 +123,7 @@
class Group<OptionGroup group> { OptionGroup Group = group; }
class HelpText<string text> { string HelpText = text; }
class MetaVarName<string name> { string MetaVarName = name; }
+class IgnoreCase<bit value> { bit IgnoreCase = value; }
// Predefined options.
Index: include/llvm/Option/OptTable.h
===================================================================
--- include/llvm/Option/OptTable.h
+++ include/llvm/Option/OptTable.h
@@ -45,6 +45,7 @@
unsigned short GroupID;
unsigned short AliasID;
const char *AliasArgs;
+ bool IgnoreCase;
};
private:
Index: lib/Option/OptTable.cpp
===================================================================
--- lib/Option/OptTable.cpp
+++ lib/Option/OptTable.cpp
@@ -13,6 +13,7 @@
#include "llvm/Option/Option.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Debug.h"
#include <algorithm>
#include <map>
@@ -170,12 +171,25 @@
return true;
}
+// Returns true if X starts with Y, ignoreing case.
+static bool startsWithIgnoreCase(StringRef X, StringRef Y) {
+ if (X.size() < Y.size())
+ return false;
+ return X.substr(0, Y.size()).equals_lower(Y);
+}
+
/// \returns Matched size. 0 means no match.
static unsigned matchOption(const OptTable::Info *I, StringRef Str) {
for (const char * const *Pre = I->Prefixes; *Pre != 0; ++Pre) {
StringRef Prefix(*Pre);
- if (Str.startswith(Prefix) && Str.substr(Prefix.size()).startswith(I->Name))
- return Prefix.size() + StringRef(I->Name).size();
+ if (Str.startswith(Prefix)) {
+ StringRef Rest = Str.substr(Prefix.size());
+ bool Matched = I->IgnoreCase
+ ? startsWithIgnoreCase(Rest, I->Name)
+ : Rest.startswith(I->Name);
+ if (Matched)
+ return Prefix.size() + StringRef(I->Name).size();
+ }
}
return 0;
}
Index: unittests/Option/OptionParsingTest.cpp
===================================================================
--- unittests/Option/OptionParsingTest.cpp
+++ unittests/Option/OptionParsingTest.cpp
@@ -17,10 +17,12 @@
using namespace llvm;
using namespace llvm::opt;
+#define SUPPORT_IGNORECASE // FIXME: Remove when no longer necessary
+
enum ID {
OPT_INVALID = 0, // This is not an option ID.
#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
- HELPTEXT, METAVAR) OPT_##ID,
+ HELPTEXT, METAVAR, IGNORECASE) OPT_##ID,
#include "Opts.inc"
LastOption
#undef OPTION
@@ -38,9 +40,9 @@
static const OptTable::Info InfoTable[] = {
#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
- HELPTEXT, METAVAR) \
+ HELPTEXT, METAVAR, IGNORECASE) \
{ PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, Option::KIND##Class, PARAM, \
- FLAGS, OPT_##GROUP, OPT_##ALIAS, ALIASARGS },
+ FLAGS, OPT_##GROUP, OPT_##ALIAS, ALIASARGS, IGNORECASE },
#include "Opts.inc"
#undef OPTION
};
@@ -157,6 +159,15 @@
EXPECT_EQ(AL->getAllArgValues(OPT_B)[1], "bar");
}
+TEST(Option, IgnoreCase) {
+ TestOptTable T;
+ unsigned MAI, MAC;
+
+ const char *MyArgs[] = { "-K" };
+ OwningPtr<InputArgList> AL(T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC));
+ EXPECT_TRUE(AL->hasArg(OPT_K));
+}
+
TEST(Option, SlurpEmpty) {
TestOptTable T;
unsigned MAI, MAC;
Index: unittests/Option/Opts.td
===================================================================
--- unittests/Option/Opts.td
+++ unittests/Option/Opts.td
@@ -23,4 +23,6 @@
def J : Flag<["-"], "J">, Alias<B>, AliasArgs<["foo"]>;
def Joo : Flag<["-"], "Joo">, Alias<B>, AliasArgs<["bar"]>;
+def K : Flag<["-"], "k">, IgnoreCase<1>;
+
def Slurp : Option<["-"], "slurp", KIND_REMAINING_ARGS>;
Index: utils/TableGen/OptParserEmitter.cpp
===================================================================
--- utils/TableGen/OptParserEmitter.cpp
+++ utils/TableGen/OptParserEmitter.cpp
@@ -152,11 +152,22 @@
OS << "/////////\n";
OS << "// Groups\n\n";
OS << "#ifdef OPTION\n";
+
+ // FIXME: Remove when option parsing clients are updated.
+ OS << "#ifdef SUPPORT_IGNORECASE\n";
+ OS << "#define OPTIONX OPTION\n";
+ OS << "#else\n";
+ OS << "#define OPTIONX(prefix, name, id, kind, group, alias, aliasargs, "
+ << "flags, param, helptext, metavar, ignorecase) "
+ << "OPTION(prefix, name, id, kind, "
+ << "group, alias, aliasargs, flags, param, helptext, metavar)\n";
+ OS << "#endif\n";
+
for (unsigned i = 0, e = Groups.size(); i != e; ++i) {
const Record &R = *Groups[i];
// Start a single option entry.
- OS << "OPTION(";
+ OS << "OPTIONX(";
// The option prefix;
OS << "0";
@@ -188,8 +199,8 @@
} else
OS << ", 0";
- // The option meta-variable name (unused).
- OS << ", 0)\n";
+ // The option meta-variable name and ignore-case bit (unused).
+ OS << ", 0, 0)\n";
}
OS << "\n";
@@ -199,7 +210,7 @@
const Record &R = *Opts[i];
// Start a single option entry.
- OS << "OPTION(";
+ OS << "OPTIONX(";
// The option prefix;
std::vector<std::string> prf = R.getValueAsListOfStrings("Prefixes");
@@ -274,8 +285,15 @@
else
OS << "0";
+ // The ignore-base bit.
+ OS << ", ";
+ bool IgnoreCase = !isa<UnsetInit>(R.getValueInit("IgnoreCase")) &&
+ R.getValueAsBit("IgnoreCase");
+ OS << (IgnoreCase ? "1" : "0");
+
OS << ")\n";
}
+ OS << "#undef OPTIONX\n"; // FIXME: Remove when option clients are updated.
OS << "#endif\n";
}
} // end namespace llvm
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D1485.2.patch
Type: text/x-patch
Size: 5963 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20130823/7937b669/attachment.bin>
More information about the llvm-commits
mailing list