#include "llvm/Support/CommandLine.h"
#include "llvm-c/Support.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/StringSaver.h"
#include "llvm/Support/raw_ostream.h"
-#include <cerrno>
#include <cstdlib>
#include <map>
-#include <system_error>
using namespace llvm;
using namespace cl;
//
namespace llvm {
namespace cl {
-TEMPLATE_INSTANTIATION(class basic_parser<bool>);
-TEMPLATE_INSTANTIATION(class basic_parser<boolOrDefault>);
-TEMPLATE_INSTANTIATION(class basic_parser<int>);
-TEMPLATE_INSTANTIATION(class basic_parser<unsigned>);
-TEMPLATE_INSTANTIATION(class basic_parser<unsigned long long>);
-TEMPLATE_INSTANTIATION(class basic_parser<double>);
-TEMPLATE_INSTANTIATION(class basic_parser<float>);
-TEMPLATE_INSTANTIATION(class basic_parser<std::string>);
-TEMPLATE_INSTANTIATION(class basic_parser<char>);
-
-TEMPLATE_INSTANTIATION(class opt<unsigned>);
-TEMPLATE_INSTANTIATION(class opt<int>);
-TEMPLATE_INSTANTIATION(class opt<std::string>);
-TEMPLATE_INSTANTIATION(class opt<char>);
-TEMPLATE_INSTANTIATION(class opt<bool>);
+template class basic_parser<bool>;
+template class basic_parser<boolOrDefault>;
+template class basic_parser<int>;
+template class basic_parser<unsigned>;
+template class basic_parser<unsigned long long>;
+template class basic_parser<double>;
+template class basic_parser<float>;
+template class basic_parser<std::string>;
+template class basic_parser<char>;
+
+template class opt<unsigned>;
+template class opt<int>;
+template class opt<std::string>;
+template class opt<char>;
+template class opt<bool>;
}
} // end namespace llvm::cl
void parser<float>::anchor() {}
void parser<std::string>::anchor() {}
void parser<char>::anchor() {}
-void StringSaver::anchor() {}
//===----------------------------------------------------------------------===//
Option *ConsumeAfterOpt; // The ConsumeAfter option if it exists.
+ // This collects the different option categories that have been registered.
+ SmallPtrSet<OptionCategory *, 16> RegisteredOptionCategories;
+
CommandLineParser() : ProgramOverview(nullptr), ConsumeAfterOpt(nullptr) {}
void ParseCommandLineOptions(int argc, const char *const *argv,
void addOption(Option *O) {
bool HadErrors = false;
- if (O->ArgStr[0]) {
+ if (O->hasArgStr()) {
// Add argument to the argument map!
if (!OptionsMap.insert(std::make_pair(O->ArgStr, O)).second) {
errs() << ProgramName << ": CommandLine Error: Option '" << O->ArgStr
}
void removeOption(Option *O) {
- SmallVector<const char *, 16> OptionNames;
+ SmallVector<StringRef, 16> OptionNames;
O->getExtraOptionNames(OptionNames);
- if (O->ArgStr[0])
+ if (O->hasArgStr())
OptionNames.push_back(O->ArgStr);
for (auto Name : OptionNames)
- OptionsMap.erase(StringRef(Name));
+ OptionsMap.erase(Name);
if (O->getFormattingFlag() == cl::Positional)
for (auto Opt = PositionalOpts.begin(); Opt != PositionalOpts.end();
nullptr != ConsumeAfterOpt);
}
- void updateArgStr(Option *O, const char *NewName) {
+ 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");
}
- OptionsMap.erase(StringRef(O->ArgStr));
+ OptionsMap.erase(O->ArgStr);
}
void printOptionValues();
+ void registerCategory(OptionCategory *cat) {
+ assert(std::count_if(RegisteredOptionCategories.begin(),
+ RegisteredOptionCategories.end(),
+ [cat](const OptionCategory *Category) {
+ return cat->getName() == Category->getName();
+ }) == 0 &&
+ "Duplicate option categories");
+
+ RegisteredOptionCategories.insert(cat);
+ }
+
private:
Option *LookupOption(StringRef &Arg, StringRef &Value);
};
void Option::removeArgument() { GlobalParser->removeOption(this); }
-void Option::setArgStr(const char *S) {
+void Option::setArgStr(StringRef S) {
if (FullyInitialized)
GlobalParser->updateArgStr(this, S);
ArgStr = S;
}
-// This collects the different option categories that have been registered.
-typedef SmallPtrSet<OptionCategory *, 16> OptionCatSet;
-static ManagedStatic<OptionCatSet> RegisteredOptionCategories;
-
// Initialise the general option category.
OptionCategory llvm::cl::GeneralCategory("General options");
void OptionCategory::registerCategory() {
- assert(std::count_if(RegisteredOptionCategories->begin(),
- RegisteredOptionCategories->end(),
- [this](const OptionCategory *Category) {
- return getName() == Category->getName();
- }) == 0 &&
- "Duplicate option categories");
-
- RegisteredOptionCategories->insert(this);
+ GlobalParser->registerCategory(this);
}
//===----------------------------------------------------------------------===//
ie = OptionsMap.end();
it != ie; ++it) {
Option *O = it->second;
- SmallVector<const char *, 16> OptionNames;
+ SmallVector<StringRef, 16> OptionNames;
O->getExtraOptionNames(OptionNames);
- if (O->ArgStr[0])
+ if (O->hasArgStr())
OptionNames.push_back(O->ArgStr);
bool PermitValue = O->getValueExpectedFlag() != cl::ValueDisallowed;
StringRef Flag = PermitValue ? LHS : Arg;
- for (size_t i = 0, e = OptionNames.size(); i != e; ++i) {
- StringRef Name = OptionNames[i];
+ for (auto Name : OptionNames) {
unsigned Distance = StringRef(Name).edit_distance(
Flag, /*AllowReplacements=*/true, /*MaxEditDistance=*/BestDistance);
if (!Best || Distance < BestDistance) {
Best = O;
BestDistance = Distance;
if (RHS.empty() || !PermitValue)
- NearestString = OptionNames[i];
+ NearestString = Name;
else
- NearestString = std::string(OptionNames[i]) + "=" + RHS.str();
+ NearestString = (Twine(Name) + "=" + RHS).str();
}
}
}
// End the token if this is whitespace.
if (isWhitespace(Src[I])) {
if (!Token.empty())
- NewArgv.push_back(Saver.SaveString(Token.c_str()));
+ NewArgv.push_back(Saver.save(Token.c_str()));
Token.clear();
continue;
}
// Append the last token after hitting EOF with no whitespace.
if (!Token.empty())
- NewArgv.push_back(Saver.SaveString(Token.c_str()));
+ NewArgv.push_back(Saver.save(Token.c_str()));
// Mark the end of response files
if (MarkEOLs)
NewArgv.push_back(nullptr);
if (State == UNQUOTED) {
// Whitespace means the end of the token.
if (isWhitespace(Src[I])) {
- NewArgv.push_back(Saver.SaveString(Token.c_str()));
+ NewArgv.push_back(Saver.save(Token.c_str()));
Token.clear();
State = INIT;
// Mark the end of lines in response files
}
// Append the last token after hitting EOF with no whitespace.
if (!Token.empty())
- NewArgv.push_back(Saver.SaveString(Token.c_str()));
+ NewArgv.push_back(Saver.save(Token.c_str()));
// Mark the end of response files
if (MarkEOLs)
NewArgv.push_back(nullptr);
return AllExpanded;
}
-namespace {
-class StrDupSaver : public StringSaver {
- std::vector<char *> Dups;
-
-public:
- ~StrDupSaver() {
- for (std::vector<char *>::iterator I = Dups.begin(), E = Dups.end(); I != E;
- ++I) {
- char *Dup = *I;
- free(Dup);
- }
- }
- const char *SaveString(const char *Str) override {
- char *Dup = strdup(Str);
- Dups.push_back(Dup);
- return Dup;
- }
-};
-}
-
/// ParseEnvironmentOptions - An alternative entry point to the
/// CommandLine library, which allows you to read the program's name
/// from the caller (as PROGNAME) and its command-line arguments from
// Get program's "name", which we wouldn't know without the caller
// telling us.
SmallVector<const char *, 20> newArgv;
- StrDupSaver Saver;
- newArgv.push_back(Saver.SaveString(progName));
+ BumpPtrAllocator A;
+ StringSaver Saver(A);
+ newArgv.push_back(Saver.save(progName));
// Parse the value of the environment variable into a "command line"
// and hand it off to ParseCommandLineOptions().
assert(hasOptions() && "No options specified!");
// Expand response files.
- SmallVector<const char *, 20> newArgv;
- for (int i = 0; i != argc; ++i)
- newArgv.push_back(argv[i]);
- StrDupSaver Saver;
+ SmallVector<const char *, 20> newArgv(argv, argv + argc);
+ BumpPtrAllocator A;
+ StringSaver Saver(A);
ExpandResponseFiles(Saver, TokenizeGNUCommandLine, newArgv);
argv = &newArgv[0];
argc = static_cast<int>(newArgv.size());
"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->ArgStr[0]) {
+ } 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!
// getValueStr - Get the value description string, using "DefaultMsg" if nothing
// has been specified yet.
//
-static const char *getValueStr(const Option &O, const char *DefaultMsg) {
- if (O.ValueStr[0] == 0)
+static StringRef getValueStr(const Option &O, StringRef DefaultMsg) {
+ if (O.ValueStr.empty())
return DefaultMsg;
return O.ValueStr;
}
//
// Return the width of the option tag for printing...
-size_t alias::getOptionWidth() const { return std::strlen(ArgStr) + 6; }
+size_t alias::getOptionWidth() const { return ArgStr.size() + 6; }
static void printHelpStr(StringRef HelpStr, size_t Indent,
size_t FirstLineIndentedBy) {
// Print out the option for the alias.
void alias::printOptionInfo(size_t GlobalWidth) const {
outs() << " -" << ArgStr;
- printHelpStr(HelpStr, GlobalWidth, std::strlen(ArgStr) + 6);
+ printHelpStr(HelpStr, GlobalWidth, ArgStr.size() + 6);
}
//===----------------------------------------------------------------------===//
// Return the width of the option tag for printing...
size_t basic_parser_impl::getOptionWidth(const Option &O) const {
- size_t Len = std::strlen(O.ArgStr);
+ size_t Len = O.ArgStr.size();
if (const char *ValName = getValueName())
- Len += std::strlen(getValueStr(O, ValName)) + 3;
+ Len += getValueStr(O, ValName).size() + 3;
return Len + 6;
}
void basic_parser_impl::printOptionName(const Option &O,
size_t GlobalWidth) const {
outs() << " -" << O.ArgStr;
- outs().indent(GlobalWidth - std::strlen(O.ArgStr));
+ outs().indent(GlobalWidth - O.ArgStr.size());
}
// parser<bool> implementation
// Return the width of the option tag for printing...
size_t generic_parser_base::getOptionWidth(const Option &O) const {
if (O.hasArgStr()) {
- size_t Size = std::strlen(O.ArgStr) + 6;
+ size_t Size = O.ArgStr.size() + 6;
for (unsigned i = 0, e = getNumOptions(); i != e; ++i)
Size = std::max(Size, std::strlen(getOption(i)) + 8);
return Size;
size_t GlobalWidth) const {
if (O.hasArgStr()) {
outs() << " -" << O.ArgStr;
- printHelpStr(O.HelpStr, GlobalWidth, std::strlen(O.ArgStr) + 6);
+ printHelpStr(O.HelpStr, GlobalWidth, O.ArgStr.size() + 6);
for (unsigned i = 0, e = getNumOptions(); i != e; ++i) {
size_t NumSpaces = GlobalWidth - strlen(getOption(i)) - 8;
outs().indent(NumSpaces) << " - " << getDescription(i) << '\n';
}
} else {
- if (O.HelpStr[0])
+ if (!O.HelpStr.empty())
outs() << " " << O.HelpStr << '\n';
for (unsigned i = 0, e = getNumOptions(); i != e; ++i) {
const char *Option = getOption(i);
const Option &O, const GenericOptionValue &Value,
const GenericOptionValue &Default, size_t GlobalWidth) const {
outs() << " -" << O.ArgStr;
- outs().indent(GlobalWidth - std::strlen(O.ArgStr));
+ outs().indent(GlobalWidth - O.ArgStr.size());
unsigned NumOpts = getNumOptions();
for (unsigned i = 0; i != NumOpts; ++i) {
// -help and -help-hidden option implementation
//
-static int OptNameCompare(const void *LHS, const void *RHS) {
- typedef std::pair<const char *, Option *> pair_ty;
-
- return strcmp(((const pair_ty *)LHS)->first, ((const pair_ty *)RHS)->first);
+static int OptNameCompare(const std::pair<const char *, Option *> *LHS,
+ const std::pair<const char *, Option *> *RHS) {
+ return strcmp(LHS->first, RHS->first);
}
// Copy Options into a vector so we can sort them as we like.
}
// Sort the options list alphabetically.
- qsort(Opts.data(), Opts.size(), sizeof(Opts[0]), OptNameCompare);
+ array_pod_sort(Opts.begin(), Opts.end(), OptNameCompare);
}
namespace {
// Invoke the printer.
void operator=(bool Value) {
- if (Value == false)
+ if (!Value)
return;
StrOptionPairVector Opts;
outs() << "USAGE: " << GlobalParser->ProgramName << " [options]";
for (auto Opt : GlobalParser->PositionalOpts) {
- if (Opt->ArgStr[0])
+ if (Opt->hasArgStr())
outs() << " --" << Opt->ArgStr;
outs() << " " << Opt->HelpStr;
}
explicit CategorizedHelpPrinter(bool showHidden) : HelpPrinter(showHidden) {}
// Helper function for printOptions().
- // It shall return true if A's name should be lexographically
- // ordered before B's name. It returns false otherwise.
- static bool OptionCategoryCompare(OptionCategory *A, OptionCategory *B) {
- return strcmp(A->getName(), B->getName()) < 0;
+ // It shall return a negative value if A's name should be lexicographically
+ // ordered before B's name. It returns a value greater equal zero otherwise.
+ static int OptionCategoryCompare(OptionCategory *const *A,
+ OptionCategory *const *B) {
+ return strcmp((*A)->getName(), (*B)->getName());
}
// Make sure we inherit our base class's operator=()
// Collect registered option categories into vector in preparation for
// sorting.
- for (OptionCatSet::const_iterator I = RegisteredOptionCategories->begin(),
- E = RegisteredOptionCategories->end();
+ for (auto I = GlobalParser->RegisteredOptionCategories.begin(),
+ E = GlobalParser->RegisteredOptionCategories.end();
I != E; ++I) {
SortedCategories.push_back(*I);
}
// Sort the different option categories alphabetically.
assert(SortedCategories.size() > 0 && "No option categories registered!");
- std::sort(SortedCategories.begin(), SortedCategories.end(),
- OptionCategoryCompare);
+ array_pod_sort(SortedCategories.begin(), SortedCategories.end(),
+ OptionCategoryCompare);
// Create map to empty vectors.
for (std::vector<OptionCategory *>::const_iterator
cl::init(false), cl::cat(GenericCategory));
void HelpPrinterWrapper::operator=(bool Value) {
- if (Value == false)
+ if (!Value)
return;
// Decide which printer to invoke. If more than one option category is
// registered then it is useful to show the categorized help instead of
// uncategorized help.
- if (RegisteredOptionCategories->size() > 1) {
+ if (GlobalParser->RegisteredOptionCategories.size() > 1) {
// unhide -help-list option so user can have uncategorized output if they
// want it.
HLOp.setHiddenFlag(NotHidden);