ArgList.cpp revision 4465a776a56de81211ae4672e5782c6bef075135
1//===--- ArgList.cpp - Argument List Management -------------------------*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include "clang/Driver/ArgList.h" 11#include "clang/Driver/Arg.h" 12#include "clang/Driver/DriverDiagnostic.h" 13#include "clang/Driver/Option.h" 14 15#include "llvm/ADT/SmallString.h" 16#include "llvm/ADT/Twine.h" 17#include "llvm/Support/raw_ostream.h" 18 19using namespace clang; 20using namespace clang::driver; 21 22void arg_iterator::SkipToNextArg() { 23 for (; Current != Args.end(); ++Current) { 24 // Done if there are no filters. 25 if (!Id0.isValid()) 26 break; 27 28 // Otherwise require a match. 29 const Option &O = (*Current)->getOption(); 30 if (O.matches(Id0) || 31 (Id1.isValid() && O.matches(Id1)) || 32 (Id2.isValid() && O.matches(Id2))) 33 break; 34 } 35} 36 37// 38 39ArgList::ArgList(arglist_type &_Args) : Args(_Args) { 40} 41 42ArgList::~ArgList() { 43} 44 45void ArgList::append(Arg *A) { 46 Args.push_back(A); 47} 48 49Arg *ArgList::getLastArgNoClaim(OptSpecifier Id) const { 50 // FIXME: Make search efficient? 51 for (const_reverse_iterator it = rbegin(), ie = rend(); it != ie; ++it) 52 if ((*it)->getOption().matches(Id)) 53 return *it; 54 return 0; 55} 56 57Arg *ArgList::getLastArg(OptSpecifier Id) const { 58 Arg *A = getLastArgNoClaim(Id); 59 if (A) 60 A->claim(); 61 return A; 62} 63 64Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1) const { 65 Arg *Res, *A0 = getLastArgNoClaim(Id0), *A1 = getLastArgNoClaim(Id1); 66 67 if (A0 && A1) 68 Res = A0->getIndex() > A1->getIndex() ? A0 : A1; 69 else 70 Res = A0 ? A0 : A1; 71 72 if (Res) 73 Res->claim(); 74 75 return Res; 76} 77 78Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1, 79 OptSpecifier Id2) const { 80 Arg *Res = 0; 81 Arg *A0 = getLastArgNoClaim(Id0); 82 Arg *A1 = getLastArgNoClaim(Id1); 83 Arg *A2 = getLastArgNoClaim(Id2); 84 85 int A0Idx = A0 ? (int) A0->getIndex() : -1; 86 int A1Idx = A1 ? (int) A1->getIndex() : -1; 87 int A2Idx = A2 ? (int) A2->getIndex() : -1; 88 89 if (A0Idx > A1Idx) { 90 if (A0Idx > A2Idx) 91 Res = A0; 92 else if (A2Idx != -1) 93 Res = A2; 94 } else { 95 if (A1Idx > A2Idx) 96 Res = A1; 97 else if (A2Idx != -1) 98 Res = A2; 99 } 100 101 if (Res) 102 Res->claim(); 103 104 return Res; 105} 106 107bool ArgList::hasFlag(OptSpecifier Pos, OptSpecifier Neg, bool Default) const { 108 if (Arg *A = getLastArg(Pos, Neg)) 109 return A->getOption().matches(Pos); 110 return Default; 111} 112 113llvm::StringRef ArgList::getLastArgValue(OptSpecifier Id, 114 llvm::StringRef Default) const { 115 if (Arg *A = getLastArg(Id)) 116 return A->getValue(*this); 117 return Default; 118} 119 120int ArgList::getLastArgIntValue(OptSpecifier Id, int Default, 121 clang::Diagnostic &Diags) const { 122 int Res = Default; 123 124 if (Arg *A = getLastArg(Id)) { 125 if (llvm::StringRef(A->getValue(*this)).getAsInteger(10, Res)) 126 Diags.Report(diag::err_drv_invalid_int_value) 127 << A->getAsString(*this) << A->getValue(*this); 128 } 129 130 return Res; 131} 132 133std::vector<std::string> ArgList::getAllArgValues(OptSpecifier Id) const { 134 llvm::SmallVector<const char *, 16> Values; 135 AddAllArgValues(Values, Id); 136 return std::vector<std::string>(Values.begin(), Values.end()); 137} 138 139void ArgList::AddLastArg(ArgStringList &Output, OptSpecifier Id) const { 140 if (Arg *A = getLastArg(Id)) { 141 A->claim(); 142 A->render(*this, Output); 143 } 144} 145 146void ArgList::AddAllArgs(ArgStringList &Output, OptSpecifier Id0, 147 OptSpecifier Id1, OptSpecifier Id2) const { 148 for (arg_iterator it = filtered_begin(Id0, Id1, Id2), 149 ie = filtered_end(); it != ie; ++it) { 150 it->claim(); 151 it->render(*this, Output); 152 } 153} 154 155void ArgList::AddAllArgValues(ArgStringList &Output, OptSpecifier Id0, 156 OptSpecifier Id1, OptSpecifier Id2) const { 157 for (arg_iterator it = filtered_begin(Id0, Id1, Id2), 158 ie = filtered_end(); it != ie; ++it) { 159 it->claim(); 160 for (unsigned i = 0, e = it->getNumValues(); i != e; ++i) 161 Output.push_back(it->getValue(*this, i)); 162 } 163} 164 165void ArgList::AddAllArgsTranslated(ArgStringList &Output, OptSpecifier Id0, 166 const char *Translation, 167 bool Joined) const { 168 for (arg_iterator it = filtered_begin(Id0), 169 ie = filtered_end(); it != ie; ++it) { 170 it->claim(); 171 172 if (Joined) { 173 Output.push_back(MakeArgString(llvm::StringRef(Translation) + 174 it->getValue(*this, 0))); 175 } else { 176 Output.push_back(Translation); 177 Output.push_back(it->getValue(*this, 0)); 178 } 179 } 180} 181 182void ArgList::ClaimAllArgs(OptSpecifier Id0) const { 183 for (arg_iterator it = filtered_begin(Id0), 184 ie = filtered_end(); it != ie; ++it) 185 it->claim(); 186} 187 188const char *ArgList::MakeArgString(const llvm::Twine &T) const { 189 llvm::SmallString<256> Str; 190 T.toVector(Str); 191 return MakeArgString(Str.str()); 192} 193 194const char *ArgList::GetOrMakeJoinedArgString(unsigned Index, 195 llvm::StringRef LHS, 196 llvm::StringRef RHS) const { 197 llvm::StringRef Cur = getArgString(Index); 198 if (Cur.size() == LHS.size() + RHS.size() && 199 Cur.startswith(LHS) && Cur.endswith(RHS)) 200 return Cur.data(); 201 202 return MakeArgString(LHS + RHS); 203} 204 205// 206 207InputArgList::InputArgList(const char **ArgBegin, const char **ArgEnd) 208 : ArgList(ActualArgs), NumInputArgStrings(ArgEnd - ArgBegin) { 209 ArgStrings.append(ArgBegin, ArgEnd); 210} 211 212InputArgList::~InputArgList() { 213 // An InputArgList always owns its arguments. 214 for (iterator it = begin(), ie = end(); it != ie; ++it) 215 delete *it; 216} 217 218unsigned InputArgList::MakeIndex(llvm::StringRef String0) const { 219 unsigned Index = ArgStrings.size(); 220 221 // Tuck away so we have a reliable const char *. 222 SynthesizedStrings.push_back(String0); 223 ArgStrings.push_back(SynthesizedStrings.back().c_str()); 224 225 return Index; 226} 227 228unsigned InputArgList::MakeIndex(llvm::StringRef String0, 229 llvm::StringRef String1) const { 230 unsigned Index0 = MakeIndex(String0); 231 unsigned Index1 = MakeIndex(String1); 232 assert(Index0 + 1 == Index1 && "Unexpected non-consecutive indices!"); 233 (void) Index1; 234 return Index0; 235} 236 237const char *InputArgList::MakeArgString(llvm::StringRef Str) const { 238 return getArgString(MakeIndex(Str)); 239} 240 241// 242 243DerivedArgList::DerivedArgList(InputArgList &_BaseArgs, bool _OnlyProxy) 244 : ArgList(_OnlyProxy ? _BaseArgs.getArgs() : ActualArgs), 245 BaseArgs(_BaseArgs), OnlyProxy(_OnlyProxy) { 246} 247 248DerivedArgList::~DerivedArgList() { 249 // We only own the arguments we explicitly synthesized. 250 for (iterator it = SynthesizedArgs.begin(), ie = SynthesizedArgs.end(); 251 it != ie; ++it) 252 delete *it; 253} 254 255const char *DerivedArgList::MakeArgString(llvm::StringRef Str) const { 256 return BaseArgs.MakeArgString(Str); 257} 258 259Arg *DerivedArgList::MakeFlagArg(const Arg *BaseArg, const Option *Opt) const { 260 Arg *A = new FlagArg(Opt, BaseArgs.MakeIndex(Opt->getName()), BaseArg); 261 SynthesizedArgs.push_back(A); 262 return A; 263} 264 265Arg *DerivedArgList::MakePositionalArg(const Arg *BaseArg, const Option *Opt, 266 llvm::StringRef Value) const { 267 unsigned Index = BaseArgs.MakeIndex(Value); 268 Arg *A = new PositionalArg(Opt, Index, BaseArgs.getArgString(Index), BaseArg); 269 SynthesizedArgs.push_back(A); 270 return A; 271} 272 273Arg *DerivedArgList::MakeSeparateArg(const Arg *BaseArg, const Option *Opt, 274 llvm::StringRef Value) const { 275 unsigned Index = BaseArgs.MakeIndex(Opt->getName(), Value); 276 Arg *A = new SeparateArg(Opt, Index, BaseArgs.getArgString(Index), BaseArg); 277 SynthesizedArgs.push_back(A); 278 return A; 279} 280 281Arg *DerivedArgList::MakeJoinedArg(const Arg *BaseArg, const Option *Opt, 282 llvm::StringRef Value) const { 283 unsigned Index = BaseArgs.MakeIndex(Opt->getName() + Value.str()); 284 Arg *A = new JoinedArg(Opt, Index, 285 BaseArgs.getArgString(Index) + strlen(Opt->getName()), 286 BaseArg); 287 SynthesizedArgs.push_back(A); 288 return A; 289} 290