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/Option/OptTable.h"
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/OptSpecifier.h"
16 #include "llvm/Option/Option.h"
17 #include "llvm/Support/CommandLine.h" // for expandResponseFiles
18 #include "llvm/Support/Compiler.h"
19 #include "llvm/Support/ErrorHandling.h"
20 #include "llvm/Support/raw_ostream.h"
31 using namespace llvm::opt
;
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 static int StrCmpOptionNameIgnoreCase(const char *A
, const char *B
) {
40 const char *X
= A
, *Y
= B
;
41 char a
= tolower(*A
), b
= tolower(*B
);
50 if (a
== '\0') // A is a prefix of B.
52 if (b
== '\0') // B is a prefix of A.
55 // Otherwise lexicographic.
56 return (a
< b
) ? -1 : 1;
60 static int StrCmpOptionName(const char *A
, const char *B
) {
61 if (int N
= StrCmpOptionNameIgnoreCase(A
, B
))
66 static inline bool operator<(const OptTable::Info
&A
, const OptTable::Info
&B
) {
70 if (int N
= StrCmpOptionName(A
.Name
, B
.Name
))
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
))
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
;
88 // Support lower_bound between info and an option name.
89 static inline bool operator<(const OptTable::Info
&I
, const char *Name
) {
90 return StrCmpOptionNameIgnoreCase(I
.Name
, Name
) < 0;
93 } // end namespace opt
94 } // end namespace llvm
96 OptSpecifier::OptSpecifier(const Option
*Opt
) : ID(Opt
->getID()) {}
98 OptTable::OptTable(ArrayRef
<Info
> OptionInfos
, bool IgnoreCase
)
99 : 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.
103 // Find start of normal options.
104 for (unsigned i
= 0, e
= getNumOptions(); i
!= e
; ++i
) {
105 unsigned Kind
= getInfo(i
+ 1).Kind
;
106 if (Kind
== Option::InputClass
) {
107 assert(!TheInputOptionID
&& "Cannot have multiple input options!");
108 TheInputOptionID
= getInfo(i
+ 1).ID
;
109 } else if (Kind
== Option::UnknownClass
) {
110 assert(!TheUnknownOptionID
&& "Cannot have multiple unknown options!");
111 TheUnknownOptionID
= getInfo(i
+ 1).ID
;
112 } else if (Kind
!= Option::GroupClass
) {
113 FirstSearchableIndex
= i
;
117 assert(FirstSearchableIndex
!= 0 && "No searchable options?");
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!");
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))) {
133 getOption(i
+ 1).dump();
134 llvm_unreachable("Options are not in order!");
140 for (unsigned i
= FirstSearchableIndex
+ 1, e
= getNumOptions() + 1;
142 if (const char *const *P
= getInfo(i
).Prefixes
) {
143 for (; *P
!= nullptr; ++P
) {
144 PrefixesUnion
.insert(*P
);
149 // Build prefix chars.
150 for (StringSet
<>::const_iterator I
= PrefixesUnion
.begin(),
151 E
= PrefixesUnion
.end(); I
!= E
; ++I
) {
152 StringRef Prefix
= I
->getKey();
153 for (StringRef::const_iterator C
= Prefix
.begin(), CE
= Prefix
.end();
155 if (!is_contained(PrefixChars
, *C
))
156 PrefixChars
.push_back(*C
);
160 OptTable::~OptTable() = default;
162 const Option
OptTable::getOption(OptSpecifier Opt
) const {
163 unsigned id
= Opt
.getID();
165 return Option(nullptr, nullptr);
166 assert((unsigned) (id
- 1) < getNumOptions() && "Invalid ID.");
167 return Option(&getInfo(id
), this);
170 static bool isInput(const StringSet
<> &Prefixes
, StringRef Arg
) {
173 for (StringSet
<>::const_iterator I
= Prefixes
.begin(),
174 E
= Prefixes
.end(); I
!= E
; ++I
)
175 if (Arg
.startswith(I
->getKey()))
180 /// \returns Matched size. 0 means no match.
181 static unsigned matchOption(const OptTable::Info
*I
, StringRef Str
,
183 for (const char * const *Pre
= I
->Prefixes
; *Pre
!= nullptr; ++Pre
) {
184 StringRef
Prefix(*Pre
);
185 if (Str
.startswith(Prefix
)) {
186 StringRef Rest
= Str
.substr(Prefix
.size());
187 bool Matched
= IgnoreCase
? Rest
.startswith_insensitive(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 StringRef
InName(In
.Name
);
200 for (size_t I
= 0; In
.Prefixes
[I
]; I
++)
201 if (Option
.endswith(InName
))
202 if (Option
.slice(0, Option
.size() - InName
.size()) == In
.Prefixes
[I
])
208 // This function is for flag value completion.
209 // Eg. When "-stdlib=" and "l" was passed to this function, it will return
210 // appropiriate values for stdlib, which starts with l.
211 std::vector
<std::string
>
212 OptTable::suggestValueCompletions(StringRef Option
, StringRef Arg
) const {
213 // Search all options and return possible values.
214 for (size_t I
= FirstSearchableIndex
, E
= OptionInfos
.size(); I
< E
; I
++) {
215 const Info
&In
= OptionInfos
[I
];
216 if (!In
.Values
|| !optionMatches(In
, Option
))
219 SmallVector
<StringRef
, 8> Candidates
;
220 StringRef(In
.Values
).split(Candidates
, ",", -1, false);
222 std::vector
<std::string
> Result
;
223 for (StringRef Val
: Candidates
)
224 if (Val
.startswith(Arg
) && Arg
.compare(Val
))
225 Result
.push_back(std::string(Val
));
231 std::vector
<std::string
>
232 OptTable::findByPrefix(StringRef Cur
, unsigned int DisableFlags
) const {
233 std::vector
<std::string
> Ret
;
234 for (size_t I
= FirstSearchableIndex
, E
= OptionInfos
.size(); I
< E
; I
++) {
235 const Info
&In
= OptionInfos
[I
];
236 if (!In
.Prefixes
|| (!In
.HelpText
&& !In
.GroupID
))
238 if (In
.Flags
& DisableFlags
)
241 for (int I
= 0; In
.Prefixes
[I
]; I
++) {
242 std::string S
= std::string(In
.Prefixes
[I
]) + std::string(In
.Name
) + "\t";
245 if (StringRef(S
).startswith(Cur
) && S
!= std::string(Cur
) + "\t")
252 unsigned OptTable::findNearest(StringRef Option
, std::string
&NearestString
,
253 unsigned FlagsToInclude
, unsigned FlagsToExclude
,
254 unsigned MinimumLength
) const {
255 assert(!Option
.empty());
257 // Consider each [option prefix + option name] pair as a candidate, finding
258 // the closest match.
259 unsigned BestDistance
= UINT_MAX
;
260 for (const Info
&CandidateInfo
:
261 ArrayRef
<Info
>(OptionInfos
).drop_front(FirstSearchableIndex
)) {
262 StringRef CandidateName
= CandidateInfo
.Name
;
264 // We can eliminate some option prefix/name pairs as candidates right away:
265 // * Ignore option candidates with empty names, such as "--", or names
266 // that do not meet the minimum length.
267 if (CandidateName
.empty() || CandidateName
.size() < MinimumLength
)
270 // * If FlagsToInclude were specified, ignore options that don't include
272 if (FlagsToInclude
&& !(CandidateInfo
.Flags
& FlagsToInclude
))
274 // * Ignore options that contain the FlagsToExclude.
275 if (CandidateInfo
.Flags
& FlagsToExclude
)
278 // * Ignore positional argument option candidates (which do not
280 if (!CandidateInfo
.Prefixes
)
283 // Now check if the candidate ends with a character commonly used when
284 // delimiting an option from its value, such as '=' or ':'. If it does,
285 // attempt to split the given option based on that delimiter.
287 char Last
= CandidateName
.back();
288 bool CandidateHasDelimiter
= Last
== '=' || Last
== ':';
289 std::string NormalizedName
= std::string(Option
);
290 if (CandidateHasDelimiter
) {
291 std::tie(LHS
, RHS
) = Option
.split(Last
);
292 NormalizedName
= std::string(LHS
);
293 if (Option
.find(Last
) == LHS
.size())
294 NormalizedName
+= Last
;
297 // Consider each possible prefix for each candidate to find the most
298 // appropriate one. For example, if a user asks for "--helm", suggest
299 // "--help" over "-help".
301 const char *const CandidatePrefix
= CandidateInfo
.Prefixes
[P
]; P
++) {
302 std::string Candidate
= (CandidatePrefix
+ CandidateName
).str();
303 StringRef CandidateRef
= Candidate
;
305 CandidateRef
.edit_distance(NormalizedName
, /*AllowReplacements=*/true,
306 /*MaxEditDistance=*/BestDistance
);
307 if (RHS
.empty() && CandidateHasDelimiter
) {
308 // The Candidate ends with a = or : delimiter, but the option passed in
309 // didn't contain the delimiter (or doesn't have anything after it).
310 // In that case, penalize the correction: `-nodefaultlibs` is more
311 // likely to be a spello for `-nodefaultlib` than `-nodefaultlib:` even
312 // though both have an unmodified editing distance of 1, since the
313 // latter would need an argument.
316 if (Distance
< BestDistance
) {
317 BestDistance
= Distance
;
318 NearestString
= (Candidate
+ RHS
).str();
325 bool OptTable::addValues(const char *Option
, const char *Values
) {
326 for (size_t I
= FirstSearchableIndex
, E
= OptionInfos
.size(); I
< E
; I
++) {
327 Info
&In
= OptionInfos
[I
];
328 if (optionMatches(In
, Option
)) {
336 // Parse a single argument, return the new argument, and update Index. If
337 // GroupedShortOptions is true, -a matches "-abc" and the argument in Args will
338 // be updated to "-bc". This overload does not support
339 // FlagsToInclude/FlagsToExclude or case insensitive options.
340 Arg
*OptTable::parseOneArgGrouped(InputArgList
&Args
, unsigned &Index
) const {
341 // Anything that doesn't start with PrefixesUnion is an input, as is '-'
343 const char *CStr
= Args
.getArgString(Index
);
345 if (isInput(PrefixesUnion
, Str
))
346 return new Arg(getOption(TheInputOptionID
), Str
, Index
++, CStr
);
348 const Info
*End
= OptionInfos
.data() + OptionInfos
.size();
349 StringRef Name
= Str
.ltrim(PrefixChars
);
350 const Info
*Start
= std::lower_bound(
351 OptionInfos
.data() + FirstSearchableIndex
, End
, Name
.data());
352 const Info
*Fallback
= nullptr;
353 unsigned Prev
= Index
;
355 // Search for the option which matches Str.
356 for (; Start
!= End
; ++Start
) {
357 unsigned ArgSize
= matchOption(Start
, Str
, IgnoreCase
);
361 Option
Opt(Start
, this);
362 if (Arg
*A
= Opt
.accept(Args
, StringRef(Args
.getArgString(Index
), ArgSize
),
366 // If Opt is a Flag of length 2 (e.g. "-a"), we know it is a prefix of
367 // the current argument (e.g. "-abc"). Match it as a fallback if no longer
368 // option (e.g. "-ab") exists.
369 if (ArgSize
== 2 && Opt
.getKind() == Option::FlagClass
)
372 // Otherwise, see if the argument is missing.
377 Option
Opt(Fallback
, this);
378 if (Arg
*A
= Opt
.accept(Args
, Str
.substr(0, 2), true, Index
)) {
382 Args
.replaceArgString(Index
, Twine('-') + Str
.substr(2));
387 return new Arg(getOption(TheUnknownOptionID
), Str
, Index
++, CStr
);
390 Arg
*OptTable::ParseOneArg(const ArgList
&Args
, unsigned &Index
,
391 unsigned FlagsToInclude
,
392 unsigned FlagsToExclude
) const {
393 unsigned Prev
= Index
;
394 const char *Str
= Args
.getArgString(Index
);
396 // Anything that doesn't start with PrefixesUnion is an input, as is '-'
398 if (isInput(PrefixesUnion
, Str
))
399 return new Arg(getOption(TheInputOptionID
), Str
, Index
++, Str
);
401 const Info
*Start
= OptionInfos
.data() + FirstSearchableIndex
;
402 const Info
*End
= OptionInfos
.data() + OptionInfos
.size();
403 StringRef Name
= StringRef(Str
).ltrim(PrefixChars
);
405 // Search for the first next option which could be a prefix.
406 Start
= std::lower_bound(Start
, End
, Name
.data());
408 // Options are stored in sorted order, with '\0' at the end of the
409 // alphabet. Since the only options which can accept a string must
410 // prefix it, we iteratively search for the next option which could
413 // FIXME: This is searching much more than necessary, but I am
414 // blanking on the simplest way to make it fast. We can solve this
415 // problem when we move to TableGen.
416 for (; Start
!= End
; ++Start
) {
417 unsigned ArgSize
= 0;
418 // Scan for first option which is a proper prefix.
419 for (; Start
!= End
; ++Start
)
420 if ((ArgSize
= matchOption(Start
, Str
, IgnoreCase
)))
425 Option
Opt(Start
, this);
427 if (FlagsToInclude
&& !Opt
.hasFlag(FlagsToInclude
))
429 if (Opt
.hasFlag(FlagsToExclude
))
432 // See if this option matches.
433 if (Arg
*A
= Opt
.accept(Args
, StringRef(Args
.getArgString(Index
), ArgSize
),
437 // Otherwise, see if this argument was missing values.
442 // If we failed to find an option and this arg started with /, then it's
443 // probably an input path.
445 return new Arg(getOption(TheInputOptionID
), Str
, Index
++, Str
);
447 return new Arg(getOption(TheUnknownOptionID
), Str
, Index
++, Str
);
450 InputArgList
OptTable::ParseArgs(ArrayRef
<const char *> ArgArr
,
451 unsigned &MissingArgIndex
,
452 unsigned &MissingArgCount
,
453 unsigned FlagsToInclude
,
454 unsigned FlagsToExclude
) const {
455 InputArgList
Args(ArgArr
.begin(), ArgArr
.end());
457 // FIXME: Handle '@' args (or at least error on them).
459 MissingArgIndex
= MissingArgCount
= 0;
460 unsigned Index
= 0, End
= ArgArr
.size();
461 while (Index
< End
) {
462 // Ingore nullptrs, they are response file's EOL markers
463 if (Args
.getArgString(Index
) == nullptr) {
467 // Ignore empty arguments (other things may still take them as arguments).
468 StringRef Str
= Args
.getArgString(Index
);
474 unsigned Prev
= Index
;
475 Arg
*A
= GroupedShortOptions
476 ? parseOneArgGrouped(Args
, Index
)
477 : ParseOneArg(Args
, Index
, FlagsToInclude
, FlagsToExclude
);
478 assert((Index
> Prev
|| GroupedShortOptions
) &&
479 "Parser failed to consume argument.");
481 // Check for missing argument error.
483 assert(Index
>= End
&& "Unexpected parser error.");
484 assert(Index
- Prev
- 1 && "No missing arguments!");
485 MissingArgIndex
= Prev
;
486 MissingArgCount
= Index
- Prev
- 1;
496 InputArgList
OptTable::parseArgs(int Argc
, char *const *Argv
,
497 OptSpecifier Unknown
, StringSaver
&Saver
,
498 function_ref
<void(StringRef
)> ErrorFn
) const {
499 SmallVector
<const char *, 0> NewArgv
;
500 // The environment variable specifies initial options which can be overridden
501 // by commnad line options.
502 cl::expandResponseFiles(Argc
, Argv
, EnvVar
, Saver
, NewArgv
);
505 opt::InputArgList Args
= ParseArgs(makeArrayRef(NewArgv
), MAI
, MAC
);
507 ErrorFn((Twine(Args
.getArgString(MAI
)) + ": missing argument").str());
509 // For each unknwon option, call ErrorFn with a formatted error message. The
510 // message includes a suggested alternative option spelling if available.
512 for (const opt::Arg
*A
: Args
.filtered(Unknown
)) {
513 std::string Spelling
= A
->getAsString(Args
);
514 if (findNearest(Spelling
, Nearest
) > 1)
515 ErrorFn("unknown argument '" + A
->getAsString(Args
) + "'");
517 ErrorFn("unknown argument '" + A
->getAsString(Args
) +
518 "', did you mean '" + Nearest
+ "'?");
523 static std::string
getOptionHelpName(const OptTable
&Opts
, OptSpecifier Id
) {
524 const Option O
= Opts
.getOption(Id
);
525 std::string Name
= O
.getPrefixedName();
527 // Add metavar, if used.
528 switch (O
.getKind()) {
529 case Option::GroupClass
: case Option::InputClass
: case Option::UnknownClass
:
530 llvm_unreachable("Invalid option with help text.");
532 case Option::MultiArgClass
:
533 if (const char *MetaVarName
= Opts
.getOptionMetaVar(Id
)) {
534 // For MultiArgs, metavar is full list of all argument names.
539 // For MultiArgs<N>, if metavar not supplied, print <value> N times.
540 for (unsigned i
=0, e
=O
.getNumArgs(); i
< e
; ++i
) {
546 case Option::FlagClass
:
549 case Option::ValuesClass
:
552 case Option::SeparateClass
: case Option::JoinedOrSeparateClass
:
553 case Option::RemainingArgsClass
: case Option::RemainingArgsJoinedClass
:
556 case Option::JoinedClass
: case Option::CommaJoinedClass
:
557 case Option::JoinedAndSeparateClass
:
558 if (const char *MetaVarName
= Opts
.getOptionMetaVar(Id
))
575 static void PrintHelpOptionList(raw_ostream
&OS
, StringRef Title
,
576 std::vector
<OptionInfo
> &OptionHelp
) {
577 OS
<< Title
<< ":\n";
579 // Find the maximum option length.
580 unsigned OptionFieldWidth
= 0;
581 for (unsigned i
= 0, e
= OptionHelp
.size(); i
!= e
; ++i
) {
582 // Limit the amount of padding we are willing to give up for alignment.
583 unsigned Length
= OptionHelp
[i
].Name
.size();
585 OptionFieldWidth
= std::max(OptionFieldWidth
, Length
);
588 const unsigned InitialPad
= 2;
589 for (unsigned i
= 0, e
= OptionHelp
.size(); i
!= e
; ++i
) {
590 const std::string
&Option
= OptionHelp
[i
].Name
;
591 int Pad
= OptionFieldWidth
- int(Option
.size());
592 OS
.indent(InitialPad
) << Option
;
594 // Break on long option names.
597 Pad
= OptionFieldWidth
+ InitialPad
;
599 OS
.indent(Pad
+ 1) << OptionHelp
[i
].HelpText
<< '\n';
603 static const char *getOptionHelpGroup(const OptTable
&Opts
, OptSpecifier Id
) {
604 unsigned GroupID
= Opts
.getOptionGroupID(Id
);
606 // If not in a group, return the default help group.
610 // Abuse the help text of the option groups to store the "help group"
613 // FIXME: Split out option groups.
614 if (const char *GroupHelp
= Opts
.getOptionHelpText(GroupID
))
617 // Otherwise keep looking.
618 return getOptionHelpGroup(Opts
, GroupID
);
621 void OptTable::printHelp(raw_ostream
&OS
, const char *Usage
, const char *Title
,
622 bool ShowHidden
, bool ShowAllAliases
) const {
623 printHelp(OS
, Usage
, Title
, /*Include*/ 0, /*Exclude*/
624 (ShowHidden
? 0 : HelpHidden
), ShowAllAliases
);
627 void OptTable::printHelp(raw_ostream
&OS
, const char *Usage
, const char *Title
,
628 unsigned FlagsToInclude
, unsigned FlagsToExclude
,
629 bool ShowAllAliases
) const {
630 OS
<< "OVERVIEW: " << Title
<< "\n\n";
631 OS
<< "USAGE: " << Usage
<< "\n\n";
633 // Render help text into a map of group-name to a list of (option, help)
635 std::map
<std::string
, std::vector
<OptionInfo
>> GroupedOptionHelp
;
637 for (unsigned Id
= 1, e
= getNumOptions() + 1; Id
!= e
; ++Id
) {
638 // FIXME: Split out option groups.
639 if (getOptionKind(Id
) == Option::GroupClass
)
642 unsigned Flags
= getInfo(Id
).Flags
;
643 if (FlagsToInclude
&& !(Flags
& FlagsToInclude
))
645 if (Flags
& FlagsToExclude
)
648 // If an alias doesn't have a help text, show a help text for the aliased
650 const char *HelpText
= getOptionHelpText(Id
);
651 if (!HelpText
&& ShowAllAliases
) {
652 const Option Alias
= getOption(Id
).getAlias();
654 HelpText
= getOptionHelpText(Alias
.getID());
657 if (HelpText
&& (strlen(HelpText
) != 0)) {
658 const char *HelpGroup
= getOptionHelpGroup(*this, Id
);
659 const std::string
&OptName
= getOptionHelpName(*this, Id
);
660 GroupedOptionHelp
[HelpGroup
].push_back({OptName
, HelpText
});
664 for (auto& OptionGroup
: GroupedOptionHelp
) {
665 if (OptionGroup
.first
!= GroupedOptionHelp
.begin()->first
)
667 PrintHelpOptionList(OS
, OptionGroup
.first
, OptionGroup
.second
);