1 //===- OptTable.cpp - Option Table Implementation -------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "llvm/ADT/STLExtras.h"
10 #include "llvm/ADT/StringRef.h"
11 #include "llvm/ADT/StringSet.h"
12 #include "llvm/Option/Arg.h"
13 #include "llvm/Option/ArgList.h"
14 #include "llvm/Option/Option.h"
15 #include "llvm/Option/OptSpecifier.h"
16 #include "llvm/Option/OptTable.h"
17 #include "llvm/Support/Compiler.h"
18 #include "llvm/Support/ErrorHandling.h"
19 #include "llvm/Support/raw_ostream.h"
30 using namespace llvm::opt
;
35 // Ordering on Info. The ordering is *almost* case-insensitive lexicographic,
36 // with an exception. '\0' comes at the end of the alphabet instead of the
37 // beginning (thus options precede any other options which prefix them).
38 static int StrCmpOptionNameIgnoreCase(const char *A
, const char *B
) {
39 const char *X
= A
, *Y
= B
;
40 char a
= tolower(*A
), b
= tolower(*B
);
49 if (a
== '\0') // A is a prefix of B.
51 if (b
== '\0') // B is a prefix of A.
54 // Otherwise lexicographic.
55 return (a
< b
) ? -1 : 1;
59 static int StrCmpOptionName(const char *A
, const char *B
) {
60 if (int N
= StrCmpOptionNameIgnoreCase(A
, B
))
65 static inline bool operator<(const OptTable::Info
&A
, const OptTable::Info
&B
) {
69 if (int N
= StrCmpOptionName(A
.Name
, B
.Name
))
72 for (const char * const *APre
= A
.Prefixes
,
73 * const *BPre
= B
.Prefixes
;
74 *APre
!= nullptr && *BPre
!= nullptr; ++APre
, ++BPre
){
75 if (int N
= StrCmpOptionName(*APre
, *BPre
))
79 // Names are the same, check that classes are in order; exactly one
80 // should be joined, and it should succeed the other.
81 assert(((A
.Kind
== Option::JoinedClass
) ^ (B
.Kind
== Option::JoinedClass
)) &&
82 "Unexpected classes for options with same name.");
83 return B
.Kind
== Option::JoinedClass
;
87 // Support lower_bound between info and an option name.
88 static inline bool operator<(const OptTable::Info
&I
, const char *Name
) {
89 return StrCmpOptionNameIgnoreCase(I
.Name
, Name
) < 0;
92 } // end namespace opt
93 } // end namespace llvm
95 OptSpecifier::OptSpecifier(const Option
*Opt
) : ID(Opt
->getID()) {}
97 OptTable::OptTable(ArrayRef
<Info
> OptionInfos
, bool IgnoreCase
)
98 : OptionInfos(OptionInfos
), IgnoreCase(IgnoreCase
) {
99 // Explicitly zero initialize the error to work around a bug in array
100 // value-initialization on MinGW with gcc 4.3.5.
102 // Find start of normal options.
103 for (unsigned i
= 0, e
= getNumOptions(); i
!= e
; ++i
) {
104 unsigned Kind
= getInfo(i
+ 1).Kind
;
105 if (Kind
== Option::InputClass
) {
106 assert(!TheInputOptionID
&& "Cannot have multiple input options!");
107 TheInputOptionID
= getInfo(i
+ 1).ID
;
108 } else if (Kind
== Option::UnknownClass
) {
109 assert(!TheUnknownOptionID
&& "Cannot have multiple unknown options!");
110 TheUnknownOptionID
= getInfo(i
+ 1).ID
;
111 } else if (Kind
!= Option::GroupClass
) {
112 FirstSearchableIndex
= i
;
116 assert(FirstSearchableIndex
!= 0 && "No searchable options?");
119 // Check that everything after the first searchable option is a
120 // regular option class.
121 for (unsigned i
= FirstSearchableIndex
, e
= getNumOptions(); i
!= e
; ++i
) {
122 Option::OptionClass Kind
= (Option::OptionClass
) getInfo(i
+ 1).Kind
;
123 assert((Kind
!= Option::InputClass
&& Kind
!= Option::UnknownClass
&&
124 Kind
!= Option::GroupClass
) &&
125 "Special options should be defined first!");
128 // Check that options are in order.
129 for (unsigned i
= FirstSearchableIndex
+ 1, e
= getNumOptions(); i
!= e
; ++i
){
130 if (!(getInfo(i
) < getInfo(i
+ 1))) {
132 getOption(i
+ 1).dump();
133 llvm_unreachable("Options are not in order!");
139 for (unsigned i
= FirstSearchableIndex
+ 1, e
= getNumOptions() + 1;
141 if (const char *const *P
= getInfo(i
).Prefixes
) {
142 for (; *P
!= nullptr; ++P
) {
143 PrefixesUnion
.insert(*P
);
148 // Build prefix chars.
149 for (StringSet
<>::const_iterator I
= PrefixesUnion
.begin(),
150 E
= PrefixesUnion
.end(); I
!= E
; ++I
) {
151 StringRef Prefix
= I
->getKey();
152 for (StringRef::const_iterator C
= Prefix
.begin(), CE
= Prefix
.end();
154 if (!is_contained(PrefixChars
, *C
))
155 PrefixChars
.push_back(*C
);
159 OptTable::~OptTable() = default;
161 const Option
OptTable::getOption(OptSpecifier Opt
) const {
162 unsigned id
= Opt
.getID();
164 return Option(nullptr, nullptr);
165 assert((unsigned) (id
- 1) < getNumOptions() && "Invalid ID.");
166 return Option(&getInfo(id
), this);
169 static bool isInput(const StringSet
<> &Prefixes
, StringRef Arg
) {
172 for (StringSet
<>::const_iterator I
= Prefixes
.begin(),
173 E
= Prefixes
.end(); I
!= E
; ++I
)
174 if (Arg
.startswith(I
->getKey()))
179 /// \returns Matched size. 0 means no match.
180 static unsigned matchOption(const OptTable::Info
*I
, StringRef Str
,
182 for (const char * const *Pre
= I
->Prefixes
; *Pre
!= nullptr; ++Pre
) {
183 StringRef
Prefix(*Pre
);
184 if (Str
.startswith(Prefix
)) {
185 StringRef Rest
= Str
.substr(Prefix
.size());
186 bool Matched
= IgnoreCase
187 ? Rest
.startswith_lower(I
->Name
)
188 : Rest
.startswith(I
->Name
);
190 return Prefix
.size() + StringRef(I
->Name
).size();
196 // Returns true if one of the Prefixes + In.Names matches Option
197 static bool optionMatches(const OptTable::Info
&In
, StringRef Option
) {
199 for (size_t I
= 0; In
.Prefixes
[I
]; I
++)
200 if (Option
== std::string(In
.Prefixes
[I
]) + In
.Name
)
205 // This function is for flag value completion.
206 // Eg. When "-stdlib=" and "l" was passed to this function, it will return
207 // appropiriate values for stdlib, which starts with l.
208 std::vector
<std::string
>
209 OptTable::suggestValueCompletions(StringRef Option
, StringRef Arg
) const {
210 // Search all options and return possible values.
211 for (size_t I
= FirstSearchableIndex
, E
= OptionInfos
.size(); I
< E
; I
++) {
212 const Info
&In
= OptionInfos
[I
];
213 if (!In
.Values
|| !optionMatches(In
, Option
))
216 SmallVector
<StringRef
, 8> Candidates
;
217 StringRef(In
.Values
).split(Candidates
, ",", -1, false);
219 std::vector
<std::string
> Result
;
220 for (StringRef Val
: Candidates
)
221 if (Val
.startswith(Arg
) && Arg
.compare(Val
))
222 Result
.push_back(Val
);
228 std::vector
<std::string
>
229 OptTable::findByPrefix(StringRef Cur
, unsigned short DisableFlags
) const {
230 std::vector
<std::string
> Ret
;
231 for (size_t I
= FirstSearchableIndex
, E
= OptionInfos
.size(); I
< E
; I
++) {
232 const Info
&In
= OptionInfos
[I
];
233 if (!In
.Prefixes
|| (!In
.HelpText
&& !In
.GroupID
))
235 if (In
.Flags
& DisableFlags
)
238 for (int I
= 0; In
.Prefixes
[I
]; I
++) {
239 std::string S
= std::string(In
.Prefixes
[I
]) + std::string(In
.Name
) + "\t";
242 if (StringRef(S
).startswith(Cur
) && S
.compare(std::string(Cur
) + "\t"))
249 unsigned OptTable::findNearest(StringRef Option
, std::string
&NearestString
,
250 unsigned FlagsToInclude
, unsigned FlagsToExclude
,
251 unsigned MinimumLength
) const {
252 assert(!Option
.empty());
254 // Consider each option as a candidate, finding the closest match.
255 unsigned BestDistance
= UINT_MAX
;
256 for (const Info
&CandidateInfo
:
257 ArrayRef
<Info
>(OptionInfos
).drop_front(FirstSearchableIndex
)) {
258 StringRef CandidateName
= CandidateInfo
.Name
;
260 // Ignore option candidates with empty names, such as "--", or names
261 // that do not meet the minimum length.
262 if (CandidateName
.empty() || CandidateName
.size() < MinimumLength
)
265 // If FlagsToInclude were specified, ignore options that don't include
267 if (FlagsToInclude
&& !(CandidateInfo
.Flags
& FlagsToInclude
))
269 // Ignore options that contain the FlagsToExclude.
270 if (CandidateInfo
.Flags
& FlagsToExclude
)
273 // Ignore positional argument option candidates (which do not
275 if (!CandidateInfo
.Prefixes
)
277 // Find the most appropriate prefix. For example, if a user asks for
278 // "--helm", suggest "--help" over "-help".
279 StringRef Prefix
= CandidateInfo
.Prefixes
[0];
280 for (int P
= 1; CandidateInfo
.Prefixes
[P
]; P
++) {
281 if (Option
.startswith(CandidateInfo
.Prefixes
[P
]))
282 Prefix
= CandidateInfo
.Prefixes
[P
];
285 // Check if the candidate ends with a character commonly used when
286 // delimiting an option from its value, such as '=' or ':'. If it does,
287 // attempt to split the given option based on that delimiter.
288 std::string Delimiter
= "";
289 char Last
= CandidateName
.back();
290 if (Last
== '=' || Last
== ':')
291 Delimiter
= std::string(1, Last
);
294 if (Delimiter
.empty())
297 std::tie(LHS
, RHS
) = Option
.split(Last
);
299 std::string NormalizedName
=
300 (LHS
.drop_front(Prefix
.size()) + Delimiter
).str();
302 CandidateName
.edit_distance(NormalizedName
, /*AllowReplacements=*/true,
303 /*MaxEditDistance=*/BestDistance
);
304 if (Distance
< BestDistance
) {
305 BestDistance
= Distance
;
306 NearestString
= (Prefix
+ CandidateName
+ RHS
).str();
312 bool OptTable::addValues(const char *Option
, const char *Values
) {
313 for (size_t I
= FirstSearchableIndex
, E
= OptionInfos
.size(); I
< E
; I
++) {
314 Info
&In
= OptionInfos
[I
];
315 if (optionMatches(In
, Option
)) {
323 Arg
*OptTable::ParseOneArg(const ArgList
&Args
, unsigned &Index
,
324 unsigned FlagsToInclude
,
325 unsigned FlagsToExclude
) const {
326 unsigned Prev
= Index
;
327 const char *Str
= Args
.getArgString(Index
);
329 // Anything that doesn't start with PrefixesUnion is an input, as is '-'
331 if (isInput(PrefixesUnion
, Str
))
332 return new Arg(getOption(TheInputOptionID
), Str
, Index
++, Str
);
334 const Info
*Start
= OptionInfos
.data() + FirstSearchableIndex
;
335 const Info
*End
= OptionInfos
.data() + OptionInfos
.size();
336 StringRef Name
= StringRef(Str
).ltrim(PrefixChars
);
338 // Search for the first next option which could be a prefix.
339 Start
= std::lower_bound(Start
, End
, Name
.data());
341 // Options are stored in sorted order, with '\0' at the end of the
342 // alphabet. Since the only options which can accept a string must
343 // prefix it, we iteratively search for the next option which could
346 // FIXME: This is searching much more than necessary, but I am
347 // blanking on the simplest way to make it fast. We can solve this
348 // problem when we move to TableGen.
349 for (; Start
!= End
; ++Start
) {
350 unsigned ArgSize
= 0;
351 // Scan for first option which is a proper prefix.
352 for (; Start
!= End
; ++Start
)
353 if ((ArgSize
= matchOption(Start
, Str
, IgnoreCase
)))
358 Option
Opt(Start
, this);
360 if (FlagsToInclude
&& !Opt
.hasFlag(FlagsToInclude
))
362 if (Opt
.hasFlag(FlagsToExclude
))
365 // See if this option matches.
366 if (Arg
*A
= Opt
.accept(Args
, Index
, ArgSize
))
369 // Otherwise, see if this argument was missing values.
374 // If we failed to find an option and this arg started with /, then it's
375 // probably an input path.
377 return new Arg(getOption(TheInputOptionID
), Str
, Index
++, Str
);
379 return new Arg(getOption(TheUnknownOptionID
), Str
, Index
++, Str
);
382 InputArgList
OptTable::ParseArgs(ArrayRef
<const char *> ArgArr
,
383 unsigned &MissingArgIndex
,
384 unsigned &MissingArgCount
,
385 unsigned FlagsToInclude
,
386 unsigned FlagsToExclude
) const {
387 InputArgList
Args(ArgArr
.begin(), ArgArr
.end());
389 // FIXME: Handle '@' args (or at least error on them).
391 MissingArgIndex
= MissingArgCount
= 0;
392 unsigned Index
= 0, End
= ArgArr
.size();
393 while (Index
< End
) {
394 // Ingore nullptrs, they are response file's EOL markers
395 if (Args
.getArgString(Index
) == nullptr) {
399 // Ignore empty arguments (other things may still take them as arguments).
400 StringRef Str
= Args
.getArgString(Index
);
406 unsigned Prev
= Index
;
407 Arg
*A
= ParseOneArg(Args
, Index
, FlagsToInclude
, FlagsToExclude
);
408 assert(Index
> Prev
&& "Parser failed to consume argument.");
410 // Check for missing argument error.
412 assert(Index
>= End
&& "Unexpected parser error.");
413 assert(Index
- Prev
- 1 && "No missing arguments!");
414 MissingArgIndex
= Prev
;
415 MissingArgCount
= Index
- Prev
- 1;
425 static std::string
getOptionHelpName(const OptTable
&Opts
, OptSpecifier Id
) {
426 const Option O
= Opts
.getOption(Id
);
427 std::string Name
= O
.getPrefixedName();
429 // Add metavar, if used.
430 switch (O
.getKind()) {
431 case Option::GroupClass
: case Option::InputClass
: case Option::UnknownClass
:
432 llvm_unreachable("Invalid option with help text.");
434 case Option::MultiArgClass
:
435 if (const char *MetaVarName
= Opts
.getOptionMetaVar(Id
)) {
436 // For MultiArgs, metavar is full list of all argument names.
441 // For MultiArgs<N>, if metavar not supplied, print <value> N times.
442 for (unsigned i
=0, e
=O
.getNumArgs(); i
< e
; ++i
) {
448 case Option::FlagClass
:
451 case Option::ValuesClass
:
454 case Option::SeparateClass
: case Option::JoinedOrSeparateClass
:
455 case Option::RemainingArgsClass
: case Option::RemainingArgsJoinedClass
:
458 case Option::JoinedClass
: case Option::CommaJoinedClass
:
459 case Option::JoinedAndSeparateClass
:
460 if (const char *MetaVarName
= Opts
.getOptionMetaVar(Id
))
477 static void PrintHelpOptionList(raw_ostream
&OS
, StringRef Title
,
478 std::vector
<OptionInfo
> &OptionHelp
) {
479 OS
<< Title
<< ":\n";
481 // Find the maximum option length.
482 unsigned OptionFieldWidth
= 0;
483 for (unsigned i
= 0, e
= OptionHelp
.size(); i
!= e
; ++i
) {
484 // Limit the amount of padding we are willing to give up for alignment.
485 unsigned Length
= OptionHelp
[i
].Name
.size();
487 OptionFieldWidth
= std::max(OptionFieldWidth
, Length
);
490 const unsigned InitialPad
= 2;
491 for (unsigned i
= 0, e
= OptionHelp
.size(); i
!= e
; ++i
) {
492 const std::string
&Option
= OptionHelp
[i
].Name
;
493 int Pad
= OptionFieldWidth
- int(Option
.size());
494 OS
.indent(InitialPad
) << Option
;
496 // Break on long option names.
499 Pad
= OptionFieldWidth
+ InitialPad
;
501 OS
.indent(Pad
+ 1) << OptionHelp
[i
].HelpText
<< '\n';
505 static const char *getOptionHelpGroup(const OptTable
&Opts
, OptSpecifier Id
) {
506 unsigned GroupID
= Opts
.getOptionGroupID(Id
);
508 // If not in a group, return the default help group.
512 // Abuse the help text of the option groups to store the "help group"
515 // FIXME: Split out option groups.
516 if (const char *GroupHelp
= Opts
.getOptionHelpText(GroupID
))
519 // Otherwise keep looking.
520 return getOptionHelpGroup(Opts
, GroupID
);
523 void OptTable::PrintHelp(raw_ostream
&OS
, const char *Usage
, const char *Title
,
524 bool ShowHidden
, bool ShowAllAliases
) const {
525 PrintHelp(OS
, Usage
, Title
, /*Include*/ 0, /*Exclude*/
526 (ShowHidden
? 0 : HelpHidden
), ShowAllAliases
);
529 void OptTable::PrintHelp(raw_ostream
&OS
, const char *Usage
, const char *Title
,
530 unsigned FlagsToInclude
, unsigned FlagsToExclude
,
531 bool ShowAllAliases
) const {
532 OS
<< "OVERVIEW: " << Title
<< "\n\n";
533 OS
<< "USAGE: " << Usage
<< "\n\n";
535 // Render help text into a map of group-name to a list of (option, help)
537 std::map
<std::string
, std::vector
<OptionInfo
>> GroupedOptionHelp
;
539 for (unsigned Id
= 1, e
= getNumOptions() + 1; Id
!= e
; ++Id
) {
540 // FIXME: Split out option groups.
541 if (getOptionKind(Id
) == Option::GroupClass
)
544 unsigned Flags
= getInfo(Id
).Flags
;
545 if (FlagsToInclude
&& !(Flags
& FlagsToInclude
))
547 if (Flags
& FlagsToExclude
)
550 // If an alias doesn't have a help text, show a help text for the aliased
552 const char *HelpText
= getOptionHelpText(Id
);
553 if (!HelpText
&& ShowAllAliases
) {
554 const Option Alias
= getOption(Id
).getAlias();
556 HelpText
= getOptionHelpText(Alias
.getID());
560 const char *HelpGroup
= getOptionHelpGroup(*this, Id
);
561 const std::string
&OptName
= getOptionHelpName(*this, Id
);
562 GroupedOptionHelp
[HelpGroup
].push_back({OptName
, HelpText
});
566 for (auto& OptionGroup
: GroupedOptionHelp
) {
567 if (OptionGroup
.first
!= GroupedOptionHelp
.begin()->first
)
569 PrintHelpOptionList(OS
, OptionGroup
.first
, OptionGroup
.second
);