aboutsummaryrefslogtreecommitdiff
path: root/lib/Support/CommandLine.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Support/CommandLine.cpp')
-rw-r--r--lib/Support/CommandLine.cpp193
1 files changed, 162 insertions, 31 deletions
diff --git a/lib/Support/CommandLine.cpp b/lib/Support/CommandLine.cpp
index 7e744993a7cb..7f1c0d320b11 100644
--- a/lib/Support/CommandLine.cpp
+++ b/lib/Support/CommandLine.cpp
@@ -186,12 +186,14 @@ static Option *LookupOption(StringRef &Arg, StringRef &Value,
/// have already been stripped.
static Option *LookupNearestOption(StringRef Arg,
const StringMap<Option*> &OptionsMap,
- const char *&NearestString) {
+ std::string &NearestString) {
// Reject all dashes.
if (Arg.empty()) return 0;
// Split on any equal sign.
- StringRef LHS = Arg.split('=').first;
+ std::pair<StringRef, StringRef> SplitArg = Arg.split('=');
+ StringRef &LHS = SplitArg.first; // LHS == Arg when no '=' is present.
+ StringRef &RHS = SplitArg.second;
// Find the closest match.
Option *Best = 0;
@@ -204,14 +206,19 @@ static Option *LookupNearestOption(StringRef Arg,
if (O->ArgStr[0])
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];
unsigned Distance = StringRef(Name).edit_distance(
- Arg, /*AllowReplacements=*/true, /*MaxEditDistance=*/BestDistance);
+ Flag, /*AllowReplacements=*/true, /*MaxEditDistance=*/BestDistance);
if (!Best || Distance < BestDistance) {
Best = O;
- NearestString = OptionNames[i];
BestDistance = Distance;
+ if (RHS.empty() || !PermitValue)
+ NearestString = OptionNames[i];
+ else
+ NearestString = std::string(OptionNames[i]) + "=" + RHS.str();
}
}
}
@@ -611,7 +618,7 @@ void cl::ParseCommandLineOptions(int argc, char **argv,
for (int i = 1; i < argc; ++i) {
Option *Handler = 0;
Option *NearestHandler = 0;
- const char *NearestHandlerString = 0;
+ std::string NearestHandlerString;
StringRef Value;
StringRef ArgName = "";
@@ -908,8 +915,6 @@ void alias::printOptionInfo(size_t GlobalWidth) const {
errs().indent(GlobalWidth-L-6) << " - " << HelpStr << "\n";
}
-
-
//===----------------------------------------------------------------------===//
// Parser Implementation code...
//
@@ -939,7 +944,11 @@ void basic_parser_impl::printOptionInfo(const Option &O,
outs().indent(GlobalWidth-getOptionWidth(O)) << " - " << O.HelpStr << '\n';
}
-
+void basic_parser_impl::printOptionName(const Option &O,
+ size_t GlobalWidth) const {
+ outs() << " -" << O.ArgStr;
+ outs().indent(GlobalWidth-std::strlen(O.ArgStr));
+}
// parser<bool> implementation
@@ -1083,6 +1092,89 @@ void generic_parser_base::printOptionInfo(const Option &O,
}
}
+static const size_t MaxOptWidth = 8; // arbitrary spacing for printOptionDiff
+
+// printGenericOptionDiff - Print the value of this option and it's default.
+//
+// "Generic" options have each value mapped to a name.
+void generic_parser_base::
+printGenericOptionDiff(const Option &O, const GenericOptionValue &Value,
+ const GenericOptionValue &Default,
+ size_t GlobalWidth) const {
+ outs() << " -" << O.ArgStr;
+ outs().indent(GlobalWidth-std::strlen(O.ArgStr));
+
+ unsigned NumOpts = getNumOptions();
+ for (unsigned i = 0; i != NumOpts; ++i) {
+ if (Value.compare(getOptionValue(i)))
+ continue;
+
+ outs() << "= " << getOption(i);
+ size_t L = std::strlen(getOption(i));
+ size_t NumSpaces = MaxOptWidth > L ? MaxOptWidth - L : 0;
+ outs().indent(NumSpaces) << " (default: ";
+ for (unsigned j = 0; j != NumOpts; ++j) {
+ if (Default.compare(getOptionValue(j)))
+ continue;
+ outs() << getOption(j);
+ break;
+ }
+ outs() << ")\n";
+ return;
+ }
+ outs() << "= *unknown option value*\n";
+}
+
+// printOptionDiff - Specializations for printing basic value types.
+//
+#define PRINT_OPT_DIFF(T) \
+ void parser<T>:: \
+ printOptionDiff(const Option &O, T V, OptionValue<T> D, \
+ size_t GlobalWidth) const { \
+ printOptionName(O, GlobalWidth); \
+ std::string Str; \
+ { \
+ raw_string_ostream SS(Str); \
+ SS << V; \
+ } \
+ outs() << "= " << Str; \
+ size_t NumSpaces = MaxOptWidth > Str.size() ? MaxOptWidth - Str.size() : 0;\
+ outs().indent(NumSpaces) << " (default: "; \
+ if (D.hasValue()) \
+ outs() << D.getValue(); \
+ else \
+ outs() << "*no default*"; \
+ outs() << ")\n"; \
+ } \
+
+PRINT_OPT_DIFF(bool)
+PRINT_OPT_DIFF(boolOrDefault)
+PRINT_OPT_DIFF(int)
+PRINT_OPT_DIFF(unsigned)
+PRINT_OPT_DIFF(double)
+PRINT_OPT_DIFF(float)
+PRINT_OPT_DIFF(char)
+
+void parser<std::string>::
+printOptionDiff(const Option &O, StringRef V, OptionValue<std::string> D,
+ size_t GlobalWidth) const {
+ printOptionName(O, GlobalWidth);
+ outs() << "= " << V;
+ size_t NumSpaces = MaxOptWidth > V.size() ? MaxOptWidth - V.size() : 0;
+ outs().indent(NumSpaces) << " (default: ";
+ if (D.hasValue())
+ outs() << D.getValue();
+ else
+ outs() << "*no default*";
+ outs() << ")\n";
+}
+
+// Print a placeholder for options that don't yet support printOptionDiff().
+void basic_parser_impl::
+printOptionNoValue(const Option &O, size_t GlobalWidth) const {
+ printOptionName(O, GlobalWidth);
+ outs() << "= *cannot print option value*\n";
+}
//===----------------------------------------------------------------------===//
// -help and -help-hidden option implementation
@@ -1094,6 +1186,35 @@ static int OptNameCompare(const void *LHS, const void *RHS) {
return strcmp(((pair_ty*)LHS)->first, ((pair_ty*)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,
+ bool ShowHidden) {
+ SmallPtrSet<Option*, 128> OptionSet; // Duplicate option detection.
+
+ for (StringMap<Option*>::iterator I = OptMap.begin(), E = OptMap.end();
+ I != E; ++I) {
+ // Ignore really-hidden options.
+ if (I->second->getOptionHiddenFlag() == ReallyHidden)
+ continue;
+
+ // Unless showhidden is set, ignore hidden flags.
+ if (I->second->getOptionHiddenFlag() == Hidden && !ShowHidden)
+ continue;
+
+ // If we've already seen this option, don't add it to the list again.
+ if (!OptionSet.insert(I->second))
+ continue;
+
+ Opts.push_back(std::pair<const char *, Option*>(I->getKey().data(),
+ I->second));
+ }
+
+ // Sort the options list alphabetically.
+ qsort(Opts.data(), Opts.size(), sizeof(Opts[0]), OptNameCompare);
+}
+
namespace {
class HelpPrinter {
@@ -1115,30 +1236,8 @@ public:
StringMap<Option*> OptMap;
GetOptionInfo(PositionalOpts, SinkOpts, OptMap);
- // Copy Options into a vector so we can sort them as we like.
SmallVector<std::pair<const char *, Option*>, 128> Opts;
- SmallPtrSet<Option*, 128> OptionSet; // Duplicate option detection.
-
- for (StringMap<Option*>::iterator I = OptMap.begin(), E = OptMap.end();
- I != E; ++I) {
- // Ignore really-hidden options.
- if (I->second->getOptionHiddenFlag() == ReallyHidden)
- continue;
-
- // Unless showhidden is set, ignore hidden flags.
- if (I->second->getOptionHiddenFlag() == Hidden && !ShowHidden)
- continue;
-
- // If we've already seen this option, don't add it to the list again.
- if (!OptionSet.insert(I->second))
- continue;
-
- Opts.push_back(std::pair<const char *, Option*>(I->getKey().data(),
- I->second));
- }
-
- // Sort the options list alphabetically.
- qsort(Opts.data(), Opts.size(), sizeof(Opts[0]), OptNameCompare);
+ sortOpts(OptMap, Opts, ShowHidden);
if (ProgramOverview)
outs() << "OVERVIEW: " << ProgramOverview << "\n";
@@ -1197,6 +1296,38 @@ static cl::opt<HelpPrinter, true, parser<bool> >
HHOp("help-hidden", cl::desc("Display all available options"),
cl::location(HiddenPrinter), cl::Hidden, cl::ValueDisallowed);
+static cl::opt<bool>
+PrintOptions("print-options",
+ cl::desc("Print non-default options after command line parsing"),
+ cl::Hidden, cl::init(false));
+
+static cl::opt<bool>
+PrintAllOptions("print-all-options",
+ cl::desc("Print all option values after command line parsing"),
+ cl::Hidden, cl::init(false));
+
+// Print the value of each option.
+void cl::PrintOptionValues() {
+ if (!PrintOptions && !PrintAllOptions) return;
+
+ // Get all the options.
+ SmallVector<Option*, 4> PositionalOpts;
+ SmallVector<Option*, 4> SinkOpts;
+ StringMap<Option*> OptMap;
+ GetOptionInfo(PositionalOpts, SinkOpts, OptMap);
+
+ SmallVector<std::pair<const char *, Option*>, 128> Opts;
+ sortOpts(OptMap, Opts, /*ShowHidden*/true);
+
+ // Compute the maximum argument length...
+ size_t MaxArgLen = 0;
+ for (size_t i = 0, e = Opts.size(); i != e; ++i)
+ MaxArgLen = std::max(MaxArgLen, Opts[i].second->getOptionWidth());
+
+ for (size_t i = 0, e = Opts.size(); i != e; ++i)
+ Opts[i].second->printOptionValue(MaxArgLen, PrintAllOptions);
+}
+
static void (*OverrideVersionPrinter)() = 0;
static int TargetArraySortFn(const void *LHS, const void *RHS) {