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