llvm.org GIT mirror llvm / 1997734
Revert "Option parsing: support case-insensitive option matching." as it broke Windows buildbot. This reverts r189416. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@189424 91177308-0d34-0410-b5e6-96231b3b80d8 Rui Ueyama 5 years ago
4 changed file(s) with 56 addition(s) and 90 deletion(s). Raw diff Collapse all Expand all
5050 /// \brief The static option information table.
5151 const Info *OptionInfos;
5252 unsigned NumOptionInfos;
53 bool IgnoreCase;
5453
5554 unsigned TheInputOptionID;
5655 unsigned TheUnknownOptionID;
7271 }
7372
7473 protected:
75 OptTable(const Info *_OptionInfos, unsigned _NumOptionInfos,
76 bool _IgnoreCase = false);
74 OptTable(const Info *_OptionInfos, unsigned _NumOptionInfos);
7775 public:
7876 ~OptTable();
7977
1818 using namespace llvm;
1919 using namespace llvm::opt;
2020
21 // Ordering on Info. The ordering is *almost* lexicographic, with two
22 // exceptions. First, '\0' comes at the end of the alphabet instead of
23 // the beginning (thus options precede any other options which prefix
24 // them). Second, for options with the same name, the less permissive
25 // version should come first; a Flag option should precede a Joined
26 // option, for example.
27
28 static int StrCmpOptionName(const char *A, const char *B) {
29 char a = *A, b = *B;
30 while (a == b) {
31 if (a == '\0')
32 return 0;
33
34 a = *++A;
35 b = *++B;
36 }
37
38 if (a == '\0') // A is a prefix of B.
39 return 1;
40 if (b == '\0') // B is a prefix of A.
41 return -1;
42
43 // Otherwise lexicographic.
44 return (a < b) ? -1 : 1;
45 }
46
2147 namespace llvm {
2248 namespace opt {
23
24 // Ordering on Info. The ordering is *almost* case-insensitive lexicographic,
25 // with an exceptions. '\0' comes at the end of the alphabet instead of the
26 // beginning (thus options precede any other options which prefix them).
27 static int StrCmpOptionNameIgnoreCase(const char *A, const char *B) {
28 size_t I = strlen(A);
29 size_t J = strlen(B);
30 // If A and B are the same length, compare them ignoring case.
31 if (I == J)
32 return strcasecmp(A, B);
33 // A is shorter than B. In this case A is less than B only when it's
34 // lexicographically less than B. strncasecmp() == 0 means A is a prefix of B,
35 // which in turn means A should appear *after* B.
36 if (I < J)
37 return strncasecmp(A, B, I) < 0 ? -1 : 1;
38 // Otherwise, vice versa.
39 return strncasecmp(A, B, J) <= 0 ? -1 : 1;
40 }
41
42 static int StrCmpOptionName(const char *A, const char *B) {
43 if (int N = StrCmpOptionNameIgnoreCase(A, B))
44 return N;
45 return strcmp(A, B);
46 }
4749
4850 static inline bool operator<(const OptTable::Info &A, const OptTable::Info &B) {
4951 if (&A == &B)
5052 return false;
5153
5254 if (int N = StrCmpOptionName(A.Name, B.Name))
53 return N < 0;
55 return N == -1;
5456
5557 for (const char * const *APre = A.Prefixes,
5658 * const *BPre = B.Prefixes;
5759 *APre != 0 && *BPre != 0; ++APre, ++BPre) {
5860 if (int N = StrCmpOptionName(*APre, *BPre))
59 return N < 0;
61 return N == -1;
6062 }
6163
6264 // Names are the same, check that classes are in order; exactly one
6870
6971 // Support lower_bound between info and an option name.
7072 static inline bool operator<(const OptTable::Info &I, const char *Name) {
71 return StrCmpOptionNameIgnoreCase(I.Name, Name) < 0;
73 return StrCmpOptionName(I.Name, Name) == -1;
7274 }
7375 static inline bool operator<(const char *Name, const OptTable::Info &I) {
74 return StrCmpOptionNameIgnoreCase(Name, I.Name) < 0;
76 return StrCmpOptionName(Name, I.Name) == -1;
7577 }
7678 }
7779 }
7880
7981 OptSpecifier::OptSpecifier(const Option *Opt) : ID(Opt->getID()) {}
8082
81 OptTable::OptTable(const Info *_OptionInfos, unsigned _NumOptionInfos,
82 bool _IgnoreCase)
83 OptTable::OptTable(const Info *_OptionInfos, unsigned _NumOptionInfos)
8384 : OptionInfos(_OptionInfos),
8485 NumOptionInfos(_NumOptionInfos),
85 IgnoreCase(_IgnoreCase),
8686 TheInputOptionID(0),
8787 TheUnknownOptionID(0),
8888 FirstSearchableIndex(0)
169169 return true;
170170 }
171171
172 // Returns true if X starts with Y, ignoring case.
173 static bool startsWithIgnoreCase(StringRef X, StringRef Y) {
174 if (X.size() < Y.size())
175 return false;
176 return X.substr(0, Y.size()).equals_lower(Y);
177 }
178
179172 /// \returns Matched size. 0 means no match.
180 static unsigned matchOption(const OptTable::Info *I, StringRef Str,
181 bool IgnoreCase) {
173 static unsigned matchOption(const OptTable::Info *I, StringRef Str) {
182174 for (const char * const *Pre = I->Prefixes; *Pre != 0; ++Pre) {
183175 StringRef Prefix(*Pre);
184 if (Str.startswith(Prefix)) {
185 StringRef Rest = Str.substr(Prefix.size());
186 bool Matched = IgnoreCase
187 ? startsWithIgnoreCase(Rest, I->Name)
188 : Rest.startswith(I->Name);
189 if (Matched)
190 return Prefix.size() + StringRef(I->Name).size();
191 }
176 if (Str.startswith(Prefix) && Str.substr(Prefix.size()).startswith(I->Name))
177 return Prefix.size() + StringRef(I->Name).size();
192178 }
193179 return 0;
194180 }
223209 unsigned ArgSize = 0;
224210 // Scan for first option which is a proper prefix.
225211 for (; Start != End; ++Start)
226 if ((ArgSize = matchOption(Start, Str, IgnoreCase)))
212 if ((ArgSize = matchOption(Start, Str)))
227213 break;
228214 if (Start == End)
229215 break;
1919 enum ID {
2020 OPT_INVALID = 0, // This is not an option ID.
2121 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
22 HELPTEXT, METAVAR) OPT_##ID,
22 HELPTEXT, METAVAR) OPT_##ID,
2323 #include "Opts.inc"
2424 LastOption
2525 #undef OPTION
4747 namespace {
4848 class TestOptTable : public OptTable {
4949 public:
50 TestOptTable(bool IgnoreCase = false)
51 : OptTable(InfoTable, array_lengthof(InfoTable), IgnoreCase) {}
50 TestOptTable()
51 : OptTable(InfoTable, array_lengthof(InfoTable)) {}
5252 };
5353 }
5454
156156 EXPECT_EQ(AL->getAllArgValues(OPT_B)[1], "bar");
157157 }
158158
159 TEST(Option, IgnoreCase) {
160 TestOptTable T(true);
161 unsigned MAI, MAC;
162
163 const char *MyArgs[] = { "-a", "-joo" };
164 OwningPtr AL(T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC));
165 EXPECT_TRUE(AL->hasArg(OPT_A));
166 EXPECT_TRUE(AL->hasArg(OPT_B));
167 }
168
169 TEST(Option, DoNotIgnoreCase) {
170 TestOptTable T;
171 unsigned MAI, MAC;
172
173 const char *MyArgs[] = { "-a", "-joo" };
174 OwningPtr AL(T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC));
175 EXPECT_FALSE(AL->hasArg(OPT_A));
176 EXPECT_FALSE(AL->hasArg(OPT_B));
177 }
178
179159 TEST(Option, SlurpEmpty) {
180160 TestOptTable T;
181161 unsigned MAI, MAC;
1212 #include "llvm/ADT/Twine.h"
1313 #include "llvm/TableGen/Record.h"
1414 #include "llvm/TableGen/TableGenBackend.h"
15 #include
1615 #include
17 #include
1816
1917 using namespace llvm;
2018
21 // Ordering on Info. The logic should match with the consumer-side function in
22 // llvm/Option/OptTable.h.
2319 static int StrCmpOptionName(const char *A, const char *B) {
24 size_t I = strlen(A);
25 size_t J = strlen(B);
26 if (I == J) {
27 if (int N = strcasecmp(A, B))
28 return N;
29 return strcmp(A, B);
30 }
31 if (I < J)
32 return strncasecmp(A, B, I) < 0 ? -1 : 1;
33 return strncasecmp(A, B, J) <= 0 ? -1 : 1;
20 char a = *A, b = *B;
21 while (a == b) {
22 if (a == '\0')
23 return 0;
24
25 a = *++A;
26 b = *++B;
27 }
28
29 if (a == '\0') // A is a prefix of B.
30 return 1;
31 if (b == '\0') // B is a prefix of A.
32 return -1;
33
34 // Otherwise lexicographic.
35 return (a < b) ? -1 : 1;
3436 }
3537
3638 static int CompareOptionRecords(const void *Av, const void *Bv) {
4749 if (!ASent)
4850 if (int Cmp = StrCmpOptionName(A->getValueAsString("Name").c_str(),
4951 B->getValueAsString("Name").c_str()))
50 return Cmp;
52 return Cmp;
5153
5254 if (!ASent) {
5355 std::vector APrefixes = A->getValueAsListOfStrings("Prefixes");