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, OptSpecifier Id0, 262 OptSpecifier Id1, OptSpecifier Id2) const { 263 for (auto Arg: filtered(Id0, Id1, Id2)) { 264 Arg->claim(); 265 Arg->render(*this, Output); 266 } 267 } 268 269 void ArgList::AddAllArgValues(ArgStringList &Output, OptSpecifier Id0, 270 OptSpecifier Id1, OptSpecifier Id2) const { 271 for (auto Arg : filtered(Id0, Id1, Id2)) { 272 Arg->claim(); 273 const auto &Values = Arg->getValues(); 274 Output.append(Values.begin(), Values.end()); 275 } 276 } 277 278 void ArgList::AddAllArgsTranslated(ArgStringList &Output, OptSpecifier Id0, 279 const char *Translation, 280 bool Joined) const { 281 for (auto Arg: filtered(Id0)) { 282 Arg->claim(); 283 284 if (Joined) { 285 Output.push_back(MakeArgString(StringRef(Translation) + 286 Arg->getValue(0))); 287 } else { 288 Output.push_back(Translation); 289 Output.push_back(Arg->getValue(0)); 290 } 291 } 292 } 293 294 void ArgList::ClaimAllArgs(OptSpecifier Id0) const { 295 for (auto Arg : filtered(Id0)) 296 Arg->claim(); 297 } 298 299 void ArgList::ClaimAllArgs() const { 300 for (const_iterator it = begin(), ie = end(); it != ie; ++it) 301 if (!(*it)->isClaimed()) 302 (*it)->claim(); 303 } 304 305 const char *ArgList::GetOrMakeJoinedArgString(unsigned Index, 306 StringRef LHS, 307 StringRef RHS) const { 308 StringRef Cur = getArgString(Index); 309 if (Cur.size() == LHS.size() + RHS.size() && 310 Cur.startswith(LHS) && Cur.endswith(RHS)) 311 return Cur.data(); 312 313 return MakeArgString(LHS + RHS); 314 } 315 316 // 317 318 void InputArgList::releaseMemory() { 319 // An InputArgList always owns its arguments. 320 for (Arg *A : *this) 321 delete A; 322 } 323 324 InputArgList::InputArgList(const char* const *ArgBegin, 325 const char* const *ArgEnd) 326 : NumInputArgStrings(ArgEnd - ArgBegin) { 327 ArgStrings.append(ArgBegin, ArgEnd); 328 } 329 330 unsigned InputArgList::MakeIndex(StringRef String0) const { 331 unsigned Index = ArgStrings.size(); 332 333 // Tuck away so we have a reliable const char *. 334 SynthesizedStrings.push_back(String0); 335 ArgStrings.push_back(SynthesizedStrings.back().c_str()); 336 337 return Index; 338 } 339 340 unsigned InputArgList::MakeIndex(StringRef String0, 341 StringRef String1) const { 342 unsigned Index0 = MakeIndex(String0); 343 unsigned Index1 = MakeIndex(String1); 344 assert(Index0 + 1 == Index1 && "Unexpected non-consecutive indices!"); 345 (void) Index1; 346 return Index0; 347 } 348 349 const char *InputArgList::MakeArgStringRef(StringRef Str) const { 350 return getArgString(MakeIndex(Str)); 351 } 352 353 // 354 355 DerivedArgList::DerivedArgList(const InputArgList &BaseArgs) 356 : BaseArgs(BaseArgs) {} 357 358 const char *DerivedArgList::MakeArgStringRef(StringRef Str) const { 359 return BaseArgs.MakeArgString(Str); 360 } 361 362 void DerivedArgList::AddSynthesizedArg(Arg *A) { 363 SynthesizedArgs.push_back(std::unique_ptr<Arg>(A)); 364 } 365 366 Arg *DerivedArgList::MakeFlagArg(const Arg *BaseArg, const Option Opt) const { 367 SynthesizedArgs.push_back( 368 make_unique<Arg>(Opt, MakeArgString(Opt.getPrefix() + Opt.getName()), 369 BaseArgs.MakeIndex(Opt.getName()), BaseArg)); 370 return SynthesizedArgs.back().get(); 371 } 372 373 Arg *DerivedArgList::MakePositionalArg(const Arg *BaseArg, const Option Opt, 374 StringRef Value) const { 375 unsigned Index = BaseArgs.MakeIndex(Value); 376 SynthesizedArgs.push_back( 377 make_unique<Arg>(Opt, MakeArgString(Opt.getPrefix() + Opt.getName()), 378 Index, BaseArgs.getArgString(Index), BaseArg)); 379 return SynthesizedArgs.back().get(); 380 } 381 382 Arg *DerivedArgList::MakeSeparateArg(const Arg *BaseArg, const Option Opt, 383 StringRef Value) const { 384 unsigned Index = BaseArgs.MakeIndex(Opt.getName(), Value); 385 SynthesizedArgs.push_back( 386 make_unique<Arg>(Opt, MakeArgString(Opt.getPrefix() + Opt.getName()), 387 Index, BaseArgs.getArgString(Index + 1), BaseArg)); 388 return SynthesizedArgs.back().get(); 389 } 390 391 Arg *DerivedArgList::MakeJoinedArg(const Arg *BaseArg, const Option Opt, 392 StringRef Value) const { 393 unsigned Index = BaseArgs.MakeIndex((Opt.getName() + Value).str()); 394 SynthesizedArgs.push_back(make_unique<Arg>( 395 Opt, MakeArgString(Opt.getPrefix() + Opt.getName()), Index, 396 BaseArgs.getArgString(Index) + Opt.getName().size(), BaseArg)); 397 return SynthesizedArgs.back().get(); 398 } 399