mirror of
https://github.com/RPCSX/llvm.git
synced 2025-01-26 14:25:18 +00:00
Revert r274054 to try to appease the bot
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@274072 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
527613bc4e
commit
ba713e39b3
@ -21,12 +21,10 @@
|
||||
#define LLVM_SUPPORT_COMMANDLINE_H
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/ManagedStatic.h"
|
||||
#include <cassert>
|
||||
#include <climits>
|
||||
#include <cstdarg>
|
||||
@ -45,9 +43,8 @@ namespace cl {
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ParseCommandLineOptions - Command line option processing entry point.
|
||||
//
|
||||
bool ParseCommandLineOptions(int argc, const char *const *argv,
|
||||
const char *Overview = nullptr,
|
||||
bool IgnoreErrors = false);
|
||||
void ParseCommandLineOptions(int argc, const char *const *argv,
|
||||
const char *Overview = nullptr);
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ParseEnvironmentOptions - Environment variable option processing alternate
|
||||
@ -173,45 +170,6 @@ public:
|
||||
// The general Option Category (used as default category).
|
||||
extern OptionCategory GeneralCategory;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// SubCommand class
|
||||
//
|
||||
class SubCommand {
|
||||
private:
|
||||
const char *const Name = nullptr;
|
||||
const char *const Description = nullptr;
|
||||
|
||||
protected:
|
||||
void registerSubCommand();
|
||||
void unregisterSubCommand();
|
||||
|
||||
public:
|
||||
SubCommand(const char *const Name, const char *const Description = nullptr)
|
||||
: Name(Name), Description(Description) {
|
||||
registerSubCommand();
|
||||
}
|
||||
SubCommand() {}
|
||||
|
||||
void reset();
|
||||
|
||||
operator bool() const;
|
||||
|
||||
const char *getName() const { return Name; }
|
||||
const char *getDescription() const { return Description; }
|
||||
|
||||
SmallVector<Option *, 4> PositionalOpts;
|
||||
SmallVector<Option *, 4> SinkOpts;
|
||||
StringMap<Option *> OptionsMap;
|
||||
|
||||
Option *ConsumeAfterOpt = nullptr; // The ConsumeAfter option if it exists.
|
||||
};
|
||||
|
||||
// A special subcommand representing no subcommand
|
||||
extern ManagedStatic<SubCommand> TopLevelSubCommand;
|
||||
|
||||
// A special subcommand that can be used to put an option into all subcommands.
|
||||
extern ManagedStatic<SubCommand> AllSubCommands;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Option Base class
|
||||
//
|
||||
@ -251,7 +209,6 @@ public:
|
||||
StringRef HelpStr; // The descriptive text message for -help
|
||||
StringRef ValueStr; // String describing what the value of this option is
|
||||
OptionCategory *Category; // The Category this option belongs to
|
||||
SmallPtrSet<SubCommand *, 4> Subs; // The subcommands this option belongs to.
|
||||
bool FullyInitialized; // Has addArguemnt been called?
|
||||
|
||||
inline enum NumOccurrencesFlag getNumOccurrencesFlag() const {
|
||||
@ -272,16 +229,6 @@ public:
|
||||
|
||||
// hasArgStr - Return true if the argstr != ""
|
||||
bool hasArgStr() const { return !ArgStr.empty(); }
|
||||
bool isPositional() const { return getFormattingFlag() == cl::Positional; }
|
||||
bool isSink() const { return getMiscFlags() & cl::Sink; }
|
||||
bool isConsumeAfter() const {
|
||||
return getNumOccurrencesFlag() == cl::ConsumeAfter;
|
||||
}
|
||||
bool isInAllSubCommands() const {
|
||||
return std::any_of(Subs.begin(), Subs.end(), [](const SubCommand *SC) {
|
||||
return SC == &*AllSubCommands;
|
||||
});
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------===
|
||||
// Accessor functions set by OptionModifiers
|
||||
@ -296,7 +243,6 @@ public:
|
||||
void setMiscFlag(enum MiscFlags M) { Misc |= M; }
|
||||
void setPosition(unsigned pos) { Position = pos; }
|
||||
void setCategory(OptionCategory &C) { Category = &C; }
|
||||
void addSubCommand(SubCommand &S) { Subs.insert(&S); }
|
||||
|
||||
protected:
|
||||
explicit Option(enum NumOccurrencesFlag OccurrencesFlag,
|
||||
@ -341,7 +287,6 @@ public:
|
||||
|
||||
public:
|
||||
inline int getNumOccurrences() const { return NumOccurrences; }
|
||||
inline void reset() { NumOccurrences = 0; }
|
||||
virtual ~Option() {}
|
||||
};
|
||||
|
||||
@ -404,14 +349,6 @@ struct cat {
|
||||
template <class Opt> void apply(Opt &O) const { O.setCategory(Category); }
|
||||
};
|
||||
|
||||
// sub - Specify the subcommand that this option belongs to.
|
||||
struct sub {
|
||||
SubCommand ⋐
|
||||
sub(SubCommand &S) : Sub(S) {}
|
||||
|
||||
template <class Opt> void apply(Opt &O) const { O.addSubCommand(Sub); }
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// OptionValue class
|
||||
|
||||
@ -1652,7 +1589,6 @@ class alias : public Option {
|
||||
error("cl::alias must have argument name specified!");
|
||||
if (!AliasFor)
|
||||
error("cl::alias must have an cl::aliasopt(option) specified!");
|
||||
Subs = AliasFor->Subs;
|
||||
addArgument();
|
||||
}
|
||||
|
||||
@ -1733,7 +1669,7 @@ void PrintHelpMessage(bool Hidden = false, bool Categorized = false);
|
||||
/// Hopefully this API can be depricated soon. Any situation where options need
|
||||
/// to be modified by tools or libraries should be handled by sane APIs rather
|
||||
/// than just handing around a global list.
|
||||
StringMap<Option *> &getRegisteredOptions(SubCommand &Sub);
|
||||
StringMap<Option *> &getRegisteredOptions();
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Standalone command line processing utilities.
|
||||
@ -1801,8 +1737,7 @@ bool ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer,
|
||||
/// Some tools (like clang-format) like to be able to hide all options that are
|
||||
/// not specific to the tool. This function allows a tool to specify a single
|
||||
/// option category to display in the -help output.
|
||||
void HideUnrelatedOptions(cl::OptionCategory &Category,
|
||||
SubCommand &Sub = *TopLevelSubCommand);
|
||||
void HideUnrelatedOptions(cl::OptionCategory &Category);
|
||||
|
||||
/// \brief Mark all options not part of the categories as cl::ReallyHidden.
|
||||
///
|
||||
@ -1811,10 +1746,7 @@ void HideUnrelatedOptions(cl::OptionCategory &Category,
|
||||
/// Some tools (like clang-format) like to be able to hide all options that are
|
||||
/// not specific to the tool. This function allows a tool to specify a single
|
||||
/// option category to display in the -help output.
|
||||
void HideUnrelatedOptions(ArrayRef<const cl::OptionCategory *> Categories,
|
||||
SubCommand &Sub = *TopLevelSubCommand);
|
||||
|
||||
void ResetCommandLineOptions();
|
||||
void HideUnrelatedOptions(ArrayRef<const cl::OptionCategory *> Categories);
|
||||
|
||||
} // End namespace cl
|
||||
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm-c/Support.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
@ -95,54 +94,35 @@ public:
|
||||
// This collects additional help to be printed.
|
||||
std::vector<const char *> MoreHelp;
|
||||
|
||||
SmallVector<Option *, 4> PositionalOpts;
|
||||
SmallVector<Option *, 4> SinkOpts;
|
||||
StringMap<Option *> OptionsMap;
|
||||
|
||||
Option *ConsumeAfterOpt; // The ConsumeAfter option if it exists.
|
||||
|
||||
// This collects the different option categories that have been registered.
|
||||
SmallPtrSet<OptionCategory *, 16> RegisteredOptionCategories;
|
||||
|
||||
// This collects the different subcommands that have been registered.
|
||||
SmallPtrSet<SubCommand *, 4> RegisteredSubCommands;
|
||||
CommandLineParser() : ProgramOverview(nullptr), ConsumeAfterOpt(nullptr) {}
|
||||
|
||||
CommandLineParser() : ProgramOverview(nullptr), ActiveSubCommand(nullptr) {
|
||||
registerSubCommand(&*TopLevelSubCommand);
|
||||
registerSubCommand(&*AllSubCommands);
|
||||
}
|
||||
void ParseCommandLineOptions(int argc, const char *const *argv,
|
||||
const char *Overview);
|
||||
|
||||
bool ParseCommandLineOptions(int argc, const char *const *argv,
|
||||
const char *Overview, bool IgnoreErrors);
|
||||
|
||||
void addLiteralOption(Option &Opt, SubCommand *SC, const char *Name) {
|
||||
if (Opt.hasArgStr())
|
||||
return;
|
||||
if (!SC->OptionsMap.insert(std::make_pair(Name, &Opt)).second) {
|
||||
errs() << ProgramName << ": CommandLine Error: Option '" << Name
|
||||
<< "' registered more than once!\n";
|
||||
report_fatal_error("inconsistency in registered CommandLine options");
|
||||
}
|
||||
|
||||
// If we're adding this to all sub-commands, add it to the ones that have
|
||||
// already been registered.
|
||||
if (SC == &*AllSubCommands) {
|
||||
for (const auto &Sub : RegisteredSubCommands) {
|
||||
if (SC == Sub)
|
||||
continue;
|
||||
addLiteralOption(Opt, Sub, Name);
|
||||
void addLiteralOption(Option &Opt, const char *Name) {
|
||||
if (!Opt.hasArgStr()) {
|
||||
if (!OptionsMap.insert(std::make_pair(Name, &Opt)).second) {
|
||||
errs() << ProgramName << ": CommandLine Error: Option '" << Name
|
||||
<< "' registered more than once!\n";
|
||||
report_fatal_error("inconsistency in registered CommandLine options");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void addLiteralOption(Option &Opt, const char *Name) {
|
||||
if (Opt.Subs.empty())
|
||||
addLiteralOption(Opt, &*TopLevelSubCommand, Name);
|
||||
else {
|
||||
for (auto SC : Opt.Subs)
|
||||
addLiteralOption(Opt, SC, Name);
|
||||
}
|
||||
}
|
||||
|
||||
void addOption(Option *O, SubCommand *SC) {
|
||||
void addOption(Option *O) {
|
||||
bool HadErrors = false;
|
||||
if (O->hasArgStr()) {
|
||||
// Add argument to the argument map!
|
||||
if (!SC->OptionsMap.insert(std::make_pair(O->ArgStr, O)).second) {
|
||||
if (!OptionsMap.insert(std::make_pair(O->ArgStr, O)).second) {
|
||||
errs() << ProgramName << ": CommandLine Error: Option '" << O->ArgStr
|
||||
<< "' registered more than once!\n";
|
||||
HadErrors = true;
|
||||
@ -151,15 +131,15 @@ public:
|
||||
|
||||
// Remember information about positional options.
|
||||
if (O->getFormattingFlag() == cl::Positional)
|
||||
SC->PositionalOpts.push_back(O);
|
||||
PositionalOpts.push_back(O);
|
||||
else if (O->getMiscFlags() & cl::Sink) // Remember sink options
|
||||
SC->SinkOpts.push_back(O);
|
||||
SinkOpts.push_back(O);
|
||||
else if (O->getNumOccurrencesFlag() == cl::ConsumeAfter) {
|
||||
if (SC->ConsumeAfterOpt) {
|
||||
if (ConsumeAfterOpt) {
|
||||
O->error("Cannot specify more than one option with cl::ConsumeAfter!");
|
||||
HadErrors = true;
|
||||
}
|
||||
SC->ConsumeAfterOpt = O;
|
||||
ConsumeAfterOpt = O;
|
||||
}
|
||||
|
||||
// Fail hard if there were errors. These are strictly unrecoverable and
|
||||
@ -168,102 +148,47 @@ public:
|
||||
// linked LLVM distribution.
|
||||
if (HadErrors)
|
||||
report_fatal_error("inconsistency in registered CommandLine options");
|
||||
|
||||
// If we're adding this to all sub-commands, add it to the ones that have
|
||||
// already been registered.
|
||||
if (SC == &*AllSubCommands) {
|
||||
for (const auto &Sub : RegisteredSubCommands) {
|
||||
if (SC == Sub)
|
||||
continue;
|
||||
addOption(O, Sub);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void addOption(Option *O) {
|
||||
if (O->Subs.empty()) {
|
||||
addOption(O, &*TopLevelSubCommand);
|
||||
} else {
|
||||
for (auto SC : O->Subs)
|
||||
addOption(O, SC);
|
||||
}
|
||||
}
|
||||
|
||||
void removeOption(Option *O, SubCommand *SC) {
|
||||
void removeOption(Option *O) {
|
||||
SmallVector<StringRef, 16> OptionNames;
|
||||
O->getExtraOptionNames(OptionNames);
|
||||
if (O->hasArgStr())
|
||||
OptionNames.push_back(O->ArgStr);
|
||||
|
||||
SubCommand &Sub = *SC;
|
||||
for (auto Name : OptionNames)
|
||||
Sub.OptionsMap.erase(Name);
|
||||
OptionsMap.erase(Name);
|
||||
|
||||
if (O->getFormattingFlag() == cl::Positional)
|
||||
for (auto Opt = Sub.PositionalOpts.begin();
|
||||
Opt != Sub.PositionalOpts.end(); ++Opt) {
|
||||
for (auto Opt = PositionalOpts.begin(); Opt != PositionalOpts.end();
|
||||
++Opt) {
|
||||
if (*Opt == O) {
|
||||
Sub.PositionalOpts.erase(Opt);
|
||||
PositionalOpts.erase(Opt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (O->getMiscFlags() & cl::Sink)
|
||||
for (auto Opt = Sub.SinkOpts.begin(); Opt != Sub.SinkOpts.end(); ++Opt) {
|
||||
for (auto Opt = SinkOpts.begin(); Opt != SinkOpts.end(); ++Opt) {
|
||||
if (*Opt == O) {
|
||||
Sub.SinkOpts.erase(Opt);
|
||||
SinkOpts.erase(Opt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (O == Sub.ConsumeAfterOpt)
|
||||
Sub.ConsumeAfterOpt = nullptr;
|
||||
else if (O == ConsumeAfterOpt)
|
||||
ConsumeAfterOpt = nullptr;
|
||||
}
|
||||
|
||||
void removeOption(Option *O) {
|
||||
if (O->Subs.empty())
|
||||
removeOption(O, &*TopLevelSubCommand);
|
||||
else {
|
||||
if (O->isInAllSubCommands()) {
|
||||
for (auto SC : RegisteredSubCommands)
|
||||
removeOption(O, SC);
|
||||
} else {
|
||||
for (auto SC : O->Subs)
|
||||
removeOption(O, SC);
|
||||
}
|
||||
}
|
||||
bool hasOptions() {
|
||||
return (!OptionsMap.empty() || !PositionalOpts.empty() ||
|
||||
nullptr != ConsumeAfterOpt);
|
||||
}
|
||||
|
||||
bool hasOptions(const SubCommand &Sub) const {
|
||||
return (!Sub.OptionsMap.empty() || !Sub.PositionalOpts.empty() ||
|
||||
nullptr != Sub.ConsumeAfterOpt);
|
||||
}
|
||||
|
||||
bool hasOptions() const {
|
||||
for (const auto &S : RegisteredSubCommands) {
|
||||
if (hasOptions(*S))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
SubCommand *getActiveSubCommand() { return ActiveSubCommand; }
|
||||
|
||||
void updateArgStr(Option *O, StringRef NewName, SubCommand *SC) {
|
||||
SubCommand &Sub = *SC;
|
||||
if (!Sub.OptionsMap.insert(std::make_pair(NewName, O)).second) {
|
||||
void updateArgStr(Option *O, StringRef NewName) {
|
||||
if (!OptionsMap.insert(std::make_pair(NewName, O)).second) {
|
||||
errs() << ProgramName << ": CommandLine Error: Option '" << O->ArgStr
|
||||
<< "' registered more than once!\n";
|
||||
report_fatal_error("inconsistency in registered CommandLine options");
|
||||
}
|
||||
Sub.OptionsMap.erase(O->ArgStr);
|
||||
}
|
||||
|
||||
void updateArgStr(Option *O, StringRef NewName) {
|
||||
if (O->Subs.empty())
|
||||
updateArgStr(O, NewName, &*TopLevelSubCommand);
|
||||
else {
|
||||
for (auto SC : O->Subs)
|
||||
updateArgStr(O, NewName, SC);
|
||||
}
|
||||
OptionsMap.erase(O->ArgStr);
|
||||
}
|
||||
|
||||
void printOptionValues();
|
||||
@ -278,58 +203,8 @@ public:
|
||||
RegisteredOptionCategories.insert(cat);
|
||||
}
|
||||
|
||||
void registerSubCommand(SubCommand *sub) {
|
||||
assert(count_if(RegisteredSubCommands,
|
||||
[sub](const SubCommand *Sub) {
|
||||
return (sub->getName() != nullptr) &&
|
||||
(Sub->getName() == sub->getName());
|
||||
}) == 0 &&
|
||||
"Duplicate subcommands");
|
||||
RegisteredSubCommands.insert(sub);
|
||||
|
||||
// For all options that have been registered for all subcommands, add the
|
||||
// option to this subcommand now.
|
||||
if (sub != &*AllSubCommands) {
|
||||
for (auto &E : AllSubCommands->OptionsMap) {
|
||||
Option *O = E.second;
|
||||
if ((O->isPositional() || O->isSink() || O->isConsumeAfter()) ||
|
||||
O->hasArgStr())
|
||||
addOption(O, sub);
|
||||
else
|
||||
addLiteralOption(*O, sub, E.first().str().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void unregisterSubCommand(SubCommand *sub) {
|
||||
RegisteredSubCommands.erase(sub);
|
||||
}
|
||||
|
||||
void reset() {
|
||||
ActiveSubCommand = nullptr;
|
||||
ProgramName.clear();
|
||||
ProgramOverview = nullptr;
|
||||
|
||||
MoreHelp.clear();
|
||||
RegisteredOptionCategories.clear();
|
||||
|
||||
for (auto SC : RegisteredSubCommands) {
|
||||
for (auto &O : SC->OptionsMap)
|
||||
O.second->reset();
|
||||
}
|
||||
RegisteredSubCommands.clear();
|
||||
|
||||
TopLevelSubCommand->reset();
|
||||
AllSubCommands->reset();
|
||||
registerSubCommand(&*TopLevelSubCommand);
|
||||
registerSubCommand(&*AllSubCommands);
|
||||
}
|
||||
|
||||
private:
|
||||
SubCommand *ActiveSubCommand;
|
||||
|
||||
Option *LookupOption(SubCommand &Sub, StringRef &Arg, StringRef &Value);
|
||||
SubCommand *LookupSubCommand(const char *Name);
|
||||
Option *LookupOption(StringRef &Arg, StringRef &Value);
|
||||
};
|
||||
|
||||
} // namespace
|
||||
@ -364,32 +239,6 @@ void OptionCategory::registerCategory() {
|
||||
GlobalParser->registerCategory(this);
|
||||
}
|
||||
|
||||
// A special subcommand representing no subcommand
|
||||
ManagedStatic<SubCommand> llvm::cl::TopLevelSubCommand;
|
||||
|
||||
// A special subcommand that can be used to put an option into all subcommands.
|
||||
ManagedStatic<SubCommand> llvm::cl::AllSubCommands;
|
||||
|
||||
void SubCommand::registerSubCommand() {
|
||||
GlobalParser->registerSubCommand(this);
|
||||
}
|
||||
|
||||
void SubCommand::unregisterSubCommand() {
|
||||
GlobalParser->unregisterSubCommand(this);
|
||||
}
|
||||
|
||||
void SubCommand::reset() {
|
||||
PositionalOpts.clear();
|
||||
SinkOpts.clear();
|
||||
OptionsMap.clear();
|
||||
|
||||
ConsumeAfterOpt = nullptr;
|
||||
}
|
||||
|
||||
SubCommand::operator bool() const {
|
||||
return (GlobalParser->getActiveSubCommand() == this);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Basic, shared command line option processing machinery.
|
||||
//
|
||||
@ -397,29 +246,25 @@ SubCommand::operator bool() const {
|
||||
/// LookupOption - Lookup the option specified by the specified option on the
|
||||
/// command line. If there is a value specified (after an equal sign) return
|
||||
/// that as well. This assumes that leading dashes have already been stripped.
|
||||
Option *CommandLineParser::LookupOption(SubCommand &Sub, StringRef &Arg,
|
||||
StringRef &Value) {
|
||||
Option *CommandLineParser::LookupOption(StringRef &Arg, StringRef &Value) {
|
||||
// Reject all dashes.
|
||||
if (Arg.empty())
|
||||
return nullptr;
|
||||
assert(&Sub != &*AllSubCommands);
|
||||
|
||||
size_t EqualPos = Arg.find('=');
|
||||
|
||||
// If we have an equals sign, remember the value.
|
||||
if (EqualPos == StringRef::npos) {
|
||||
// Look up the option.
|
||||
auto I = Sub.OptionsMap.find(Arg);
|
||||
if (I == Sub.OptionsMap.end())
|
||||
return nullptr;
|
||||
|
||||
return I != Sub.OptionsMap.end() ? I->second : nullptr;
|
||||
StringMap<Option *>::const_iterator I = OptionsMap.find(Arg);
|
||||
return I != OptionsMap.end() ? I->second : nullptr;
|
||||
}
|
||||
|
||||
// If the argument before the = is a valid option name, we match. If not,
|
||||
// return Arg unmolested.
|
||||
auto I = Sub.OptionsMap.find(Arg.substr(0, EqualPos));
|
||||
if (I == Sub.OptionsMap.end())
|
||||
StringMap<Option *>::const_iterator I =
|
||||
OptionsMap.find(Arg.substr(0, EqualPos));
|
||||
if (I == OptionsMap.end())
|
||||
return nullptr;
|
||||
|
||||
Value = Arg.substr(EqualPos + 1);
|
||||
@ -427,21 +272,6 @@ Option *CommandLineParser::LookupOption(SubCommand &Sub, StringRef &Arg,
|
||||
return I->second;
|
||||
}
|
||||
|
||||
SubCommand *CommandLineParser::LookupSubCommand(const char *Name) {
|
||||
if (Name == nullptr)
|
||||
return &*TopLevelSubCommand;
|
||||
for (auto S : RegisteredSubCommands) {
|
||||
if (S == &*AllSubCommands)
|
||||
continue;
|
||||
if (S->getName() == nullptr)
|
||||
continue;
|
||||
|
||||
if (StringRef(S->getName()) == StringRef(Name))
|
||||
return S;
|
||||
}
|
||||
return &*TopLevelSubCommand;
|
||||
}
|
||||
|
||||
/// LookupNearestOption - Lookup the closest match to the option specified by
|
||||
/// the specified option on the command line. If there is a value specified
|
||||
/// (after an equal sign) return that as well. This assumes that leading dashes
|
||||
@ -990,16 +820,14 @@ void cl::ParseEnvironmentOptions(const char *progName, const char *envVar,
|
||||
ParseCommandLineOptions(newArgc, &newArgv[0], Overview);
|
||||
}
|
||||
|
||||
bool cl::ParseCommandLineOptions(int argc, const char *const *argv,
|
||||
const char *Overview, bool IgnoreErrors) {
|
||||
return GlobalParser->ParseCommandLineOptions(argc, argv, Overview,
|
||||
IgnoreErrors);
|
||||
void cl::ParseCommandLineOptions(int argc, const char *const *argv,
|
||||
const char *Overview) {
|
||||
GlobalParser->ParseCommandLineOptions(argc, argv, Overview);
|
||||
}
|
||||
|
||||
bool CommandLineParser::ParseCommandLineOptions(int argc,
|
||||
void CommandLineParser::ParseCommandLineOptions(int argc,
|
||||
const char *const *argv,
|
||||
const char *Overview,
|
||||
bool IgnoreErrors) {
|
||||
const char *Overview) {
|
||||
assert(hasOptions() && "No options specified!");
|
||||
|
||||
// Expand response files.
|
||||
@ -1022,30 +850,6 @@ bool CommandLineParser::ParseCommandLineOptions(int argc,
|
||||
// Determine whether or not there are an unlimited number of positionals
|
||||
bool HasUnlimitedPositionals = false;
|
||||
|
||||
// So that we can parse different command lines multiple times in succession
|
||||
// we reset all option values to look like they have never been seen before.
|
||||
for (auto SC : RegisteredSubCommands) {
|
||||
for (auto &O : SC->OptionsMap)
|
||||
O.second->reset();
|
||||
}
|
||||
|
||||
int FirstArg = 1;
|
||||
SubCommand *ChosenSubCommand = &*TopLevelSubCommand;
|
||||
if (argc >= 2 && argv[FirstArg][0] != '-') {
|
||||
// If the first argument specifies a valid subcommand, start processing
|
||||
// options from the second argument.
|
||||
ChosenSubCommand = LookupSubCommand(argv[FirstArg]);
|
||||
if (ChosenSubCommand != &*TopLevelSubCommand)
|
||||
FirstArg = 2;
|
||||
}
|
||||
GlobalParser->ActiveSubCommand = ChosenSubCommand;
|
||||
|
||||
assert(ChosenSubCommand);
|
||||
auto &ConsumeAfterOpt = ChosenSubCommand->ConsumeAfterOpt;
|
||||
auto &PositionalOpts = ChosenSubCommand->PositionalOpts;
|
||||
auto &SinkOpts = ChosenSubCommand->SinkOpts;
|
||||
auto &OptionsMap = ChosenSubCommand->OptionsMap;
|
||||
|
||||
if (ConsumeAfterOpt) {
|
||||
assert(PositionalOpts.size() > 0 &&
|
||||
"Cannot specify cl::ConsumeAfter without a positional argument!");
|
||||
@ -1061,28 +865,23 @@ bool CommandLineParser::ParseCommandLineOptions(int argc,
|
||||
else if (ConsumeAfterOpt) {
|
||||
// ConsumeAfter cannot be combined with "optional" positional options
|
||||
// unless there is only one positional argument...
|
||||
if (PositionalOpts.size() > 1) {
|
||||
if (!IgnoreErrors)
|
||||
Opt->error("error - this positional option will never be matched, "
|
||||
"because it does not Require a value, and a "
|
||||
"cl::ConsumeAfter option is active!");
|
||||
ErrorParsing = true;
|
||||
}
|
||||
if (PositionalOpts.size() > 1)
|
||||
ErrorParsing |= Opt->error(
|
||||
"error - this positional option will never be matched, "
|
||||
"because it does not Require a value, and a "
|
||||
"cl::ConsumeAfter option is active!");
|
||||
} else if (UnboundedFound && !Opt->hasArgStr()) {
|
||||
// This option does not "require" a value... Make sure this option is
|
||||
// not specified after an option that eats all extra arguments, or this
|
||||
// one will never get any!
|
||||
//
|
||||
if (!IgnoreErrors) {
|
||||
Opt->error("error - option can never match, because "
|
||||
"another positional argument will match an "
|
||||
"unbounded number of values, and this option"
|
||||
" does not require a value!");
|
||||
errs() << ProgramName << ": CommandLine Error: Option '"
|
||||
<< Opt->ArgStr << "' is all messed up!\n";
|
||||
errs() << PositionalOpts.size();
|
||||
}
|
||||
ErrorParsing = true;
|
||||
ErrorParsing |= Opt->error("error - option can never match, because "
|
||||
"another positional argument will match an "
|
||||
"unbounded number of values, and this option"
|
||||
" does not require a value!");
|
||||
errs() << ProgramName << ": CommandLine Error: Option '" << Opt->ArgStr
|
||||
<< "' is all messed up!\n";
|
||||
errs() << PositionalOpts.size();
|
||||
}
|
||||
UnboundedFound |= EatsUnboundedNumberOfValues(Opt);
|
||||
}
|
||||
@ -1101,7 +900,7 @@ bool CommandLineParser::ParseCommandLineOptions(int argc,
|
||||
|
||||
// Loop over all of the arguments... processing them.
|
||||
bool DashDashFound = false; // Have we read '--'?
|
||||
for (int i = FirstArg; i < argc; ++i) {
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
Option *Handler = nullptr;
|
||||
Option *NearestHandler = nullptr;
|
||||
std::string NearestHandlerString;
|
||||
@ -1148,7 +947,7 @@ bool CommandLineParser::ParseCommandLineOptions(int argc,
|
||||
while (!ArgName.empty() && ArgName[0] == '-')
|
||||
ArgName = ArgName.substr(1);
|
||||
|
||||
Handler = LookupOption(*ChosenSubCommand, ArgName, Value);
|
||||
Handler = LookupOption(ArgName, Value);
|
||||
if (!Handler || Handler->getFormattingFlag() != cl::Positional) {
|
||||
ProvidePositionalOption(ActivePositionalArg, argv[i], i);
|
||||
continue; // We are done!
|
||||
@ -1160,7 +959,7 @@ bool CommandLineParser::ParseCommandLineOptions(int argc,
|
||||
while (!ArgName.empty() && ArgName[0] == '-')
|
||||
ArgName = ArgName.substr(1);
|
||||
|
||||
Handler = LookupOption(*ChosenSubCommand, ArgName, Value);
|
||||
Handler = LookupOption(ArgName, Value);
|
||||
|
||||
// Check to see if this "option" is really a prefixed or grouped argument.
|
||||
if (!Handler)
|
||||
@ -1176,15 +975,13 @@ bool CommandLineParser::ParseCommandLineOptions(int argc,
|
||||
|
||||
if (!Handler) {
|
||||
if (SinkOpts.empty()) {
|
||||
if (!IgnoreErrors) {
|
||||
errs() << ProgramName << ": Unknown command line argument '"
|
||||
<< argv[i] << "'. Try: '" << argv[0] << " -help'\n";
|
||||
errs() << ProgramName << ": Unknown command line argument '" << argv[i]
|
||||
<< "'. Try: '" << argv[0] << " -help'\n";
|
||||
|
||||
if (NearestHandler) {
|
||||
// If we know a near match, report it as well.
|
||||
errs() << ProgramName << ": Did you mean '-" << NearestHandlerString
|
||||
<< "'?\n";
|
||||
}
|
||||
if (NearestHandler) {
|
||||
// If we know a near match, report it as well.
|
||||
errs() << ProgramName << ": Did you mean '-" << NearestHandlerString
|
||||
<< "'?\n";
|
||||
}
|
||||
|
||||
ErrorParsing = true;
|
||||
@ -1207,21 +1004,17 @@ bool CommandLineParser::ParseCommandLineOptions(int argc,
|
||||
|
||||
// Check and handle positional arguments now...
|
||||
if (NumPositionalRequired > PositionalVals.size()) {
|
||||
if (!IgnoreErrors) {
|
||||
errs() << ProgramName
|
||||
<< ": Not enough positional command line arguments specified!\n"
|
||||
<< "Must specify at least " << NumPositionalRequired
|
||||
<< " positional arguments: See: " << argv[0] << " -help\n";
|
||||
}
|
||||
errs() << ProgramName
|
||||
<< ": Not enough positional command line arguments specified!\n"
|
||||
<< "Must specify at least " << NumPositionalRequired
|
||||
<< " positional arguments: See: " << argv[0] << " -help\n";
|
||||
|
||||
ErrorParsing = true;
|
||||
} else if (!HasUnlimitedPositionals &&
|
||||
PositionalVals.size() > PositionalOpts.size()) {
|
||||
if (!IgnoreErrors) {
|
||||
errs() << ProgramName << ": Too many positional arguments specified!\n"
|
||||
<< "Can specify at most " << PositionalOpts.size()
|
||||
<< " positional arguments: See: " << argv[0] << " -help\n";
|
||||
}
|
||||
errs() << ProgramName << ": Too many positional arguments specified!\n"
|
||||
<< "Can specify at most " << PositionalOpts.size()
|
||||
<< " positional arguments: See: " << argv[0] << " -help\n";
|
||||
ErrorParsing = true;
|
||||
|
||||
} else if (!ConsumeAfterOpt) {
|
||||
@ -1316,12 +1109,8 @@ bool CommandLineParser::ParseCommandLineOptions(int argc,
|
||||
MoreHelp.clear();
|
||||
|
||||
// If we had an error processing our arguments, don't let the program execute
|
||||
if (ErrorParsing) {
|
||||
if (!IgnoreErrors)
|
||||
exit(1);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
if (ErrorParsing)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -1671,11 +1460,6 @@ static int OptNameCompare(const std::pair<const char *, Option *> *LHS,
|
||||
return strcmp(LHS->first, RHS->first);
|
||||
}
|
||||
|
||||
static int SubNameCompare(const std::pair<const char *, SubCommand *> *LHS,
|
||||
const std::pair<const char *, SubCommand *> *RHS) {
|
||||
return strcmp(LHS->first, RHS->first);
|
||||
}
|
||||
|
||||
// Copy Options into a vector so we can sort them as we like.
|
||||
static void sortOpts(StringMap<Option *> &OptMap,
|
||||
SmallVectorImpl<std::pair<const char *, Option *>> &Opts,
|
||||
@ -1704,17 +1488,6 @@ static void sortOpts(StringMap<Option *> &OptMap,
|
||||
array_pod_sort(Opts.begin(), Opts.end(), OptNameCompare);
|
||||
}
|
||||
|
||||
static void
|
||||
sortSubCommands(const SmallPtrSetImpl<SubCommand *> &SubMap,
|
||||
SmallVectorImpl<std::pair<const char *, SubCommand *>> &Subs) {
|
||||
for (const auto &S : SubMap) {
|
||||
if (S->getName() == nullptr)
|
||||
continue;
|
||||
Subs.push_back(std::make_pair(S->getName(), S));
|
||||
}
|
||||
array_pod_sort(Subs.begin(), Subs.end(), SubNameCompare);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class HelpPrinter {
|
||||
@ -1722,25 +1495,12 @@ protected:
|
||||
const bool ShowHidden;
|
||||
typedef SmallVector<std::pair<const char *, Option *>, 128>
|
||||
StrOptionPairVector;
|
||||
typedef SmallVector<std::pair<const char *, SubCommand *>, 128>
|
||||
StrSubCommandPairVector;
|
||||
// Print the options. Opts is assumed to be alphabetically sorted.
|
||||
virtual void printOptions(StrOptionPairVector &Opts, size_t MaxArgLen) {
|
||||
for (size_t i = 0, e = Opts.size(); i != e; ++i)
|
||||
Opts[i].second->printOptionInfo(MaxArgLen);
|
||||
}
|
||||
|
||||
void printSubCommands(StrSubCommandPairVector &Subs, size_t MaxSubLen) {
|
||||
for (const auto &S : Subs) {
|
||||
outs() << " " << S.first;
|
||||
if (S.second->getDescription()) {
|
||||
outs().indent(MaxSubLen - strlen(S.first));
|
||||
outs() << " - " << S.second->getDescription();
|
||||
}
|
||||
outs() << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
explicit HelpPrinter(bool showHidden) : ShowHidden(showHidden) {}
|
||||
virtual ~HelpPrinter() {}
|
||||
@ -1750,56 +1510,23 @@ public:
|
||||
if (!Value)
|
||||
return;
|
||||
|
||||
SubCommand *Sub = GlobalParser->getActiveSubCommand();
|
||||
auto &OptionsMap = Sub->OptionsMap;
|
||||
auto &PositionalOpts = Sub->PositionalOpts;
|
||||
auto &ConsumeAfterOpt = Sub->ConsumeAfterOpt;
|
||||
|
||||
StrOptionPairVector Opts;
|
||||
sortOpts(OptionsMap, Opts, ShowHidden);
|
||||
|
||||
StrSubCommandPairVector Subs;
|
||||
sortSubCommands(GlobalParser->RegisteredSubCommands, Subs);
|
||||
sortOpts(GlobalParser->OptionsMap, Opts, ShowHidden);
|
||||
|
||||
if (GlobalParser->ProgramOverview)
|
||||
outs() << "OVERVIEW: " << GlobalParser->ProgramOverview << "\n";
|
||||
|
||||
if (Sub == &*TopLevelSubCommand)
|
||||
outs() << "USAGE: " << GlobalParser->ProgramName
|
||||
<< " [subcommand] [options]";
|
||||
else {
|
||||
if (Sub->getDescription() != nullptr) {
|
||||
outs() << "SUBCOMMAND '" << Sub->getName()
|
||||
<< "': " << Sub->getDescription() << "\n\n";
|
||||
}
|
||||
outs() << "USAGE: " << GlobalParser->ProgramName << " " << Sub->getName()
|
||||
<< " [options]";
|
||||
}
|
||||
outs() << "USAGE: " << GlobalParser->ProgramName << " [options]";
|
||||
|
||||
for (auto Opt : PositionalOpts) {
|
||||
for (auto Opt : GlobalParser->PositionalOpts) {
|
||||
if (Opt->hasArgStr())
|
||||
outs() << " --" << Opt->ArgStr;
|
||||
outs() << " " << Opt->HelpStr;
|
||||
}
|
||||
|
||||
// Print the consume after option info if it exists...
|
||||
if (ConsumeAfterOpt)
|
||||
outs() << " " << ConsumeAfterOpt->HelpStr;
|
||||
|
||||
if (Sub == &*TopLevelSubCommand && Subs.size() > 2) {
|
||||
// Compute the maximum subcommand length...
|
||||
size_t MaxSubLen = 0;
|
||||
for (size_t i = 0, e = Subs.size(); i != e; ++i)
|
||||
MaxSubLen = std::max(MaxSubLen, strlen(Subs[i].first));
|
||||
|
||||
outs() << "\n\n";
|
||||
outs() << "SUBCOMMANDS:\n\n";
|
||||
printSubCommands(Subs, MaxSubLen);
|
||||
outs() << "\n";
|
||||
outs() << " Type \"" << GlobalParser->ProgramName
|
||||
<< " <subcommand> -help\" to get more help on a specific "
|
||||
"subcommand";
|
||||
}
|
||||
if (GlobalParser->ConsumeAfterOpt)
|
||||
outs() << " " << GlobalParser->ConsumeAfterOpt->HelpStr;
|
||||
|
||||
outs() << "\n\n";
|
||||
|
||||
@ -1948,13 +1675,12 @@ static cl::opt<HelpPrinter, true, parser<bool>> HLOp(
|
||||
"help-list",
|
||||
cl::desc("Display list of available options (-help-list-hidden for more)"),
|
||||
cl::location(UncategorizedNormalPrinter), cl::Hidden, cl::ValueDisallowed,
|
||||
cl::cat(GenericCategory), cl::sub(*AllSubCommands));
|
||||
cl::cat(GenericCategory));
|
||||
|
||||
static cl::opt<HelpPrinter, true, parser<bool>>
|
||||
HLHOp("help-list-hidden", cl::desc("Display list of all available options"),
|
||||
cl::location(UncategorizedHiddenPrinter), cl::Hidden,
|
||||
cl::ValueDisallowed, cl::cat(GenericCategory),
|
||||
cl::sub(*AllSubCommands));
|
||||
cl::ValueDisallowed, cl::cat(GenericCategory));
|
||||
|
||||
// Define uncategorized/categorized help printers. These printers change their
|
||||
// behaviour at runtime depending on whether one or more Option categories have
|
||||
@ -1962,23 +1688,22 @@ static cl::opt<HelpPrinter, true, parser<bool>>
|
||||
static cl::opt<HelpPrinterWrapper, true, parser<bool>>
|
||||
HOp("help", cl::desc("Display available options (-help-hidden for more)"),
|
||||
cl::location(WrappedNormalPrinter), cl::ValueDisallowed,
|
||||
cl::cat(GenericCategory), cl::sub(*AllSubCommands));
|
||||
cl::cat(GenericCategory));
|
||||
|
||||
static cl::opt<HelpPrinterWrapper, true, parser<bool>>
|
||||
HHOp("help-hidden", cl::desc("Display all available options"),
|
||||
cl::location(WrappedHiddenPrinter), cl::Hidden, cl::ValueDisallowed,
|
||||
cl::cat(GenericCategory), cl::sub(*AllSubCommands));
|
||||
cl::cat(GenericCategory));
|
||||
|
||||
static cl::opt<bool> PrintOptions(
|
||||
"print-options",
|
||||
cl::desc("Print non-default options after command line parsing"),
|
||||
cl::Hidden, cl::init(false), cl::cat(GenericCategory),
|
||||
cl::sub(*AllSubCommands));
|
||||
cl::Hidden, cl::init(false), cl::cat(GenericCategory));
|
||||
|
||||
static cl::opt<bool> PrintAllOptions(
|
||||
"print-all-options",
|
||||
cl::desc("Print all option values after command line parsing"), cl::Hidden,
|
||||
cl::init(false), cl::cat(GenericCategory), cl::sub(*AllSubCommands));
|
||||
cl::init(false), cl::cat(GenericCategory));
|
||||
|
||||
void HelpPrinterWrapper::operator=(bool Value) {
|
||||
if (!Value)
|
||||
@ -2005,7 +1730,7 @@ void CommandLineParser::printOptionValues() {
|
||||
return;
|
||||
|
||||
SmallVector<std::pair<const char *, Option *>, 128> Opts;
|
||||
sortOpts(ActiveSubCommand->OptionsMap, Opts, /*ShowHidden*/ true);
|
||||
sortOpts(OptionsMap, Opts, /*ShowHidden*/ true);
|
||||
|
||||
// Compute the maximum argument length...
|
||||
size_t MaxArgLen = 0;
|
||||
@ -2114,25 +1839,22 @@ void cl::AddExtraVersionPrinter(void (*func)()) {
|
||||
ExtraVersionPrinters->push_back(func);
|
||||
}
|
||||
|
||||
StringMap<Option *> &cl::getRegisteredOptions(SubCommand &Sub) {
|
||||
auto &Subs = GlobalParser->RegisteredSubCommands;
|
||||
assert(std::find(Subs.begin(), Subs.end(), &Sub) != Subs.end());
|
||||
return Sub.OptionsMap;
|
||||
StringMap<Option *> &cl::getRegisteredOptions() {
|
||||
return GlobalParser->OptionsMap;
|
||||
}
|
||||
|
||||
void cl::HideUnrelatedOptions(cl::OptionCategory &Category, SubCommand &Sub) {
|
||||
for (auto &I : Sub.OptionsMap) {
|
||||
void cl::HideUnrelatedOptions(cl::OptionCategory &Category) {
|
||||
for (auto &I : GlobalParser->OptionsMap) {
|
||||
if (I.second->Category != &Category &&
|
||||
I.second->Category != &GenericCategory)
|
||||
I.second->setHiddenFlag(cl::ReallyHidden);
|
||||
}
|
||||
}
|
||||
|
||||
void cl::HideUnrelatedOptions(ArrayRef<const cl::OptionCategory *> Categories,
|
||||
SubCommand &Sub) {
|
||||
void cl::HideUnrelatedOptions(ArrayRef<const cl::OptionCategory *> Categories) {
|
||||
auto CategoriesBegin = Categories.begin();
|
||||
auto CategoriesEnd = Categories.end();
|
||||
for (auto &I : Sub.OptionsMap) {
|
||||
for (auto &I : GlobalParser->OptionsMap) {
|
||||
if (std::find(CategoriesBegin, CategoriesEnd, I.second->Category) ==
|
||||
CategoriesEnd &&
|
||||
I.second->Category != &GenericCategory)
|
||||
@ -2140,9 +1862,7 @@ void cl::HideUnrelatedOptions(ArrayRef<const cl::OptionCategory *> Categories,
|
||||
}
|
||||
}
|
||||
|
||||
void cl::ResetCommandLineOptions() { GlobalParser->reset(); }
|
||||
|
||||
void LLVMParseCommandLineOptions(int argc, const char *const *argv,
|
||||
const char *Overview) {
|
||||
llvm::cl::ParseCommandLineOptions(argc, argv, Overview, true);
|
||||
llvm::cl::ParseCommandLineOptions(argc, argv, Overview);
|
||||
}
|
||||
|
@ -67,22 +67,6 @@ public:
|
||||
: Base(M0, M1, M2, M3) {}
|
||||
|
||||
~StackOption() override { this->removeArgument(); }
|
||||
|
||||
template <class DT> StackOption<T> &operator=(const DT &V) {
|
||||
this->setValue(V);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
class StackSubCommand : public cl::SubCommand {
|
||||
public:
|
||||
StackSubCommand(const char *const Name,
|
||||
const char *const Description = nullptr)
|
||||
: SubCommand(Name, Description) {}
|
||||
|
||||
StackSubCommand() : SubCommand() {}
|
||||
|
||||
~StackSubCommand() { unregisterSubCommand(); }
|
||||
};
|
||||
|
||||
|
||||
@ -94,8 +78,7 @@ TEST(CommandLineTest, ModifyExisitingOption) {
|
||||
const char ArgString[] = "new-test-option";
|
||||
const char ValueString[] = "Integer";
|
||||
|
||||
StringMap<cl::Option *> &Map =
|
||||
cl::getRegisteredOptions(*cl::TopLevelSubCommand);
|
||||
StringMap<cl::Option *> &Map = cl::getRegisteredOptions();
|
||||
|
||||
ASSERT_TRUE(Map.count("test-option") == 1) <<
|
||||
"Could not find option in map.";
|
||||
@ -254,8 +237,7 @@ TEST(CommandLineTest, HideUnrelatedOptions) {
|
||||
ASSERT_EQ(cl::NotHidden, TestOption2.getOptionHiddenFlag())
|
||||
<< "Hid extra option that should be visable.";
|
||||
|
||||
StringMap<cl::Option *> &Map =
|
||||
cl::getRegisteredOptions(*cl::TopLevelSubCommand);
|
||||
StringMap<cl::Option *> &Map = cl::getRegisteredOptions();
|
||||
ASSERT_EQ(cl::NotHidden, Map["help"]->getOptionHiddenFlag())
|
||||
<< "Hid default option that should be visable.";
|
||||
}
|
||||
@ -279,189 +261,9 @@ TEST(CommandLineTest, HideUnrelatedOptionsMulti) {
|
||||
ASSERT_EQ(cl::NotHidden, TestOption3.getOptionHiddenFlag())
|
||||
<< "Hid extra option that should be visable.";
|
||||
|
||||
StringMap<cl::Option *> &Map =
|
||||
cl::getRegisteredOptions(*cl::TopLevelSubCommand);
|
||||
StringMap<cl::Option *> &Map = cl::getRegisteredOptions();
|
||||
ASSERT_EQ(cl::NotHidden, Map["help"]->getOptionHiddenFlag())
|
||||
<< "Hid default option that should be visable.";
|
||||
}
|
||||
|
||||
TEST(CommandLineTest, SetValueInSubcategories) {
|
||||
cl::ResetCommandLineOptions();
|
||||
|
||||
StackSubCommand SC1("sc1", "First subcommand");
|
||||
StackSubCommand SC2("sc2", "Second subcommand");
|
||||
|
||||
StackOption<bool> TopLevelOpt("top-level", cl::init(false));
|
||||
StackOption<bool> SC1Opt("sc1", cl::sub(SC1), cl::init(false));
|
||||
StackOption<bool> SC2Opt("sc2", cl::sub(SC2), cl::init(false));
|
||||
|
||||
EXPECT_FALSE(TopLevelOpt);
|
||||
EXPECT_FALSE(SC1Opt);
|
||||
EXPECT_FALSE(SC2Opt);
|
||||
const char *args[] = {"prog", "-top-level"};
|
||||
EXPECT_TRUE(cl::ParseCommandLineOptions(2, args, nullptr, true));
|
||||
EXPECT_TRUE(TopLevelOpt);
|
||||
EXPECT_FALSE(SC1Opt);
|
||||
EXPECT_FALSE(SC2Opt);
|
||||
|
||||
TopLevelOpt = false;
|
||||
|
||||
EXPECT_FALSE(TopLevelOpt);
|
||||
EXPECT_FALSE(SC1Opt);
|
||||
EXPECT_FALSE(SC2Opt);
|
||||
const char *args2[] = {"prog", "sc1", "-sc1"};
|
||||
EXPECT_TRUE(cl::ParseCommandLineOptions(3, args2, nullptr, true));
|
||||
EXPECT_FALSE(TopLevelOpt);
|
||||
EXPECT_TRUE(SC1Opt);
|
||||
EXPECT_FALSE(SC2Opt);
|
||||
|
||||
SC1Opt = false;
|
||||
|
||||
EXPECT_FALSE(TopLevelOpt);
|
||||
EXPECT_FALSE(SC1Opt);
|
||||
EXPECT_FALSE(SC2Opt);
|
||||
const char *args3[] = {"prog", "sc2", "-sc2"};
|
||||
EXPECT_TRUE(cl::ParseCommandLineOptions(3, args3, nullptr, true));
|
||||
EXPECT_FALSE(TopLevelOpt);
|
||||
EXPECT_FALSE(SC1Opt);
|
||||
EXPECT_TRUE(SC2Opt);
|
||||
}
|
||||
|
||||
TEST(CommandLineTest, LookupFailsInWrongSubCommand) {
|
||||
cl::ResetCommandLineOptions();
|
||||
|
||||
StackSubCommand SC1("sc1", "First subcommand");
|
||||
StackSubCommand SC2("sc2", "Second subcommand");
|
||||
|
||||
StackOption<bool> SC1Opt("sc1", cl::sub(SC1), cl::init(false));
|
||||
StackOption<bool> SC2Opt("sc2", cl::sub(SC2), cl::init(false));
|
||||
|
||||
const char *args[] = {"prog", "sc1", "-sc2"};
|
||||
EXPECT_FALSE(cl::ParseCommandLineOptions(3, args, nullptr, true));
|
||||
}
|
||||
|
||||
TEST(CommandLineTest, AddToAllSubCommands) {
|
||||
cl::ResetCommandLineOptions();
|
||||
|
||||
StackSubCommand SC1("sc1", "First subcommand");
|
||||
StackOption<bool> AllOpt("everywhere", cl::sub(*cl::AllSubCommands),
|
||||
cl::init(false));
|
||||
StackSubCommand SC2("sc2", "Second subcommand");
|
||||
|
||||
const char *args[] = {"prog", "-everywhere"};
|
||||
const char *args2[] = {"prog", "sc1", "-everywhere"};
|
||||
const char *args3[] = {"prog", "sc2", "-everywhere"};
|
||||
|
||||
EXPECT_FALSE(AllOpt);
|
||||
EXPECT_TRUE(cl::ParseCommandLineOptions(2, args, nullptr, true));
|
||||
EXPECT_TRUE(AllOpt);
|
||||
|
||||
AllOpt = false;
|
||||
|
||||
EXPECT_FALSE(AllOpt);
|
||||
EXPECT_TRUE(cl::ParseCommandLineOptions(3, args2, nullptr, true));
|
||||
EXPECT_TRUE(AllOpt);
|
||||
|
||||
AllOpt = false;
|
||||
|
||||
EXPECT_FALSE(AllOpt);
|
||||
EXPECT_TRUE(cl::ParseCommandLineOptions(3, args3, nullptr, true));
|
||||
EXPECT_TRUE(AllOpt);
|
||||
}
|
||||
|
||||
TEST(CommandLineTest, ReparseCommandLineOptions) {
|
||||
cl::ResetCommandLineOptions();
|
||||
|
||||
StackOption<bool> TopLevelOpt("top-level", cl::sub(*cl::TopLevelSubCommand),
|
||||
cl::init(false));
|
||||
|
||||
const char *args[] = {"prog", "-top-level"};
|
||||
|
||||
EXPECT_FALSE(TopLevelOpt);
|
||||
EXPECT_TRUE(cl::ParseCommandLineOptions(2, args, nullptr, true));
|
||||
EXPECT_TRUE(TopLevelOpt);
|
||||
|
||||
TopLevelOpt = false;
|
||||
|
||||
EXPECT_FALSE(TopLevelOpt);
|
||||
EXPECT_TRUE(cl::ParseCommandLineOptions(2, args, nullptr, true));
|
||||
EXPECT_TRUE(TopLevelOpt);
|
||||
}
|
||||
|
||||
TEST(CommandLineTest, RemoveFromRegularSubCommand) {
|
||||
cl::ResetCommandLineOptions();
|
||||
|
||||
StackSubCommand SC("sc", "Subcommand");
|
||||
StackOption<bool> RemoveOption("remove-option", cl::sub(SC), cl::init(false));
|
||||
StackOption<bool> KeepOption("keep-option", cl::sub(SC), cl::init(false));
|
||||
|
||||
const char *args[] = {"prog", "sc", "-remove-option"};
|
||||
|
||||
EXPECT_FALSE(RemoveOption);
|
||||
EXPECT_TRUE(cl::ParseCommandLineOptions(3, args, nullptr, true));
|
||||
EXPECT_TRUE(RemoveOption);
|
||||
|
||||
RemoveOption.removeArgument();
|
||||
|
||||
EXPECT_FALSE(cl::ParseCommandLineOptions(3, args, nullptr, true));
|
||||
}
|
||||
|
||||
TEST(CommandLineTest, RemoveFromTopLevelSubCommand) {
|
||||
cl::ResetCommandLineOptions();
|
||||
|
||||
StackOption<bool> TopLevelRemove(
|
||||
"top-level-remove", cl::sub(*cl::TopLevelSubCommand), cl::init(false));
|
||||
StackOption<bool> TopLevelKeep(
|
||||
"top-level-keep", cl::sub(*cl::TopLevelSubCommand), cl::init(false));
|
||||
|
||||
const char *args[] = {"prog", "-top-level-remove"};
|
||||
|
||||
EXPECT_FALSE(TopLevelRemove);
|
||||
EXPECT_TRUE(cl::ParseCommandLineOptions(2, args, nullptr, true));
|
||||
EXPECT_TRUE(TopLevelRemove);
|
||||
|
||||
TopLevelRemove.removeArgument();
|
||||
|
||||
EXPECT_FALSE(cl::ParseCommandLineOptions(2, args, nullptr, true));
|
||||
}
|
||||
|
||||
TEST(CommandLineTest, RemoveFromAllSubCommands) {
|
||||
cl::ResetCommandLineOptions();
|
||||
|
||||
StackSubCommand SC1("sc1", "First Subcommand");
|
||||
StackSubCommand SC2("sc2", "Second Subcommand");
|
||||
StackOption<bool> RemoveOption("remove-option", cl::sub(*cl::AllSubCommands),
|
||||
cl::init(false));
|
||||
StackOption<bool> KeepOption("keep-option", cl::sub(*cl::AllSubCommands),
|
||||
cl::init(false));
|
||||
|
||||
const char *args0[] = {"prog", "-remove-option"};
|
||||
const char *args1[] = {"prog", "sc1", "-remove-option"};
|
||||
const char *args2[] = {"prog", "sc2", "-remove-option"};
|
||||
|
||||
// It should work for all subcommands including the top-level.
|
||||
EXPECT_FALSE(RemoveOption);
|
||||
EXPECT_TRUE(cl::ParseCommandLineOptions(2, args0, nullptr, true));
|
||||
EXPECT_TRUE(RemoveOption);
|
||||
|
||||
RemoveOption = false;
|
||||
|
||||
EXPECT_FALSE(RemoveOption);
|
||||
EXPECT_TRUE(cl::ParseCommandLineOptions(3, args1, nullptr, true));
|
||||
EXPECT_TRUE(RemoveOption);
|
||||
|
||||
RemoveOption = false;
|
||||
|
||||
EXPECT_FALSE(RemoveOption);
|
||||
EXPECT_TRUE(cl::ParseCommandLineOptions(3, args2, nullptr, true));
|
||||
EXPECT_TRUE(RemoveOption);
|
||||
|
||||
RemoveOption.removeArgument();
|
||||
|
||||
// It should not work for any subcommands including the top-level.
|
||||
EXPECT_FALSE(cl::ParseCommandLineOptions(2, args0, nullptr, true));
|
||||
EXPECT_FALSE(cl::ParseCommandLineOptions(3, args1, nullptr, true));
|
||||
EXPECT_FALSE(cl::ParseCommandLineOptions(3, args2, nullptr, true));
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
@ -231,7 +231,7 @@ TEST_F(ProgramEnvTest, TestExecuteNoWait) {
|
||||
// LoopCount should only be incremented once.
|
||||
while (true) {
|
||||
++LoopCount;
|
||||
ProcessInfo WaitResult = llvm::sys::Wait(PI1, 0, true, &Error);
|
||||
ProcessInfo WaitResult = Wait(PI1, 0, true, &Error);
|
||||
ASSERT_TRUE(Error.empty());
|
||||
if (WaitResult.Pid == PI1.Pid)
|
||||
break;
|
||||
@ -248,7 +248,7 @@ TEST_F(ProgramEnvTest, TestExecuteNoWait) {
|
||||
// cse, LoopCount should be greater than 1 (more than one increment occurs).
|
||||
while (true) {
|
||||
++LoopCount;
|
||||
ProcessInfo WaitResult = llvm::sys::Wait(PI2, 0, false, &Error);
|
||||
ProcessInfo WaitResult = Wait(PI2, 0, false, &Error);
|
||||
ASSERT_TRUE(Error.empty());
|
||||
if (WaitResult.Pid == PI2.Pid)
|
||||
break;
|
||||
|
Loading…
x
Reference in New Issue
Block a user