OptTable.cpp 19 KB

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