diff options
author | Chris Lattner <sabre@nondot.org> | 2009-09-20 05:03:30 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2009-09-20 05:03:30 +0000 |
commit | b168737a7479bc5c1cfdf62f8cc0f9ad652c2676 (patch) | |
tree | 8d5aaa17bf3928d9eaa31037f207ad8dc318c5e8 /lib/Support | |
parent | 3892baac42daadf760d140168720be1d6e585aa8 (diff) | |
download | external_llvm-b168737a7479bc5c1cfdf62f8cc0f9ad652c2676.zip external_llvm-b168737a7479bc5c1cfdf62f8cc0f9ad652c2676.tar.gz external_llvm-b168737a7479bc5c1cfdf62f8cc0f9ad652c2676.tar.bz2 |
Several changes together in a murky mess:
1. Change some "\n" -> '\n'.
2. eliminte some std::string's by using raw_ostream::indent.
3. move a bunch of code out of the main arg parser routine into
a new static HandlePrefixedOrGroupedOption function.
4. Greatly simplify the implementation of getOptionPred, and make
it avoid splitting prefix options at = when that doesn't match
a non-prefix option.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@82362 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Support')
-rw-r--r-- | lib/Support/CommandLine.cpp | 186 |
1 files changed, 102 insertions, 84 deletions
diff --git a/lib/Support/CommandLine.cpp b/lib/Support/CommandLine.cpp index 7de7ba6..fbd58aa 100644 --- a/lib/Support/CommandLine.cpp +++ b/lib/Support/CommandLine.cpp @@ -150,29 +150,34 @@ static void GetOptionInfo(std::vector<Option*> &PositionalOpts, /// 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. +/// that as well. This assumes that leading dashes have already been stripped. static Option *LookupOption(StringRef &Arg, StringRef &Value, const StringMap<Option*> &OptionsMap) { - // Eat leading dashes. - while (!Arg.empty() && Arg[0] == '-') - Arg = Arg.substr(1); - // Reject all dashes. if (Arg.empty()) return 0; size_t EqualPos = Arg.find('='); // If we have an equals sign, remember the value. - if (EqualPos != StringRef::npos) { - Value = Arg.substr(EqualPos+1); - Arg = Arg.substr(0, EqualPos); + if (EqualPos == StringRef::npos) { + // Look up the option. + StringMap<Option*>::const_iterator I = OptionsMap.find(Arg); + return I != OptionsMap.end() ? I->second : 0; } - // Look up the option. - StringMap<Option*>::const_iterator I = OptionsMap.find(Arg); - return I != OptionsMap.end() ? I->second : 0; + // If the argument before the = is a valid option name, we match. If not, + // return Arg unmolested. + StringMap<Option*>::const_iterator I = + OptionsMap.find(Arg.substr(0, EqualPos)); + if (I == OptionsMap.end()) return 0; + + Value = Arg.substr(EqualPos+1); + Arg = Arg.substr(0, EqualPos); + return I->second; } + + /// ProvideOption - For Value, this differentiates between an empty value ("") /// and a null value (StringRef()). The later is accepted for arguments that /// don't allow a value (-foo) the former is rejected (-foo=). @@ -260,23 +265,17 @@ static inline bool isPrefixedOrGrouping(const Option *O) { // static Option *getOptionPred(StringRef Name, size_t &Length, bool (*Pred)(const Option*), - StringMap<Option*> &OptionsMap) { + const StringMap<Option*> &OptionsMap) { - StringMap<Option*>::iterator OMI = OptionsMap.find(Name); - if (OMI != OptionsMap.end() && Pred(OMI->second)) { - Length = Name.size(); - return OMI->second; - } + StringMap<Option*>::const_iterator OMI = OptionsMap.find(Name); - if (Name.size() == 1) return 0; - do { + // Loop while we haven't found an option and Name still has at least two + // characters in it (so that the next iteration will not be the empty + // string. + while (OMI == OptionsMap.end() && Name.size() > 1) { Name = Name.substr(0, Name.size()-1); // Chop off the last character. OMI = OptionsMap.find(Name); - - // Loop while we haven't found an option and Name still has at least two - // characters in it (so that the next iteration will not be the empty - // string. - } while ((OMI == OptionsMap.end() || !Pred(OMI->second)) && Name.size() > 1); + } if (OMI != OptionsMap.end() && Pred(OMI->second)) { Length = Name.size(); @@ -285,6 +284,57 @@ static Option *getOptionPred(StringRef Name, size_t &Length, return 0; // No option found! } +/// HandlePrefixedOrGroupedOption - The specified argument string (which started +/// with at least one '-') does not fully match an available option. Check to +/// see if this is a prefix or grouped option. If so, split arg into output an +/// Arg/Value pair and return the Option to parse it with. +static Option *HandlePrefixedOrGroupedOption(StringRef &Arg, StringRef &Value, + bool &ErrorParsing, + const StringMap<Option*> &OptionsMap) { + if (Arg.size() == 1) return 0; + + // Do the lookup! + size_t Length = 0; + Option *PGOpt = getOptionPred(Arg, Length, isPrefixedOrGrouping, OptionsMap); + if (PGOpt == 0) return 0; + + // If the option is a prefixed option, then the value is simply the + // rest of the name... so fall through to later processing, by + // setting up the argument name flags and value fields. + if (PGOpt->getFormattingFlag() == cl::Prefix) { + Value = Arg.substr(Length); + Arg = Arg.substr(0, Length); + assert(OptionsMap.count(Arg) && OptionsMap.find(Arg)->second == PGOpt); + return PGOpt; + } + + // This must be a grouped option... handle them now. Grouping options can't + // have values. + assert(isGrouping(PGOpt) && "Broken getOptionPred!"); + + do { + // Move current arg name out of Arg into OneArgName. + StringRef OneArgName = Arg.substr(0, Length); + Arg = Arg.substr(Length); + + // Because ValueRequired is an invalid flag for grouped arguments, + // we don't need to pass argc/argv in. + assert(PGOpt->getValueExpectedFlag() != cl::ValueRequired && + "Option can not be cl::Grouping AND cl::ValueRequired!"); + int Dummy; + ErrorParsing |= ProvideOption(PGOpt, OneArgName, + StringRef(), 0, 0, Dummy); + + // Get the next grouping option. + PGOpt = getOptionPred(Arg, Length, isGrouping, OptionsMap); + } while (PGOpt && Length != Arg.size()); + + // Return the last option with Arg cut down to just the last one. + return PGOpt; +} + + + static bool RequiresValue(const Option *O) { return O->getNumOccurrencesFlag() == cl::Required || O->getNumOccurrencesFlag() == cl::OneOrMore; @@ -365,13 +415,12 @@ void cl::ParseEnvironmentOptions(const char *progName, const char *envVar, /// ExpandResponseFiles - Copy the contents of argv into newArgv, /// substituting the contents of the response files for the arguments /// of type @file. -static void ExpandResponseFiles(int argc, char** argv, +static void ExpandResponseFiles(unsigned argc, char** argv, std::vector<char*>& newArgv) { - for (int i = 1; i != argc; ++i) { - char* arg = argv[i]; + for (unsigned i = 1; i != argc; ++i) { + char *arg = argv[i]; if (arg[0] == '@') { - sys::PathWithStatus respFile(++arg); // Check that the response file is not empty (mmap'ing empty @@ -538,6 +587,10 @@ void cl::ParseCommandLineOptions(int argc, char **argv, // option is another positional argument. If so, treat it as an argument, // otherwise feed it to the eating positional. ArgName = argv[i]+1; + // Eat leading dashes. + while (!ArgName.empty() && ArgName[0] == '-') + ArgName = ArgName.substr(1); + Handler = LookupOption(ArgName, Value, Opts); if (!Handler || Handler->getFormattingFlag() != cl::Positional) { ProvidePositionalOption(ActivePositionalArg, argv[i], i); @@ -546,51 +599,16 @@ void cl::ParseCommandLineOptions(int argc, char **argv, } else { // We start with a '-', must be an argument. ArgName = argv[i]+1; + // Eat leading dashes. + while (!ArgName.empty() && ArgName[0] == '-') + ArgName = ArgName.substr(1); + Handler = LookupOption(ArgName, Value, Opts); // Check to see if this "option" is really a prefixed or grouped argument. - if (Handler == 0) { - StringRef RealName(ArgName); - if (RealName.size() > 1) { - size_t Length = 0; - Option *PGOpt = - getOptionPred(RealName, Length, isPrefixedOrGrouping, Opts); - - // If the option is a prefixed option, then the value is simply the - // rest of the name... so fall through to later processing, by - // setting up the argument name flags and value fields. - if (PGOpt && PGOpt->getFormattingFlag() == cl::Prefix) { - ArgName = argv[i]+1; - Value = ArgName.substr(Length); - assert(Opts.count(ArgName.substr(0, Length)) && - Opts[ArgName.substr(0, Length)] == PGOpt); - Handler = PGOpt; - } else if (PGOpt) { - // This must be a grouped option... handle them now. - assert(isGrouping(PGOpt) && "Broken getOptionPred!"); - - do { - // Move current arg name out of RealName into RealArgName. - StringRef RealArgName = RealName.substr(0, Length); - RealName = RealName.substr(Length); - - // Because ValueRequired is an invalid flag for grouped arguments, - // we don't need to pass argc/argv in. - // - assert(PGOpt->getValueExpectedFlag() != cl::ValueRequired && - "Option can not be cl::Grouping AND cl::ValueRequired!"); - int Dummy; - ErrorParsing |= ProvideOption(PGOpt, RealArgName, - StringRef(), 0, 0, Dummy); - - // Get the next grouping option. - PGOpt = getOptionPred(RealName, Length, isGrouping, Opts); - } while (PGOpt && Length != RealName.size()); - - Handler = PGOpt; // Ate all of the options. - } - } - } + if (Handler == 0) + Handler = HandlePrefixedOrGroupedOption(ArgName, Value, + ErrorParsing, Opts); } if (Handler == 0) { @@ -650,7 +668,7 @@ void cl::ParseCommandLineOptions(int argc, char **argv, ErrorParsing = true; } else if (ConsumeAfterOpt == 0) { - // Positional args have already been handled if ConsumeAfter is specified... + // Positional args have already been handled if ConsumeAfter is specified. unsigned ValNo = 0, NumVals = static_cast<unsigned>(PositionalVals.size()); for (size_t i = 0, e = PositionalOpts.size(); i != e; ++i) { if (RequiresValue(PositionalOpts[i])) { @@ -807,8 +825,8 @@ 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 << std::string(GlobalWidth-L-6, ' ') << " - " - << HelpStr << "\n"; + errs() << " -" << ArgStr; + errs().indent(GlobalWidth-L-6) << " - " << HelpStr << "\n"; } @@ -967,21 +985,21 @@ void generic_parser_base::printOptionInfo(const Option &O, size_t GlobalWidth) const { if (O.hasArgStr()) { size_t L = std::strlen(O.ArgStr); - outs() << " -" << O.ArgStr << std::string(GlobalWidth-L-6, ' ') - << " - " << O.HelpStr << '\n'; + outs() << " -" << O.ArgStr; + outs().indent(GlobalWidth-L-6) << " - " << O.HelpStr << '\n'; for (unsigned i = 0, e = getNumOptions(); i != e; ++i) { size_t NumSpaces = GlobalWidth-strlen(getOption(i))-8; - outs() << " =" << getOption(i) << std::string(NumSpaces, ' ') - << " - " << getDescription(i) << '\n'; + outs() << " =" << getOption(i); + outs().indent(NumSpaces) << " - " << getDescription(i) << '\n'; } } else { if (O.HelpStr[0]) - outs() << " " << O.HelpStr << "\n"; + outs() << " " << O.HelpStr << '\n'; for (unsigned i = 0, e = getNumOptions(); i != e; ++i) { size_t L = std::strlen(getOption(i)); - outs() << " -" << getOption(i) << std::string(GlobalWidth-L-8, ' ') - << " - " << getDescription(i) << "\n"; + outs() << " -" << getOption(i); + outs().indent(GlobalWidth-L-8) << " - " << getDescription(i) << '\n'; } } } @@ -1121,7 +1139,7 @@ public: #endif outs() << ".\n" << " Built " << __DATE__ << " (" << __TIME__ << ").\n" - << " Host: " << sys::getHostTriple() << "\n" + << " Host: " << sys::getHostTriple() << '\n' << "\n" << " Registered Targets:\n"; @@ -1135,9 +1153,9 @@ public: std::sort(Targets.begin(), Targets.end()); for (unsigned i = 0, e = Targets.size(); i != e; ++i) { - outs() << " " << Targets[i].first - << std::string(Width - Targets[i].first.length(), ' ') << " - " - << Targets[i].second->getShortDescription() << "\n"; + outs() << " " << Targets[i].first; + outs().indent(Width - Targets[i].first.length()) << " - " + << Targets[i].second->getShortDescription() << '\n'; } if (Targets.empty()) outs() << " (none)\n"; |