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