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