diff options
Diffstat (limited to 'lib/Driver/OptTable.cpp')
-rw-r--r-- | lib/Driver/OptTable.cpp | 158 |
1 files changed, 80 insertions, 78 deletions
diff --git a/lib/Driver/OptTable.cpp b/lib/Driver/OptTable.cpp index a3e38b2..6e7b695 100644 --- a/lib/Driver/OptTable.cpp +++ b/lib/Driver/OptTable.cpp @@ -11,6 +11,7 @@ #include "clang/Driver/Arg.h" #include "clang/Driver/ArgList.h" #include "clang/Driver/Option.h" +#include "clang/Driver/Options.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/ErrorHandling.h" #include <algorithm> @@ -54,6 +55,13 @@ static inline bool operator<(const OptTable::Info &A, const OptTable::Info &B) { if (int N = StrCmpOptionName(A.Name, B.Name)) return N == -1; + for (const char * const *APre = A.Prefixes, + * const *BPre = B.Prefixes; + *APre != 0 && *BPre != 0; ++APre, ++BPre) { + if (int N = StrCmpOptionName(*APre, *BPre)) + return N == -1; + } + // Names are the same, check that classes are in order; exactly one // should be joined, and it should succeed the other. assert(((A.Kind == Option::JoinedClass) ^ (B.Kind == Option::JoinedClass)) && @@ -78,23 +86,24 @@ OptSpecifier::OptSpecifier(const Option *Opt) : ID(Opt->getID()) {} // OptTable::OptTable(const Info *_OptionInfos, unsigned _NumOptionInfos) - : OptionInfos(_OptionInfos), NumOptionInfos(_NumOptionInfos), - Options(new Option*[NumOptionInfos]), - TheInputOption(0), TheUnknownOption(0), FirstSearchableIndex(0) + : OptionInfos(_OptionInfos), + NumOptionInfos(_NumOptionInfos), + TheInputOptionID(0), + TheUnknownOptionID(0), + FirstSearchableIndex(0) { // Explicitly zero initialize the error to work around a bug in array // value-initialization on MinGW with gcc 4.3.5. - memset(Options, 0, sizeof(*Options) * NumOptionInfos); // Find start of normal options. for (unsigned i = 0, e = getNumOptions(); i != e; ++i) { unsigned Kind = getInfo(i + 1).Kind; if (Kind == Option::InputClass) { - assert(!TheInputOption && "Cannot have multiple input options!"); - TheInputOption = getOption(i + 1); + assert(!TheInputOptionID && "Cannot have multiple input options!"); + TheInputOptionID = getInfo(i + 1).ID; } else if (Kind == Option::UnknownClass) { - assert(!TheUnknownOption && "Cannot have multiple input options!"); - TheUnknownOption = getOption(i + 1); + assert(!TheUnknownOptionID && "Cannot have multiple unknown options!"); + TheUnknownOptionID = getInfo(i + 1).ID; } else if (Kind != Option::GroupClass) { FirstSearchableIndex = i; break; @@ -115,91 +124,80 @@ OptTable::OptTable(const Info *_OptionInfos, unsigned _NumOptionInfos) // Check that options are in order. for (unsigned i = FirstSearchableIndex+1, e = getNumOptions(); i != e; ++i) { if (!(getInfo(i) < getInfo(i + 1))) { - getOption(i)->dump(); - getOption(i + 1)->dump(); + getOption(i).dump(); + getOption(i + 1).dump(); llvm_unreachable("Options are not in order!"); } } #endif + + // Build prefixes. + for (unsigned i = FirstSearchableIndex+1, e = getNumOptions(); i != e; ++i) { + if (const char *const *P = getInfo(i).Prefixes) { + for (; *P != 0; ++P) { + PrefixesUnion.insert(*P); + } + } + } + + // Build prefix chars. + for (llvm::StringSet<>::const_iterator I = PrefixesUnion.begin(), + E = PrefixesUnion.end(); I != E; ++I) { + StringRef Prefix = I->getKey(); + for (StringRef::const_iterator C = Prefix.begin(), CE = Prefix.end(); + C != CE; ++C) + if (std::find(PrefixChars.begin(), PrefixChars.end(), *C) + == PrefixChars.end()) + PrefixChars.push_back(*C); + } } OptTable::~OptTable() { - for (unsigned i = 0, e = getNumOptions(); i != e; ++i) - delete Options[i]; - delete[] Options; } -Option *OptTable::CreateOption(unsigned id) const { - const Info &info = getInfo(id); - const OptionGroup *Group = - cast_or_null<OptionGroup>(getOption(info.GroupID)); - const Option *Alias = getOption(info.AliasID); - - Option *Opt = 0; - switch (info.Kind) { - case Option::InputClass: - Opt = new InputOption(id); break; - case Option::UnknownClass: - Opt = new UnknownOption(id); break; - case Option::GroupClass: - Opt = new OptionGroup(id, info.Name, Group); break; - case Option::FlagClass: - Opt = new FlagOption(id, info.Name, Group, Alias); break; - case Option::JoinedClass: - Opt = new JoinedOption(id, info.Name, Group, Alias); break; - case Option::SeparateClass: - Opt = new SeparateOption(id, info.Name, Group, Alias); break; - case Option::CommaJoinedClass: - Opt = new CommaJoinedOption(id, info.Name, Group, Alias); break; - case Option::MultiArgClass: - Opt = new MultiArgOption(id, info.Name, Group, Alias, info.Param); break; - case Option::JoinedOrSeparateClass: - Opt = new JoinedOrSeparateOption(id, info.Name, Group, Alias); break; - case Option::JoinedAndSeparateClass: - Opt = new JoinedAndSeparateOption(id, info.Name, Group, Alias); break; - } +const Option OptTable::getOption(OptSpecifier Opt) const { + unsigned id = Opt.getID(); + if (id == 0) + return Option(0, 0); + assert((unsigned) (id - 1) < getNumOptions() && "Invalid ID."); + return Option(&getInfo(id), this); +} - if (info.Flags & DriverOption) - Opt->setDriverOption(true); - if (info.Flags & LinkerInput) - Opt->setLinkerInput(true); - if (info.Flags & NoArgumentUnused) - Opt->setNoArgumentUnused(true); - if (info.Flags & NoForward) - Opt->setNoForward(true); - if (info.Flags & RenderAsInput) - Opt->setNoOptAsInput(true); - if (info.Flags & RenderJoined) { - assert((info.Kind == Option::JoinedOrSeparateClass || - info.Kind == Option::SeparateClass) && "Invalid option."); - Opt->setRenderStyle(Option::RenderJoinedStyle); - } - if (info.Flags & RenderSeparate) { - assert((info.Kind == Option::JoinedOrSeparateClass || - info.Kind == Option::JoinedClass) && "Invalid option."); - Opt->setRenderStyle(Option::RenderSeparateStyle); - } - if (info.Flags & Unsupported) - Opt->setUnsupported(true); - if (info.Flags & CC1Option) - Opt->setIsCC1Option(true); +static bool isInput(const llvm::StringSet<> &Prefixes, StringRef Arg) { + if (Arg == "-") + return true; + for (llvm::StringSet<>::const_iterator I = Prefixes.begin(), + E = Prefixes.end(); I != E; ++I) + if (Arg.startswith(I->getKey())) + return false; + return true; +} - return Opt; +/// \returns Matched size. 0 means no match. +static unsigned matchOption(const OptTable::Info *I, StringRef Str) { + for (const char * const *Pre = I->Prefixes; *Pre != 0; ++Pre) { + StringRef Prefix(*Pre); + if (Str.startswith(Prefix) && Str.substr(Prefix.size()).startswith(I->Name)) + return Prefix.size() + StringRef(I->Name).size(); + } + return 0; } Arg *OptTable::ParseOneArg(const ArgList &Args, unsigned &Index) const { unsigned Prev = Index; const char *Str = Args.getArgString(Index); - // Anything that doesn't start with '-' is an input, as is '-' itself. - if (Str[0] != '-' || Str[1] == '\0') - return new Arg(TheInputOption, Index++, Str); + // Anything that doesn't start with PrefixesUnion is an input, as is '-' + // itself. + if (isInput(PrefixesUnion, Str)) + return new Arg(getOption(TheInputOptionID), Str, Index++, Str); const Info *Start = OptionInfos + FirstSearchableIndex; const Info *End = OptionInfos + getNumOptions(); + StringRef Name = StringRef(Str).ltrim(PrefixChars); // Search for the first next option which could be a prefix. - Start = std::lower_bound(Start, End, Str); + Start = std::lower_bound(Start, End, Name.data()); // Options are stored in sorted order, with '\0' at the end of the // alphabet. Since the only options which can accept a string must @@ -210,15 +208,16 @@ Arg *OptTable::ParseOneArg(const ArgList &Args, unsigned &Index) const { // blanking on the simplest way to make it fast. We can solve this // problem when we move to TableGen. for (; Start != End; ++Start) { + unsigned ArgSize = 0; // Scan for first option which is a proper prefix. for (; Start != End; ++Start) - if (memcmp(Str, Start->Name, strlen(Start->Name)) == 0) + if ((ArgSize = matchOption(Start, Str))) break; if (Start == End) break; // See if this option matches. - if (Arg *A = getOption(Start - OptionInfos + 1)->accept(Args, Index)) + if (Arg *A = Option(Start, this).accept(Args, Index, ArgSize)) return A; // Otherwise, see if this argument was missing values. @@ -226,7 +225,7 @@ Arg *OptTable::ParseOneArg(const ArgList &Args, unsigned &Index) const { return 0; } - return new Arg(TheUnknownOption, Index++, Str); + return new Arg(getOption(TheUnknownOptionID), Str, Index++, Str); } InputArgList *OptTable::ParseArgs(const char* const *ArgBegin, @@ -266,10 +265,11 @@ InputArgList *OptTable::ParseArgs(const char* const *ArgBegin, } static std::string getOptionHelpName(const OptTable &Opts, OptSpecifier Id) { - std::string Name = Opts.getOptionName(Id); + const Option O = Opts.getOption(Id); + std::string Name = O.getPrefixedName(); // Add metavar, if used. - switch (Opts.getOptionKind(Id)) { + switch (O.getKind()) { case Option::GroupClass: case Option::InputClass: case Option::UnknownClass: llvm_unreachable("Invalid option with help text."); @@ -346,7 +346,8 @@ static const char *getOptionHelpGroup(const OptTable &Opts, OptSpecifier Id) { } void OptTable::PrintHelp(raw_ostream &OS, const char *Name, - const char *Title, bool ShowHidden) const { + const char *Title, unsigned short FlagsToInclude, + unsigned short FlagsToExclude) const { OS << "OVERVIEW: " << Title << "\n"; OS << '\n'; OS << "USAGE: " << Name << " [options] <inputs>\n"; @@ -365,7 +366,8 @@ void OptTable::PrintHelp(raw_ostream &OS, const char *Name, if (getOptionKind(Id) == Option::GroupClass) continue; - if (!ShowHidden && isOptionHelpHidden(Id)) + if ((FlagsToInclude && !(getInfo(Id).Flags & FlagsToInclude)) || + getInfo(Id).Flags & FlagsToExclude) continue; if (const char *Text = getOptionHelpText(Id)) { |