LLVM API Documentation

OptTable.cpp
Go to the documentation of this file.
00001 //===--- OptTable.cpp - Option Table Implementation -----------------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 
00010 #include "llvm/Option/OptTable.h"
00011 #include "llvm/Option/Arg.h"
00012 #include "llvm/Option/ArgList.h"
00013 #include "llvm/Option/Option.h"
00014 #include "llvm/Support/ErrorHandling.h"
00015 #include "llvm/Support/raw_ostream.h"
00016 #include <algorithm>
00017 #include <cctype>
00018 #include <map>
00019 
00020 using namespace llvm;
00021 using namespace llvm::opt;
00022 
00023 namespace llvm {
00024 namespace opt {
00025 
00026 // Ordering on Info. The ordering is *almost* case-insensitive lexicographic,
00027 // with an exceptions. '\0' comes at the end of the alphabet instead of the
00028 // beginning (thus options precede any other options which prefix them).
00029 static int StrCmpOptionNameIgnoreCase(const char *A, const char *B) {
00030   const char *X = A, *Y = B;
00031   char a = tolower(*A), b = tolower(*B);
00032   while (a == b) {
00033     if (a == '\0')
00034       return 0;
00035 
00036     a = tolower(*++X);
00037     b = tolower(*++Y);
00038   }
00039 
00040   if (a == '\0') // A is a prefix of B.
00041     return 1;
00042   if (b == '\0') // B is a prefix of A.
00043     return -1;
00044 
00045   // Otherwise lexicographic.
00046   return (a < b) ? -1 : 1;
00047 }
00048 
00049 #ifndef NDEBUG
00050 static int StrCmpOptionName(const char *A, const char *B) {
00051   if (int N = StrCmpOptionNameIgnoreCase(A, B))
00052     return N;
00053   return strcmp(A, B);
00054 }
00055 
00056 static inline bool operator<(const OptTable::Info &A, const OptTable::Info &B) {
00057   if (&A == &B)
00058     return false;
00059 
00060   if (int N = StrCmpOptionName(A.Name, B.Name))
00061     return N < 0;
00062 
00063   for (const char * const *APre = A.Prefixes,
00064                   * const *BPre = B.Prefixes;
00065                           *APre != nullptr && *BPre != nullptr; ++APre, ++BPre){
00066     if (int N = StrCmpOptionName(*APre, *BPre))
00067       return N < 0;
00068   }
00069 
00070   // Names are the same, check that classes are in order; exactly one
00071   // should be joined, and it should succeed the other.
00072   assert(((A.Kind == Option::JoinedClass) ^ (B.Kind == Option::JoinedClass)) &&
00073          "Unexpected classes for options with same name.");
00074   return B.Kind == Option::JoinedClass;
00075 }
00076 #endif
00077 
00078 // Support lower_bound between info and an option name.
00079 static inline bool operator<(const OptTable::Info &I, const char *Name) {
00080   return StrCmpOptionNameIgnoreCase(I.Name, Name) < 0;
00081 }
00082 }
00083 }
00084 
00085 OptSpecifier::OptSpecifier(const Option *Opt) : ID(Opt->getID()) {}
00086 
00087 OptTable::OptTable(const Info *_OptionInfos, unsigned _NumOptionInfos,
00088                    bool _IgnoreCase)
00089   : OptionInfos(_OptionInfos),
00090     NumOptionInfos(_NumOptionInfos),
00091     IgnoreCase(_IgnoreCase),
00092     TheInputOptionID(0),
00093     TheUnknownOptionID(0),
00094     FirstSearchableIndex(0)
00095 {
00096   // Explicitly zero initialize the error to work around a bug in array
00097   // value-initialization on MinGW with gcc 4.3.5.
00098 
00099   // Find start of normal options.
00100   for (unsigned i = 0, e = getNumOptions(); i != e; ++i) {
00101     unsigned Kind = getInfo(i + 1).Kind;
00102     if (Kind == Option::InputClass) {
00103       assert(!TheInputOptionID && "Cannot have multiple input options!");
00104       TheInputOptionID = getInfo(i + 1).ID;
00105     } else if (Kind == Option::UnknownClass) {
00106       assert(!TheUnknownOptionID && "Cannot have multiple unknown options!");
00107       TheUnknownOptionID = getInfo(i + 1).ID;
00108     } else if (Kind != Option::GroupClass) {
00109       FirstSearchableIndex = i;
00110       break;
00111     }
00112   }
00113   assert(FirstSearchableIndex != 0 && "No searchable options?");
00114 
00115 #ifndef NDEBUG
00116   // Check that everything after the first searchable option is a
00117   // regular option class.
00118   for (unsigned i = FirstSearchableIndex, e = getNumOptions(); i != e; ++i) {
00119     Option::OptionClass Kind = (Option::OptionClass) getInfo(i + 1).Kind;
00120     assert((Kind != Option::InputClass && Kind != Option::UnknownClass &&
00121             Kind != Option::GroupClass) &&
00122            "Special options should be defined first!");
00123   }
00124 
00125   // Check that options are in order.
00126   for (unsigned i = FirstSearchableIndex + 1, e = getNumOptions(); i != e; ++i){
00127     if (!(getInfo(i) < getInfo(i + 1))) {
00128       getOption(i).dump();
00129       getOption(i + 1).dump();
00130       llvm_unreachable("Options are not in order!");
00131     }
00132   }
00133 #endif
00134 
00135   // Build prefixes.
00136   for (unsigned i = FirstSearchableIndex + 1, e = getNumOptions() + 1;
00137                 i != e; ++i) {
00138     if (const char *const *P = getInfo(i).Prefixes) {
00139       for (; *P != nullptr; ++P) {
00140         PrefixesUnion.insert(*P);
00141       }
00142     }
00143   }
00144 
00145   // Build prefix chars.
00146   for (llvm::StringSet<>::const_iterator I = PrefixesUnion.begin(),
00147                                          E = PrefixesUnion.end(); I != E; ++I) {
00148     StringRef Prefix = I->getKey();
00149     for (StringRef::const_iterator C = Prefix.begin(), CE = Prefix.end();
00150                                    C != CE; ++C)
00151       if (std::find(PrefixChars.begin(), PrefixChars.end(), *C)
00152             == PrefixChars.end())
00153         PrefixChars.push_back(*C);
00154   }
00155 }
00156 
00157 OptTable::~OptTable() {
00158 }
00159 
00160 const Option OptTable::getOption(OptSpecifier Opt) const {
00161   unsigned id = Opt.getID();
00162   if (id == 0)
00163     return Option(nullptr, nullptr);
00164   assert((unsigned) (id - 1) < getNumOptions() && "Invalid ID.");
00165   return Option(&getInfo(id), this);
00166 }
00167 
00168 static bool isInput(const llvm::StringSet<> &Prefixes, StringRef Arg) {
00169   if (Arg == "-")
00170     return true;
00171   for (llvm::StringSet<>::const_iterator I = Prefixes.begin(),
00172                                          E = Prefixes.end(); I != E; ++I)
00173     if (Arg.startswith(I->getKey()))
00174       return false;
00175   return true;
00176 }
00177 
00178 /// \returns Matched size. 0 means no match.
00179 static unsigned matchOption(const OptTable::Info *I, StringRef Str,
00180                             bool IgnoreCase) {
00181   for (const char * const *Pre = I->Prefixes; *Pre != nullptr; ++Pre) {
00182     StringRef Prefix(*Pre);
00183     if (Str.startswith(Prefix)) {
00184       StringRef Rest = Str.substr(Prefix.size());
00185       bool Matched = IgnoreCase
00186           ? Rest.startswith_lower(I->Name)
00187           : Rest.startswith(I->Name);
00188       if (Matched)
00189         return Prefix.size() + StringRef(I->Name).size();
00190     }
00191   }
00192   return 0;
00193 }
00194 
00195 Arg *OptTable::ParseOneArg(const ArgList &Args, unsigned &Index,
00196                            unsigned FlagsToInclude,
00197                            unsigned FlagsToExclude) const {
00198   unsigned Prev = Index;
00199   const char *Str = Args.getArgString(Index);
00200 
00201   // Anything that doesn't start with PrefixesUnion is an input, as is '-'
00202   // itself.
00203   if (isInput(PrefixesUnion, Str))
00204     return new Arg(getOption(TheInputOptionID), Str, Index++, Str);
00205 
00206   const Info *Start = OptionInfos + FirstSearchableIndex;
00207   const Info *End = OptionInfos + getNumOptions();
00208   StringRef Name = StringRef(Str).ltrim(PrefixChars);
00209 
00210   // Search for the first next option which could be a prefix.
00211   Start = std::lower_bound(Start, End, Name.data());
00212 
00213   // Options are stored in sorted order, with '\0' at the end of the
00214   // alphabet. Since the only options which can accept a string must
00215   // prefix it, we iteratively search for the next option which could
00216   // be a prefix.
00217   //
00218   // FIXME: This is searching much more than necessary, but I am
00219   // blanking on the simplest way to make it fast. We can solve this
00220   // problem when we move to TableGen.
00221   for (; Start != End; ++Start) {
00222     unsigned ArgSize = 0;
00223     // Scan for first option which is a proper prefix.
00224     for (; Start != End; ++Start)
00225       if ((ArgSize = matchOption(Start, Str, IgnoreCase)))
00226         break;
00227     if (Start == End)
00228       break;
00229 
00230     Option Opt(Start, this);
00231 
00232     if (FlagsToInclude && !Opt.hasFlag(FlagsToInclude))
00233       continue;
00234     if (Opt.hasFlag(FlagsToExclude))
00235       continue;
00236 
00237     // See if this option matches.
00238     if (Arg *A = Opt.accept(Args, Index, ArgSize))
00239       return A;
00240 
00241     // Otherwise, see if this argument was missing values.
00242     if (Prev != Index)
00243       return nullptr;
00244   }
00245 
00246   // If we failed to find an option and this arg started with /, then it's
00247   // probably an input path.
00248   if (Str[0] == '/')
00249     return new Arg(getOption(TheInputOptionID), Str, Index++, Str);
00250 
00251   return new Arg(getOption(TheUnknownOptionID), Str, Index++, Str);
00252 }
00253 
00254 InputArgList *OptTable::ParseArgs(const char *const *ArgBegin,
00255                                   const char *const *ArgEnd,
00256                                   unsigned &MissingArgIndex,
00257                                   unsigned &MissingArgCount,
00258                                   unsigned FlagsToInclude,
00259                                   unsigned FlagsToExclude) const {
00260   InputArgList *Args = new InputArgList(ArgBegin, ArgEnd);
00261 
00262   // FIXME: Handle '@' args (or at least error on them).
00263 
00264   MissingArgIndex = MissingArgCount = 0;
00265   unsigned Index = 0, End = ArgEnd - ArgBegin;
00266   while (Index < End) {
00267     // Ingore nullptrs, they are response file's EOL markers
00268     if (Args->getArgString(Index) == nullptr) {
00269       ++Index;
00270       continue;
00271     }
00272     // Ignore empty arguments (other things may still take them as arguments).
00273     StringRef Str = Args->getArgString(Index);
00274     if (Str == "") {
00275       ++Index;
00276       continue;
00277     }
00278 
00279     unsigned Prev = Index;
00280     Arg *A = ParseOneArg(*Args, Index, FlagsToInclude, FlagsToExclude);
00281     assert(Index > Prev && "Parser failed to consume argument.");
00282 
00283     // Check for missing argument error.
00284     if (!A) {
00285       assert(Index >= End && "Unexpected parser error.");
00286       assert(Index - Prev - 1 && "No missing arguments!");
00287       MissingArgIndex = Prev;
00288       MissingArgCount = Index - Prev - 1;
00289       break;
00290     }
00291 
00292     Args->append(A);
00293   }
00294 
00295   return Args;
00296 }
00297 
00298 static std::string getOptionHelpName(const OptTable &Opts, OptSpecifier Id) {
00299   const Option O = Opts.getOption(Id);
00300   std::string Name = O.getPrefixedName();
00301 
00302   // Add metavar, if used.
00303   switch (O.getKind()) {
00304   case Option::GroupClass: case Option::InputClass: case Option::UnknownClass:
00305     llvm_unreachable("Invalid option with help text.");
00306 
00307   case Option::MultiArgClass:
00308     if (const char *MetaVarName = Opts.getOptionMetaVar(Id)) {
00309       // For MultiArgs, metavar is full list of all argument names.
00310       Name += ' ';
00311       Name += MetaVarName;
00312     }
00313     else {
00314       // For MultiArgs<N>, if metavar not supplied, print <value> N times.
00315       for (unsigned i=0, e=O.getNumArgs(); i< e; ++i) {
00316         Name += " <value>";
00317       }
00318     }
00319     break;
00320 
00321   case Option::FlagClass:
00322     break;
00323 
00324   case Option::SeparateClass: case Option::JoinedOrSeparateClass:
00325   case Option::RemainingArgsClass:
00326     Name += ' ';
00327     // FALLTHROUGH
00328   case Option::JoinedClass: case Option::CommaJoinedClass:
00329   case Option::JoinedAndSeparateClass:
00330     if (const char *MetaVarName = Opts.getOptionMetaVar(Id))
00331       Name += MetaVarName;
00332     else
00333       Name += "<value>";
00334     break;
00335   }
00336 
00337   return Name;
00338 }
00339 
00340 static void PrintHelpOptionList(raw_ostream &OS, StringRef Title,
00341                                 std::vector<std::pair<std::string,
00342                                 const char*> > &OptionHelp) {
00343   OS << Title << ":\n";
00344 
00345   // Find the maximum option length.
00346   unsigned OptionFieldWidth = 0;
00347   for (unsigned i = 0, e = OptionHelp.size(); i != e; ++i) {
00348     // Skip titles.
00349     if (!OptionHelp[i].second)
00350       continue;
00351 
00352     // Limit the amount of padding we are willing to give up for alignment.
00353     unsigned Length = OptionHelp[i].first.size();
00354     if (Length <= 23)
00355       OptionFieldWidth = std::max(OptionFieldWidth, Length);
00356   }
00357 
00358   const unsigned InitialPad = 2;
00359   for (unsigned i = 0, e = OptionHelp.size(); i != e; ++i) {
00360     const std::string &Option = OptionHelp[i].first;
00361     int Pad = OptionFieldWidth - int(Option.size());
00362     OS.indent(InitialPad) << Option;
00363 
00364     // Break on long option names.
00365     if (Pad < 0) {
00366       OS << "\n";
00367       Pad = OptionFieldWidth + InitialPad;
00368     }
00369     OS.indent(Pad + 1) << OptionHelp[i].second << '\n';
00370   }
00371 }
00372 
00373 static const char *getOptionHelpGroup(const OptTable &Opts, OptSpecifier Id) {
00374   unsigned GroupID = Opts.getOptionGroupID(Id);
00375 
00376   // If not in a group, return the default help group.
00377   if (!GroupID)
00378     return "OPTIONS";
00379 
00380   // Abuse the help text of the option groups to store the "help group"
00381   // name.
00382   //
00383   // FIXME: Split out option groups.
00384   if (const char *GroupHelp = Opts.getOptionHelpText(GroupID))
00385     return GroupHelp;
00386 
00387   // Otherwise keep looking.
00388   return getOptionHelpGroup(Opts, GroupID);
00389 }
00390 
00391 void OptTable::PrintHelp(raw_ostream &OS, const char *Name, const char *Title,
00392                          bool ShowHidden) const {
00393   PrintHelp(OS, Name, Title, /*Include*/ 0, /*Exclude*/
00394             (ShowHidden ? 0 : HelpHidden));
00395 }
00396 
00397 
00398 void OptTable::PrintHelp(raw_ostream &OS, const char *Name, const char *Title,
00399                          unsigned FlagsToInclude,
00400                          unsigned FlagsToExclude) const {
00401   OS << "OVERVIEW: " << Title << "\n";
00402   OS << '\n';
00403   OS << "USAGE: " << Name << " [options] <inputs>\n";
00404   OS << '\n';
00405 
00406   // Render help text into a map of group-name to a list of (option, help)
00407   // pairs.
00408   typedef std::map<std::string,
00409                  std::vector<std::pair<std::string, const char*> > > helpmap_ty;
00410   helpmap_ty GroupedOptionHelp;
00411 
00412   for (unsigned i = 0, e = getNumOptions(); i != e; ++i) {
00413     unsigned Id = i + 1;
00414 
00415     // FIXME: Split out option groups.
00416     if (getOptionKind(Id) == Option::GroupClass)
00417       continue;
00418 
00419     unsigned Flags = getInfo(Id).Flags;
00420     if (FlagsToInclude && !(Flags & FlagsToInclude))
00421       continue;
00422     if (Flags & FlagsToExclude)
00423       continue;
00424 
00425     if (const char *Text = getOptionHelpText(Id)) {
00426       const char *HelpGroup = getOptionHelpGroup(*this, Id);
00427       const std::string &OptName = getOptionHelpName(*this, Id);
00428       GroupedOptionHelp[HelpGroup].push_back(std::make_pair(OptName, Text));
00429     }
00430   }
00431 
00432   for (helpmap_ty::iterator it = GroupedOptionHelp .begin(),
00433          ie = GroupedOptionHelp.end(); it != ie; ++it) {
00434     if (it != GroupedOptionHelp .begin())
00435       OS << "\n";
00436     PrintHelpOptionList(OS, it->first, it->second);
00437   }
00438 
00439   OS.flush();
00440 }