clang API Documentation

Option.cpp
Go to the documentation of this file.
00001 //===--- Option.cpp - Abstract Driver Options -----------------------------===//
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 "clang/Driver/Option.h"
00011 
00012 #include "clang/Driver/Arg.h"
00013 #include "clang/Driver/ArgList.h"
00014 #include "llvm/Support/raw_ostream.h"
00015 #include "llvm/Support/ErrorHandling.h"
00016 #include <cassert>
00017 #include <algorithm>
00018 using namespace clang::driver;
00019 
00020 Option::Option(OptionClass _Kind, OptSpecifier _ID, const char *_Name,
00021                const OptionGroup *_Group, const Option *_Alias)
00022   : Kind(_Kind), ID(_ID.getID()), Name(_Name), Group(_Group), Alias(_Alias),
00023     Unsupported(false), LinkerInput(false), NoOptAsInput(false),
00024     DriverOption(false), NoArgumentUnused(false), NoForward(false) {
00025 
00026   // Multi-level aliases are not supported, and alias options cannot
00027   // have groups. This just simplifies option tracking, it is not an
00028   // inherent limitation.
00029   assert((!Alias || (!Alias->Alias && !Group)) &&
00030          "Multi-level aliases and aliases with groups are unsupported.");
00031 
00032   // Initialize rendering options based on the class.
00033   switch (Kind) {
00034   case GroupClass:
00035   case InputClass:
00036   case UnknownClass:
00037     RenderStyle = RenderValuesStyle;
00038     break;
00039 
00040   case JoinedClass:
00041   case JoinedAndSeparateClass:
00042     RenderStyle = RenderJoinedStyle;
00043     break;
00044 
00045   case CommaJoinedClass:
00046     RenderStyle = RenderCommaJoinedStyle;
00047     break;
00048 
00049   case FlagClass:
00050   case SeparateClass:
00051   case MultiArgClass:
00052   case JoinedOrSeparateClass:
00053     RenderStyle = RenderSeparateStyle;
00054     break;
00055   }
00056 }
00057 
00058 Option::~Option() {
00059 }
00060 
00061 void Option::dump() const {
00062   llvm::errs() << "<";
00063   switch (Kind) {
00064 #define P(N) case N: llvm::errs() << #N; break
00065     P(GroupClass);
00066     P(InputClass);
00067     P(UnknownClass);
00068     P(FlagClass);
00069     P(JoinedClass);
00070     P(SeparateClass);
00071     P(CommaJoinedClass);
00072     P(MultiArgClass);
00073     P(JoinedOrSeparateClass);
00074     P(JoinedAndSeparateClass);
00075 #undef P
00076   }
00077 
00078   llvm::errs() << " Name:\"" << Name << '"';
00079 
00080   if (Group) {
00081     llvm::errs() << " Group:";
00082     Group->dump();
00083   }
00084 
00085   if (Alias) {
00086     llvm::errs() << " Alias:";
00087     Alias->dump();
00088   }
00089 
00090   if (const MultiArgOption *MOA = dyn_cast<MultiArgOption>(this))
00091     llvm::errs() << " NumArgs:" << MOA->getNumArgs();
00092 
00093   llvm::errs() << ">\n";
00094 }
00095 
00096 bool Option::matches(OptSpecifier Opt) const {
00097   // Aliases are never considered in matching, look through them.
00098   if (Alias)
00099     return Alias->matches(Opt);
00100 
00101   // Check exact match.
00102   if (ID == Opt)
00103     return true;
00104 
00105   if (Group)
00106     return Group->matches(Opt);
00107   return false;
00108 }
00109 
00110 OptionGroup::OptionGroup(OptSpecifier ID, const char *Name,
00111                          const OptionGroup *Group)
00112   : Option(Option::GroupClass, ID, Name, Group, 0) {
00113 }
00114 
00115 Arg *OptionGroup::accept(const ArgList &Args, unsigned &Index) const {
00116   llvm_unreachable("accept() should never be called on an OptionGroup");
00117 }
00118 
00119 InputOption::InputOption(OptSpecifier ID)
00120   : Option(Option::InputClass, ID, "<input>", 0, 0) {
00121 }
00122 
00123 Arg *InputOption::accept(const ArgList &Args, unsigned &Index) const {
00124   llvm_unreachable("accept() should never be called on an InputOption");
00125 }
00126 
00127 UnknownOption::UnknownOption(OptSpecifier ID)
00128   : Option(Option::UnknownClass, ID, "<unknown>", 0, 0) {
00129 }
00130 
00131 Arg *UnknownOption::accept(const ArgList &Args, unsigned &Index) const {
00132   llvm_unreachable("accept() should never be called on an UnknownOption");
00133 }
00134 
00135 FlagOption::FlagOption(OptSpecifier ID, const char *Name,
00136                        const OptionGroup *Group, const Option *Alias)
00137   : Option(Option::FlagClass, ID, Name, Group, Alias) {
00138 }
00139 
00140 Arg *FlagOption::accept(const ArgList &Args, unsigned &Index) const {
00141   // Matches iff this is an exact match.
00142   // FIXME: Avoid strlen.
00143   if (getName().size() != strlen(Args.getArgString(Index)))
00144     return 0;
00145 
00146   return new Arg(getUnaliasedOption(), Index++);
00147 }
00148 
00149 JoinedOption::JoinedOption(OptSpecifier ID, const char *Name,
00150                            const OptionGroup *Group, const Option *Alias)
00151   : Option(Option::JoinedClass, ID, Name, Group, Alias) {
00152 }
00153 
00154 Arg *JoinedOption::accept(const ArgList &Args, unsigned &Index) const {
00155   // Always matches.
00156   const char *Value = Args.getArgString(Index) + getName().size();
00157   return new Arg(getUnaliasedOption(), Index++, Value);
00158 }
00159 
00160 CommaJoinedOption::CommaJoinedOption(OptSpecifier ID, const char *Name,
00161                                      const OptionGroup *Group,
00162                                      const Option *Alias)
00163   : Option(Option::CommaJoinedClass, ID, Name, Group, Alias) {
00164 }
00165 
00166 Arg *CommaJoinedOption::accept(const ArgList &Args,
00167                                unsigned &Index) const {
00168   // Always matches.
00169   const char *Str = Args.getArgString(Index) + getName().size();
00170   Arg *A = new Arg(getUnaliasedOption(), Index++);
00171 
00172   // Parse out the comma separated values.
00173   const char *Prev = Str;
00174   for (;; ++Str) {
00175     char c = *Str;
00176 
00177     if (!c || c == ',') {
00178       if (Prev != Str) {
00179         char *Value = new char[Str - Prev + 1];
00180         memcpy(Value, Prev, Str - Prev);
00181         Value[Str - Prev] = '\0';
00182         A->getValues().push_back(Value);
00183       }
00184 
00185       if (!c)
00186         break;
00187 
00188       Prev = Str + 1;
00189     }
00190   }
00191   A->setOwnsValues(true);
00192 
00193   return A;
00194 }
00195 
00196 SeparateOption::SeparateOption(OptSpecifier ID, const char *Name,
00197                                const OptionGroup *Group, const Option *Alias)
00198   : Option(Option::SeparateClass, ID, Name, Group, Alias) {
00199 }
00200 
00201 Arg *SeparateOption::accept(const ArgList &Args, unsigned &Index) const {
00202   // Matches iff this is an exact match.
00203   // FIXME: Avoid strlen.
00204   if (getName().size() != strlen(Args.getArgString(Index)))
00205     return 0;
00206 
00207   Index += 2;
00208   if (Index > Args.getNumInputArgStrings())
00209     return 0;
00210 
00211   return new Arg(getUnaliasedOption(), Index - 2, Args.getArgString(Index - 1));
00212 }
00213 
00214 MultiArgOption::MultiArgOption(OptSpecifier ID, const char *Name,
00215                                const OptionGroup *Group, const Option *Alias,
00216                                unsigned _NumArgs)
00217   : Option(Option::MultiArgClass, ID, Name, Group, Alias), NumArgs(_NumArgs) {
00218   assert(NumArgs > 1  && "Invalid MultiArgOption!");
00219 }
00220 
00221 Arg *MultiArgOption::accept(const ArgList &Args, unsigned &Index) const {
00222   // Matches iff this is an exact match.
00223   // FIXME: Avoid strlen.
00224   if (getName().size() != strlen(Args.getArgString(Index)))
00225     return 0;
00226 
00227   Index += 1 + NumArgs;
00228   if (Index > Args.getNumInputArgStrings())
00229     return 0;
00230 
00231   Arg *A = new Arg(getUnaliasedOption(), Index - 1 - NumArgs,
00232                    Args.getArgString(Index - NumArgs));
00233   for (unsigned i = 1; i != NumArgs; ++i)
00234     A->getValues().push_back(Args.getArgString(Index - NumArgs + i));
00235   return A;
00236 }
00237 
00238 JoinedOrSeparateOption::JoinedOrSeparateOption(OptSpecifier ID,
00239                                                const char *Name,
00240                                                const OptionGroup *Group,
00241                                                const Option *Alias)
00242   : Option(Option::JoinedOrSeparateClass, ID, Name, Group, Alias) {
00243 }
00244 
00245 Arg *JoinedOrSeparateOption::accept(const ArgList &Args,
00246                                     unsigned &Index) const {
00247   // If this is not an exact match, it is a joined arg.
00248   // FIXME: Avoid strlen.
00249   if (getName().size() != strlen(Args.getArgString(Index))) {
00250     const char *Value = Args.getArgString(Index) + getName().size();
00251     return new Arg(this, Index++, Value);
00252   }
00253 
00254   // Otherwise it must be separate.
00255   Index += 2;
00256   if (Index > Args.getNumInputArgStrings())
00257     return 0;
00258 
00259   return new Arg(getUnaliasedOption(), Index - 2, Args.getArgString(Index - 1));
00260 }
00261 
00262 JoinedAndSeparateOption::JoinedAndSeparateOption(OptSpecifier ID,
00263                                                  const char *Name,
00264                                                  const OptionGroup *Group,
00265                                                  const Option *Alias)
00266   : Option(Option::JoinedAndSeparateClass, ID, Name, Group, Alias) {
00267 }
00268 
00269 Arg *JoinedAndSeparateOption::accept(const ArgList &Args,
00270                                      unsigned &Index) const {
00271   // Always matches.
00272 
00273   Index += 2;
00274   if (Index > Args.getNumInputArgStrings())
00275     return 0;
00276 
00277   return new Arg(getUnaliasedOption(), Index - 2,
00278                  Args.getArgString(Index-2)+getName().size(),
00279                  Args.getArgString(Index-1));
00280 }