clang API Documentation
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 }