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