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 "llvm/Option/ArgList.h" 11 #include "llvm/ADT/STLExtras.h" 12 #include "llvm/ADT/SmallString.h" 13 #include "llvm/ADT/Twine.h" 14 #include "llvm/Option/Arg.h" 15 #include "llvm/Option/Option.h" 16 #include "llvm/Support/raw_ostream.h" 17 18 using namespace llvm; 19 using namespace llvm::opt; 20 21 void arg_iterator::SkipToNextArg() { 22 for (; Current != Args.end(); ++Current) { 23 // Done if there are no filters. 24 if (!Id0.isValid()) 25 break; 26 27 // Otherwise require a match. 28 const Option &O = (*Current)->getOption(); 29 if (O.matches(Id0) || 30 (Id1.isValid() && O.matches(Id1)) || 31 (Id2.isValid() && O.matches(Id2))) 32 break; 33 } 34 } 35 36 void ArgList::append(Arg *A) { 37 Args.push_back(A); 38 } 39 40 void ArgList::eraseArg(OptSpecifier Id) { 41 Args.erase(std::remove_if(begin(), end(), 42 [=](Arg *A) { return A->getOption().matches(Id); }), 43 end()); 44 } 45 46 Arg *ArgList::getLastArgNoClaim(OptSpecifier Id) const { 47 // FIXME: Make search efficient? 48 for (const_reverse_iterator it = rbegin(), ie = rend(); it != ie; ++it) 49 if ((*it)->getOption().matches(Id)) 50 return *it; 51 return nullptr; 52 } 53 54 Arg *ArgList::getLastArgNoClaim(OptSpecifier Id0, OptSpecifier Id1) const { 55 // FIXME: Make search efficient? 56 for (const_reverse_iterator it = rbegin(), ie = rend(); it != ie; ++it) 57 if ((*it)->getOption().matches(Id0) || 58 (*it)->getOption().matches(Id1)) 59 return *it; 60 return nullptr; 61 } 62 63 Arg *ArgList::getLastArgNoClaim(OptSpecifier Id0, OptSpecifier Id1, 64 OptSpecifier Id2) const { 65 // FIXME: Make search efficient? 66 for (const_reverse_iterator it = rbegin(), ie = rend(); it != ie; ++it) 67 if ((*it)->getOption().matches(Id0) || (*it)->getOption().matches(Id1) || 68 (*it)->getOption().matches(Id2)) 69 return *it; 70 return nullptr; 71 } 72 73 Arg *ArgList::getLastArgNoClaim(OptSpecifier Id0, OptSpecifier Id1, 74 OptSpecifier Id2, OptSpecifier Id3) const { 75 // FIXME: Make search efficient? 76 for (const_reverse_iterator it = rbegin(), ie = rend(); it != ie; ++it) 77 if ((*it)->getOption().matches(Id0) || (*it)->getOption().matches(Id1) || 78 (*it)->getOption().matches(Id2) || (*it)->getOption().matches(Id3)) 79 return *it; 80 return nullptr; 81 } 82 83 Arg *ArgList::getLastArg(OptSpecifier Id) const { 84 Arg *Res = nullptr; 85 for (const_iterator it = begin(), ie = end(); it != ie; ++it) { 86 if ((*it)->getOption().matches(Id)) { 87 Res = *it; 88 Res->claim(); 89 } 90 } 91 92 return Res; 93 } 94 95 Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1) const { 96 Arg *Res = nullptr; 97 for (const_iterator it = begin(), ie = end(); it != ie; ++it) { 98 if ((*it)->getOption().matches(Id0) || 99 (*it)->getOption().matches(Id1)) { 100 Res = *it; 101 Res->claim(); 102 103 } 104 } 105 106 return Res; 107 } 108 109 Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1, 110 OptSpecifier Id2) const { 111 Arg *Res = nullptr; 112 for (const_iterator it = begin(), ie = end(); it != ie; ++it) { 113 if ((*it)->getOption().matches(Id0) || 114 (*it)->getOption().matches(Id1) || 115 (*it)->getOption().matches(Id2)) { 116 Res = *it; 117 Res->claim(); 118 } 119 } 120 121 return Res; 122 } 123 124 Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1, 125 OptSpecifier Id2, OptSpecifier Id3) const { 126 Arg *Res = nullptr; 127 for (const_iterator it = begin(), ie = end(); it != ie; ++it) { 128 if ((*it)->getOption().matches(Id0) || 129 (*it)->getOption().matches(Id1) || 130 (*it)->getOption().matches(Id2) || 131 (*it)->getOption().matches(Id3)) { 132 Res = *it; 133 Res->claim(); 134 } 135 } 136 137 return Res; 138 } 139 140 Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1, 141 OptSpecifier Id2, OptSpecifier Id3, 142 OptSpecifier Id4) const { 143 Arg *Res = nullptr; 144 for (const_iterator it = begin(), ie = end(); it != ie; ++it) { 145 if ((*it)->getOption().matches(Id0) || 146 (*it)->getOption().matches(Id1) || 147 (*it)->getOption().matches(Id2) || 148 (*it)->getOption().matches(Id3) || 149 (*it)->getOption().matches(Id4)) { 150 Res = *it; 151 Res->claim(); 152 } 153 } 154 155 return Res; 156 } 157 158 Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1, 159 OptSpecifier Id2, OptSpecifier Id3, 160 OptSpecifier Id4, OptSpecifier Id5) const { 161 Arg *Res = nullptr; 162 for (const_iterator it = begin(), ie = end(); it != ie; ++it) { 163 if ((*it)->getOption().matches(Id0) || 164 (*it)->getOption().matches(Id1) || 165 (*it)->getOption().matches(Id2) || 166 (*it)->getOption().matches(Id3) || 167 (*it)->getOption().matches(Id4) || 168 (*it)->getOption().matches(Id5)) { 169 Res = *it; 170 Res->claim(); 171 } 172 } 173 174 return Res; 175 } 176 177 Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1, 178 OptSpecifier Id2, OptSpecifier Id3, 179 OptSpecifier Id4, OptSpecifier Id5, 180 OptSpecifier Id6) const { 181 Arg *Res = nullptr; 182 for (const_iterator it = begin(), ie = end(); it != ie; ++it) { 183 if ((*it)->getOption().matches(Id0) || 184 (*it)->getOption().matches(Id1) || 185 (*it)->getOption().matches(Id2) || 186 (*it)->getOption().matches(Id3) || 187 (*it)->getOption().matches(Id4) || 188 (*it)->getOption().matches(Id5) || 189 (*it)->getOption().matches(Id6)) { 190 Res = *it; 191 Res->claim(); 192 } 193 } 194 195 return Res; 196 } 197 198 Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1, 199 OptSpecifier Id2, OptSpecifier Id3, 200 OptSpecifier Id4, OptSpecifier Id5, 201 OptSpecifier Id6, OptSpecifier Id7) const { 202 Arg *Res = nullptr; 203 for (const_iterator it = begin(), ie = end(); it != ie; ++it) { 204 if ((*it)->getOption().matches(Id0) || 205 (*it)->getOption().matches(Id1) || 206 (*it)->getOption().matches(Id2) || 207 (*it)->getOption().matches(Id3) || 208 (*it)->getOption().matches(Id4) || 209 (*it)->getOption().matches(Id5) || 210 (*it)->getOption().matches(Id6) || 211 (*it)->getOption().matches(Id7)) { 212 Res = *it; 213 Res->claim(); 214 } 215 } 216 217 return Res; 218 } 219 220 bool ArgList::hasFlag(OptSpecifier Pos, OptSpecifier Neg, bool Default) const { 221 if (Arg *A = getLastArg(Pos, Neg)) 222 return A->getOption().matches(Pos); 223 return Default; 224 } 225 226 bool ArgList::hasFlag(OptSpecifier Pos, OptSpecifier PosAlias, OptSpecifier Neg, 227 bool Default) const { 228 if (Arg *A = getLastArg(Pos, PosAlias, Neg)) 229 return A->getOption().matches(Pos) || A->getOption().matches(PosAlias); 230 return Default; 231 } 232 233 StringRef ArgList::getLastArgValue(OptSpecifier Id, 234 StringRef Default) const { 235 if (Arg *A = getLastArg(Id)) 236 return A->getValue(); 237 return Default; 238 } 239 240 std::vector<std::string> ArgList::getAllArgValues(OptSpecifier Id) const { 241 SmallVector<const char *, 16> Values; 242 AddAllArgValues(Values, Id); 243 return std::vector<std::string>(Values.begin(), Values.end()); 244 } 245 246 void ArgList::AddLastArg(ArgStringList &Output, OptSpecifier Id) const { 247 if (Arg *A = getLastArg(Id)) { 248 A->claim(); 249 A->render(*this, Output); 250 } 251 } 252 253 void ArgList::AddLastArg(ArgStringList &Output, OptSpecifier Id0, 254 OptSpecifier Id1) const { 255 if (Arg *A = getLastArg(Id0, Id1)) { 256 A->claim(); 257 A->render(*this, Output); 258 } 259 } 260 261 void ArgList::AddAllArgs(ArgStringList &Output, 262 ArrayRef<OptSpecifier> Ids) const { 263 for (const Arg *Arg : Args) { 264 for (OptSpecifier Id : Ids) { 265 if (Arg->getOption().matches(Id)) { 266 Arg->claim(); 267 Arg->render(*this, Output); 268 break; 269 } 270 } 271 } 272 } 273 274 /// This 3-opt variant of AddAllArgs could be eliminated in favor of one 275 /// that accepts a single specifier, given the above which accepts any number. 276 void ArgList::AddAllArgs(ArgStringList &Output, OptSpecifier Id0, 277 OptSpecifier Id1, OptSpecifier Id2) const { 278 for (auto Arg: filtered(Id0, Id1, Id2)) { 279 Arg->claim(); 280 Arg->render(*this, Output); 281 } 282 } 283 284 void ArgList::AddAllArgValues(ArgStringList &Output, OptSpecifier Id0, 285 OptSpecifier Id1, OptSpecifier Id2) const { 286 for (auto Arg : filtered(Id0, Id1, Id2)) { 287 Arg->claim(); 288 const auto &Values = Arg->getValues(); 289 Output.append(Values.begin(), Values.end()); 290 } 291 } 292 293 void ArgList::AddAllArgsTranslated(ArgStringList &Output, OptSpecifier Id0, 294 const char *Translation, 295 bool Joined) const { 296 for (auto Arg: filtered(Id0)) { 297 Arg->claim(); 298 299 if (Joined) { 300 Output.push_back(MakeArgString(StringRef(Translation) + 301 Arg->getValue(0))); 302 } else { 303 Output.push_back(Translation); 304 Output.push_back(Arg->getValue(0)); 305 } 306 } 307 } 308 309 void ArgList::ClaimAllArgs(OptSpecifier Id0) const { 310 for (auto Arg : filtered(Id0)) 311 Arg->claim(); 312 } 313 314 void ArgList::ClaimAllArgs() const { 315 for (const_iterator it = begin(), ie = end(); it != ie; ++it) 316 if (!(*it)->isClaimed()) 317 (*it)->claim(); 318 } 319 320 const char *ArgList::GetOrMakeJoinedArgString(unsigned Index, 321 StringRef LHS, 322 StringRef RHS) const { 323 StringRef Cur = getArgString(Index); 324 if (Cur.size() == LHS.size() + RHS.size() && 325 Cur.startswith(LHS) && Cur.endswith(RHS)) 326 return Cur.data(); 327 328 return MakeArgString(LHS + RHS); 329 } 330 331 // 332 333 void InputArgList::releaseMemory() { 334 // An InputArgList always owns its arguments. 335 for (Arg *A : *this) 336 delete A; 337 } 338 339 InputArgList::InputArgList(const char* const *ArgBegin, 340 const char* const *ArgEnd) 341 : NumInputArgStrings(ArgEnd - ArgBegin) { 342 ArgStrings.append(ArgBegin, ArgEnd); 343 } 344 345 unsigned InputArgList::MakeIndex(StringRef String0) const { 346 unsigned Index = ArgStrings.size(); 347 348 // Tuck away so we have a reliable const char *. 349 SynthesizedStrings.push_back(String0); 350 ArgStrings.push_back(SynthesizedStrings.back().c_str()); 351 352 return Index; 353 } 354 355 unsigned InputArgList::MakeIndex(StringRef String0, 356 StringRef String1) const { 357 unsigned Index0 = MakeIndex(String0); 358 unsigned Index1 = MakeIndex(String1); 359 assert(Index0 + 1 == Index1 && "Unexpected non-consecutive indices!"); 360 (void) Index1; 361 return Index0; 362 } 363 364 const char *InputArgList::MakeArgStringRef(StringRef Str) const { 365 return getArgString(MakeIndex(Str)); 366 } 367 368 // 369 370 DerivedArgList::DerivedArgList(const InputArgList &BaseArgs) 371 : BaseArgs(BaseArgs) {} 372 373 const char *DerivedArgList::MakeArgStringRef(StringRef Str) const { 374 return BaseArgs.MakeArgString(Str); 375 } 376 377 void DerivedArgList::AddSynthesizedArg(Arg *A) { 378 SynthesizedArgs.push_back(std::unique_ptr<Arg>(A)); 379 } 380 381 Arg *DerivedArgList::MakeFlagArg(const Arg *BaseArg, const Option Opt) const { 382 SynthesizedArgs.push_back( 383 make_unique<Arg>(Opt, MakeArgString(Opt.getPrefix() + Opt.getName()), 384 BaseArgs.MakeIndex(Opt.getName()), BaseArg)); 385 return SynthesizedArgs.back().get(); 386 } 387 388 Arg *DerivedArgList::MakePositionalArg(const Arg *BaseArg, const Option Opt, 389 StringRef Value) const { 390 unsigned Index = BaseArgs.MakeIndex(Value); 391 SynthesizedArgs.push_back( 392 make_unique<Arg>(Opt, MakeArgString(Opt.getPrefix() + Opt.getName()), 393 Index, BaseArgs.getArgString(Index), BaseArg)); 394 return SynthesizedArgs.back().get(); 395 } 396 397 Arg *DerivedArgList::MakeSeparateArg(const Arg *BaseArg, const Option Opt, 398 StringRef Value) const { 399 unsigned Index = BaseArgs.MakeIndex(Opt.getName(), Value); 400 SynthesizedArgs.push_back( 401 make_unique<Arg>(Opt, MakeArgString(Opt.getPrefix() + Opt.getName()), 402 Index, BaseArgs.getArgString(Index + 1), BaseArg)); 403 return SynthesizedArgs.back().get(); 404 } 405 406 Arg *DerivedArgList::MakeJoinedArg(const Arg *BaseArg, const Option Opt, 407 StringRef Value) const { 408 unsigned Index = BaseArgs.MakeIndex((Opt.getName() + Value).str()); 409 SynthesizedArgs.push_back(make_unique<Arg>( 410 Opt, MakeArgString(Opt.getPrefix() + Opt.getName()), Index, 411 BaseArgs.getArgString(Index) + Opt.getName().size(), BaseArg)); 412 return SynthesizedArgs.back().get(); 413 } 414