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