1 | //===-- CommandLine.cpp - Command line parser 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 | // |
9 | // This class implements a command line argument processor that is useful when |
10 | // creating a tool. It provides a simple, minimalistic interface that is easily |
11 | // extensible and supports nonlocal (library) command line options. |
12 | // |
13 | // Note that rather than trying to figure out what this code does, you could try |
14 | // reading the library documentation located in docs/CommandLine.html |
15 | // |
16 | //===----------------------------------------------------------------------===// |
17 | |
18 | #include "llvm/Support/CommandLine.h" |
19 | |
20 | #include "DebugOptions.h" |
21 | |
22 | #include "llvm-c/Support.h" |
23 | #include "llvm/ADT/ArrayRef.h" |
24 | #include "llvm/ADT/STLFunctionalExtras.h" |
25 | #include "llvm/ADT/SmallPtrSet.h" |
26 | #include "llvm/ADT/SmallString.h" |
27 | #include "llvm/ADT/StringExtras.h" |
28 | #include "llvm/ADT/StringMap.h" |
29 | #include "llvm/ADT/StringRef.h" |
30 | #include "llvm/ADT/Twine.h" |
31 | #include "llvm/Config/config.h" |
32 | #include "llvm/Support/Compiler.h" |
33 | #include "llvm/Support/ConvertUTF.h" |
34 | #include "llvm/Support/Debug.h" |
35 | #include "llvm/Support/Error.h" |
36 | #include "llvm/Support/ErrorHandling.h" |
37 | #include "llvm/Support/FileSystem.h" |
38 | #include "llvm/Support/ManagedStatic.h" |
39 | #include "llvm/Support/MemoryBuffer.h" |
40 | #include "llvm/Support/Path.h" |
41 | #include "llvm/Support/Process.h" |
42 | #include "llvm/Support/StringSaver.h" |
43 | #include "llvm/Support/VirtualFileSystem.h" |
44 | #include "llvm/Support/raw_ostream.h" |
45 | #include <cstdlib> |
46 | #include <optional> |
47 | #include <string> |
48 | using namespace llvm; |
49 | using namespace cl; |
50 | |
51 | #define DEBUG_TYPE "commandline" |
52 | |
53 | //===----------------------------------------------------------------------===// |
54 | // Template instantiations and anchors. |
55 | // |
56 | namespace llvm { |
57 | namespace cl { |
58 | template class LLVM_EXPORT_TEMPLATE basic_parser<bool>; |
59 | template class LLVM_EXPORT_TEMPLATE basic_parser<boolOrDefault>; |
60 | template class LLVM_EXPORT_TEMPLATE basic_parser<int>; |
61 | template class LLVM_EXPORT_TEMPLATE basic_parser<long>; |
62 | template class LLVM_EXPORT_TEMPLATE basic_parser<long long>; |
63 | template class LLVM_EXPORT_TEMPLATE basic_parser<unsigned>; |
64 | template class LLVM_EXPORT_TEMPLATE basic_parser<unsigned long>; |
65 | template class LLVM_EXPORT_TEMPLATE basic_parser<unsigned long long>; |
66 | template class LLVM_EXPORT_TEMPLATE basic_parser<double>; |
67 | template class LLVM_EXPORT_TEMPLATE basic_parser<float>; |
68 | template class LLVM_EXPORT_TEMPLATE basic_parser<std::string>; |
69 | template class LLVM_EXPORT_TEMPLATE basic_parser<char>; |
70 | |
71 | template class opt<unsigned>; |
72 | template class opt<int>; |
73 | template class opt<std::string>; |
74 | template class opt<char>; |
75 | template class opt<bool>; |
76 | } // namespace cl |
77 | } // namespace llvm |
78 | |
79 | // Pin the vtables to this file. |
80 | void GenericOptionValue::anchor() {} |
81 | void OptionValue<boolOrDefault>::anchor() {} |
82 | void OptionValue<std::string>::anchor() {} |
83 | void Option::anchor() {} |
84 | void basic_parser_impl::anchor() {} |
85 | void parser<bool>::anchor() {} |
86 | void parser<boolOrDefault>::anchor() {} |
87 | void parser<int>::anchor() {} |
88 | void parser<long>::anchor() {} |
89 | void parser<long long>::anchor() {} |
90 | void parser<unsigned>::anchor() {} |
91 | void parser<unsigned long>::anchor() {} |
92 | void parser<unsigned long long>::anchor() {} |
93 | void parser<double>::anchor() {} |
94 | void parser<float>::anchor() {} |
95 | void parser<std::string>::anchor() {} |
96 | void parser<char>::anchor() {} |
97 | |
98 | //===----------------------------------------------------------------------===// |
99 | |
100 | const static size_t DefaultPad = 2; |
101 | |
102 | static StringRef ArgPrefix = "-" ; |
103 | static StringRef ArgPrefixLong = "--" ; |
104 | static StringRef ArgHelpPrefix = " - " ; |
105 | |
106 | static size_t argPlusPrefixesSize(StringRef ArgName, size_t Pad = DefaultPad) { |
107 | size_t Len = ArgName.size(); |
108 | if (Len == 1) |
109 | return Len + Pad + ArgPrefix.size() + ArgHelpPrefix.size(); |
110 | return Len + Pad + ArgPrefixLong.size() + ArgHelpPrefix.size(); |
111 | } |
112 | |
113 | static SmallString<8> argPrefix(StringRef ArgName, size_t Pad = DefaultPad) { |
114 | SmallString<8> Prefix; |
115 | for (size_t I = 0; I < Pad; ++I) { |
116 | Prefix.push_back(Elt: ' '); |
117 | } |
118 | Prefix.append(RHS: ArgName.size() > 1 ? ArgPrefixLong : ArgPrefix); |
119 | return Prefix; |
120 | } |
121 | |
122 | // Option predicates... |
123 | static inline bool isGrouping(const Option *O) { |
124 | return O->getMiscFlags() & cl::Grouping; |
125 | } |
126 | static inline bool isPrefixedOrGrouping(const Option *O) { |
127 | return isGrouping(O) || O->getFormattingFlag() == cl::Prefix || |
128 | O->getFormattingFlag() == cl::AlwaysPrefix; |
129 | } |
130 | |
131 | |
132 | namespace { |
133 | |
134 | class PrintArg { |
135 | StringRef ArgName; |
136 | size_t Pad; |
137 | public: |
138 | PrintArg(StringRef ArgName, size_t Pad = DefaultPad) : ArgName(ArgName), Pad(Pad) {} |
139 | friend raw_ostream &operator<<(raw_ostream &OS, const PrintArg &); |
140 | }; |
141 | |
142 | raw_ostream &operator<<(raw_ostream &OS, const PrintArg& Arg) { |
143 | OS << argPrefix(ArgName: Arg.ArgName, Pad: Arg.Pad) << Arg.ArgName; |
144 | return OS; |
145 | } |
146 | |
147 | class CommandLineParser { |
148 | public: |
149 | // Globals for name and overview of program. Program name is not a string to |
150 | // avoid static ctor/dtor issues. |
151 | std::string ProgramName; |
152 | StringRef ProgramOverview; |
153 | |
154 | // This collects additional help to be printed. |
155 | std::vector<StringRef> MoreHelp; |
156 | |
157 | // This collects Options added with the cl::DefaultOption flag. Since they can |
158 | // be overridden, they are not added to the appropriate SubCommands until |
159 | // ParseCommandLineOptions actually runs. |
160 | SmallVector<Option*, 4> DefaultOptions; |
161 | |
162 | // This collects the different option categories that have been registered. |
163 | SmallPtrSet<OptionCategory *, 16> RegisteredOptionCategories; |
164 | |
165 | // This collects the different subcommands that have been registered. |
166 | SmallPtrSet<SubCommand *, 4> RegisteredSubCommands; |
167 | |
168 | CommandLineParser() { registerSubCommand(sub: &SubCommand::getTopLevel()); } |
169 | |
170 | void ResetAllOptionOccurrences(); |
171 | |
172 | bool ParseCommandLineOptions(int argc, const char *const *argv, |
173 | StringRef Overview, raw_ostream *Errs = nullptr, |
174 | bool LongOptionsUseDoubleDash = false); |
175 | |
176 | void forEachSubCommand(Option &Opt, function_ref<void(SubCommand &)> Action) { |
177 | if (Opt.Subs.empty()) { |
178 | Action(SubCommand::getTopLevel()); |
179 | return; |
180 | } |
181 | if (Opt.Subs.size() == 1 && *Opt.Subs.begin() == &SubCommand::getAll()) { |
182 | for (auto *SC : RegisteredSubCommands) |
183 | Action(*SC); |
184 | Action(SubCommand::getAll()); |
185 | return; |
186 | } |
187 | for (auto *SC : Opt.Subs) { |
188 | assert(SC != &SubCommand::getAll() && |
189 | "SubCommand::getAll() should not be used with other subcommands" ); |
190 | Action(*SC); |
191 | } |
192 | } |
193 | |
194 | void addLiteralOption(Option &Opt, SubCommand *SC, StringRef Name) { |
195 | if (Opt.hasArgStr()) |
196 | return; |
197 | if (!SC->OptionsMap.insert(KV: std::make_pair(x&: Name, y: &Opt)).second) { |
198 | errs() << ProgramName << ": CommandLine Error: Option '" << Name |
199 | << "' registered more than once!\n" ; |
200 | report_fatal_error(reason: "inconsistency in registered CommandLine options" ); |
201 | } |
202 | } |
203 | |
204 | void addLiteralOption(Option &Opt, StringRef Name) { |
205 | forEachSubCommand( |
206 | Opt, Action: [&](SubCommand &SC) { addLiteralOption(Opt, SC: &SC, Name); }); |
207 | } |
208 | |
209 | void addOption(Option *O, SubCommand *SC) { |
210 | bool HadErrors = false; |
211 | if (O->hasArgStr()) { |
212 | // If it's a DefaultOption, check to make sure it isn't already there. |
213 | if (O->isDefaultOption() && SC->OptionsMap.contains(Key: O->ArgStr)) |
214 | return; |
215 | |
216 | // Add argument to the argument map! |
217 | if (!SC->OptionsMap.insert(KV: std::make_pair(x&: O->ArgStr, y&: O)).second) { |
218 | errs() << ProgramName << ": CommandLine Error: Option '" << O->ArgStr |
219 | << "' registered more than once!\n" ; |
220 | HadErrors = true; |
221 | } |
222 | } |
223 | |
224 | // Remember information about positional options. |
225 | if (O->getFormattingFlag() == cl::Positional) |
226 | SC->PositionalOpts.push_back(Elt: O); |
227 | else if (O->getMiscFlags() & cl::Sink) // Remember sink options |
228 | SC->SinkOpts.push_back(Elt: O); |
229 | else if (O->getNumOccurrencesFlag() == cl::ConsumeAfter) { |
230 | if (SC->ConsumeAfterOpt) { |
231 | O->error(Message: "Cannot specify more than one option with cl::ConsumeAfter!" ); |
232 | HadErrors = true; |
233 | } |
234 | SC->ConsumeAfterOpt = O; |
235 | } |
236 | |
237 | // Fail hard if there were errors. These are strictly unrecoverable and |
238 | // indicate serious issues such as conflicting option names or an |
239 | // incorrectly |
240 | // linked LLVM distribution. |
241 | if (HadErrors) |
242 | report_fatal_error(reason: "inconsistency in registered CommandLine options" ); |
243 | } |
244 | |
245 | void addOption(Option *O, bool ProcessDefaultOption = false) { |
246 | if (!ProcessDefaultOption && O->isDefaultOption()) { |
247 | DefaultOptions.push_back(Elt: O); |
248 | return; |
249 | } |
250 | forEachSubCommand(Opt&: *O, Action: [&](SubCommand &SC) { addOption(O, SC: &SC); }); |
251 | } |
252 | |
253 | void removeOption(Option *O, SubCommand *SC) { |
254 | SmallVector<StringRef, 16> OptionNames; |
255 | O->getExtraOptionNames(OptionNames); |
256 | if (O->hasArgStr()) |
257 | OptionNames.push_back(Elt: O->ArgStr); |
258 | |
259 | SubCommand &Sub = *SC; |
260 | auto End = Sub.OptionsMap.end(); |
261 | for (auto Name : OptionNames) { |
262 | auto I = Sub.OptionsMap.find(Key: Name); |
263 | if (I != End && I->getValue() == O) |
264 | Sub.OptionsMap.erase(I); |
265 | } |
266 | |
267 | if (O->getFormattingFlag() == cl::Positional) |
268 | for (auto *Opt = Sub.PositionalOpts.begin(); |
269 | Opt != Sub.PositionalOpts.end(); ++Opt) { |
270 | if (*Opt == O) { |
271 | Sub.PositionalOpts.erase(CI: Opt); |
272 | break; |
273 | } |
274 | } |
275 | else if (O->getMiscFlags() & cl::Sink) |
276 | for (auto *Opt = Sub.SinkOpts.begin(); Opt != Sub.SinkOpts.end(); ++Opt) { |
277 | if (*Opt == O) { |
278 | Sub.SinkOpts.erase(CI: Opt); |
279 | break; |
280 | } |
281 | } |
282 | else if (O == Sub.ConsumeAfterOpt) |
283 | Sub.ConsumeAfterOpt = nullptr; |
284 | } |
285 | |
286 | void removeOption(Option *O) { |
287 | forEachSubCommand(Opt&: *O, Action: [&](SubCommand &SC) { removeOption(O, SC: &SC); }); |
288 | } |
289 | |
290 | bool hasOptions(const SubCommand &Sub) const { |
291 | return (!Sub.OptionsMap.empty() || !Sub.PositionalOpts.empty() || |
292 | nullptr != Sub.ConsumeAfterOpt); |
293 | } |
294 | |
295 | bool hasOptions() const { |
296 | for (const auto *S : RegisteredSubCommands) { |
297 | if (hasOptions(Sub: *S)) |
298 | return true; |
299 | } |
300 | return false; |
301 | } |
302 | |
303 | bool hasNamedSubCommands() const { |
304 | for (const auto *S : RegisteredSubCommands) |
305 | if (!S->getName().empty()) |
306 | return true; |
307 | return false; |
308 | } |
309 | |
310 | SubCommand *getActiveSubCommand() { return ActiveSubCommand; } |
311 | |
312 | void updateArgStr(Option *O, StringRef NewName, SubCommand *SC) { |
313 | SubCommand &Sub = *SC; |
314 | if (!Sub.OptionsMap.insert(KV: std::make_pair(x&: NewName, y&: O)).second) { |
315 | errs() << ProgramName << ": CommandLine Error: Option '" << O->ArgStr |
316 | << "' registered more than once!\n" ; |
317 | report_fatal_error(reason: "inconsistency in registered CommandLine options" ); |
318 | } |
319 | Sub.OptionsMap.erase(Key: O->ArgStr); |
320 | } |
321 | |
322 | void updateArgStr(Option *O, StringRef NewName) { |
323 | forEachSubCommand(Opt&: *O, |
324 | Action: [&](SubCommand &SC) { updateArgStr(O, NewName, SC: &SC); }); |
325 | } |
326 | |
327 | void printOptionValues(); |
328 | |
329 | void registerCategory(OptionCategory *cat) { |
330 | assert(count_if(RegisteredOptionCategories, |
331 | [cat](const OptionCategory *Category) { |
332 | return cat->getName() == Category->getName(); |
333 | }) == 0 && |
334 | "Duplicate option categories" ); |
335 | |
336 | RegisteredOptionCategories.insert(Ptr: cat); |
337 | } |
338 | |
339 | void registerSubCommand(SubCommand *sub) { |
340 | assert(count_if(RegisteredSubCommands, |
341 | [sub](const SubCommand *Sub) { |
342 | return (!sub->getName().empty()) && |
343 | (Sub->getName() == sub->getName()); |
344 | }) == 0 && |
345 | "Duplicate subcommands" ); |
346 | RegisteredSubCommands.insert(Ptr: sub); |
347 | |
348 | // For all options that have been registered for all subcommands, add the |
349 | // option to this subcommand now. |
350 | assert(sub != &SubCommand::getAll() && |
351 | "SubCommand::getAll() should not be registered" ); |
352 | for (auto &E : SubCommand::getAll().OptionsMap) { |
353 | Option *O = E.second; |
354 | if ((O->isPositional() || O->isSink() || O->isConsumeAfter()) || |
355 | O->hasArgStr()) |
356 | addOption(O, SC: sub); |
357 | else |
358 | addLiteralOption(Opt&: *O, SC: sub, Name: E.first()); |
359 | } |
360 | } |
361 | |
362 | void unregisterSubCommand(SubCommand *sub) { |
363 | RegisteredSubCommands.erase(Ptr: sub); |
364 | } |
365 | |
366 | iterator_range<typename SmallPtrSet<SubCommand *, 4>::iterator> |
367 | getRegisteredSubcommands() { |
368 | return make_range(x: RegisteredSubCommands.begin(), |
369 | y: RegisteredSubCommands.end()); |
370 | } |
371 | |
372 | void reset() { |
373 | ActiveSubCommand = nullptr; |
374 | ProgramName.clear(); |
375 | ProgramOverview = StringRef(); |
376 | |
377 | MoreHelp.clear(); |
378 | RegisteredOptionCategories.clear(); |
379 | |
380 | ResetAllOptionOccurrences(); |
381 | RegisteredSubCommands.clear(); |
382 | |
383 | SubCommand::getTopLevel().reset(); |
384 | SubCommand::getAll().reset(); |
385 | registerSubCommand(sub: &SubCommand::getTopLevel()); |
386 | |
387 | DefaultOptions.clear(); |
388 | } |
389 | |
390 | private: |
391 | SubCommand *ActiveSubCommand = nullptr; |
392 | |
393 | Option *LookupOption(SubCommand &Sub, StringRef &Arg, StringRef &Value); |
394 | Option *LookupLongOption(SubCommand &Sub, StringRef &Arg, StringRef &Value, |
395 | bool LongOptionsUseDoubleDash, bool HaveDoubleDash) { |
396 | Option *Opt = LookupOption(Sub, Arg, Value); |
397 | if (Opt && LongOptionsUseDoubleDash && !HaveDoubleDash && !isGrouping(O: Opt)) |
398 | return nullptr; |
399 | return Opt; |
400 | } |
401 | SubCommand *LookupSubCommand(StringRef Name, std::string &NearestString); |
402 | }; |
403 | |
404 | } // namespace |
405 | |
406 | static ManagedStatic<CommandLineParser> GlobalParser; |
407 | |
408 | template <typename T, T TrueVal, T FalseVal> |
409 | static bool parseBool(Option &O, StringRef ArgName, StringRef Arg, T &Value) { |
410 | if (Arg == "" || Arg == "true" || Arg == "TRUE" || Arg == "True" || |
411 | Arg == "1" ) { |
412 | Value = TrueVal; |
413 | return false; |
414 | } |
415 | |
416 | if (Arg == "false" || Arg == "FALSE" || Arg == "False" || Arg == "0" ) { |
417 | Value = FalseVal; |
418 | return false; |
419 | } |
420 | return O.error(Message: "'" + Arg + |
421 | "' is invalid value for boolean argument! Try 0 or 1" ); |
422 | } |
423 | |
424 | void cl::AddLiteralOption(Option &O, StringRef Name) { |
425 | GlobalParser->addLiteralOption(Opt&: O, Name); |
426 | } |
427 | |
428 | extrahelp::(StringRef Help) : morehelp(Help) { |
429 | GlobalParser->MoreHelp.push_back(x: Help); |
430 | } |
431 | |
432 | void Option::addArgument() { |
433 | GlobalParser->addOption(O: this); |
434 | FullyInitialized = true; |
435 | } |
436 | |
437 | void Option::removeArgument() { GlobalParser->removeOption(O: this); } |
438 | |
439 | void Option::setArgStr(StringRef S) { |
440 | if (FullyInitialized) |
441 | GlobalParser->updateArgStr(O: this, NewName: S); |
442 | assert(!S.starts_with("-" ) && "Option can't start with '-" ); |
443 | ArgStr = S; |
444 | if (ArgStr.size() == 1) |
445 | setMiscFlag(Grouping); |
446 | } |
447 | |
448 | void Option::addCategory(OptionCategory &C) { |
449 | assert(!Categories.empty() && "Categories cannot be empty." ); |
450 | // Maintain backward compatibility by replacing the default GeneralCategory |
451 | // if it's still set. Otherwise, just add the new one. The GeneralCategory |
452 | // must be explicitly added if you want multiple categories that include it. |
453 | if (&C != &getGeneralCategory() && Categories[0] == &getGeneralCategory()) |
454 | Categories[0] = &C; |
455 | else if (!is_contained(Range&: Categories, Element: &C)) |
456 | Categories.push_back(Elt: &C); |
457 | } |
458 | |
459 | void Option::reset() { |
460 | NumOccurrences = 0; |
461 | setDefault(); |
462 | if (isDefaultOption()) |
463 | removeArgument(); |
464 | } |
465 | |
466 | void OptionCategory::registerCategory() { |
467 | GlobalParser->registerCategory(cat: this); |
468 | } |
469 | |
470 | // A special subcommand representing no subcommand. It is particularly important |
471 | // that this ManagedStatic uses constant initailization and not dynamic |
472 | // initialization because it is referenced from cl::opt constructors, which run |
473 | // dynamically in an arbitrary order. |
474 | LLVM_REQUIRE_CONSTANT_INITIALIZATION |
475 | static ManagedStatic<SubCommand> TopLevelSubCommand; |
476 | |
477 | // A special subcommand that can be used to put an option into all subcommands. |
478 | static ManagedStatic<SubCommand> AllSubCommands; |
479 | |
480 | SubCommand &SubCommand::getTopLevel() { return *TopLevelSubCommand; } |
481 | |
482 | SubCommand &SubCommand::getAll() { return *AllSubCommands; } |
483 | |
484 | void SubCommand::registerSubCommand() { |
485 | GlobalParser->registerSubCommand(sub: this); |
486 | } |
487 | |
488 | void SubCommand::unregisterSubCommand() { |
489 | GlobalParser->unregisterSubCommand(sub: this); |
490 | } |
491 | |
492 | void SubCommand::reset() { |
493 | PositionalOpts.clear(); |
494 | SinkOpts.clear(); |
495 | OptionsMap.clear(); |
496 | |
497 | ConsumeAfterOpt = nullptr; |
498 | } |
499 | |
500 | SubCommand::operator bool() const { |
501 | return (GlobalParser->getActiveSubCommand() == this); |
502 | } |
503 | |
504 | //===----------------------------------------------------------------------===// |
505 | // Basic, shared command line option processing machinery. |
506 | // |
507 | |
508 | /// LookupOption - Lookup the option specified by the specified option on the |
509 | /// command line. If there is a value specified (after an equal sign) return |
510 | /// that as well. This assumes that leading dashes have already been stripped. |
511 | Option *CommandLineParser::LookupOption(SubCommand &Sub, StringRef &Arg, |
512 | StringRef &Value) { |
513 | // Reject all dashes. |
514 | if (Arg.empty()) |
515 | return nullptr; |
516 | assert(&Sub != &SubCommand::getAll()); |
517 | |
518 | size_t EqualPos = Arg.find(C: '='); |
519 | |
520 | // If we have an equals sign, remember the value. |
521 | if (EqualPos == StringRef::npos) { |
522 | // Look up the option. |
523 | return Sub.OptionsMap.lookup(Key: Arg); |
524 | } |
525 | |
526 | // If the argument before the = is a valid option name and the option allows |
527 | // non-prefix form (ie is not AlwaysPrefix), we match. If not, signal match |
528 | // failure by returning nullptr. |
529 | auto I = Sub.OptionsMap.find(Key: Arg.substr(Start: 0, N: EqualPos)); |
530 | if (I == Sub.OptionsMap.end()) |
531 | return nullptr; |
532 | |
533 | auto *O = I->second; |
534 | if (O->getFormattingFlag() == cl::AlwaysPrefix) |
535 | return nullptr; |
536 | |
537 | Value = Arg.substr(Start: EqualPos + 1); |
538 | Arg = Arg.substr(Start: 0, N: EqualPos); |
539 | return I->second; |
540 | } |
541 | |
542 | SubCommand *CommandLineParser::LookupSubCommand(StringRef Name, |
543 | std::string &NearestString) { |
544 | if (Name.empty()) |
545 | return &SubCommand::getTopLevel(); |
546 | // Find a subcommand with the edit distance == 1. |
547 | SubCommand *NearestMatch = nullptr; |
548 | for (auto *S : RegisteredSubCommands) { |
549 | assert(S != &SubCommand::getAll() && |
550 | "SubCommand::getAll() is not expected in RegisteredSubCommands" ); |
551 | if (S->getName().empty()) |
552 | continue; |
553 | |
554 | if (S->getName() == Name) |
555 | return S; |
556 | |
557 | if (!NearestMatch && S->getName().edit_distance(Other: Name) < 2) |
558 | NearestMatch = S; |
559 | } |
560 | |
561 | if (NearestMatch) |
562 | NearestString = NearestMatch->getName(); |
563 | |
564 | return &SubCommand::getTopLevel(); |
565 | } |
566 | |
567 | /// LookupNearestOption - Lookup the closest match to the option specified by |
568 | /// the specified option on the command line. If there is a value specified |
569 | /// (after an equal sign) return that as well. This assumes that leading dashes |
570 | /// have already been stripped. |
571 | static Option *LookupNearestOption(StringRef Arg, |
572 | const StringMap<Option *> &OptionsMap, |
573 | std::string &NearestString) { |
574 | // Reject all dashes. |
575 | if (Arg.empty()) |
576 | return nullptr; |
577 | |
578 | // Split on any equal sign. |
579 | std::pair<StringRef, StringRef> SplitArg = Arg.split(Separator: '='); |
580 | StringRef &LHS = SplitArg.first; // LHS == Arg when no '=' is present. |
581 | StringRef &RHS = SplitArg.second; |
582 | |
583 | // Find the closest match. |
584 | Option *Best = nullptr; |
585 | unsigned BestDistance = 0; |
586 | for (StringMap<Option *>::const_iterator it = OptionsMap.begin(), |
587 | ie = OptionsMap.end(); |
588 | it != ie; ++it) { |
589 | Option *O = it->second; |
590 | // Do not suggest really hidden options (not shown in any help). |
591 | if (O->getOptionHiddenFlag() == ReallyHidden) |
592 | continue; |
593 | |
594 | SmallVector<StringRef, 16> OptionNames; |
595 | O->getExtraOptionNames(OptionNames); |
596 | if (O->hasArgStr()) |
597 | OptionNames.push_back(Elt: O->ArgStr); |
598 | |
599 | bool PermitValue = O->getValueExpectedFlag() != cl::ValueDisallowed; |
600 | StringRef Flag = PermitValue ? LHS : Arg; |
601 | for (const auto &Name : OptionNames) { |
602 | unsigned Distance = StringRef(Name).edit_distance( |
603 | Other: Flag, /*AllowReplacements=*/true, /*MaxEditDistance=*/BestDistance); |
604 | if (!Best || Distance < BestDistance) { |
605 | Best = O; |
606 | BestDistance = Distance; |
607 | if (RHS.empty() || !PermitValue) |
608 | NearestString = std::string(Name); |
609 | else |
610 | NearestString = (Twine(Name) + "=" + RHS).str(); |
611 | } |
612 | } |
613 | } |
614 | |
615 | return Best; |
616 | } |
617 | |
618 | /// CommaSeparateAndAddOccurrence - A wrapper around Handler->addOccurrence() |
619 | /// that does special handling of cl::CommaSeparated options. |
620 | static bool CommaSeparateAndAddOccurrence(Option *Handler, unsigned pos, |
621 | StringRef ArgName, StringRef Value, |
622 | bool MultiArg = false) { |
623 | // Check to see if this option accepts a comma separated list of values. If |
624 | // it does, we have to split up the value into multiple values. |
625 | if (Handler->getMiscFlags() & CommaSeparated) { |
626 | StringRef Val(Value); |
627 | StringRef::size_type Pos = Val.find(C: ','); |
628 | |
629 | while (Pos != StringRef::npos) { |
630 | // Process the portion before the comma. |
631 | if (Handler->addOccurrence(pos, ArgName, Value: Val.substr(Start: 0, N: Pos), MultiArg)) |
632 | return true; |
633 | // Erase the portion before the comma, AND the comma. |
634 | Val = Val.substr(Start: Pos + 1); |
635 | // Check for another comma. |
636 | Pos = Val.find(C: ','); |
637 | } |
638 | |
639 | Value = Val; |
640 | } |
641 | |
642 | return Handler->addOccurrence(pos, ArgName, Value, MultiArg); |
643 | } |
644 | |
645 | /// ProvideOption - For Value, this differentiates between an empty value ("") |
646 | /// and a null value (StringRef()). The later is accepted for arguments that |
647 | /// don't allow a value (-foo) the former is rejected (-foo=). |
648 | static inline bool ProvideOption(Option *Handler, StringRef ArgName, |
649 | StringRef Value, int argc, |
650 | const char *const *argv, int &i) { |
651 | // Is this a multi-argument option? |
652 | unsigned NumAdditionalVals = Handler->getNumAdditionalVals(); |
653 | |
654 | // Enforce value requirements |
655 | switch (Handler->getValueExpectedFlag()) { |
656 | case ValueRequired: |
657 | if (!Value.data()) { // No value specified? |
658 | // If no other argument or the option only supports prefix form, we |
659 | // cannot look at the next argument. |
660 | if (i + 1 >= argc || Handler->getFormattingFlag() == cl::AlwaysPrefix) |
661 | return Handler->error(Message: "requires a value!" ); |
662 | // Steal the next argument, like for '-o filename' |
663 | assert(argv && "null check" ); |
664 | Value = StringRef(argv[++i]); |
665 | } |
666 | break; |
667 | case ValueDisallowed: |
668 | if (NumAdditionalVals > 0) |
669 | return Handler->error(Message: "multi-valued option specified" |
670 | " with ValueDisallowed modifier!" ); |
671 | |
672 | if (Value.data()) |
673 | return Handler->error(Message: "does not allow a value! '" + Twine(Value) + |
674 | "' specified." ); |
675 | break; |
676 | case ValueOptional: |
677 | break; |
678 | } |
679 | |
680 | // If this isn't a multi-arg option, just run the handler. |
681 | if (NumAdditionalVals == 0) |
682 | return CommaSeparateAndAddOccurrence(Handler, pos: i, ArgName, Value); |
683 | |
684 | // If it is, run the handle several times. |
685 | bool MultiArg = false; |
686 | |
687 | if (Value.data()) { |
688 | if (CommaSeparateAndAddOccurrence(Handler, pos: i, ArgName, Value, MultiArg)) |
689 | return true; |
690 | --NumAdditionalVals; |
691 | MultiArg = true; |
692 | } |
693 | |
694 | while (NumAdditionalVals > 0) { |
695 | if (i + 1 >= argc) |
696 | return Handler->error(Message: "not enough values!" ); |
697 | assert(argv && "null check" ); |
698 | Value = StringRef(argv[++i]); |
699 | |
700 | if (CommaSeparateAndAddOccurrence(Handler, pos: i, ArgName, Value, MultiArg)) |
701 | return true; |
702 | MultiArg = true; |
703 | --NumAdditionalVals; |
704 | } |
705 | return false; |
706 | } |
707 | |
708 | bool llvm::cl::ProvidePositionalOption(Option *Handler, StringRef Arg, int i) { |
709 | int Dummy = i; |
710 | return ProvideOption(Handler, ArgName: Handler->ArgStr, Value: Arg, argc: 0, argv: nullptr, i&: Dummy); |
711 | } |
712 | |
713 | // getOptionPred - Check to see if there are any options that satisfy the |
714 | // specified predicate with names that are the prefixes in Name. This is |
715 | // checked by progressively stripping characters off of the name, checking to |
716 | // see if there options that satisfy the predicate. If we find one, return it, |
717 | // otherwise return null. |
718 | // |
719 | static Option *getOptionPred(StringRef Name, size_t &Length, |
720 | bool (*Pred)(const Option *), |
721 | const StringMap<Option *> &OptionsMap) { |
722 | StringMap<Option *>::const_iterator OMI = OptionsMap.find(Key: Name); |
723 | if (OMI != OptionsMap.end() && !Pred(OMI->getValue())) |
724 | OMI = OptionsMap.end(); |
725 | |
726 | // Loop while we haven't found an option and Name still has at least two |
727 | // characters in it (so that the next iteration will not be the empty |
728 | // string. |
729 | while (OMI == OptionsMap.end() && Name.size() > 1) { |
730 | Name = Name.drop_back(); |
731 | OMI = OptionsMap.find(Key: Name); |
732 | if (OMI != OptionsMap.end() && !Pred(OMI->getValue())) |
733 | OMI = OptionsMap.end(); |
734 | } |
735 | |
736 | if (OMI != OptionsMap.end() && Pred(OMI->second)) { |
737 | Length = Name.size(); |
738 | return OMI->second; // Found one! |
739 | } |
740 | return nullptr; // No option found! |
741 | } |
742 | |
743 | /// HandlePrefixedOrGroupedOption - The specified argument string (which started |
744 | /// with at least one '-') does not fully match an available option. Check to |
745 | /// see if this is a prefix or grouped option. If so, split arg into output an |
746 | /// Arg/Value pair and return the Option to parse it with. |
747 | static Option * |
748 | HandlePrefixedOrGroupedOption(StringRef &Arg, StringRef &Value, |
749 | bool &ErrorParsing, |
750 | const StringMap<Option *> &OptionsMap) { |
751 | if (Arg.size() == 1) |
752 | return nullptr; |
753 | |
754 | // Do the lookup! |
755 | size_t Length = 0; |
756 | Option *PGOpt = getOptionPred(Name: Arg, Length, Pred: isPrefixedOrGrouping, OptionsMap); |
757 | if (!PGOpt) |
758 | return nullptr; |
759 | |
760 | do { |
761 | StringRef MaybeValue = |
762 | (Length < Arg.size()) ? Arg.substr(Start: Length) : StringRef(); |
763 | Arg = Arg.substr(Start: 0, N: Length); |
764 | assert(OptionsMap.count(Arg) && OptionsMap.find(Arg)->second == PGOpt); |
765 | |
766 | // cl::Prefix options do not preserve '=' when used separately. |
767 | // The behavior for them with grouped options should be the same. |
768 | if (MaybeValue.empty() || PGOpt->getFormattingFlag() == cl::AlwaysPrefix || |
769 | (PGOpt->getFormattingFlag() == cl::Prefix && MaybeValue[0] != '=')) { |
770 | Value = MaybeValue; |
771 | return PGOpt; |
772 | } |
773 | |
774 | if (MaybeValue[0] == '=') { |
775 | Value = MaybeValue.substr(Start: 1); |
776 | return PGOpt; |
777 | } |
778 | |
779 | // This must be a grouped option. |
780 | assert(isGrouping(PGOpt) && "Broken getOptionPred!" ); |
781 | |
782 | // Grouping options inside a group can't have values. |
783 | if (PGOpt->getValueExpectedFlag() == cl::ValueRequired) { |
784 | ErrorParsing |= PGOpt->error(Message: "may not occur within a group!" ); |
785 | return nullptr; |
786 | } |
787 | |
788 | // Because the value for the option is not required, we don't need to pass |
789 | // argc/argv in. |
790 | int Dummy = 0; |
791 | ErrorParsing |= ProvideOption(Handler: PGOpt, ArgName: Arg, Value: StringRef(), argc: 0, argv: nullptr, i&: Dummy); |
792 | |
793 | // Get the next grouping option. |
794 | Arg = MaybeValue; |
795 | PGOpt = getOptionPred(Name: Arg, Length, Pred: isGrouping, OptionsMap); |
796 | } while (PGOpt); |
797 | |
798 | // We could not find a grouping option in the remainder of Arg. |
799 | return nullptr; |
800 | } |
801 | |
802 | static bool RequiresValue(const Option *O) { |
803 | return O->getNumOccurrencesFlag() == cl::Required || |
804 | O->getNumOccurrencesFlag() == cl::OneOrMore; |
805 | } |
806 | |
807 | static bool EatsUnboundedNumberOfValues(const Option *O) { |
808 | return O->getNumOccurrencesFlag() == cl::ZeroOrMore || |
809 | O->getNumOccurrencesFlag() == cl::OneOrMore; |
810 | } |
811 | |
812 | static bool isWhitespace(char C) { |
813 | return C == ' ' || C == '\t' || C == '\r' || C == '\n'; |
814 | } |
815 | |
816 | static bool isWhitespaceOrNull(char C) { |
817 | return isWhitespace(C) || C == '\0'; |
818 | } |
819 | |
820 | static bool isQuote(char C) { return C == '\"' || C == '\''; } |
821 | |
822 | void cl::TokenizeGNUCommandLine(StringRef Src, StringSaver &Saver, |
823 | SmallVectorImpl<const char *> &NewArgv, |
824 | bool MarkEOLs) { |
825 | SmallString<128> Token; |
826 | for (size_t I = 0, E = Src.size(); I != E; ++I) { |
827 | // Consume runs of whitespace. |
828 | if (Token.empty()) { |
829 | while (I != E && isWhitespace(C: Src[I])) { |
830 | // Mark the end of lines in response files. |
831 | if (MarkEOLs && Src[I] == '\n') |
832 | NewArgv.push_back(Elt: nullptr); |
833 | ++I; |
834 | } |
835 | if (I == E) |
836 | break; |
837 | } |
838 | |
839 | char C = Src[I]; |
840 | |
841 | // Backslash escapes the next character. |
842 | if (I + 1 < E && C == '\\') { |
843 | ++I; // Skip the escape. |
844 | Token.push_back(Elt: Src[I]); |
845 | continue; |
846 | } |
847 | |
848 | // Consume a quoted string. |
849 | if (isQuote(C)) { |
850 | ++I; |
851 | while (I != E && Src[I] != C) { |
852 | // Backslash escapes the next character. |
853 | if (Src[I] == '\\' && I + 1 != E) |
854 | ++I; |
855 | Token.push_back(Elt: Src[I]); |
856 | ++I; |
857 | } |
858 | if (I == E) |
859 | break; |
860 | continue; |
861 | } |
862 | |
863 | // End the token if this is whitespace. |
864 | if (isWhitespace(C)) { |
865 | if (!Token.empty()) |
866 | NewArgv.push_back(Elt: Saver.save(S: Token.str()).data()); |
867 | // Mark the end of lines in response files. |
868 | if (MarkEOLs && C == '\n') |
869 | NewArgv.push_back(Elt: nullptr); |
870 | Token.clear(); |
871 | continue; |
872 | } |
873 | |
874 | // This is a normal character. Append it. |
875 | Token.push_back(Elt: C); |
876 | } |
877 | |
878 | // Append the last token after hitting EOF with no whitespace. |
879 | if (!Token.empty()) |
880 | NewArgv.push_back(Elt: Saver.save(S: Token.str()).data()); |
881 | } |
882 | |
883 | /// Backslashes are interpreted in a rather complicated way in the Windows-style |
884 | /// command line, because backslashes are used both to separate path and to |
885 | /// escape double quote. This method consumes runs of backslashes as well as the |
886 | /// following double quote if it's escaped. |
887 | /// |
888 | /// * If an even number of backslashes is followed by a double quote, one |
889 | /// backslash is output for every pair of backslashes, and the last double |
890 | /// quote remains unconsumed. The double quote will later be interpreted as |
891 | /// the start or end of a quoted string in the main loop outside of this |
892 | /// function. |
893 | /// |
894 | /// * If an odd number of backslashes is followed by a double quote, one |
895 | /// backslash is output for every pair of backslashes, and a double quote is |
896 | /// output for the last pair of backslash-double quote. The double quote is |
897 | /// consumed in this case. |
898 | /// |
899 | /// * Otherwise, backslashes are interpreted literally. |
900 | static size_t parseBackslash(StringRef Src, size_t I, SmallString<128> &Token) { |
901 | size_t E = Src.size(); |
902 | int BackslashCount = 0; |
903 | // Skip the backslashes. |
904 | do { |
905 | ++I; |
906 | ++BackslashCount; |
907 | } while (I != E && Src[I] == '\\'); |
908 | |
909 | bool FollowedByDoubleQuote = (I != E && Src[I] == '"'); |
910 | if (FollowedByDoubleQuote) { |
911 | Token.append(NumInputs: BackslashCount / 2, Elt: '\\'); |
912 | if (BackslashCount % 2 == 0) |
913 | return I - 1; |
914 | Token.push_back(Elt: '"'); |
915 | return I; |
916 | } |
917 | Token.append(NumInputs: BackslashCount, Elt: '\\'); |
918 | return I - 1; |
919 | } |
920 | |
921 | // Windows treats whitespace, double quotes, and backslashes specially, except |
922 | // when parsing the first token of a full command line, in which case |
923 | // backslashes are not special. |
924 | static bool isWindowsSpecialChar(char C) { |
925 | return isWhitespaceOrNull(C) || C == '\\' || C == '\"'; |
926 | } |
927 | static bool isWindowsSpecialCharInCommandName(char C) { |
928 | return isWhitespaceOrNull(C) || C == '\"'; |
929 | } |
930 | |
931 | // Windows tokenization implementation. The implementation is designed to be |
932 | // inlined and specialized for the two user entry points. |
933 | static inline void tokenizeWindowsCommandLineImpl( |
934 | StringRef Src, StringSaver &Saver, function_ref<void(StringRef)> AddToken, |
935 | bool AlwaysCopy, function_ref<void()> MarkEOL, bool InitialCommandName) { |
936 | SmallString<128> Token; |
937 | |
938 | // Sometimes, this function will be handling a full command line including an |
939 | // executable pathname at the start. In that situation, the initial pathname |
940 | // needs different handling from the following arguments, because when |
941 | // CreateProcess or cmd.exe scans the pathname, it doesn't treat \ as |
942 | // escaping the quote character, whereas when libc scans the rest of the |
943 | // command line, it does. |
944 | bool CommandName = InitialCommandName; |
945 | |
946 | // Try to do as much work inside the state machine as possible. |
947 | enum { INIT, UNQUOTED, QUOTED } State = INIT; |
948 | |
949 | for (size_t I = 0, E = Src.size(); I < E; ++I) { |
950 | switch (State) { |
951 | case INIT: { |
952 | assert(Token.empty() && "token should be empty in initial state" ); |
953 | // Eat whitespace before a token. |
954 | while (I < E && isWhitespaceOrNull(C: Src[I])) { |
955 | if (Src[I] == '\n') |
956 | MarkEOL(); |
957 | ++I; |
958 | } |
959 | // Stop if this was trailing whitespace. |
960 | if (I >= E) |
961 | break; |
962 | size_t Start = I; |
963 | if (CommandName) { |
964 | while (I < E && !isWindowsSpecialCharInCommandName(C: Src[I])) |
965 | ++I; |
966 | } else { |
967 | while (I < E && !isWindowsSpecialChar(C: Src[I])) |
968 | ++I; |
969 | } |
970 | StringRef NormalChars = Src.slice(Start, End: I); |
971 | if (I >= E || isWhitespaceOrNull(C: Src[I])) { |
972 | // No special characters: slice out the substring and start the next |
973 | // token. Copy the string if the caller asks us to. |
974 | AddToken(AlwaysCopy ? Saver.save(S: NormalChars) : NormalChars); |
975 | if (I < E && Src[I] == '\n') { |
976 | MarkEOL(); |
977 | CommandName = InitialCommandName; |
978 | } else { |
979 | CommandName = false; |
980 | } |
981 | } else if (Src[I] == '\"') { |
982 | Token += NormalChars; |
983 | State = QUOTED; |
984 | } else if (Src[I] == '\\') { |
985 | assert(!CommandName && "or else we'd have treated it as a normal char" ); |
986 | Token += NormalChars; |
987 | I = parseBackslash(Src, I, Token); |
988 | State = UNQUOTED; |
989 | } else { |
990 | llvm_unreachable("unexpected special character" ); |
991 | } |
992 | break; |
993 | } |
994 | |
995 | case UNQUOTED: |
996 | if (isWhitespaceOrNull(C: Src[I])) { |
997 | // Whitespace means the end of the token. If we are in this state, the |
998 | // token must have contained a special character, so we must copy the |
999 | // token. |
1000 | AddToken(Saver.save(S: Token.str())); |
1001 | Token.clear(); |
1002 | if (Src[I] == '\n') { |
1003 | CommandName = InitialCommandName; |
1004 | MarkEOL(); |
1005 | } else { |
1006 | CommandName = false; |
1007 | } |
1008 | State = INIT; |
1009 | } else if (Src[I] == '\"') { |
1010 | State = QUOTED; |
1011 | } else if (Src[I] == '\\' && !CommandName) { |
1012 | I = parseBackslash(Src, I, Token); |
1013 | } else { |
1014 | Token.push_back(Elt: Src[I]); |
1015 | } |
1016 | break; |
1017 | |
1018 | case QUOTED: |
1019 | if (Src[I] == '\"') { |
1020 | if (I < (E - 1) && Src[I + 1] == '"') { |
1021 | // Consecutive double-quotes inside a quoted string implies one |
1022 | // double-quote. |
1023 | Token.push_back(Elt: '"'); |
1024 | ++I; |
1025 | } else { |
1026 | // Otherwise, end the quoted portion and return to the unquoted state. |
1027 | State = UNQUOTED; |
1028 | } |
1029 | } else if (Src[I] == '\\' && !CommandName) { |
1030 | I = parseBackslash(Src, I, Token); |
1031 | } else { |
1032 | Token.push_back(Elt: Src[I]); |
1033 | } |
1034 | break; |
1035 | } |
1036 | } |
1037 | |
1038 | if (State != INIT) |
1039 | AddToken(Saver.save(S: Token.str())); |
1040 | } |
1041 | |
1042 | void cl::TokenizeWindowsCommandLine(StringRef Src, StringSaver &Saver, |
1043 | SmallVectorImpl<const char *> &NewArgv, |
1044 | bool MarkEOLs) { |
1045 | auto AddToken = [&](StringRef Tok) { NewArgv.push_back(Elt: Tok.data()); }; |
1046 | auto OnEOL = [&]() { |
1047 | if (MarkEOLs) |
1048 | NewArgv.push_back(Elt: nullptr); |
1049 | }; |
1050 | tokenizeWindowsCommandLineImpl(Src, Saver, AddToken, |
1051 | /*AlwaysCopy=*/true, MarkEOL: OnEOL, InitialCommandName: false); |
1052 | } |
1053 | |
1054 | void cl::TokenizeWindowsCommandLineNoCopy(StringRef Src, StringSaver &Saver, |
1055 | SmallVectorImpl<StringRef> &NewArgv) { |
1056 | auto AddToken = [&](StringRef Tok) { NewArgv.push_back(Elt: Tok); }; |
1057 | auto OnEOL = []() {}; |
1058 | tokenizeWindowsCommandLineImpl(Src, Saver, AddToken, /*AlwaysCopy=*/false, |
1059 | MarkEOL: OnEOL, InitialCommandName: false); |
1060 | } |
1061 | |
1062 | void cl::TokenizeWindowsCommandLineFull(StringRef Src, StringSaver &Saver, |
1063 | SmallVectorImpl<const char *> &NewArgv, |
1064 | bool MarkEOLs) { |
1065 | auto AddToken = [&](StringRef Tok) { NewArgv.push_back(Elt: Tok.data()); }; |
1066 | auto OnEOL = [&]() { |
1067 | if (MarkEOLs) |
1068 | NewArgv.push_back(Elt: nullptr); |
1069 | }; |
1070 | tokenizeWindowsCommandLineImpl(Src, Saver, AddToken, |
1071 | /*AlwaysCopy=*/true, MarkEOL: OnEOL, InitialCommandName: true); |
1072 | } |
1073 | |
1074 | void cl::tokenizeConfigFile(StringRef Source, StringSaver &Saver, |
1075 | SmallVectorImpl<const char *> &NewArgv, |
1076 | bool MarkEOLs) { |
1077 | for (const char *Cur = Source.begin(); Cur != Source.end();) { |
1078 | SmallString<128> Line; |
1079 | // Check for comment line. |
1080 | if (isWhitespace(C: *Cur)) { |
1081 | while (Cur != Source.end() && isWhitespace(C: *Cur)) |
1082 | ++Cur; |
1083 | continue; |
1084 | } |
1085 | if (*Cur == '#') { |
1086 | while (Cur != Source.end() && *Cur != '\n') |
1087 | ++Cur; |
1088 | continue; |
1089 | } |
1090 | // Find end of the current line. |
1091 | const char *Start = Cur; |
1092 | for (const char *End = Source.end(); Cur != End; ++Cur) { |
1093 | if (*Cur == '\\') { |
1094 | if (Cur + 1 != End) { |
1095 | ++Cur; |
1096 | if (*Cur == '\n' || |
1097 | (*Cur == '\r' && (Cur + 1 != End) && Cur[1] == '\n')) { |
1098 | Line.append(in_start: Start, in_end: Cur - 1); |
1099 | if (*Cur == '\r') |
1100 | ++Cur; |
1101 | Start = Cur + 1; |
1102 | } |
1103 | } |
1104 | } else if (*Cur == '\n') |
1105 | break; |
1106 | } |
1107 | // Tokenize line. |
1108 | Line.append(in_start: Start, in_end: Cur); |
1109 | cl::TokenizeGNUCommandLine(Src: Line, Saver, NewArgv, MarkEOLs); |
1110 | } |
1111 | } |
1112 | |
1113 | // It is called byte order marker but the UTF-8 BOM is actually not affected |
1114 | // by the host system's endianness. |
1115 | static bool hasUTF8ByteOrderMark(ArrayRef<char> S) { |
1116 | return (S.size() >= 3 && S[0] == '\xef' && S[1] == '\xbb' && S[2] == '\xbf'); |
1117 | } |
1118 | |
1119 | // Substitute <CFGDIR> with the file's base path. |
1120 | static void ExpandBasePaths(StringRef BasePath, StringSaver &Saver, |
1121 | const char *&Arg) { |
1122 | assert(sys::path::is_absolute(BasePath)); |
1123 | constexpr StringLiteral Token("<CFGDIR>" ); |
1124 | const StringRef ArgString(Arg); |
1125 | |
1126 | SmallString<128> ResponseFile; |
1127 | StringRef::size_type StartPos = 0; |
1128 | for (StringRef::size_type TokenPos = ArgString.find(Str: Token); |
1129 | TokenPos != StringRef::npos; |
1130 | TokenPos = ArgString.find(Str: Token, From: StartPos)) { |
1131 | // Token may appear more than once per arg (e.g. comma-separated linker |
1132 | // args). Support by using path-append on any subsequent appearances. |
1133 | const StringRef LHS = ArgString.substr(Start: StartPos, N: TokenPos - StartPos); |
1134 | if (ResponseFile.empty()) |
1135 | ResponseFile = LHS; |
1136 | else |
1137 | llvm::sys::path::append(path&: ResponseFile, a: LHS); |
1138 | ResponseFile.append(RHS: BasePath); |
1139 | StartPos = TokenPos + Token.size(); |
1140 | } |
1141 | |
1142 | if (!ResponseFile.empty()) { |
1143 | // Path-append the remaining arg substring if at least one token appeared. |
1144 | const StringRef Remaining = ArgString.substr(Start: StartPos); |
1145 | if (!Remaining.empty()) |
1146 | llvm::sys::path::append(path&: ResponseFile, a: Remaining); |
1147 | Arg = Saver.save(S: ResponseFile.str()).data(); |
1148 | } |
1149 | } |
1150 | |
1151 | // FName must be an absolute path. |
1152 | Error ExpansionContext::expandResponseFile( |
1153 | StringRef FName, SmallVectorImpl<const char *> &NewArgv) { |
1154 | assert(sys::path::is_absolute(FName)); |
1155 | llvm::ErrorOr<std::unique_ptr<MemoryBuffer>> MemBufOrErr = |
1156 | FS->getBufferForFile(Name: FName); |
1157 | if (!MemBufOrErr) { |
1158 | std::error_code EC = MemBufOrErr.getError(); |
1159 | return llvm::createStringError(EC, S: Twine("cannot not open file '" ) + FName + |
1160 | "': " + EC.message()); |
1161 | } |
1162 | MemoryBuffer &MemBuf = *MemBufOrErr.get(); |
1163 | StringRef Str(MemBuf.getBufferStart(), MemBuf.getBufferSize()); |
1164 | |
1165 | // If we have a UTF-16 byte order mark, convert to UTF-8 for parsing. |
1166 | ArrayRef<char> BufRef(MemBuf.getBufferStart(), MemBuf.getBufferEnd()); |
1167 | std::string UTF8Buf; |
1168 | if (hasUTF16ByteOrderMark(SrcBytes: BufRef)) { |
1169 | if (!convertUTF16ToUTF8String(SrcBytes: BufRef, Out&: UTF8Buf)) |
1170 | return llvm::createStringError(EC: std::errc::illegal_byte_sequence, |
1171 | Fmt: "Could not convert UTF16 to UTF8" ); |
1172 | Str = StringRef(UTF8Buf); |
1173 | } |
1174 | // If we see UTF-8 BOM sequence at the beginning of a file, we shall remove |
1175 | // these bytes before parsing. |
1176 | // Reference: http://en.wikipedia.org/wiki/UTF-8#Byte_order_mark |
1177 | else if (hasUTF8ByteOrderMark(S: BufRef)) |
1178 | Str = StringRef(BufRef.data() + 3, BufRef.size() - 3); |
1179 | |
1180 | // Tokenize the contents into NewArgv. |
1181 | Tokenizer(Str, Saver, NewArgv, MarkEOLs); |
1182 | |
1183 | // Expanded file content may require additional transformations, like using |
1184 | // absolute paths instead of relative in '@file' constructs or expanding |
1185 | // macros. |
1186 | if (!RelativeNames && !InConfigFile) |
1187 | return Error::success(); |
1188 | |
1189 | StringRef BasePath = llvm::sys::path::parent_path(path: FName); |
1190 | for (const char *&Arg : NewArgv) { |
1191 | if (!Arg) |
1192 | continue; |
1193 | |
1194 | // Substitute <CFGDIR> with the file's base path. |
1195 | if (InConfigFile) |
1196 | ExpandBasePaths(BasePath, Saver, Arg); |
1197 | |
1198 | // Discover the case, when argument should be transformed into '@file' and |
1199 | // evaluate 'file' for it. |
1200 | StringRef ArgStr(Arg); |
1201 | StringRef FileName; |
1202 | bool ConfigInclusion = false; |
1203 | if (ArgStr.consume_front(Prefix: "@" )) { |
1204 | FileName = ArgStr; |
1205 | if (!llvm::sys::path::is_relative(path: FileName)) |
1206 | continue; |
1207 | } else if (ArgStr.consume_front(Prefix: "--config=" )) { |
1208 | FileName = ArgStr; |
1209 | ConfigInclusion = true; |
1210 | } else { |
1211 | continue; |
1212 | } |
1213 | |
1214 | // Update expansion construct. |
1215 | SmallString<128> ResponseFile; |
1216 | ResponseFile.push_back(Elt: '@'); |
1217 | if (ConfigInclusion && !llvm::sys::path::has_parent_path(path: FileName)) { |
1218 | SmallString<128> FilePath; |
1219 | if (!findConfigFile(FileName, FilePath)) |
1220 | return createStringError( |
1221 | EC: std::make_error_code(e: std::errc::no_such_file_or_directory), |
1222 | S: "cannot not find configuration file: " + FileName); |
1223 | ResponseFile.append(RHS: FilePath); |
1224 | } else { |
1225 | ResponseFile.append(RHS: BasePath); |
1226 | llvm::sys::path::append(path&: ResponseFile, a: FileName); |
1227 | } |
1228 | Arg = Saver.save(S: ResponseFile.str()).data(); |
1229 | } |
1230 | return Error::success(); |
1231 | } |
1232 | |
1233 | /// Expand response files on a command line recursively using the given |
1234 | /// StringSaver and tokenization strategy. |
1235 | Error ExpansionContext::expandResponseFiles( |
1236 | SmallVectorImpl<const char *> &Argv) { |
1237 | struct ResponseFileRecord { |
1238 | std::string File; |
1239 | size_t End; |
1240 | }; |
1241 | |
1242 | // To detect recursive response files, we maintain a stack of files and the |
1243 | // position of the last argument in the file. This position is updated |
1244 | // dynamically as we recursively expand files. |
1245 | SmallVector<ResponseFileRecord, 3> FileStack; |
1246 | |
1247 | // Push a dummy entry that represents the initial command line, removing |
1248 | // the need to check for an empty list. |
1249 | FileStack.push_back(Elt: {.File: "" , .End: Argv.size()}); |
1250 | |
1251 | // Don't cache Argv.size() because it can change. |
1252 | for (unsigned I = 0; I != Argv.size();) { |
1253 | while (I == FileStack.back().End) { |
1254 | // Passing the end of a file's argument list, so we can remove it from the |
1255 | // stack. |
1256 | FileStack.pop_back(); |
1257 | } |
1258 | |
1259 | const char *Arg = Argv[I]; |
1260 | // Check if it is an EOL marker |
1261 | if (Arg == nullptr) { |
1262 | ++I; |
1263 | continue; |
1264 | } |
1265 | |
1266 | if (Arg[0] != '@') { |
1267 | ++I; |
1268 | continue; |
1269 | } |
1270 | |
1271 | const char *FName = Arg + 1; |
1272 | // Note that CurrentDir is only used for top-level rsp files, the rest will |
1273 | // always have an absolute path deduced from the containing file. |
1274 | SmallString<128> CurrDir; |
1275 | if (llvm::sys::path::is_relative(path: FName)) { |
1276 | if (CurrentDir.empty()) { |
1277 | if (auto CWD = FS->getCurrentWorkingDirectory()) { |
1278 | CurrDir = *CWD; |
1279 | } else { |
1280 | return createStringError( |
1281 | EC: CWD.getError(), S: Twine("cannot get absolute path for: " ) + FName); |
1282 | } |
1283 | } else { |
1284 | CurrDir = CurrentDir; |
1285 | } |
1286 | llvm::sys::path::append(path&: CurrDir, a: FName); |
1287 | FName = CurrDir.c_str(); |
1288 | } |
1289 | |
1290 | ErrorOr<llvm::vfs::Status> Res = FS->status(Path: FName); |
1291 | if (!Res || !Res->exists()) { |
1292 | std::error_code EC = Res.getError(); |
1293 | if (!InConfigFile) { |
1294 | // If the specified file does not exist, leave '@file' unexpanded, as |
1295 | // libiberty does. |
1296 | if (!EC || EC == llvm::errc::no_such_file_or_directory) { |
1297 | ++I; |
1298 | continue; |
1299 | } |
1300 | } |
1301 | if (!EC) |
1302 | EC = llvm::errc::no_such_file_or_directory; |
1303 | return createStringError(EC, S: Twine("cannot not open file '" ) + FName + |
1304 | "': " + EC.message()); |
1305 | } |
1306 | const llvm::vfs::Status &FileStatus = Res.get(); |
1307 | |
1308 | auto IsEquivalent = |
1309 | [FileStatus, this](const ResponseFileRecord &RFile) -> ErrorOr<bool> { |
1310 | ErrorOr<llvm::vfs::Status> RHS = FS->status(Path: RFile.File); |
1311 | if (!RHS) |
1312 | return RHS.getError(); |
1313 | return FileStatus.equivalent(Other: *RHS); |
1314 | }; |
1315 | |
1316 | // Check for recursive response files. |
1317 | for (const auto &F : drop_begin(RangeOrContainer&: FileStack)) { |
1318 | if (ErrorOr<bool> R = IsEquivalent(F)) { |
1319 | if (R.get()) |
1320 | return createStringError( |
1321 | EC: R.getError(), S: Twine("recursive expansion of: '" ) + F.File + "'" ); |
1322 | } else { |
1323 | return createStringError(EC: R.getError(), |
1324 | S: Twine("cannot open file: " ) + F.File); |
1325 | } |
1326 | } |
1327 | |
1328 | // Replace this response file argument with the tokenization of its |
1329 | // contents. Nested response files are expanded in subsequent iterations. |
1330 | SmallVector<const char *, 0> ExpandedArgv; |
1331 | if (Error Err = expandResponseFile(FName, NewArgv&: ExpandedArgv)) |
1332 | return Err; |
1333 | |
1334 | for (ResponseFileRecord &Record : FileStack) { |
1335 | // Increase the end of all active records by the number of newly expanded |
1336 | // arguments, minus the response file itself. |
1337 | Record.End += ExpandedArgv.size() - 1; |
1338 | } |
1339 | |
1340 | FileStack.push_back(Elt: {.File: FName, .End: I + ExpandedArgv.size()}); |
1341 | Argv.erase(CI: Argv.begin() + I); |
1342 | Argv.insert(I: Argv.begin() + I, From: ExpandedArgv.begin(), To: ExpandedArgv.end()); |
1343 | } |
1344 | |
1345 | // If successful, the top of the file stack will mark the end of the Argv |
1346 | // stream. A failure here indicates a bug in the stack popping logic above. |
1347 | // Note that FileStack may have more than one element at this point because we |
1348 | // don't have a chance to pop the stack when encountering recursive files at |
1349 | // the end of the stream, so seeing that doesn't indicate a bug. |
1350 | assert(FileStack.size() > 0 && Argv.size() == FileStack.back().End); |
1351 | return Error::success(); |
1352 | } |
1353 | |
1354 | bool cl::expandResponseFiles(int Argc, const char *const *Argv, |
1355 | const char *EnvVar, StringSaver &Saver, |
1356 | SmallVectorImpl<const char *> &NewArgv) { |
1357 | #ifdef _WIN32 |
1358 | auto Tokenize = cl::TokenizeWindowsCommandLine; |
1359 | #else |
1360 | auto Tokenize = cl::TokenizeGNUCommandLine; |
1361 | #endif |
1362 | // The environment variable specifies initial options. |
1363 | if (EnvVar) |
1364 | if (std::optional<std::string> EnvValue = sys::Process::GetEnv(name: EnvVar)) |
1365 | Tokenize(*EnvValue, Saver, NewArgv, /*MarkEOLs=*/false); |
1366 | |
1367 | // Command line options can override the environment variable. |
1368 | NewArgv.append(in_start: Argv + 1, in_end: Argv + Argc); |
1369 | ExpansionContext ECtx(Saver.getAllocator(), Tokenize); |
1370 | if (Error Err = ECtx.expandResponseFiles(Argv&: NewArgv)) { |
1371 | errs() << toString(E: std::move(Err)) << '\n'; |
1372 | return false; |
1373 | } |
1374 | return true; |
1375 | } |
1376 | |
1377 | bool cl::ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer, |
1378 | SmallVectorImpl<const char *> &Argv) { |
1379 | ExpansionContext ECtx(Saver.getAllocator(), Tokenizer); |
1380 | if (Error Err = ECtx.expandResponseFiles(Argv)) { |
1381 | errs() << toString(E: std::move(Err)) << '\n'; |
1382 | return false; |
1383 | } |
1384 | return true; |
1385 | } |
1386 | |
1387 | ExpansionContext::ExpansionContext(BumpPtrAllocator &A, TokenizerCallback T) |
1388 | : Saver(A), Tokenizer(T), FS(vfs::getRealFileSystem().get()) {} |
1389 | |
1390 | bool ExpansionContext::findConfigFile(StringRef FileName, |
1391 | SmallVectorImpl<char> &FilePath) { |
1392 | SmallString<128> CfgFilePath; |
1393 | const auto FileExists = [this](SmallString<128> Path) -> bool { |
1394 | auto Status = FS->status(Path); |
1395 | return Status && |
1396 | Status->getType() == llvm::sys::fs::file_type::regular_file; |
1397 | }; |
1398 | |
1399 | // If file name contains directory separator, treat it as a path to |
1400 | // configuration file. |
1401 | if (llvm::sys::path::has_parent_path(path: FileName)) { |
1402 | CfgFilePath = FileName; |
1403 | if (llvm::sys::path::is_relative(path: FileName) && FS->makeAbsolute(Path&: CfgFilePath)) |
1404 | return false; |
1405 | if (!FileExists(CfgFilePath)) |
1406 | return false; |
1407 | FilePath.assign(in_start: CfgFilePath.begin(), in_end: CfgFilePath.end()); |
1408 | return true; |
1409 | } |
1410 | |
1411 | // Look for the file in search directories. |
1412 | for (const StringRef &Dir : SearchDirs) { |
1413 | if (Dir.empty()) |
1414 | continue; |
1415 | CfgFilePath.assign(RHS: Dir); |
1416 | llvm::sys::path::append(path&: CfgFilePath, a: FileName); |
1417 | llvm::sys::path::native(path&: CfgFilePath); |
1418 | if (FileExists(CfgFilePath)) { |
1419 | FilePath.assign(in_start: CfgFilePath.begin(), in_end: CfgFilePath.end()); |
1420 | return true; |
1421 | } |
1422 | } |
1423 | |
1424 | return false; |
1425 | } |
1426 | |
1427 | Error ExpansionContext::readConfigFile(StringRef CfgFile, |
1428 | SmallVectorImpl<const char *> &Argv) { |
1429 | SmallString<128> AbsPath; |
1430 | if (sys::path::is_relative(path: CfgFile)) { |
1431 | AbsPath.assign(RHS: CfgFile); |
1432 | if (std::error_code EC = FS->makeAbsolute(Path&: AbsPath)) |
1433 | return make_error<StringError>( |
1434 | Args&: EC, Args: Twine("cannot get absolute path for " + CfgFile)); |
1435 | CfgFile = AbsPath.str(); |
1436 | } |
1437 | InConfigFile = true; |
1438 | RelativeNames = true; |
1439 | if (Error Err = expandResponseFile(FName: CfgFile, NewArgv&: Argv)) |
1440 | return Err; |
1441 | return expandResponseFiles(Argv); |
1442 | } |
1443 | |
1444 | static void initCommonOptions(); |
1445 | bool cl::ParseCommandLineOptions(int argc, const char *const *argv, |
1446 | StringRef Overview, raw_ostream *Errs, |
1447 | const char *EnvVar, |
1448 | bool LongOptionsUseDoubleDash) { |
1449 | initCommonOptions(); |
1450 | SmallVector<const char *, 20> NewArgv; |
1451 | BumpPtrAllocator A; |
1452 | StringSaver Saver(A); |
1453 | NewArgv.push_back(Elt: argv[0]); |
1454 | |
1455 | // Parse options from environment variable. |
1456 | if (EnvVar) { |
1457 | if (std::optional<std::string> EnvValue = |
1458 | sys::Process::GetEnv(name: StringRef(EnvVar))) |
1459 | TokenizeGNUCommandLine(Src: *EnvValue, Saver, NewArgv); |
1460 | } |
1461 | |
1462 | // Append options from command line. |
1463 | for (int I = 1; I < argc; ++I) |
1464 | NewArgv.push_back(Elt: argv[I]); |
1465 | int NewArgc = static_cast<int>(NewArgv.size()); |
1466 | |
1467 | // Parse all options. |
1468 | return GlobalParser->ParseCommandLineOptions(argc: NewArgc, argv: &NewArgv[0], Overview, |
1469 | Errs, LongOptionsUseDoubleDash); |
1470 | } |
1471 | |
1472 | /// Reset all options at least once, so that we can parse different options. |
1473 | void CommandLineParser::ResetAllOptionOccurrences() { |
1474 | // Reset all option values to look like they have never been seen before. |
1475 | // Options might be reset twice (they can be reference in both OptionsMap |
1476 | // and one of the other members), but that does not harm. |
1477 | for (auto *SC : RegisteredSubCommands) { |
1478 | for (auto &O : SC->OptionsMap) |
1479 | O.second->reset(); |
1480 | for (Option *O : SC->PositionalOpts) |
1481 | O->reset(); |
1482 | for (Option *O : SC->SinkOpts) |
1483 | O->reset(); |
1484 | if (SC->ConsumeAfterOpt) |
1485 | SC->ConsumeAfterOpt->reset(); |
1486 | } |
1487 | } |
1488 | |
1489 | bool CommandLineParser::ParseCommandLineOptions(int argc, |
1490 | const char *const *argv, |
1491 | StringRef Overview, |
1492 | raw_ostream *Errs, |
1493 | bool LongOptionsUseDoubleDash) { |
1494 | assert(hasOptions() && "No options specified!" ); |
1495 | |
1496 | ProgramOverview = Overview; |
1497 | bool IgnoreErrors = Errs; |
1498 | if (!Errs) |
1499 | Errs = &errs(); |
1500 | bool ErrorParsing = false; |
1501 | |
1502 | // Expand response files. |
1503 | SmallVector<const char *, 20> newArgv(argv, argv + argc); |
1504 | BumpPtrAllocator A; |
1505 | #ifdef _WIN32 |
1506 | auto Tokenize = cl::TokenizeWindowsCommandLine; |
1507 | #else |
1508 | auto Tokenize = cl::TokenizeGNUCommandLine; |
1509 | #endif |
1510 | ExpansionContext ECtx(A, Tokenize); |
1511 | if (Error Err = ECtx.expandResponseFiles(Argv&: newArgv)) { |
1512 | *Errs << toString(E: std::move(Err)) << '\n'; |
1513 | return false; |
1514 | } |
1515 | argv = &newArgv[0]; |
1516 | argc = static_cast<int>(newArgv.size()); |
1517 | |
1518 | // Copy the program name into ProgName, making sure not to overflow it. |
1519 | ProgramName = std::string(sys::path::filename(path: StringRef(argv[0]))); |
1520 | |
1521 | // Check out the positional arguments to collect information about them. |
1522 | unsigned NumPositionalRequired = 0; |
1523 | |
1524 | // Determine whether or not there are an unlimited number of positionals |
1525 | bool HasUnlimitedPositionals = false; |
1526 | |
1527 | int FirstArg = 1; |
1528 | SubCommand *ChosenSubCommand = &SubCommand::getTopLevel(); |
1529 | std::string NearestSubCommandString; |
1530 | bool MaybeNamedSubCommand = |
1531 | argc >= 2 && argv[FirstArg][0] != '-' && hasNamedSubCommands(); |
1532 | if (MaybeNamedSubCommand) { |
1533 | // If the first argument specifies a valid subcommand, start processing |
1534 | // options from the second argument. |
1535 | ChosenSubCommand = |
1536 | LookupSubCommand(Name: StringRef(argv[FirstArg]), NearestString&: NearestSubCommandString); |
1537 | if (ChosenSubCommand != &SubCommand::getTopLevel()) |
1538 | FirstArg = 2; |
1539 | } |
1540 | GlobalParser->ActiveSubCommand = ChosenSubCommand; |
1541 | |
1542 | assert(ChosenSubCommand); |
1543 | auto &ConsumeAfterOpt = ChosenSubCommand->ConsumeAfterOpt; |
1544 | auto &PositionalOpts = ChosenSubCommand->PositionalOpts; |
1545 | auto &SinkOpts = ChosenSubCommand->SinkOpts; |
1546 | auto &OptionsMap = ChosenSubCommand->OptionsMap; |
1547 | |
1548 | for (auto *O: DefaultOptions) { |
1549 | addOption(O, ProcessDefaultOption: true); |
1550 | } |
1551 | |
1552 | if (ConsumeAfterOpt) { |
1553 | assert(PositionalOpts.size() > 0 && |
1554 | "Cannot specify cl::ConsumeAfter without a positional argument!" ); |
1555 | } |
1556 | if (!PositionalOpts.empty()) { |
1557 | |
1558 | // Calculate how many positional values are _required_. |
1559 | bool UnboundedFound = false; |
1560 | for (size_t i = 0, e = PositionalOpts.size(); i != e; ++i) { |
1561 | Option *Opt = PositionalOpts[i]; |
1562 | if (RequiresValue(O: Opt)) |
1563 | ++NumPositionalRequired; |
1564 | else if (ConsumeAfterOpt) { |
1565 | // ConsumeAfter cannot be combined with "optional" positional options |
1566 | // unless there is only one positional argument... |
1567 | if (PositionalOpts.size() > 1) { |
1568 | if (!IgnoreErrors) |
1569 | Opt->error(Message: "error - this positional option will never be matched, " |
1570 | "because it does not Require a value, and a " |
1571 | "cl::ConsumeAfter option is active!" ); |
1572 | ErrorParsing = true; |
1573 | } |
1574 | } else if (UnboundedFound && !Opt->hasArgStr()) { |
1575 | // This option does not "require" a value... Make sure this option is |
1576 | // not specified after an option that eats all extra arguments, or this |
1577 | // one will never get any! |
1578 | // |
1579 | if (!IgnoreErrors) |
1580 | Opt->error(Message: "error - option can never match, because " |
1581 | "another positional argument will match an " |
1582 | "unbounded number of values, and this option" |
1583 | " does not require a value!" ); |
1584 | *Errs << ProgramName << ": CommandLine Error: Option '" << Opt->ArgStr |
1585 | << "' is all messed up!\n" ; |
1586 | *Errs << PositionalOpts.size(); |
1587 | ErrorParsing = true; |
1588 | } |
1589 | UnboundedFound |= EatsUnboundedNumberOfValues(O: Opt); |
1590 | } |
1591 | HasUnlimitedPositionals = UnboundedFound || ConsumeAfterOpt; |
1592 | } |
1593 | |
1594 | // PositionalVals - A vector of "positional" arguments we accumulate into |
1595 | // the process at the end. |
1596 | // |
1597 | SmallVector<std::pair<StringRef, unsigned>, 4> PositionalVals; |
1598 | |
1599 | // If the program has named positional arguments, and the name has been run |
1600 | // across, keep track of which positional argument was named. Otherwise put |
1601 | // the positional args into the PositionalVals list... |
1602 | Option *ActivePositionalArg = nullptr; |
1603 | |
1604 | // Loop over all of the arguments... processing them. |
1605 | bool DashDashFound = false; // Have we read '--'? |
1606 | for (int i = FirstArg; i < argc; ++i) { |
1607 | Option *Handler = nullptr; |
1608 | std::string NearestHandlerString; |
1609 | StringRef Value; |
1610 | StringRef ArgName = "" ; |
1611 | bool HaveDoubleDash = false; |
1612 | |
1613 | // Check to see if this is a positional argument. This argument is |
1614 | // considered to be positional if it doesn't start with '-', if it is "-" |
1615 | // itself, or if we have seen "--" already. |
1616 | // |
1617 | if (argv[i][0] != '-' || argv[i][1] == 0 || DashDashFound) { |
1618 | // Positional argument! |
1619 | if (ActivePositionalArg) { |
1620 | ProvidePositionalOption(Handler: ActivePositionalArg, Arg: StringRef(argv[i]), i); |
1621 | continue; // We are done! |
1622 | } |
1623 | |
1624 | if (!PositionalOpts.empty()) { |
1625 | PositionalVals.push_back(Elt: std::make_pair(x: StringRef(argv[i]), y&: i)); |
1626 | |
1627 | // All of the positional arguments have been fulfulled, give the rest to |
1628 | // the consume after option... if it's specified... |
1629 | // |
1630 | if (PositionalVals.size() >= NumPositionalRequired && ConsumeAfterOpt) { |
1631 | for (++i; i < argc; ++i) |
1632 | PositionalVals.push_back(Elt: std::make_pair(x: StringRef(argv[i]), y&: i)); |
1633 | break; // Handle outside of the argument processing loop... |
1634 | } |
1635 | |
1636 | // Delay processing positional arguments until the end... |
1637 | continue; |
1638 | } |
1639 | } else if (argv[i][0] == '-' && argv[i][1] == '-' && argv[i][2] == 0 && |
1640 | !DashDashFound) { |
1641 | DashDashFound = true; // This is the mythical "--"? |
1642 | continue; // Don't try to process it as an argument itself. |
1643 | } else if (ActivePositionalArg && |
1644 | (ActivePositionalArg->getMiscFlags() & PositionalEatsArgs)) { |
1645 | // If there is a positional argument eating options, check to see if this |
1646 | // option is another positional argument. If so, treat it as an argument, |
1647 | // otherwise feed it to the eating positional. |
1648 | ArgName = StringRef(argv[i] + 1); |
1649 | // Eat second dash. |
1650 | if (ArgName.consume_front(Prefix: "-" )) |
1651 | HaveDoubleDash = true; |
1652 | |
1653 | Handler = LookupLongOption(Sub&: *ChosenSubCommand, Arg&: ArgName, Value, |
1654 | LongOptionsUseDoubleDash, HaveDoubleDash); |
1655 | if (!Handler || Handler->getFormattingFlag() != cl::Positional) { |
1656 | ProvidePositionalOption(Handler: ActivePositionalArg, Arg: StringRef(argv[i]), i); |
1657 | continue; // We are done! |
1658 | } |
1659 | } else { // We start with a '-', must be an argument. |
1660 | ArgName = StringRef(argv[i] + 1); |
1661 | // Eat second dash. |
1662 | if (ArgName.consume_front(Prefix: "-" )) |
1663 | HaveDoubleDash = true; |
1664 | |
1665 | Handler = LookupLongOption(Sub&: *ChosenSubCommand, Arg&: ArgName, Value, |
1666 | LongOptionsUseDoubleDash, HaveDoubleDash); |
1667 | |
1668 | // If Handler is not found in a specialized subcommand, look up handler |
1669 | // in the top-level subcommand. |
1670 | // cl::opt without cl::sub belongs to top-level subcommand. |
1671 | if (!Handler && ChosenSubCommand != &SubCommand::getTopLevel()) |
1672 | Handler = LookupLongOption(Sub&: SubCommand::getTopLevel(), Arg&: ArgName, Value, |
1673 | LongOptionsUseDoubleDash, HaveDoubleDash); |
1674 | |
1675 | // Check to see if this "option" is really a prefixed or grouped argument. |
1676 | if (!Handler && !(LongOptionsUseDoubleDash && HaveDoubleDash)) |
1677 | Handler = HandlePrefixedOrGroupedOption(Arg&: ArgName, Value, ErrorParsing, |
1678 | OptionsMap); |
1679 | |
1680 | // Otherwise, look for the closest available option to report to the user |
1681 | // in the upcoming error. |
1682 | if (!Handler && SinkOpts.empty()) |
1683 | LookupNearestOption(Arg: ArgName, OptionsMap, NearestString&: NearestHandlerString); |
1684 | } |
1685 | |
1686 | if (!Handler) { |
1687 | if (!SinkOpts.empty()) { |
1688 | for (Option *SinkOpt : SinkOpts) |
1689 | SinkOpt->addOccurrence(pos: i, ArgName: "" , Value: StringRef(argv[i])); |
1690 | continue; |
1691 | } |
1692 | |
1693 | auto ReportUnknownArgument = [&](bool IsArg, |
1694 | StringRef NearestArgumentName) { |
1695 | *Errs << ProgramName << ": Unknown " |
1696 | << (IsArg ? "command line argument" : "subcommand" ) << " '" |
1697 | << argv[i] << "'. Try: '" << argv[0] << " --help'\n" ; |
1698 | |
1699 | if (NearestArgumentName.empty()) |
1700 | return; |
1701 | |
1702 | *Errs << ProgramName << ": Did you mean '" ; |
1703 | if (IsArg) |
1704 | *Errs << PrintArg(NearestArgumentName, 0); |
1705 | else |
1706 | *Errs << NearestArgumentName; |
1707 | *Errs << "'?\n" ; |
1708 | }; |
1709 | |
1710 | if (i > 1 || !MaybeNamedSubCommand) |
1711 | ReportUnknownArgument(/*IsArg=*/true, NearestHandlerString); |
1712 | else |
1713 | ReportUnknownArgument(/*IsArg=*/false, NearestSubCommandString); |
1714 | |
1715 | ErrorParsing = true; |
1716 | continue; |
1717 | } |
1718 | |
1719 | // If this is a named positional argument, just remember that it is the |
1720 | // active one... |
1721 | if (Handler->getFormattingFlag() == cl::Positional) { |
1722 | if ((Handler->getMiscFlags() & PositionalEatsArgs) && !Value.empty()) { |
1723 | Handler->error(Message: "This argument does not take a value.\n" |
1724 | "\tInstead, it consumes any positional arguments until " |
1725 | "the next recognized option." , Errs&: *Errs); |
1726 | ErrorParsing = true; |
1727 | } |
1728 | ActivePositionalArg = Handler; |
1729 | } |
1730 | else |
1731 | ErrorParsing |= ProvideOption(Handler, ArgName, Value, argc, argv, i); |
1732 | } |
1733 | |
1734 | // Check and handle positional arguments now... |
1735 | if (NumPositionalRequired > PositionalVals.size()) { |
1736 | *Errs << ProgramName |
1737 | << ": Not enough positional command line arguments specified!\n" |
1738 | << "Must specify at least " << NumPositionalRequired |
1739 | << " positional argument" << (NumPositionalRequired > 1 ? "s" : "" ) |
1740 | << ": See: " << argv[0] << " --help\n" ; |
1741 | |
1742 | ErrorParsing = true; |
1743 | } else if (!HasUnlimitedPositionals && |
1744 | PositionalVals.size() > PositionalOpts.size()) { |
1745 | *Errs << ProgramName << ": Too many positional arguments specified!\n" |
1746 | << "Can specify at most " << PositionalOpts.size() |
1747 | << " positional arguments: See: " << argv[0] << " --help\n" ; |
1748 | ErrorParsing = true; |
1749 | |
1750 | } else if (!ConsumeAfterOpt) { |
1751 | // Positional args have already been handled if ConsumeAfter is specified. |
1752 | unsigned ValNo = 0, NumVals = static_cast<unsigned>(PositionalVals.size()); |
1753 | for (Option *Opt : PositionalOpts) { |
1754 | if (RequiresValue(O: Opt)) { |
1755 | ProvidePositionalOption(Handler: Opt, Arg: PositionalVals[ValNo].first, |
1756 | i: PositionalVals[ValNo].second); |
1757 | ValNo++; |
1758 | --NumPositionalRequired; // We fulfilled our duty... |
1759 | } |
1760 | |
1761 | // If we _can_ give this option more arguments, do so now, as long as we |
1762 | // do not give it values that others need. 'Done' controls whether the |
1763 | // option even _WANTS_ any more. |
1764 | // |
1765 | bool Done = Opt->getNumOccurrencesFlag() == cl::Required; |
1766 | while (NumVals - ValNo > NumPositionalRequired && !Done) { |
1767 | switch (Opt->getNumOccurrencesFlag()) { |
1768 | case cl::Optional: |
1769 | Done = true; // Optional arguments want _at most_ one value |
1770 | [[fallthrough]]; |
1771 | case cl::ZeroOrMore: // Zero or more will take all they can get... |
1772 | case cl::OneOrMore: // One or more will take all they can get... |
1773 | ProvidePositionalOption(Handler: Opt, Arg: PositionalVals[ValNo].first, |
1774 | i: PositionalVals[ValNo].second); |
1775 | ValNo++; |
1776 | break; |
1777 | default: |
1778 | llvm_unreachable("Internal error, unexpected NumOccurrences flag in " |
1779 | "positional argument processing!" ); |
1780 | } |
1781 | } |
1782 | } |
1783 | } else { |
1784 | assert(ConsumeAfterOpt && NumPositionalRequired <= PositionalVals.size()); |
1785 | unsigned ValNo = 0; |
1786 | for (Option *Opt : PositionalOpts) |
1787 | if (RequiresValue(O: Opt)) { |
1788 | ErrorParsing |= ProvidePositionalOption( |
1789 | Handler: Opt, Arg: PositionalVals[ValNo].first, i: PositionalVals[ValNo].second); |
1790 | ValNo++; |
1791 | } |
1792 | |
1793 | // Handle the case where there is just one positional option, and it's |
1794 | // optional. In this case, we want to give JUST THE FIRST option to the |
1795 | // positional option and keep the rest for the consume after. The above |
1796 | // loop would have assigned no values to positional options in this case. |
1797 | // |
1798 | if (PositionalOpts.size() == 1 && ValNo == 0 && !PositionalVals.empty()) { |
1799 | ErrorParsing |= ProvidePositionalOption(Handler: PositionalOpts[0], |
1800 | Arg: PositionalVals[ValNo].first, |
1801 | i: PositionalVals[ValNo].second); |
1802 | ValNo++; |
1803 | } |
1804 | |
1805 | // Handle over all of the rest of the arguments to the |
1806 | // cl::ConsumeAfter command line option... |
1807 | for (; ValNo != PositionalVals.size(); ++ValNo) |
1808 | ErrorParsing |= |
1809 | ProvidePositionalOption(Handler: ConsumeAfterOpt, Arg: PositionalVals[ValNo].first, |
1810 | i: PositionalVals[ValNo].second); |
1811 | } |
1812 | |
1813 | // Loop over args and make sure all required args are specified! |
1814 | for (const auto &Opt : OptionsMap) { |
1815 | switch (Opt.second->getNumOccurrencesFlag()) { |
1816 | case Required: |
1817 | case OneOrMore: |
1818 | if (Opt.second->getNumOccurrences() == 0) { |
1819 | Opt.second->error(Message: "must be specified at least once!" ); |
1820 | ErrorParsing = true; |
1821 | } |
1822 | [[fallthrough]]; |
1823 | default: |
1824 | break; |
1825 | } |
1826 | } |
1827 | |
1828 | // Now that we know if -debug is specified, we can use it. |
1829 | // Note that if ReadResponseFiles == true, this must be done before the |
1830 | // memory allocated for the expanded command line is free()d below. |
1831 | LLVM_DEBUG(dbgs() << "Args: " ; |
1832 | for (int i = 0; i < argc; ++i) dbgs() << argv[i] << ' '; |
1833 | dbgs() << '\n';); |
1834 | |
1835 | // Free all of the memory allocated to the map. Command line options may only |
1836 | // be processed once! |
1837 | MoreHelp.clear(); |
1838 | |
1839 | // If we had an error processing our arguments, don't let the program execute |
1840 | if (ErrorParsing) { |
1841 | if (!IgnoreErrors) |
1842 | exit(status: 1); |
1843 | return false; |
1844 | } |
1845 | return true; |
1846 | } |
1847 | |
1848 | //===----------------------------------------------------------------------===// |
1849 | // Option Base class implementation |
1850 | // |
1851 | |
1852 | bool Option::error(const Twine &Message, StringRef ArgName, raw_ostream &Errs) { |
1853 | if (!ArgName.data()) |
1854 | ArgName = ArgStr; |
1855 | if (ArgName.empty()) |
1856 | Errs << HelpStr; // Be nice for positional arguments |
1857 | else |
1858 | Errs << GlobalParser->ProgramName << ": for the " << PrintArg(ArgName, 0); |
1859 | |
1860 | Errs << " option: " << Message << "\n" ; |
1861 | return true; |
1862 | } |
1863 | |
1864 | bool Option::addOccurrence(unsigned pos, StringRef ArgName, StringRef Value, |
1865 | bool MultiArg) { |
1866 | if (!MultiArg) |
1867 | NumOccurrences++; // Increment the number of times we have been seen |
1868 | |
1869 | return handleOccurrence(pos, ArgName, Arg: Value); |
1870 | } |
1871 | |
1872 | // getValueStr - Get the value description string, using "DefaultMsg" if nothing |
1873 | // has been specified yet. |
1874 | // |
1875 | static StringRef getValueStr(const Option &O, StringRef DefaultMsg) { |
1876 | if (O.ValueStr.empty()) |
1877 | return DefaultMsg; |
1878 | return O.ValueStr; |
1879 | } |
1880 | |
1881 | //===----------------------------------------------------------------------===// |
1882 | // cl::alias class implementation |
1883 | // |
1884 | |
1885 | // Return the width of the option tag for printing... |
1886 | size_t alias::getOptionWidth() const { |
1887 | return argPlusPrefixesSize(ArgName: ArgStr); |
1888 | } |
1889 | |
1890 | void Option::printHelpStr(StringRef HelpStr, size_t Indent, |
1891 | size_t FirstLineIndentedBy) { |
1892 | assert(Indent >= FirstLineIndentedBy); |
1893 | std::pair<StringRef, StringRef> Split = HelpStr.split(Separator: '\n'); |
1894 | outs().indent(NumSpaces: Indent - FirstLineIndentedBy) |
1895 | << ArgHelpPrefix << Split.first << "\n" ; |
1896 | while (!Split.second.empty()) { |
1897 | Split = Split.second.split(Separator: '\n'); |
1898 | outs().indent(NumSpaces: Indent) << Split.first << "\n" ; |
1899 | } |
1900 | } |
1901 | |
1902 | void Option::printEnumValHelpStr(StringRef HelpStr, size_t BaseIndent, |
1903 | size_t FirstLineIndentedBy) { |
1904 | const StringRef ValHelpPrefix = " " ; |
1905 | assert(BaseIndent >= FirstLineIndentedBy); |
1906 | std::pair<StringRef, StringRef> Split = HelpStr.split(Separator: '\n'); |
1907 | outs().indent(NumSpaces: BaseIndent - FirstLineIndentedBy) |
1908 | << ArgHelpPrefix << ValHelpPrefix << Split.first << "\n" ; |
1909 | while (!Split.second.empty()) { |
1910 | Split = Split.second.split(Separator: '\n'); |
1911 | outs().indent(NumSpaces: BaseIndent + ValHelpPrefix.size()) << Split.first << "\n" ; |
1912 | } |
1913 | } |
1914 | |
1915 | // Print out the option for the alias. |
1916 | void alias::printOptionInfo(size_t GlobalWidth) const { |
1917 | outs() << PrintArg(ArgStr); |
1918 | printHelpStr(HelpStr, Indent: GlobalWidth, FirstLineIndentedBy: argPlusPrefixesSize(ArgName: ArgStr)); |
1919 | } |
1920 | |
1921 | //===----------------------------------------------------------------------===// |
1922 | // Parser Implementation code... |
1923 | // |
1924 | |
1925 | // basic_parser implementation |
1926 | // |
1927 | |
1928 | // Return the width of the option tag for printing... |
1929 | size_t basic_parser_impl::getOptionWidth(const Option &O) const { |
1930 | size_t Len = argPlusPrefixesSize(ArgName: O.ArgStr); |
1931 | auto ValName = getValueName(); |
1932 | if (!ValName.empty()) { |
1933 | size_t FormattingLen = 3; |
1934 | if (O.getMiscFlags() & PositionalEatsArgs) |
1935 | FormattingLen = 6; |
1936 | Len += getValueStr(O, DefaultMsg: ValName).size() + FormattingLen; |
1937 | } |
1938 | |
1939 | return Len; |
1940 | } |
1941 | |
1942 | // printOptionInfo - Print out information about this option. The |
1943 | // to-be-maintained width is specified. |
1944 | // |
1945 | void basic_parser_impl::printOptionInfo(const Option &O, |
1946 | size_t GlobalWidth) const { |
1947 | outs() << PrintArg(O.ArgStr); |
1948 | |
1949 | auto ValName = getValueName(); |
1950 | if (!ValName.empty()) { |
1951 | if (O.getMiscFlags() & PositionalEatsArgs) { |
1952 | outs() << " <" << getValueStr(O, DefaultMsg: ValName) << ">..." ; |
1953 | } else if (O.getValueExpectedFlag() == ValueOptional) |
1954 | outs() << "[=<" << getValueStr(O, DefaultMsg: ValName) << ">]" ; |
1955 | else { |
1956 | outs() << (O.ArgStr.size() == 1 ? " <" : "=<" ) << getValueStr(O, DefaultMsg: ValName) |
1957 | << '>'; |
1958 | } |
1959 | } |
1960 | |
1961 | Option::printHelpStr(HelpStr: O.HelpStr, Indent: GlobalWidth, FirstLineIndentedBy: getOptionWidth(O)); |
1962 | } |
1963 | |
1964 | void basic_parser_impl::printOptionName(const Option &O, |
1965 | size_t GlobalWidth) const { |
1966 | outs() << PrintArg(O.ArgStr); |
1967 | outs().indent(NumSpaces: GlobalWidth - O.ArgStr.size()); |
1968 | } |
1969 | |
1970 | // parser<bool> implementation |
1971 | // |
1972 | bool parser<bool>::parse(Option &O, StringRef ArgName, StringRef Arg, |
1973 | bool &Value) { |
1974 | return parseBool<bool, true, false>(O, ArgName, Arg, Value); |
1975 | } |
1976 | |
1977 | // parser<boolOrDefault> implementation |
1978 | // |
1979 | bool parser<boolOrDefault>::parse(Option &O, StringRef ArgName, StringRef Arg, |
1980 | boolOrDefault &Value) { |
1981 | return parseBool<boolOrDefault, BOU_TRUE, BOU_FALSE>(O, ArgName, Arg, Value); |
1982 | } |
1983 | |
1984 | // parser<int> implementation |
1985 | // |
1986 | bool parser<int>::parse(Option &O, StringRef ArgName, StringRef Arg, |
1987 | int &Value) { |
1988 | if (Arg.getAsInteger(Radix: 0, Result&: Value)) |
1989 | return O.error(Message: "'" + Arg + "' value invalid for integer argument!" ); |
1990 | return false; |
1991 | } |
1992 | |
1993 | // parser<long> implementation |
1994 | // |
1995 | bool parser<long>::parse(Option &O, StringRef ArgName, StringRef Arg, |
1996 | long &Value) { |
1997 | if (Arg.getAsInteger(Radix: 0, Result&: Value)) |
1998 | return O.error(Message: "'" + Arg + "' value invalid for long argument!" ); |
1999 | return false; |
2000 | } |
2001 | |
2002 | // parser<long long> implementation |
2003 | // |
2004 | bool parser<long long>::parse(Option &O, StringRef ArgName, StringRef Arg, |
2005 | long long &Value) { |
2006 | if (Arg.getAsInteger(Radix: 0, Result&: Value)) |
2007 | return O.error(Message: "'" + Arg + "' value invalid for llong argument!" ); |
2008 | return false; |
2009 | } |
2010 | |
2011 | // parser<unsigned> implementation |
2012 | // |
2013 | bool parser<unsigned>::parse(Option &O, StringRef ArgName, StringRef Arg, |
2014 | unsigned &Value) { |
2015 | |
2016 | if (Arg.getAsInteger(Radix: 0, Result&: Value)) |
2017 | return O.error(Message: "'" + Arg + "' value invalid for uint argument!" ); |
2018 | return false; |
2019 | } |
2020 | |
2021 | // parser<unsigned long> implementation |
2022 | // |
2023 | bool parser<unsigned long>::parse(Option &O, StringRef ArgName, StringRef Arg, |
2024 | unsigned long &Value) { |
2025 | |
2026 | if (Arg.getAsInteger(Radix: 0, Result&: Value)) |
2027 | return O.error(Message: "'" + Arg + "' value invalid for ulong argument!" ); |
2028 | return false; |
2029 | } |
2030 | |
2031 | // parser<unsigned long long> implementation |
2032 | // |
2033 | bool parser<unsigned long long>::parse(Option &O, StringRef ArgName, |
2034 | StringRef Arg, |
2035 | unsigned long long &Value) { |
2036 | |
2037 | if (Arg.getAsInteger(Radix: 0, Result&: Value)) |
2038 | return O.error(Message: "'" + Arg + "' value invalid for ullong argument!" ); |
2039 | return false; |
2040 | } |
2041 | |
2042 | // parser<double>/parser<float> implementation |
2043 | // |
2044 | static bool parseDouble(Option &O, StringRef Arg, double &Value) { |
2045 | if (to_float(T: Arg, Num&: Value)) |
2046 | return false; |
2047 | return O.error(Message: "'" + Arg + "' value invalid for floating point argument!" ); |
2048 | } |
2049 | |
2050 | bool parser<double>::parse(Option &O, StringRef ArgName, StringRef Arg, |
2051 | double &Val) { |
2052 | return parseDouble(O, Arg, Value&: Val); |
2053 | } |
2054 | |
2055 | bool parser<float>::parse(Option &O, StringRef ArgName, StringRef Arg, |
2056 | float &Val) { |
2057 | double dVal; |
2058 | if (parseDouble(O, Arg, Value&: dVal)) |
2059 | return true; |
2060 | Val = (float)dVal; |
2061 | return false; |
2062 | } |
2063 | |
2064 | // generic_parser_base implementation |
2065 | // |
2066 | |
2067 | // findOption - Return the option number corresponding to the specified |
2068 | // argument string. If the option is not found, getNumOptions() is returned. |
2069 | // |
2070 | unsigned generic_parser_base::findOption(StringRef Name) { |
2071 | unsigned e = getNumOptions(); |
2072 | |
2073 | for (unsigned i = 0; i != e; ++i) { |
2074 | if (getOption(N: i) == Name) |
2075 | return i; |
2076 | } |
2077 | return e; |
2078 | } |
2079 | |
2080 | static StringRef EqValue = "=<value>" ; |
2081 | static StringRef EmptyOption = "<empty>" ; |
2082 | static StringRef OptionPrefix = " =" ; |
2083 | static size_t getOptionPrefixesSize() { |
2084 | return OptionPrefix.size() + ArgHelpPrefix.size(); |
2085 | } |
2086 | |
2087 | static bool shouldPrintOption(StringRef Name, StringRef Description, |
2088 | const Option &O) { |
2089 | return O.getValueExpectedFlag() != ValueOptional || !Name.empty() || |
2090 | !Description.empty(); |
2091 | } |
2092 | |
2093 | // Return the width of the option tag for printing... |
2094 | size_t generic_parser_base::getOptionWidth(const Option &O) const { |
2095 | if (O.hasArgStr()) { |
2096 | size_t Size = |
2097 | argPlusPrefixesSize(ArgName: O.ArgStr) + EqValue.size(); |
2098 | for (unsigned i = 0, e = getNumOptions(); i != e; ++i) { |
2099 | StringRef Name = getOption(N: i); |
2100 | if (!shouldPrintOption(Name, Description: getDescription(N: i), O)) |
2101 | continue; |
2102 | size_t NameSize = Name.empty() ? EmptyOption.size() : Name.size(); |
2103 | Size = std::max(a: Size, b: NameSize + getOptionPrefixesSize()); |
2104 | } |
2105 | return Size; |
2106 | } else { |
2107 | size_t BaseSize = 0; |
2108 | for (unsigned i = 0, e = getNumOptions(); i != e; ++i) |
2109 | BaseSize = std::max(a: BaseSize, b: getOption(N: i).size() + 8); |
2110 | return BaseSize; |
2111 | } |
2112 | } |
2113 | |
2114 | // printOptionInfo - Print out information about this option. The |
2115 | // to-be-maintained width is specified. |
2116 | // |
2117 | void generic_parser_base::printOptionInfo(const Option &O, |
2118 | size_t GlobalWidth) const { |
2119 | if (O.hasArgStr()) { |
2120 | // When the value is optional, first print a line just describing the |
2121 | // option without values. |
2122 | if (O.getValueExpectedFlag() == ValueOptional) { |
2123 | for (unsigned i = 0, e = getNumOptions(); i != e; ++i) { |
2124 | if (getOption(N: i).empty()) { |
2125 | outs() << PrintArg(O.ArgStr); |
2126 | Option::printHelpStr(HelpStr: O.HelpStr, Indent: GlobalWidth, |
2127 | FirstLineIndentedBy: argPlusPrefixesSize(ArgName: O.ArgStr)); |
2128 | break; |
2129 | } |
2130 | } |
2131 | } |
2132 | |
2133 | outs() << PrintArg(O.ArgStr) << EqValue; |
2134 | Option::printHelpStr(HelpStr: O.HelpStr, Indent: GlobalWidth, |
2135 | FirstLineIndentedBy: EqValue.size() + |
2136 | argPlusPrefixesSize(ArgName: O.ArgStr)); |
2137 | for (unsigned i = 0, e = getNumOptions(); i != e; ++i) { |
2138 | StringRef OptionName = getOption(N: i); |
2139 | StringRef Description = getDescription(N: i); |
2140 | if (!shouldPrintOption(Name: OptionName, Description, O)) |
2141 | continue; |
2142 | size_t FirstLineIndent = OptionName.size() + getOptionPrefixesSize(); |
2143 | outs() << OptionPrefix << OptionName; |
2144 | if (OptionName.empty()) { |
2145 | outs() << EmptyOption; |
2146 | assert(FirstLineIndent >= EmptyOption.size()); |
2147 | FirstLineIndent += EmptyOption.size(); |
2148 | } |
2149 | if (!Description.empty()) |
2150 | Option::printEnumValHelpStr(HelpStr: Description, BaseIndent: GlobalWidth, FirstLineIndentedBy: FirstLineIndent); |
2151 | else |
2152 | outs() << '\n'; |
2153 | } |
2154 | } else { |
2155 | if (!O.HelpStr.empty()) |
2156 | outs() << " " << O.HelpStr << '\n'; |
2157 | for (unsigned i = 0, e = getNumOptions(); i != e; ++i) { |
2158 | StringRef Option = getOption(N: i); |
2159 | outs() << " " << PrintArg(Option); |
2160 | Option::printHelpStr(HelpStr: getDescription(N: i), Indent: GlobalWidth, FirstLineIndentedBy: Option.size() + 8); |
2161 | } |
2162 | } |
2163 | } |
2164 | |
2165 | static const size_t MaxOptWidth = 8; // arbitrary spacing for printOptionDiff |
2166 | |
2167 | // printGenericOptionDiff - Print the value of this option and it's default. |
2168 | // |
2169 | // "Generic" options have each value mapped to a name. |
2170 | void generic_parser_base::printGenericOptionDiff( |
2171 | const Option &O, const GenericOptionValue &Value, |
2172 | const GenericOptionValue &Default, size_t GlobalWidth) const { |
2173 | outs() << " " << PrintArg(O.ArgStr); |
2174 | outs().indent(NumSpaces: GlobalWidth - O.ArgStr.size()); |
2175 | |
2176 | unsigned NumOpts = getNumOptions(); |
2177 | for (unsigned i = 0; i != NumOpts; ++i) { |
2178 | if (!Value.compare(V: getOptionValue(N: i))) |
2179 | continue; |
2180 | |
2181 | outs() << "= " << getOption(N: i); |
2182 | size_t L = getOption(N: i).size(); |
2183 | size_t NumSpaces = MaxOptWidth > L ? MaxOptWidth - L : 0; |
2184 | outs().indent(NumSpaces) << " (default: " ; |
2185 | for (unsigned j = 0; j != NumOpts; ++j) { |
2186 | if (!Default.compare(V: getOptionValue(N: j))) |
2187 | continue; |
2188 | outs() << getOption(N: j); |
2189 | break; |
2190 | } |
2191 | outs() << ")\n" ; |
2192 | return; |
2193 | } |
2194 | outs() << "= *unknown option value*\n" ; |
2195 | } |
2196 | |
2197 | // printOptionDiff - Specializations for printing basic value types. |
2198 | // |
2199 | #define PRINT_OPT_DIFF(T) \ |
2200 | void parser<T>::printOptionDiff(const Option &O, T V, OptionValue<T> D, \ |
2201 | size_t GlobalWidth) const { \ |
2202 | printOptionName(O, GlobalWidth); \ |
2203 | std::string Str; \ |
2204 | { \ |
2205 | raw_string_ostream SS(Str); \ |
2206 | SS << V; \ |
2207 | } \ |
2208 | outs() << "= " << Str; \ |
2209 | size_t NumSpaces = \ |
2210 | MaxOptWidth > Str.size() ? MaxOptWidth - Str.size() : 0; \ |
2211 | outs().indent(NumSpaces) << " (default: "; \ |
2212 | if (D.hasValue()) \ |
2213 | outs() << D.getValue(); \ |
2214 | else \ |
2215 | outs() << "*no default*"; \ |
2216 | outs() << ")\n"; \ |
2217 | } |
2218 | |
2219 | PRINT_OPT_DIFF(bool) |
2220 | PRINT_OPT_DIFF(boolOrDefault) |
2221 | PRINT_OPT_DIFF(int) |
2222 | PRINT_OPT_DIFF(long) |
2223 | PRINT_OPT_DIFF(long long) |
2224 | PRINT_OPT_DIFF(unsigned) |
2225 | PRINT_OPT_DIFF(unsigned long) |
2226 | PRINT_OPT_DIFF(unsigned long long) |
2227 | PRINT_OPT_DIFF(double) |
2228 | PRINT_OPT_DIFF(float) |
2229 | PRINT_OPT_DIFF(char) |
2230 | |
2231 | void parser<std::string>::printOptionDiff(const Option &O, StringRef V, |
2232 | const OptionValue<std::string> &D, |
2233 | size_t GlobalWidth) const { |
2234 | printOptionName(O, GlobalWidth); |
2235 | outs() << "= " << V; |
2236 | size_t NumSpaces = MaxOptWidth > V.size() ? MaxOptWidth - V.size() : 0; |
2237 | outs().indent(NumSpaces) << " (default: " ; |
2238 | if (D.hasValue()) |
2239 | outs() << D.getValue(); |
2240 | else |
2241 | outs() << "*no default*" ; |
2242 | outs() << ")\n" ; |
2243 | } |
2244 | |
2245 | // Print a placeholder for options that don't yet support printOptionDiff(). |
2246 | void basic_parser_impl::printOptionNoValue(const Option &O, |
2247 | size_t GlobalWidth) const { |
2248 | printOptionName(O, GlobalWidth); |
2249 | outs() << "= *cannot print option value*\n" ; |
2250 | } |
2251 | |
2252 | //===----------------------------------------------------------------------===// |
2253 | // -help and -help-hidden option implementation |
2254 | // |
2255 | |
2256 | static int OptNameCompare(const std::pair<const char *, Option *> *LHS, |
2257 | const std::pair<const char *, Option *> *RHS) { |
2258 | return strcmp(s1: LHS->first, s2: RHS->first); |
2259 | } |
2260 | |
2261 | static int SubNameCompare(const std::pair<const char *, SubCommand *> *LHS, |
2262 | const std::pair<const char *, SubCommand *> *RHS) { |
2263 | return strcmp(s1: LHS->first, s2: RHS->first); |
2264 | } |
2265 | |
2266 | // Copy Options into a vector so we can sort them as we like. |
2267 | static void sortOpts(StringMap<Option *> &OptMap, |
2268 | SmallVectorImpl<std::pair<const char *, Option *>> &Opts, |
2269 | bool ShowHidden) { |
2270 | SmallPtrSet<Option *, 32> OptionSet; // Duplicate option detection. |
2271 | |
2272 | for (StringMap<Option *>::iterator I = OptMap.begin(), E = OptMap.end(); |
2273 | I != E; ++I) { |
2274 | // Ignore really-hidden options. |
2275 | if (I->second->getOptionHiddenFlag() == ReallyHidden) |
2276 | continue; |
2277 | |
2278 | // Unless showhidden is set, ignore hidden flags. |
2279 | if (I->second->getOptionHiddenFlag() == Hidden && !ShowHidden) |
2280 | continue; |
2281 | |
2282 | // If we've already seen this option, don't add it to the list again. |
2283 | if (!OptionSet.insert(Ptr: I->second).second) |
2284 | continue; |
2285 | |
2286 | Opts.push_back( |
2287 | Elt: std::pair<const char *, Option *>(I->getKey().data(), I->second)); |
2288 | } |
2289 | |
2290 | // Sort the options list alphabetically. |
2291 | array_pod_sort(Start: Opts.begin(), End: Opts.end(), Compare: OptNameCompare); |
2292 | } |
2293 | |
2294 | static void |
2295 | sortSubCommands(const SmallPtrSetImpl<SubCommand *> &SubMap, |
2296 | SmallVectorImpl<std::pair<const char *, SubCommand *>> &Subs) { |
2297 | for (auto *S : SubMap) { |
2298 | if (S->getName().empty()) |
2299 | continue; |
2300 | Subs.push_back(Elt: std::make_pair(x: S->getName().data(), y&: S)); |
2301 | } |
2302 | array_pod_sort(Start: Subs.begin(), End: Subs.end(), Compare: SubNameCompare); |
2303 | } |
2304 | |
2305 | namespace { |
2306 | |
2307 | class HelpPrinter { |
2308 | protected: |
2309 | const bool ShowHidden; |
2310 | typedef SmallVector<std::pair<const char *, Option *>, 128> |
2311 | StrOptionPairVector; |
2312 | typedef SmallVector<std::pair<const char *, SubCommand *>, 128> |
2313 | StrSubCommandPairVector; |
2314 | // Print the options. Opts is assumed to be alphabetically sorted. |
2315 | virtual void printOptions(StrOptionPairVector &Opts, size_t MaxArgLen) { |
2316 | for (const auto &Opt : Opts) |
2317 | Opt.second->printOptionInfo(GlobalWidth: MaxArgLen); |
2318 | } |
2319 | |
2320 | void printSubCommands(StrSubCommandPairVector &Subs, size_t MaxSubLen) { |
2321 | for (const auto &S : Subs) { |
2322 | outs() << " " << S.first; |
2323 | if (!S.second->getDescription().empty()) { |
2324 | outs().indent(NumSpaces: MaxSubLen - strlen(s: S.first)); |
2325 | outs() << " - " << S.second->getDescription(); |
2326 | } |
2327 | outs() << "\n" ; |
2328 | } |
2329 | } |
2330 | |
2331 | public: |
2332 | explicit HelpPrinter(bool showHidden) : ShowHidden(showHidden) {} |
2333 | virtual ~HelpPrinter() = default; |
2334 | |
2335 | // Invoke the printer. |
2336 | void operator=(bool Value) { |
2337 | if (!Value) |
2338 | return; |
2339 | printHelp(); |
2340 | |
2341 | // Halt the program since help information was printed |
2342 | exit(status: 0); |
2343 | } |
2344 | |
2345 | void printHelp() { |
2346 | SubCommand *Sub = GlobalParser->getActiveSubCommand(); |
2347 | auto &OptionsMap = Sub->OptionsMap; |
2348 | auto &PositionalOpts = Sub->PositionalOpts; |
2349 | auto &ConsumeAfterOpt = Sub->ConsumeAfterOpt; |
2350 | |
2351 | StrOptionPairVector Opts; |
2352 | sortOpts(OptMap&: OptionsMap, Opts, ShowHidden); |
2353 | |
2354 | StrSubCommandPairVector Subs; |
2355 | sortSubCommands(SubMap: GlobalParser->RegisteredSubCommands, Subs); |
2356 | |
2357 | if (!GlobalParser->ProgramOverview.empty()) |
2358 | outs() << "OVERVIEW: " << GlobalParser->ProgramOverview << "\n" ; |
2359 | |
2360 | if (Sub == &SubCommand::getTopLevel()) { |
2361 | outs() << "USAGE: " << GlobalParser->ProgramName; |
2362 | if (!Subs.empty()) |
2363 | outs() << " [subcommand]" ; |
2364 | outs() << " [options]" ; |
2365 | } else { |
2366 | if (!Sub->getDescription().empty()) { |
2367 | outs() << "SUBCOMMAND '" << Sub->getName() |
2368 | << "': " << Sub->getDescription() << "\n\n" ; |
2369 | } |
2370 | outs() << "USAGE: " << GlobalParser->ProgramName << " " << Sub->getName() |
2371 | << " [options]" ; |
2372 | } |
2373 | |
2374 | for (auto *Opt : PositionalOpts) { |
2375 | if (Opt->hasArgStr()) |
2376 | outs() << " --" << Opt->ArgStr; |
2377 | outs() << " " << Opt->HelpStr; |
2378 | } |
2379 | |
2380 | // Print the consume after option info if it exists... |
2381 | if (ConsumeAfterOpt) |
2382 | outs() << " " << ConsumeAfterOpt->HelpStr; |
2383 | |
2384 | if (Sub == &SubCommand::getTopLevel() && !Subs.empty()) { |
2385 | // Compute the maximum subcommand length... |
2386 | size_t MaxSubLen = 0; |
2387 | for (const auto &Sub : Subs) |
2388 | MaxSubLen = std::max(a: MaxSubLen, b: strlen(s: Sub.first)); |
2389 | |
2390 | outs() << "\n\n" ; |
2391 | outs() << "SUBCOMMANDS:\n\n" ; |
2392 | printSubCommands(Subs, MaxSubLen); |
2393 | outs() << "\n" ; |
2394 | outs() << " Type \"" << GlobalParser->ProgramName |
2395 | << " <subcommand> --help\" to get more help on a specific " |
2396 | "subcommand" ; |
2397 | } |
2398 | |
2399 | outs() << "\n\n" ; |
2400 | |
2401 | // Compute the maximum argument length... |
2402 | size_t MaxArgLen = 0; |
2403 | for (const auto &Opt : Opts) |
2404 | MaxArgLen = std::max(a: MaxArgLen, b: Opt.second->getOptionWidth()); |
2405 | |
2406 | outs() << "OPTIONS:\n" ; |
2407 | printOptions(Opts, MaxArgLen); |
2408 | |
2409 | // Print any extra help the user has declared. |
2410 | for (const auto &I : GlobalParser->MoreHelp) |
2411 | outs() << I; |
2412 | GlobalParser->MoreHelp.clear(); |
2413 | } |
2414 | }; |
2415 | |
2416 | class CategorizedHelpPrinter : public HelpPrinter { |
2417 | public: |
2418 | explicit CategorizedHelpPrinter(bool showHidden) : HelpPrinter(showHidden) {} |
2419 | |
2420 | // Helper function for printOptions(). |
2421 | // It shall return a negative value if A's name should be lexicographically |
2422 | // ordered before B's name. It returns a value greater than zero if B's name |
2423 | // should be ordered before A's name, and it returns 0 otherwise. |
2424 | static int OptionCategoryCompare(OptionCategory *const *A, |
2425 | OptionCategory *const *B) { |
2426 | return (*A)->getName().compare(RHS: (*B)->getName()); |
2427 | } |
2428 | |
2429 | // Make sure we inherit our base class's operator=() |
2430 | using HelpPrinter::operator=; |
2431 | |
2432 | protected: |
2433 | void printOptions(StrOptionPairVector &Opts, size_t MaxArgLen) override { |
2434 | std::vector<OptionCategory *> SortedCategories; |
2435 | DenseMap<OptionCategory *, std::vector<Option *>> CategorizedOptions; |
2436 | |
2437 | // Collect registered option categories into vector in preparation for |
2438 | // sorting. |
2439 | llvm::append_range(C&: SortedCategories, |
2440 | R&: GlobalParser->RegisteredOptionCategories); |
2441 | |
2442 | // Sort the different option categories alphabetically. |
2443 | assert(SortedCategories.size() > 0 && "No option categories registered!" ); |
2444 | array_pod_sort(Start: SortedCategories.begin(), End: SortedCategories.end(), |
2445 | Compare: OptionCategoryCompare); |
2446 | |
2447 | // Walk through pre-sorted options and assign into categories. |
2448 | // Because the options are already alphabetically sorted the |
2449 | // options within categories will also be alphabetically sorted. |
2450 | for (const auto &I : Opts) { |
2451 | Option *Opt = I.second; |
2452 | for (OptionCategory *Cat : Opt->Categories) { |
2453 | assert(llvm::is_contained(SortedCategories, Cat) && |
2454 | "Option has an unregistered category" ); |
2455 | CategorizedOptions[Cat].push_back(x: Opt); |
2456 | } |
2457 | } |
2458 | |
2459 | // Now do printing. |
2460 | for (OptionCategory *Category : SortedCategories) { |
2461 | // Hide empty categories for --help, but show for --help-hidden. |
2462 | const auto &CategoryOptions = CategorizedOptions[Category]; |
2463 | if (CategoryOptions.empty()) |
2464 | continue; |
2465 | |
2466 | // Print category information. |
2467 | outs() << "\n" ; |
2468 | outs() << Category->getName() << ":\n" ; |
2469 | |
2470 | // Check if description is set. |
2471 | if (!Category->getDescription().empty()) |
2472 | outs() << Category->getDescription() << "\n\n" ; |
2473 | else |
2474 | outs() << "\n" ; |
2475 | |
2476 | // Loop over the options in the category and print. |
2477 | for (const Option *Opt : CategoryOptions) |
2478 | Opt->printOptionInfo(GlobalWidth: MaxArgLen); |
2479 | } |
2480 | } |
2481 | }; |
2482 | |
2483 | // This wraps the Uncategorizing and Categorizing printers and decides |
2484 | // at run time which should be invoked. |
2485 | class HelpPrinterWrapper { |
2486 | private: |
2487 | HelpPrinter &UncategorizedPrinter; |
2488 | CategorizedHelpPrinter &CategorizedPrinter; |
2489 | |
2490 | public: |
2491 | explicit HelpPrinterWrapper(HelpPrinter &UncategorizedPrinter, |
2492 | CategorizedHelpPrinter &CategorizedPrinter) |
2493 | : UncategorizedPrinter(UncategorizedPrinter), |
2494 | CategorizedPrinter(CategorizedPrinter) {} |
2495 | |
2496 | // Invoke the printer. |
2497 | void operator=(bool Value); |
2498 | }; |
2499 | |
2500 | } // End anonymous namespace |
2501 | |
2502 | #if defined(__GNUC__) |
2503 | // GCC and GCC-compatible compilers define __OPTIMIZE__ when optimizations are |
2504 | // enabled. |
2505 | # if defined(__OPTIMIZE__) |
2506 | # define LLVM_IS_DEBUG_BUILD 0 |
2507 | # else |
2508 | # define LLVM_IS_DEBUG_BUILD 1 |
2509 | # endif |
2510 | #elif defined(_MSC_VER) |
2511 | // MSVC doesn't have a predefined macro indicating if optimizations are enabled. |
2512 | // Use _DEBUG instead. This macro actually corresponds to the choice between |
2513 | // debug and release CRTs, but it is a reasonable proxy. |
2514 | # if defined(_DEBUG) |
2515 | # define LLVM_IS_DEBUG_BUILD 1 |
2516 | # else |
2517 | # define LLVM_IS_DEBUG_BUILD 0 |
2518 | # endif |
2519 | #else |
2520 | // Otherwise, for an unknown compiler, assume this is an optimized build. |
2521 | # define LLVM_IS_DEBUG_BUILD 0 |
2522 | #endif |
2523 | |
2524 | namespace { |
2525 | class VersionPrinter { |
2526 | public: |
2527 | void print(std::vector<VersionPrinterTy> = {}) { |
2528 | raw_ostream &OS = outs(); |
2529 | #ifdef PACKAGE_VENDOR |
2530 | OS << PACKAGE_VENDOR << " " ; |
2531 | #else |
2532 | OS << "LLVM (http://llvm.org/):\n " ; |
2533 | #endif |
2534 | OS << PACKAGE_NAME << " version " << PACKAGE_VERSION << "\n " ; |
2535 | #if LLVM_IS_DEBUG_BUILD |
2536 | OS << "DEBUG build" ; |
2537 | #else |
2538 | OS << "Optimized build" ; |
2539 | #endif |
2540 | #ifndef NDEBUG |
2541 | OS << " with assertions" ; |
2542 | #endif |
2543 | OS << ".\n" ; |
2544 | |
2545 | // Iterate over any registered extra printers and call them to add further |
2546 | // information. |
2547 | if (!ExtraPrinters.empty()) { |
2548 | for (const auto &I : ExtraPrinters) |
2549 | I(outs()); |
2550 | } |
2551 | } |
2552 | void operator=(bool OptionWasSpecified); |
2553 | }; |
2554 | |
2555 | struct CommandLineCommonOptions { |
2556 | // Declare the four HelpPrinter instances that are used to print out help, or |
2557 | // help-hidden as an uncategorized list or in categories. |
2558 | HelpPrinter UncategorizedNormalPrinter{false}; |
2559 | HelpPrinter UncategorizedHiddenPrinter{true}; |
2560 | CategorizedHelpPrinter CategorizedNormalPrinter{false}; |
2561 | CategorizedHelpPrinter CategorizedHiddenPrinter{true}; |
2562 | // Declare HelpPrinter wrappers that will decide whether or not to invoke |
2563 | // a categorizing help printer |
2564 | HelpPrinterWrapper WrappedNormalPrinter{UncategorizedNormalPrinter, |
2565 | CategorizedNormalPrinter}; |
2566 | HelpPrinterWrapper WrappedHiddenPrinter{UncategorizedHiddenPrinter, |
2567 | CategorizedHiddenPrinter}; |
2568 | // Define a category for generic options that all tools should have. |
2569 | cl::OptionCategory GenericCategory{"Generic Options" }; |
2570 | |
2571 | // Define uncategorized help printers. |
2572 | // --help-list is hidden by default because if Option categories are being |
2573 | // used then --help behaves the same as --help-list. |
2574 | cl::opt<HelpPrinter, true, parser<bool>> HLOp{ |
2575 | "help-list" , |
2576 | cl::desc( |
2577 | "Display list of available options (--help-list-hidden for more)" ), |
2578 | cl::location(L&: UncategorizedNormalPrinter), |
2579 | cl::Hidden, |
2580 | cl::ValueDisallowed, |
2581 | cl::cat(GenericCategory), |
2582 | cl::sub(SubCommand::getAll())}; |
2583 | |
2584 | cl::opt<HelpPrinter, true, parser<bool>> HLHOp{ |
2585 | "help-list-hidden" , |
2586 | cl::desc("Display list of all available options" ), |
2587 | cl::location(L&: UncategorizedHiddenPrinter), |
2588 | cl::Hidden, |
2589 | cl::ValueDisallowed, |
2590 | cl::cat(GenericCategory), |
2591 | cl::sub(SubCommand::getAll())}; |
2592 | |
2593 | // Define uncategorized/categorized help printers. These printers change their |
2594 | // behaviour at runtime depending on whether one or more Option categories |
2595 | // have been declared. |
2596 | cl::opt<HelpPrinterWrapper, true, parser<bool>> HOp{ |
2597 | "help" , |
2598 | cl::desc("Display available options (--help-hidden for more)" ), |
2599 | cl::location(L&: WrappedNormalPrinter), |
2600 | cl::ValueDisallowed, |
2601 | cl::cat(GenericCategory), |
2602 | cl::sub(SubCommand::getAll())}; |
2603 | |
2604 | cl::alias HOpA{"h" , cl::desc("Alias for --help" ), cl::aliasopt(HOp), |
2605 | cl::DefaultOption}; |
2606 | |
2607 | cl::opt<HelpPrinterWrapper, true, parser<bool>> HHOp{ |
2608 | "help-hidden" , |
2609 | cl::desc("Display all available options" ), |
2610 | cl::location(L&: WrappedHiddenPrinter), |
2611 | cl::Hidden, |
2612 | cl::ValueDisallowed, |
2613 | cl::cat(GenericCategory), |
2614 | cl::sub(SubCommand::getAll())}; |
2615 | |
2616 | cl::opt<bool> PrintOptions{ |
2617 | "print-options" , |
2618 | cl::desc("Print non-default options after command line parsing" ), |
2619 | cl::Hidden, |
2620 | cl::init(Val: false), |
2621 | cl::cat(GenericCategory), |
2622 | cl::sub(SubCommand::getAll())}; |
2623 | |
2624 | cl::opt<bool> PrintAllOptions{ |
2625 | "print-all-options" , |
2626 | cl::desc("Print all option values after command line parsing" ), |
2627 | cl::Hidden, |
2628 | cl::init(Val: false), |
2629 | cl::cat(GenericCategory), |
2630 | cl::sub(SubCommand::getAll())}; |
2631 | |
2632 | VersionPrinterTy OverrideVersionPrinter = nullptr; |
2633 | |
2634 | std::vector<VersionPrinterTy> ExtraVersionPrinters; |
2635 | |
2636 | // Define the --version option that prints out the LLVM version for the tool |
2637 | VersionPrinter VersionPrinterInstance; |
2638 | |
2639 | cl::opt<VersionPrinter, true, parser<bool>> VersOp{ |
2640 | "version" , cl::desc("Display the version of this program" ), |
2641 | cl::location(L&: VersionPrinterInstance), cl::ValueDisallowed, |
2642 | cl::cat(GenericCategory)}; |
2643 | }; |
2644 | } // End anonymous namespace |
2645 | |
2646 | // Lazy-initialized global instance of options controlling the command-line |
2647 | // parser and general handling. |
2648 | static ManagedStatic<CommandLineCommonOptions> CommonOptions; |
2649 | |
2650 | static void initCommonOptions() { |
2651 | *CommonOptions; |
2652 | initDebugCounterOptions(); |
2653 | initGraphWriterOptions(); |
2654 | initSignalsOptions(); |
2655 | initStatisticOptions(); |
2656 | initTimerOptions(); |
2657 | initTypeSizeOptions(); |
2658 | initWithColorOptions(); |
2659 | initDebugOptions(); |
2660 | initRandomSeedOptions(); |
2661 | } |
2662 | |
2663 | OptionCategory &cl::getGeneralCategory() { |
2664 | // Initialise the general option category. |
2665 | static OptionCategory GeneralCategory{"General options" }; |
2666 | return GeneralCategory; |
2667 | } |
2668 | |
2669 | void VersionPrinter::operator=(bool OptionWasSpecified) { |
2670 | if (!OptionWasSpecified) |
2671 | return; |
2672 | |
2673 | if (CommonOptions->OverrideVersionPrinter != nullptr) { |
2674 | CommonOptions->OverrideVersionPrinter(outs()); |
2675 | exit(status: 0); |
2676 | } |
2677 | print(ExtraPrinters: CommonOptions->ExtraVersionPrinters); |
2678 | |
2679 | exit(status: 0); |
2680 | } |
2681 | |
2682 | void HelpPrinterWrapper::operator=(bool Value) { |
2683 | if (!Value) |
2684 | return; |
2685 | |
2686 | // Decide which printer to invoke. If more than one option category is |
2687 | // registered then it is useful to show the categorized help instead of |
2688 | // uncategorized help. |
2689 | if (GlobalParser->RegisteredOptionCategories.size() > 1) { |
2690 | // unhide --help-list option so user can have uncategorized output if they |
2691 | // want it. |
2692 | CommonOptions->HLOp.setHiddenFlag(NotHidden); |
2693 | |
2694 | CategorizedPrinter = true; // Invoke categorized printer |
2695 | } else { |
2696 | UncategorizedPrinter = true; // Invoke uncategorized printer |
2697 | } |
2698 | } |
2699 | |
2700 | // Print the value of each option. |
2701 | void cl::PrintOptionValues() { GlobalParser->printOptionValues(); } |
2702 | |
2703 | void CommandLineParser::printOptionValues() { |
2704 | if (!CommonOptions->PrintOptions && !CommonOptions->PrintAllOptions) |
2705 | return; |
2706 | |
2707 | SmallVector<std::pair<const char *, Option *>, 128> Opts; |
2708 | sortOpts(OptMap&: ActiveSubCommand->OptionsMap, Opts, /*ShowHidden*/ true); |
2709 | |
2710 | // Compute the maximum argument length... |
2711 | size_t MaxArgLen = 0; |
2712 | for (const auto &Opt : Opts) |
2713 | MaxArgLen = std::max(a: MaxArgLen, b: Opt.second->getOptionWidth()); |
2714 | |
2715 | for (const auto &Opt : Opts) |
2716 | Opt.second->printOptionValue(GlobalWidth: MaxArgLen, Force: CommonOptions->PrintAllOptions); |
2717 | } |
2718 | |
2719 | // Utility function for printing the help message. |
2720 | void cl::PrintHelpMessage(bool Hidden, bool Categorized) { |
2721 | if (!Hidden && !Categorized) |
2722 | CommonOptions->UncategorizedNormalPrinter.printHelp(); |
2723 | else if (!Hidden && Categorized) |
2724 | CommonOptions->CategorizedNormalPrinter.printHelp(); |
2725 | else if (Hidden && !Categorized) |
2726 | CommonOptions->UncategorizedHiddenPrinter.printHelp(); |
2727 | else |
2728 | CommonOptions->CategorizedHiddenPrinter.printHelp(); |
2729 | } |
2730 | |
2731 | ArrayRef<StringRef> cl::getCompilerBuildConfig() { |
2732 | static const StringRef Config[] = { |
2733 | // Placeholder to ensure the array always has elements, since it's an |
2734 | // error to have a zero-sized array. Slice this off before returning. |
2735 | "" , |
2736 | // Actual compiler build config feature list: |
2737 | #if LLVM_IS_DEBUG_BUILD |
2738 | "+unoptimized" , |
2739 | #endif |
2740 | #ifndef NDEBUG |
2741 | "+assertions" , |
2742 | #endif |
2743 | #ifdef EXPENSIVE_CHECKS |
2744 | "+expensive-checks" , |
2745 | #endif |
2746 | #if __has_feature(address_sanitizer) |
2747 | "+asan" , |
2748 | #endif |
2749 | #if __has_feature(dataflow_sanitizer) |
2750 | "+dfsan" , |
2751 | #endif |
2752 | #if __has_feature(hwaddress_sanitizer) |
2753 | "+hwasan" , |
2754 | #endif |
2755 | #if __has_feature(memory_sanitizer) |
2756 | "+msan" , |
2757 | #endif |
2758 | #if __has_feature(thread_sanitizer) |
2759 | "+tsan" , |
2760 | #endif |
2761 | #if __has_feature(undefined_behavior_sanitizer) |
2762 | "+ubsan" , |
2763 | #endif |
2764 | }; |
2765 | return ArrayRef(Config).drop_front(N: 1); |
2766 | } |
2767 | |
2768 | // Utility function for printing the build config. |
2769 | void cl::printBuildConfig(raw_ostream &OS) { |
2770 | #if LLVM_VERSION_PRINTER_SHOW_BUILD_CONFIG |
2771 | OS << "Build config: " ; |
2772 | llvm::interleaveComma(c: cl::getCompilerBuildConfig(), os&: OS); |
2773 | OS << '\n'; |
2774 | #endif |
2775 | } |
2776 | |
2777 | /// Utility function for printing version number. |
2778 | void cl::PrintVersionMessage() { |
2779 | CommonOptions->VersionPrinterInstance.print(ExtraPrinters: CommonOptions->ExtraVersionPrinters); |
2780 | } |
2781 | |
2782 | void cl::SetVersionPrinter(VersionPrinterTy func) { |
2783 | CommonOptions->OverrideVersionPrinter = func; |
2784 | } |
2785 | |
2786 | void cl::(VersionPrinterTy func) { |
2787 | CommonOptions->ExtraVersionPrinters.push_back(x: func); |
2788 | } |
2789 | |
2790 | StringMap<Option *> &cl::getRegisteredOptions(SubCommand &Sub) { |
2791 | initCommonOptions(); |
2792 | auto &Subs = GlobalParser->RegisteredSubCommands; |
2793 | (void)Subs; |
2794 | assert(Subs.contains(&Sub)); |
2795 | return Sub.OptionsMap; |
2796 | } |
2797 | |
2798 | iterator_range<typename SmallPtrSet<SubCommand *, 4>::iterator> |
2799 | cl::getRegisteredSubcommands() { |
2800 | return GlobalParser->getRegisteredSubcommands(); |
2801 | } |
2802 | |
2803 | void cl::HideUnrelatedOptions(cl::OptionCategory &Category, SubCommand &Sub) { |
2804 | initCommonOptions(); |
2805 | for (auto &I : Sub.OptionsMap) { |
2806 | bool Unrelated = true; |
2807 | for (auto &Cat : I.second->Categories) { |
2808 | if (Cat == &Category || Cat == &CommonOptions->GenericCategory) |
2809 | Unrelated = false; |
2810 | } |
2811 | if (Unrelated) |
2812 | I.second->setHiddenFlag(cl::ReallyHidden); |
2813 | } |
2814 | } |
2815 | |
2816 | void cl::HideUnrelatedOptions(ArrayRef<const cl::OptionCategory *> Categories, |
2817 | SubCommand &Sub) { |
2818 | initCommonOptions(); |
2819 | for (auto &I : Sub.OptionsMap) { |
2820 | bool Unrelated = true; |
2821 | for (auto &Cat : I.second->Categories) { |
2822 | if (is_contained(Range&: Categories, Element: Cat) || |
2823 | Cat == &CommonOptions->GenericCategory) |
2824 | Unrelated = false; |
2825 | } |
2826 | if (Unrelated) |
2827 | I.second->setHiddenFlag(cl::ReallyHidden); |
2828 | } |
2829 | } |
2830 | |
2831 | void cl::ResetCommandLineParser() { GlobalParser->reset(); } |
2832 | void cl::ResetAllOptionOccurrences() { |
2833 | GlobalParser->ResetAllOptionOccurrences(); |
2834 | } |
2835 | |
2836 | void LLVMParseCommandLineOptions(int argc, const char *const *argv, |
2837 | const char *Overview) { |
2838 | llvm::cl::ParseCommandLineOptions(argc, argv, Overview: StringRef(Overview), |
2839 | Errs: &llvm::nulls()); |
2840 | } |
2841 | |