X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FSupport%2FCommandLine.cpp;h=238adcce0a121aebdde989e178639248c04241f5;hb=adf01b3f18442ae8db6b8948e70d82d9df415119;hp=2ab4103de2ec55ab3c6e46eb0a67098b7f5345ed;hpb=7e7ae5ad692760aa8d97477f061a05b10948cf57;p=oota-llvm.git diff --git a/lib/Support/CommandLine.cpp b/lib/Support/CommandLine.cpp index 2ab4103de2e..238adcce0a1 100644 --- a/lib/Support/CommandLine.cpp +++ b/lib/Support/CommandLine.cpp @@ -22,9 +22,9 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetRegistry.h" -#include "llvm/System/Host.h" -#include "llvm/System/Path.h" +#include "llvm/Support/system_error.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/Path.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" @@ -44,6 +44,7 @@ TEMPLATE_INSTANTIATION(class basic_parser); TEMPLATE_INSTANTIATION(class basic_parser); TEMPLATE_INSTANTIATION(class basic_parser); TEMPLATE_INSTANTIATION(class basic_parser); +TEMPLATE_INSTANTIATION(class basic_parser); TEMPLATE_INSTANTIATION(class basic_parser); TEMPLATE_INSTANTIATION(class basic_parser); TEMPLATE_INSTANTIATION(class basic_parser); @@ -62,6 +63,7 @@ void parser::anchor() {} void parser::anchor() {} void parser::anchor() {} void parser::anchor() {} +void parser::anchor() {} void parser::anchor() {} void parser::anchor() {} void parser::anchor() {} @@ -179,6 +181,52 @@ static Option *LookupOption(StringRef &Arg, StringRef &Value, return I->second; } +/// 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 +/// have already been stripped. +static Option *LookupNearestOption(StringRef Arg, + const StringMap &OptionsMap, + std::string &NearestString) { + // Reject all dashes. + if (Arg.empty()) return 0; + + // Split on any equal sign. + std::pair SplitArg = Arg.split('='); + StringRef &LHS = SplitArg.first; // LHS == Arg when no '=' is present. + StringRef &RHS = SplitArg.second; + + // Find the closest match. + Option *Best = 0; + unsigned BestDistance = 0; + for (StringMap::const_iterator it = OptionsMap.begin(), + ie = OptionsMap.end(); it != ie; ++it) { + Option *O = it->second; + SmallVector OptionNames; + O->getExtraOptionNames(OptionNames); + 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( + Flag, /*AllowReplacements=*/true, /*MaxEditDistance=*/BestDistance); + if (!Best || Distance < BestDistance) { + Best = O; + BestDistance = Distance; + if (RHS.empty() || !PermitValue) + NearestString = OptionNames[i]; + else + NearestString = std::string(OptionNames[i]) + "=" + RHS.str(); + } + } + } + + return Best; +} + /// CommaSeparateAndAddOccurence - A wrapper around Handler->addOccurence() that /// does special handling of cl::CommaSeparated options. static bool CommaSeparateAndAddOccurence(Option *Handler, unsigned pos, @@ -463,10 +511,6 @@ static void ExpandResponseFiles(unsigned argc, char** argv, const sys::FileStatus *FileStat = respFile.getFileStatus(); if (FileStat && FileStat->getSize() != 0) { - // Mmap the response file into memory. - OwningPtr - respFilePtr(MemoryBuffer::getFile(respFile.c_str())); - // If we could open the file, parse its contents, otherwise // pass the @file option verbatim. @@ -475,7 +519,9 @@ static void ExpandResponseFiles(unsigned argc, char** argv, // itself contain additional @file options; any such options will be // processed recursively.") - if (respFilePtr != 0) { + // Mmap the response file into memory. + OwningPtr respFilePtr; + if (!MemoryBuffer::getFile(respFile.c_str(), respFilePtr)) { ParseCStringVector(newArgv, respFilePtr->getBufferStart()); continue; } @@ -506,7 +552,7 @@ void cl::ParseCommandLineOptions(int argc, char **argv, } // Copy the program name into ProgName, making sure not to overflow it. - std::string ProgName = sys::Path(argv[0]).getLast(); + std::string ProgName = sys::path::filename(argv[0]); size_t Len = std::min(ProgName.size(), size_t(79)); memcpy(ProgramName, ProgName.data(), Len); ProgramName[Len] = '\0'; @@ -572,6 +618,8 @@ void cl::ParseCommandLineOptions(int argc, char **argv, bool DashDashFound = false; // Have we read '--'? for (int i = 1; i < argc; ++i) { Option *Handler = 0; + Option *NearestHandler = 0; + std::string NearestHandlerString; StringRef Value; StringRef ArgName = ""; @@ -645,12 +693,25 @@ void cl::ParseCommandLineOptions(int argc, char **argv, if (Handler == 0) Handler = HandlePrefixedOrGroupedOption(ArgName, Value, ErrorParsing, Opts); + + // Otherwise, look for the closest available option to report to the user + // in the upcoming error. + if (Handler == 0 && SinkOpts.empty()) + NearestHandler = LookupNearestOption(ArgName, Opts, + NearestHandlerString); } if (Handler == 0) { if (SinkOpts.empty()) { 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"; + } + ErrorParsing = true; } else { for (SmallVectorImpl::iterator I = SinkOpts.begin(), @@ -676,8 +737,8 @@ void cl::ParseCommandLineOptions(int argc, char **argv, << " positional arguments: See: " << argv[0] << " -help\n"; ErrorParsing = true; - } else if (!HasUnlimitedPositionals - && PositionalVals.size() > PositionalOpts.size()) { + } else if (!HasUnlimitedPositionals && + PositionalVals.size() > PositionalOpts.size()) { errs() << ProgramName << ": Too many positional arguments specified!\n" << "Can specify at most " << PositionalOpts.size() @@ -765,6 +826,15 @@ void cl::ParseCommandLineOptions(int argc, char **argv, } } + // Now that we know if -debug is specified, we can use it. + // Note that if ReadResponseFiles == true, this must be done before the + // memory allocated for the expanded command line is free()d below. + DEBUG(dbgs() << "Args: "; + for (int i = 0; i < argc; ++i) + dbgs() << argv[i] << ' '; + dbgs() << '\n'; + ); + // Free all of the memory allocated to the map. Command line options may only // be processed once! Opts.clear(); @@ -779,12 +849,6 @@ void cl::ParseCommandLineOptions(int argc, char **argv, free(*i); } - DEBUG(dbgs() << "Args: "; - for (int i = 0; i < argc; ++i) - dbgs() << argv[i] << ' '; - dbgs() << '\n'; - ); - // If we had an error processing our arguments, don't let the program execute if (ErrorParsing) exit(1); } @@ -848,12 +912,10 @@ size_t alias::getOptionWidth() const { // Print out the option for the alias. void alias::printOptionInfo(size_t GlobalWidth) const { size_t L = std::strlen(ArgStr); - errs() << " -" << ArgStr; - errs().indent(GlobalWidth-L-6) << " - " << HelpStr << "\n"; + outs() << " -" << ArgStr; + outs().indent(GlobalWidth-L-6) << " - " << HelpStr << "\n"; } - - //===----------------------------------------------------------------------===// // Parser Implementation code... // @@ -883,7 +945,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 implementation @@ -941,6 +1007,16 @@ bool parser::parse(Option &O, StringRef ArgName, return false; } +// parser implementation +// +bool parser::parse(Option &O, StringRef ArgName, + StringRef Arg, unsigned long long &Value){ + + if (Arg.getAsInteger(0, Value)) + return O.error("'" + Arg + "' value invalid for uint argument!"); + return false; +} + // parser/parser implementation // static bool parseDouble(Option &O, StringRef Arg, double &Value) { @@ -1027,6 +1103,90 @@ 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:: \ + printOptionDiff(const Option &O, T V, OptionValue 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(unsigned long long) +PRINT_OPT_DIFF(double) +PRINT_OPT_DIFF(float) +PRINT_OPT_DIFF(char) + +void parser:: +printOptionDiff(const Option &O, StringRef V, OptionValue 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 @@ -1038,6 +1198,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 &OptMap, + SmallVectorImpl< std::pair > &Opts, + bool ShowHidden) { + SmallPtrSet OptionSet; // Duplicate option detection. + + for (StringMap::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(I->getKey().data(), + I->second)); + } + + // Sort the options list alphabetically. + qsort(Opts.data(), Opts.size(), sizeof(Opts[0]), OptNameCompare); +} + namespace { class HelpPrinter { @@ -1059,30 +1248,8 @@ public: StringMap OptMap; GetOptionInfo(PositionalOpts, SinkOpts, OptMap); - // Copy Options into a vector so we can sort them as we like. SmallVector, 128> Opts; - SmallPtrSet OptionSet; // Duplicate option detection. - - for (StringMap::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(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"; @@ -1141,13 +1308,42 @@ static cl::opt > HHOp("help-hidden", cl::desc("Display all available options"), cl::location(HiddenPrinter), cl::Hidden, cl::ValueDisallowed); -static void (*OverrideVersionPrinter)() = 0; +static cl::opt +PrintOptions("print-options", + cl::desc("Print non-default options after command line parsing"), + cl::Hidden, cl::init(false)); + +static cl::opt +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 PositionalOpts; + SmallVector SinkOpts; + StringMap OptMap; + GetOptionInfo(PositionalOpts, SinkOpts, OptMap); + + SmallVector, 128> Opts; + sortOpts(OptMap, Opts, /*ShowHidden*/true); -static int TargetArraySortFn(const void *LHS, const void *RHS) { - typedef std::pair pair_ty; - return strcmp(((const pair_ty*)LHS)->first, ((const pair_ty*)RHS)->first); + // 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 std::vector* ExtraVersionPrinters = 0; + namespace { class VersionPrinter { public: @@ -1170,39 +1366,31 @@ public: std::string CPU = sys::getHostCPUName(); if (CPU == "generic") CPU = "(unknown)"; OS << ".\n" +#if (ENABLE_TIMESTAMPS == 1) << " Built " << __DATE__ << " (" << __TIME__ << ").\n" +#endif << " Host: " << sys::getHostTriple() << '\n' - << " Host CPU: " << CPU << '\n' - << '\n' - << " Registered Targets:\n"; - - std::vector > Targets; - size_t Width = 0; - for (TargetRegistry::iterator it = TargetRegistry::begin(), - ie = TargetRegistry::end(); it != ie; ++it) { - Targets.push_back(std::make_pair(it->getName(), &*it)); - Width = std::max(Width, strlen(Targets.back().first)); - } - if (!Targets.empty()) - qsort(&Targets[0], Targets.size(), sizeof(Targets[0]), - TargetArraySortFn); - - for (unsigned i = 0, e = Targets.size(); i != e; ++i) { - OS << " " << Targets[i].first; - OS.indent(Width - strlen(Targets[i].first)) << " - " - << Targets[i].second->getShortDescription() << '\n'; - } - if (Targets.empty()) - OS << " (none)\n"; + << " Host CPU: " << CPU << '\n'; } void operator=(bool OptionWasSpecified) { if (!OptionWasSpecified) return; - if (OverrideVersionPrinter == 0) { - print(); + if (OverrideVersionPrinter != 0) { + (*OverrideVersionPrinter)(); exit(1); } - (*OverrideVersionPrinter)(); + print(); + + // Iterate over any registered extra printers and call them to add further + // information. + if (ExtraVersionPrinters != 0) { + outs() << '\n'; + for (std::vector::iterator I = ExtraVersionPrinters->begin(), + E = ExtraVersionPrinters->end(); + I != E; ++I) + (*I)(); + } + exit(1); } }; @@ -1235,3 +1423,10 @@ void cl::PrintVersionMessage() { void cl::SetVersionPrinter(void (*func)()) { OverrideVersionPrinter = func; } + +void cl::AddExtraVersionPrinter(void (*func)()) { + if (ExtraVersionPrinters == 0) + ExtraVersionPrinters = new std::vector; + + ExtraVersionPrinters->push_back(func); +}