Line data Source code
1 : //===- OptTable.cpp - Option Table Implementation -------------------------===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 :
10 : #include "llvm/ADT/STLExtras.h"
11 : #include "llvm/ADT/StringRef.h"
12 : #include "llvm/ADT/StringSet.h"
13 : #include "llvm/Option/Arg.h"
14 : #include "llvm/Option/ArgList.h"
15 : #include "llvm/Option/Option.h"
16 : #include "llvm/Option/OptSpecifier.h"
17 : #include "llvm/Option/OptTable.h"
18 : #include "llvm/Support/Compiler.h"
19 : #include "llvm/Support/ErrorHandling.h"
20 : #include "llvm/Support/raw_ostream.h"
21 : #include <algorithm>
22 : #include <cassert>
23 : #include <cctype>
24 : #include <cstring>
25 : #include <map>
26 : #include <string>
27 : #include <utility>
28 : #include <vector>
29 :
30 : using namespace llvm;
31 : using namespace llvm::opt;
32 :
33 : namespace llvm {
34 : namespace opt {
35 :
36 : // Ordering on Info. The ordering is *almost* case-insensitive lexicographic,
37 : // with an exception. '\0' comes at the end of the alphabet instead of the
38 : // beginning (thus options precede any other options which prefix them).
39 30212045 : static int StrCmpOptionNameIgnoreCase(const char *A, const char *B) {
40 : const char *X = A, *Y = B;
41 30212045 : char a = tolower(*A), b = tolower(*B);
42 70403012 : while (a == b) {
43 41922419 : if (a == '\0')
44 : return 0;
45 :
46 40190967 : a = tolower(*++X);
47 40190967 : b = tolower(*++Y);
48 : }
49 :
50 28480593 : if (a == '\0') // A is a prefix of B.
51 : return 1;
52 27952002 : if (b == '\0') // B is a prefix of A.
53 : return -1;
54 :
55 : // Otherwise lexicographic.
56 26435718 : return (a < b) ? -1 : 1;
57 : }
58 :
59 : #ifndef NDEBUG
60 : static int StrCmpOptionName(const char *A, const char *B) {
61 : if (int N = StrCmpOptionNameIgnoreCase(A, B))
62 : return N;
63 : return strcmp(A, B);
64 : }
65 :
66 : static inline bool operator<(const OptTable::Info &A, const OptTable::Info &B) {
67 : if (&A == &B)
68 : return false;
69 :
70 : if (int N = StrCmpOptionName(A.Name, B.Name))
71 : return N < 0;
72 :
73 : for (const char * const *APre = A.Prefixes,
74 : * const *BPre = B.Prefixes;
75 : *APre != nullptr && *BPre != nullptr; ++APre, ++BPre){
76 : if (int N = StrCmpOptionName(*APre, *BPre))
77 : return N < 0;
78 : }
79 :
80 : // Names are the same, check that classes are in order; exactly one
81 : // should be joined, and it should succeed the other.
82 : assert(((A.Kind == Option::JoinedClass) ^ (B.Kind == Option::JoinedClass)) &&
83 : "Unexpected classes for options with same name.");
84 : return B.Kind == Option::JoinedClass;
85 : }
86 : #endif
87 :
88 : // Support lower_bound between info and an option name.
89 0 : static inline bool operator<(const OptTable::Info &I, const char *Name) {
90 30212043 : return StrCmpOptionNameIgnoreCase(I.Name, Name) < 0;
91 : }
92 :
93 : } // end namespace opt
94 : } // end namespace llvm
95 :
96 414 : OptSpecifier::OptSpecifier(const Option *Opt) : ID(Opt->getID()) {}
97 :
98 91046 : OptTable::OptTable(ArrayRef<Info> OptionInfos, bool IgnoreCase)
99 91046 : : OptionInfos(OptionInfos), IgnoreCase(IgnoreCase) {
100 : // Explicitly zero initialize the error to work around a bug in array
101 : // value-initialization on MinGW with gcc 4.3.5.
102 :
103 : // Find start of normal options.
104 5056700 : for (unsigned i = 0, e = getNumOptions(); i != e; ++i) {
105 5056700 : unsigned Kind = getInfo(i + 1).Kind;
106 5056700 : if (Kind == Option::InputClass) {
107 : assert(!TheInputOptionID && "Cannot have multiple input options!");
108 91046 : TheInputOptionID = getInfo(i + 1).ID;
109 4965654 : } else if (Kind == Option::UnknownClass) {
110 : assert(!TheUnknownOptionID && "Cannot have multiple unknown options!");
111 91046 : TheUnknownOptionID = getInfo(i + 1).ID;
112 4874608 : } else if (Kind != Option::GroupClass) {
113 91046 : FirstSearchableIndex = i;
114 91046 : break;
115 : }
116 : }
117 : assert(FirstSearchableIndex != 0 && "No searchable options?");
118 :
119 : #ifndef NDEBUG
120 : // Check that everything after the first searchable option is a
121 : // regular option class.
122 : for (unsigned i = FirstSearchableIndex, e = getNumOptions(); i != e; ++i) {
123 : Option::OptionClass Kind = (Option::OptionClass) getInfo(i + 1).Kind;
124 : assert((Kind != Option::InputClass && Kind != Option::UnknownClass &&
125 : Kind != Option::GroupClass) &&
126 : "Special options should be defined first!");
127 : }
128 :
129 : // Check that options are in order.
130 : for (unsigned i = FirstSearchableIndex + 1, e = getNumOptions(); i != e; ++i){
131 : if (!(getInfo(i) < getInfo(i + 1))) {
132 : getOption(i).dump();
133 : getOption(i + 1).dump();
134 : llvm_unreachable("Options are not in order!");
135 : }
136 : }
137 : #endif
138 :
139 : // Build prefixes.
140 204085537 : for (unsigned i = FirstSearchableIndex + 1, e = getNumOptions() + 1;
141 204085537 : i != e; ++i) {
142 203994491 : if (const char *const *P = getInfo(i).Prefixes) {
143 430835273 : for (; *P != nullptr; ++P) {
144 : PrefixesUnion.insert(*P);
145 : }
146 : }
147 : }
148 :
149 : // Build prefix chars.
150 91046 : for (StringSet<>::const_iterator I = PrefixesUnion.begin(),
151 362229 : E = PrefixesUnion.end(); I != E; ++I) {
152 : StringRef Prefix = I->getKey();
153 363535 : for (StringRef::const_iterator C = Prefix.begin(), CE = Prefix.end();
154 634718 : C != CE; ++C)
155 363535 : if (!is_contained(PrefixChars, *C))
156 179549 : PrefixChars.push_back(*C);
157 : }
158 91046 : }
159 :
160 : OptTable::~OptTable() = default;
161 :
162 212712545 : const Option OptTable::getOption(OptSpecifier Opt) const {
163 212712545 : unsigned id = Opt.getID();
164 212712545 : if (id == 0)
165 144815523 : return Option(nullptr, nullptr);
166 : assert((unsigned) (id - 1) < getNumOptions() && "Invalid ID.");
167 67897022 : return Option(&getInfo(id), this);
168 : }
169 :
170 5397858 : static bool isInput(const StringSet<> &Prefixes, StringRef Arg) {
171 : if (Arg == "-")
172 : return true;
173 2698800 : for (StringSet<>::const_iterator I = Prefixes.begin(),
174 5501948 : E = Prefixes.end(); I != E; ++I)
175 : if (Arg.startswith(I->getKey()))
176 : return false;
177 : return true;
178 : }
179 :
180 : /// \returns Matched size. 0 means no match.
181 184833015 : static unsigned matchOption(const OptTable::Info *I, StringRef Str,
182 : bool IgnoreCase) {
183 386358896 : for (const char * const *Pre = I->Prefixes; *Pre != nullptr; ++Pre) {
184 : StringRef Prefix(*Pre);
185 : if (Str.startswith(Prefix)) {
186 37365056 : StringRef Rest = Str.substr(Prefix.size());
187 : bool Matched = IgnoreCase
188 74730112 : ? Rest.startswith_lower(I->Name)
189 37170027 : : Rest.startswith(I->Name);
190 195029 : if (Matched)
191 5212196 : return Prefix.size() + StringRef(I->Name).size();
192 : }
193 : }
194 : return 0;
195 : }
196 :
197 : // Returns true if one of the Prefixes + In.Names matches Option
198 0 : static bool optionMatches(const OptTable::Info &In, StringRef Option) {
199 0 : if (In.Prefixes)
200 0 : for (size_t I = 0; In.Prefixes[I]; I++)
201 0 : if (Option == std::string(In.Prefixes[I]) + In.Name)
202 0 : return true;
203 : return false;
204 : }
205 :
206 : // This function is for flag value completion.
207 : // Eg. When "-stdlib=" and "l" was passed to this function, it will return
208 : // appropiriate values for stdlib, which starts with l.
209 : std::vector<std::string>
210 36 : OptTable::suggestValueCompletions(StringRef Option, StringRef Arg) const {
211 : // Search all options and return possible values.
212 61910 : for (size_t I = FirstSearchableIndex, E = OptionInfos.size(); I < E; I++) {
213 61893 : const Info &In = OptionInfos[I];
214 61893 : if (!In.Values || !optionMatches(In, Option))
215 61874 : continue;
216 :
217 : SmallVector<StringRef, 8> Candidates;
218 38 : StringRef(In.Values).split(Candidates, ",", -1, false);
219 :
220 19 : std::vector<std::string> Result;
221 346 : for (StringRef Val : Candidates)
222 291 : if (Val.startswith(Arg) && Arg.compare(Val))
223 291 : Result.push_back(Val);
224 : return Result;
225 : }
226 : return {};
227 : }
228 :
229 : std::vector<std::string>
230 13 : OptTable::findByPrefix(StringRef Cur, unsigned short DisableFlags) const {
231 : std::vector<std::string> Ret;
232 30381 : for (size_t I = FirstSearchableIndex, E = OptionInfos.size(); I < E; I++) {
233 30368 : const Info &In = OptionInfos[I];
234 30368 : if (!In.Prefixes || (!In.HelpText && !In.GroupID))
235 : continue;
236 26351 : if (In.Flags & DisableFlags)
237 : continue;
238 :
239 44397 : for (int I = 0; In.Prefixes[I]; I++) {
240 47506 : std::string S = std::string(In.Prefixes[I]) + std::string(In.Name) + "\t";
241 23753 : if (In.HelpText)
242 : S += In.HelpText;
243 34027 : if (StringRef(S).startswith(Cur) && S.compare(std::string(Cur) + "\t"))
244 5137 : Ret.push_back(S);
245 : }
246 : }
247 13 : return Ret;
248 : }
249 :
250 99 : unsigned OptTable::findNearest(StringRef Option, std::string &NearestString,
251 : unsigned FlagsToInclude, unsigned FlagsToExclude,
252 : unsigned MinimumLength) const {
253 : assert(!Option.empty());
254 :
255 : // Consider each option as a candidate, finding the closest match.
256 : unsigned BestDistance = UINT_MAX;
257 205827 : for (const Info &CandidateInfo :
258 205926 : ArrayRef<Info>(OptionInfos).drop_front(FirstSearchableIndex)) {
259 205827 : StringRef CandidateName = CandidateInfo.Name;
260 :
261 : // Ignore option candidates with empty names, such as "--", or names
262 : // that do not meet the minimum length.
263 205827 : if (CandidateName.empty() || CandidateName.size() < MinimumLength)
264 104282 : continue;
265 :
266 : // If FlagsToInclude were specified, ignore options that don't include
267 : // those flags.
268 185360 : if (FlagsToInclude && !(CandidateInfo.Flags & FlagsToInclude))
269 : continue;
270 : // Ignore options that contain the FlagsToExclude.
271 121620 : if (CandidateInfo.Flags & FlagsToExclude)
272 : continue;
273 :
274 : // Ignore positional argument option candidates (which do not
275 : // have prefixes).
276 101545 : if (!CandidateInfo.Prefixes)
277 : continue;
278 : // Find the most appropriate prefix. For example, if a user asks for
279 : // "--helm", suggest "--help" over "-help".
280 101545 : StringRef Prefix = CandidateInfo.Prefixes[0];
281 105731 : for (int P = 1; CandidateInfo.Prefixes[P]; P++) {
282 : if (Option.startswith(CandidateInfo.Prefixes[P]))
283 2197 : Prefix = CandidateInfo.Prefixes[P];
284 : }
285 :
286 : // Check if the candidate ends with a character commonly used when
287 : // delimiting an option from its value, such as '=' or ':'. If it does,
288 : // attempt to split the given option based on that delimiter.
289 101545 : std::string Delimiter = "";
290 101545 : char Last = CandidateName.back();
291 101545 : if (Last == '=' || Last == ':')
292 27402 : Delimiter = std::string(1, Last);
293 :
294 101545 : StringRef LHS, RHS;
295 101545 : if (Delimiter.empty())
296 87844 : LHS = Option;
297 : else
298 27402 : std::tie(LHS, RHS) = Option.split(Last);
299 :
300 : std::string NormalizedName =
301 101545 : (LHS.drop_front(Prefix.size()) + Delimiter).str();
302 : unsigned Distance =
303 101545 : CandidateName.edit_distance(NormalizedName, /*AllowReplacements=*/true,
304 : /*MaxEditDistance=*/BestDistance);
305 101545 : if (Distance < BestDistance) {
306 : BestDistance = Distance;
307 824 : NearestString = (Prefix + CandidateName + RHS).str();
308 : }
309 : }
310 99 : return BestDistance;
311 : }
312 :
313 260829 : bool OptTable::addValues(const char *Option, const char *Values) {
314 374375512 : for (size_t I = FirstSearchableIndex, E = OptionInfos.size(); I < E; I++) {
315 374375512 : Info &In = OptionInfos[I];
316 374375512 : if (optionMatches(In, Option)) {
317 260829 : In.Values = Values;
318 260829 : return true;
319 : }
320 : }
321 : return false;
322 : }
323 :
324 2698930 : Arg *OptTable::ParseOneArg(const ArgList &Args, unsigned &Index,
325 : unsigned FlagsToInclude,
326 : unsigned FlagsToExclude) const {
327 2698930 : unsigned Prev = Index;
328 2698930 : const char *Str = Args.getArgString(Index);
329 :
330 : // Anything that doesn't start with PrefixesUnion is an input, as is '-'
331 : // itself.
332 2698930 : if (isInput(PrefixesUnion, Str))
333 71619 : return new Arg(getOption(TheInputOptionID), Str, Index++, Str);
334 :
335 2675057 : const Info *Start = OptionInfos.data() + FirstSearchableIndex;
336 2675057 : const Info *End = OptionInfos.data() + OptionInfos.size();
337 2675057 : StringRef Name = StringRef(Str).ltrim(PrefixChars);
338 :
339 : // Search for the first next option which could be a prefix.
340 2675057 : Start = std::lower_bound(Start, End, Name.data());
341 :
342 : // Options are stored in sorted order, with '\0' at the end of the
343 : // alphabet. Since the only options which can accept a string must
344 : // prefix it, we iteratively search for the next option which could
345 : // be a prefix.
346 : //
347 : // FIXME: This is searching much more than necessary, but I am
348 : // blanking on the simplest way to make it fast. We can solve this
349 : // problem when we move to TableGen.
350 2678419 : for (; Start != End; ++Start) {
351 : unsigned ArgSize = 0;
352 : // Scan for first option which is a proper prefix.
353 184905023 : for (; Start != End; ++Start)
354 369665416 : if ((ArgSize = matchOption(Start, Str, IgnoreCase)))
355 : break;
356 2678413 : if (Start == End)
357 : break;
358 :
359 2606098 : Option Opt(Start, this);
360 :
361 2606098 : if (FlagsToInclude && !Opt.hasFlag(FlagsToInclude))
362 1589 : continue;
363 5210472 : if (Opt.hasFlag(FlagsToExclude))
364 : continue;
365 :
366 : // See if this option matches.
367 2604509 : if (Arg *A = Opt.accept(Args, Index, ArgSize))
368 2602736 : return A;
369 :
370 : // Otherwise, see if this argument was missing values.
371 1787 : if (Prev != Index)
372 : return nullptr;
373 : }
374 :
375 : // If we failed to find an option and this arg started with /, then it's
376 : // probably an input path.
377 72321 : if (Str[0] == '/')
378 144358 : return new Arg(getOption(TheInputOptionID), Str, Index++, Str);
379 :
380 284 : return new Arg(getOption(TheUnknownOptionID), Str, Index++, Str);
381 : }
382 :
383 94139 : InputArgList OptTable::ParseArgs(ArrayRef<const char *> ArgArr,
384 : unsigned &MissingArgIndex,
385 : unsigned &MissingArgCount,
386 : unsigned FlagsToInclude,
387 : unsigned FlagsToExclude) const {
388 94139 : InputArgList Args(ArgArr.begin(), ArgArr.end());
389 :
390 : // FIXME: Handle '@' args (or at least error on them).
391 :
392 94139 : MissingArgIndex = MissingArgCount = 0;
393 94139 : unsigned Index = 0, End = ArgArr.size();
394 2793246 : while (Index < End) {
395 : // Ingore nullptrs, they are response file's EOL markers
396 2699118 : if (Args.getArgString(Index) == nullptr) {
397 254 : ++Index;
398 254 : continue;
399 : }
400 : // Ignore empty arguments (other things may still take them as arguments).
401 : StringRef Str = Args.getArgString(Index);
402 : if (Str == "") {
403 32 : ++Index;
404 32 : continue;
405 : }
406 :
407 : unsigned Prev = Index;
408 2698832 : Arg *A = ParseOneArg(Args, Index, FlagsToInclude, FlagsToExclude);
409 : assert(Index > Prev && "Parser failed to consume argument.");
410 :
411 : // Check for missing argument error.
412 2698832 : if (!A) {
413 : assert(Index >= End && "Unexpected parser error.");
414 : assert(Index - Prev - 1 && "No missing arguments!");
415 11 : MissingArgIndex = Prev;
416 11 : MissingArgCount = Index - Prev - 1;
417 : break;
418 : }
419 :
420 2698821 : Args.append(A);
421 : }
422 :
423 94139 : return Args;
424 : }
425 :
426 4015 : static std::string getOptionHelpName(const OptTable &Opts, OptSpecifier Id) {
427 4015 : const Option O = Opts.getOption(Id);
428 4015 : std::string Name = O.getPrefixedName();
429 :
430 : // Add metavar, if used.
431 4015 : switch (O.getKind()) {
432 : case Option::GroupClass: case Option::InputClass: case Option::UnknownClass:
433 : llvm_unreachable("Invalid option with help text.");
434 :
435 2 : case Option::MultiArgClass:
436 2 : if (const char *MetaVarName = Opts.getOptionMetaVar(Id)) {
437 : // For MultiArgs, metavar is full list of all argument names.
438 : Name += ' ';
439 : Name += MetaVarName;
440 : }
441 : else {
442 : // For MultiArgs<N>, if metavar not supplied, print <value> N times.
443 0 : for (unsigned i=0, e=O.getNumArgs(); i< e; ++i) {
444 : Name += " <value>";
445 : }
446 : }
447 : break;
448 :
449 : case Option::FlagClass:
450 : break;
451 :
452 : case Option::ValuesClass:
453 : break;
454 :
455 : case Option::SeparateClass: case Option::JoinedOrSeparateClass:
456 : case Option::RemainingArgsClass: case Option::RemainingArgsJoinedClass:
457 : Name += ' ';
458 : LLVM_FALLTHROUGH;
459 1321 : case Option::JoinedClass: case Option::CommaJoinedClass:
460 : case Option::JoinedAndSeparateClass:
461 1321 : if (const char *MetaVarName = Opts.getOptionMetaVar(Id))
462 : Name += MetaVarName;
463 : else
464 : Name += "<value>";
465 : break;
466 : }
467 :
468 4015 : return Name;
469 : }
470 :
471 : namespace {
472 31557 : struct OptionInfo {
473 : std::string Name;
474 : StringRef HelpText;
475 : };
476 : } // namespace
477 :
478 37 : static void PrintHelpOptionList(raw_ostream &OS, StringRef Title,
479 : std::vector<OptionInfo> &OptionHelp) {
480 37 : OS << Title << ":\n";
481 :
482 : // Find the maximum option length.
483 37 : unsigned OptionFieldWidth = 0;
484 4089 : for (unsigned i = 0, e = OptionHelp.size(); i != e; ++i) {
485 : // Limit the amount of padding we are willing to give up for alignment.
486 4015 : unsigned Length = OptionHelp[i].Name.size();
487 4015 : if (Length <= 23)
488 2961 : OptionFieldWidth = std::max(OptionFieldWidth, Length);
489 : }
490 :
491 : const unsigned InitialPad = 2;
492 4052 : for (unsigned i = 0, e = OptionHelp.size(); i != e; ++i) {
493 4015 : const std::string &Option = OptionHelp[i].Name;
494 4015 : int Pad = OptionFieldWidth - int(Option.size());
495 4015 : OS.indent(InitialPad) << Option;
496 :
497 : // Break on long option names.
498 4015 : if (Pad < 0) {
499 1054 : OS << "\n";
500 1054 : Pad = OptionFieldWidth + InitialPad;
501 : }
502 4015 : OS.indent(Pad + 1) << OptionHelp[i].HelpText << '\n';
503 : }
504 37 : }
505 :
506 8754 : static const char *getOptionHelpGroup(const OptTable &Opts, OptSpecifier Id) {
507 : unsigned GroupID = Opts.getOptionGroupID(Id);
508 :
509 : // If not in a group, return the default help group.
510 8754 : if (!GroupID)
511 : return "OPTIONS";
512 :
513 : // Abuse the help text of the option groups to store the "help group"
514 : // name.
515 : //
516 : // FIXME: Split out option groups.
517 5190 : if (const char *GroupHelp = Opts.getOptionHelpText(GroupID))
518 : return GroupHelp;
519 :
520 : // Otherwise keep looking.
521 4739 : return getOptionHelpGroup(Opts, GroupID);
522 : }
523 :
524 18 : void OptTable::PrintHelp(raw_ostream &OS, const char *Usage, const char *Title,
525 : bool ShowHidden, bool ShowAllAliases) const {
526 36 : PrintHelp(OS, Usage, Title, /*Include*/ 0, /*Exclude*/
527 : (ShowHidden ? 0 : HelpHidden), ShowAllAliases);
528 18 : }
529 :
530 25 : void OptTable::PrintHelp(raw_ostream &OS, const char *Usage, const char *Title,
531 : unsigned FlagsToInclude, unsigned FlagsToExclude,
532 : bool ShowAllAliases) const {
533 25 : OS << "OVERVIEW: " << Title << "\n\n";
534 25 : OS << "USAGE: " << Usage << "\n\n";
535 :
536 : // Render help text into a map of group-name to a list of (option, help)
537 : // pairs.
538 : std::map<std::string, std::vector<OptionInfo>> GroupedOptionHelp;
539 :
540 18182 : for (unsigned Id = 1, e = getNumOptions() + 1; Id != e; ++Id) {
541 : // FIXME: Split out option groups.
542 18157 : if (getOptionKind(Id) == Option::GroupClass)
543 : continue;
544 :
545 17762 : unsigned Flags = getInfo(Id).Flags;
546 17762 : if (FlagsToInclude && !(Flags & FlagsToInclude))
547 : continue;
548 10674 : if (Flags & FlagsToExclude)
549 : continue;
550 :
551 : // If an alias doesn't have a help text, show a help text for the aliased
552 : // option instead.
553 : const char *HelpText = getOptionHelpText(Id);
554 8891 : if (!HelpText && ShowAllAliases) {
555 170 : const Option Alias = getOption(Id).getAlias();
556 170 : if (Alias.isValid())
557 : HelpText = getOptionHelpText(Alias.getID());
558 : }
559 :
560 8891 : if (HelpText) {
561 4015 : const char *HelpGroup = getOptionHelpGroup(*this, Id);
562 4015 : const std::string &OptName = getOptionHelpName(*this, Id);
563 8429 : GroupedOptionHelp[HelpGroup].push_back({OptName, HelpText});
564 : }
565 : }
566 :
567 62 : for (auto& OptionGroup : GroupedOptionHelp) {
568 74 : if (OptionGroup.first != GroupedOptionHelp.begin()->first)
569 12 : OS << "\n";
570 74 : PrintHelpOptionList(OS, OptionGroup.first, OptionGroup.second);
571 : }
572 :
573 : OS.flush();
574 25 : }
|