LLVM 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 "llvm/Option/Option.h" 00011 #include "llvm/ADT/Twine.h" 00012 #include "llvm/Option/Arg.h" 00013 #include "llvm/Option/ArgList.h" 00014 #include "llvm/Support/ErrorHandling.h" 00015 #include "llvm/Support/raw_ostream.h" 00016 #include <algorithm> 00017 #include <cassert> 00018 00019 using namespace llvm; 00020 using namespace llvm::opt; 00021 00022 Option::Option(const OptTable::Info *info, const OptTable *owner) 00023 : Info(info), Owner(owner) { 00024 00025 // Multi-level aliases are not supported. This just simplifies option 00026 // tracking, it is not an inherent limitation. 00027 assert((!Info || !getAlias().isValid() || !getAlias().getAlias().isValid()) && 00028 "Multi-level aliases are not supported."); 00029 00030 if (Info && getAliasArgs()) { 00031 assert(getAlias().isValid() && "Only alias options can have alias args."); 00032 assert(getKind() == FlagClass && "Only Flag aliases can have alias args."); 00033 assert(getAlias().getKind() != FlagClass && 00034 "Cannot provide alias args to a flag option."); 00035 } 00036 } 00037 00038 Option::~Option() { 00039 } 00040 00041 void Option::dump() const { 00042 llvm::errs() << "<"; 00043 switch (getKind()) { 00044 #define P(N) case N: llvm::errs() << #N; break 00045 P(GroupClass); 00046 P(InputClass); 00047 P(UnknownClass); 00048 P(FlagClass); 00049 P(JoinedClass); 00050 P(SeparateClass); 00051 P(CommaJoinedClass); 00052 P(MultiArgClass); 00053 P(JoinedOrSeparateClass); 00054 P(JoinedAndSeparateClass); 00055 P(RemainingArgsClass); 00056 #undef P 00057 } 00058 00059 if (Info->Prefixes) { 00060 llvm::errs() << " Prefixes:["; 00061 for (const char * const *Pre = Info->Prefixes; *Pre != nullptr; ++Pre) { 00062 llvm::errs() << '"' << *Pre << (*(Pre + 1) == nullptr ? "\"" : "\", "); 00063 } 00064 llvm::errs() << ']'; 00065 } 00066 00067 llvm::errs() << " Name:\"" << getName() << '"'; 00068 00069 const Option Group = getGroup(); 00070 if (Group.isValid()) { 00071 llvm::errs() << " Group:"; 00072 Group.dump(); 00073 } 00074 00075 const Option Alias = getAlias(); 00076 if (Alias.isValid()) { 00077 llvm::errs() << " Alias:"; 00078 Alias.dump(); 00079 } 00080 00081 if (getKind() == MultiArgClass) 00082 llvm::errs() << " NumArgs:" << getNumArgs(); 00083 00084 llvm::errs() << ">\n"; 00085 } 00086 00087 bool Option::matches(OptSpecifier Opt) const { 00088 // Aliases are never considered in matching, look through them. 00089 const Option Alias = getAlias(); 00090 if (Alias.isValid()) 00091 return Alias.matches(Opt); 00092 00093 // Check exact match. 00094 if (getID() == Opt.getID()) 00095 return true; 00096 00097 const Option Group = getGroup(); 00098 if (Group.isValid()) 00099 return Group.matches(Opt); 00100 return false; 00101 } 00102 00103 Arg *Option::accept(const ArgList &Args, 00104 unsigned &Index, 00105 unsigned ArgSize) const { 00106 const Option &UnaliasedOption = getUnaliasedOption(); 00107 StringRef Spelling; 00108 // If the option was an alias, get the spelling from the unaliased one. 00109 if (getID() == UnaliasedOption.getID()) { 00110 Spelling = StringRef(Args.getArgString(Index), ArgSize); 00111 } else { 00112 Spelling = Args.MakeArgString(Twine(UnaliasedOption.getPrefix()) + 00113 Twine(UnaliasedOption.getName())); 00114 } 00115 00116 switch (getKind()) { 00117 case FlagClass: { 00118 if (ArgSize != strlen(Args.getArgString(Index))) 00119 return nullptr; 00120 00121 Arg *A = new Arg(UnaliasedOption, Spelling, Index++); 00122 if (getAliasArgs()) { 00123 const char *Val = getAliasArgs(); 00124 while (*Val != '\0') { 00125 A->getValues().push_back(Val); 00126 00127 // Move past the '\0' to the next argument. 00128 Val += strlen(Val) + 1; 00129 } 00130 } 00131 return A; 00132 } 00133 case JoinedClass: { 00134 const char *Value = Args.getArgString(Index) + ArgSize; 00135 return new Arg(UnaliasedOption, Spelling, Index++, Value); 00136 } 00137 case CommaJoinedClass: { 00138 // Always matches. 00139 const char *Str = Args.getArgString(Index) + ArgSize; 00140 Arg *A = new Arg(UnaliasedOption, Spelling, Index++); 00141 00142 // Parse out the comma separated values. 00143 const char *Prev = Str; 00144 for (;; ++Str) { 00145 char c = *Str; 00146 00147 if (!c || c == ',') { 00148 if (Prev != Str) { 00149 char *Value = new char[Str - Prev + 1]; 00150 memcpy(Value, Prev, Str - Prev); 00151 Value[Str - Prev] = '\0'; 00152 A->getValues().push_back(Value); 00153 } 00154 00155 if (!c) 00156 break; 00157 00158 Prev = Str + 1; 00159 } 00160 } 00161 A->setOwnsValues(true); 00162 00163 return A; 00164 } 00165 case SeparateClass: 00166 // Matches iff this is an exact match. 00167 // FIXME: Avoid strlen. 00168 if (ArgSize != strlen(Args.getArgString(Index))) 00169 return nullptr; 00170 00171 Index += 2; 00172 if (Index > Args.getNumInputArgStrings() || 00173 Args.getArgString(Index - 1) == nullptr) 00174 return nullptr; 00175 00176 return new Arg(UnaliasedOption, Spelling, 00177 Index - 2, Args.getArgString(Index - 1)); 00178 case MultiArgClass: { 00179 // Matches iff this is an exact match. 00180 // FIXME: Avoid strlen. 00181 if (ArgSize != strlen(Args.getArgString(Index))) 00182 return nullptr; 00183 00184 Index += 1 + getNumArgs(); 00185 if (Index > Args.getNumInputArgStrings()) 00186 return nullptr; 00187 00188 Arg *A = new Arg(UnaliasedOption, Spelling, Index - 1 - getNumArgs(), 00189 Args.getArgString(Index - getNumArgs())); 00190 for (unsigned i = 1; i != getNumArgs(); ++i) 00191 A->getValues().push_back(Args.getArgString(Index - getNumArgs() + i)); 00192 return A; 00193 } 00194 case JoinedOrSeparateClass: { 00195 // If this is not an exact match, it is a joined arg. 00196 // FIXME: Avoid strlen. 00197 if (ArgSize != strlen(Args.getArgString(Index))) { 00198 const char *Value = Args.getArgString(Index) + ArgSize; 00199 return new Arg(*this, Spelling, Index++, Value); 00200 } 00201 00202 // Otherwise it must be separate. 00203 Index += 2; 00204 if (Index > Args.getNumInputArgStrings() || 00205 Args.getArgString(Index - 1) == nullptr) 00206 return nullptr; 00207 00208 return new Arg(UnaliasedOption, Spelling, 00209 Index - 2, Args.getArgString(Index - 1)); 00210 } 00211 case JoinedAndSeparateClass: 00212 // Always matches. 00213 Index += 2; 00214 if (Index > Args.getNumInputArgStrings() || 00215 Args.getArgString(Index - 1) == nullptr) 00216 return nullptr; 00217 00218 return new Arg(UnaliasedOption, Spelling, Index - 2, 00219 Args.getArgString(Index - 2) + ArgSize, 00220 Args.getArgString(Index - 1)); 00221 case RemainingArgsClass: { 00222 // Matches iff this is an exact match. 00223 // FIXME: Avoid strlen. 00224 if (ArgSize != strlen(Args.getArgString(Index))) 00225 return nullptr; 00226 Arg *A = new Arg(UnaliasedOption, Spelling, Index++); 00227 while (Index < Args.getNumInputArgStrings() && 00228 Args.getArgString(Index) != nullptr) 00229 A->getValues().push_back(Args.getArgString(Index++)); 00230 return A; 00231 } 00232 default: 00233 llvm_unreachable("Invalid option kind!"); 00234 } 00235 }