1249259Sdim//===--- ArgList.cpp - Argument List Management ---------------------------===// 2249259Sdim// 3249259Sdim// The LLVM Compiler Infrastructure 4249259Sdim// 5249259Sdim// This file is distributed under the University of Illinois Open Source 6249259Sdim// License. See LICENSE.TXT for details. 7249259Sdim// 8249259Sdim//===----------------------------------------------------------------------===// 9249259Sdim 10249259Sdim#include "llvm/Option/ArgList.h" 11249259Sdim#include "llvm/ADT/SmallString.h" 12249259Sdim#include "llvm/ADT/Twine.h" 13249259Sdim#include "llvm/Option/Arg.h" 14249259Sdim#include "llvm/Option/Option.h" 15249259Sdim#include "llvm/Support/raw_ostream.h" 16249259Sdim 17249259Sdimusing namespace llvm; 18249259Sdimusing namespace llvm::opt; 19249259Sdim 20249259Sdimvoid arg_iterator::SkipToNextArg() { 21249259Sdim for (; Current != Args.end(); ++Current) { 22249259Sdim // Done if there are no filters. 23249259Sdim if (!Id0.isValid()) 24249259Sdim break; 25249259Sdim 26249259Sdim // Otherwise require a match. 27249259Sdim const Option &O = (*Current)->getOption(); 28249259Sdim if (O.matches(Id0) || 29249259Sdim (Id1.isValid() && O.matches(Id1)) || 30249259Sdim (Id2.isValid() && O.matches(Id2))) 31249259Sdim break; 32249259Sdim } 33249259Sdim} 34249259Sdim 35249259Sdim// 36249259Sdim 37249259SdimArgList::ArgList() { 38249259Sdim} 39249259Sdim 40249259SdimArgList::~ArgList() { 41249259Sdim} 42249259Sdim 43249259Sdimvoid ArgList::append(Arg *A) { 44249259Sdim Args.push_back(A); 45249259Sdim} 46249259Sdim 47249259Sdimvoid ArgList::eraseArg(OptSpecifier Id) { 48249259Sdim for (iterator it = begin(), ie = end(); it != ie; ) { 49249259Sdim if ((*it)->getOption().matches(Id)) { 50249259Sdim it = Args.erase(it); 51249259Sdim ie = end(); 52249259Sdim } else { 53249259Sdim ++it; 54249259Sdim } 55249259Sdim } 56249259Sdim} 57249259Sdim 58249259SdimArg *ArgList::getLastArgNoClaim(OptSpecifier Id) const { 59249259Sdim // FIXME: Make search efficient? 60249259Sdim for (const_reverse_iterator it = rbegin(), ie = rend(); it != ie; ++it) 61249259Sdim if ((*it)->getOption().matches(Id)) 62249259Sdim return *it; 63249259Sdim return 0; 64249259Sdim} 65249259Sdim 66249259SdimArg *ArgList::getLastArg(OptSpecifier Id) const { 67249259Sdim Arg *Res = 0; 68249259Sdim for (const_iterator it = begin(), ie = end(); it != ie; ++it) { 69249259Sdim if ((*it)->getOption().matches(Id)) { 70249259Sdim Res = *it; 71249259Sdim Res->claim(); 72249259Sdim } 73249259Sdim } 74249259Sdim 75249259Sdim return Res; 76249259Sdim} 77249259Sdim 78249259SdimArg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1) const { 79249259Sdim Arg *Res = 0; 80249259Sdim for (const_iterator it = begin(), ie = end(); it != ie; ++it) { 81249259Sdim if ((*it)->getOption().matches(Id0) || 82249259Sdim (*it)->getOption().matches(Id1)) { 83249259Sdim Res = *it; 84249259Sdim Res->claim(); 85249259Sdim 86249259Sdim } 87249259Sdim } 88249259Sdim 89249259Sdim return Res; 90249259Sdim} 91249259Sdim 92249259SdimArg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1, 93249259Sdim OptSpecifier Id2) const { 94249259Sdim Arg *Res = 0; 95249259Sdim for (const_iterator it = begin(), ie = end(); it != ie; ++it) { 96249259Sdim if ((*it)->getOption().matches(Id0) || 97249259Sdim (*it)->getOption().matches(Id1) || 98249259Sdim (*it)->getOption().matches(Id2)) { 99249259Sdim Res = *it; 100249259Sdim Res->claim(); 101249259Sdim } 102249259Sdim } 103249259Sdim 104249259Sdim return Res; 105249259Sdim} 106249259Sdim 107249259SdimArg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1, 108249259Sdim OptSpecifier Id2, OptSpecifier Id3) const { 109249259Sdim Arg *Res = 0; 110249259Sdim for (const_iterator it = begin(), ie = end(); it != ie; ++it) { 111249259Sdim if ((*it)->getOption().matches(Id0) || 112249259Sdim (*it)->getOption().matches(Id1) || 113249259Sdim (*it)->getOption().matches(Id2) || 114249259Sdim (*it)->getOption().matches(Id3)) { 115249259Sdim Res = *it; 116249259Sdim Res->claim(); 117249259Sdim } 118249259Sdim } 119249259Sdim 120249259Sdim return Res; 121249259Sdim} 122249259Sdim 123249259SdimArg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1, 124249259Sdim OptSpecifier Id2, OptSpecifier Id3, 125249259Sdim OptSpecifier Id4) const { 126249259Sdim Arg *Res = 0; 127249259Sdim for (const_iterator it = begin(), ie = end(); it != ie; ++it) { 128249259Sdim if ((*it)->getOption().matches(Id0) || 129249259Sdim (*it)->getOption().matches(Id1) || 130249259Sdim (*it)->getOption().matches(Id2) || 131249259Sdim (*it)->getOption().matches(Id3) || 132249259Sdim (*it)->getOption().matches(Id4)) { 133249259Sdim Res = *it; 134249259Sdim Res->claim(); 135249259Sdim } 136249259Sdim } 137249259Sdim 138249259Sdim return Res; 139249259Sdim} 140249259Sdim 141249259SdimArg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1, 142249259Sdim OptSpecifier Id2, OptSpecifier Id3, 143249259Sdim OptSpecifier Id4, OptSpecifier Id5) const { 144249259Sdim Arg *Res = 0; 145249259Sdim for (const_iterator it = begin(), ie = end(); it != ie; ++it) { 146249259Sdim if ((*it)->getOption().matches(Id0) || 147249259Sdim (*it)->getOption().matches(Id1) || 148249259Sdim (*it)->getOption().matches(Id2) || 149249259Sdim (*it)->getOption().matches(Id3) || 150249259Sdim (*it)->getOption().matches(Id4) || 151249259Sdim (*it)->getOption().matches(Id5)) { 152249259Sdim Res = *it; 153249259Sdim Res->claim(); 154249259Sdim } 155249259Sdim } 156249259Sdim 157249259Sdim return Res; 158249259Sdim} 159249259Sdim 160249259SdimArg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1, 161249259Sdim OptSpecifier Id2, OptSpecifier Id3, 162249259Sdim OptSpecifier Id4, OptSpecifier Id5, 163249259Sdim OptSpecifier Id6) const { 164249259Sdim Arg *Res = 0; 165249259Sdim for (const_iterator it = begin(), ie = end(); it != ie; ++it) { 166249259Sdim if ((*it)->getOption().matches(Id0) || 167249259Sdim (*it)->getOption().matches(Id1) || 168249259Sdim (*it)->getOption().matches(Id2) || 169249259Sdim (*it)->getOption().matches(Id3) || 170249259Sdim (*it)->getOption().matches(Id4) || 171249259Sdim (*it)->getOption().matches(Id5) || 172249259Sdim (*it)->getOption().matches(Id6)) { 173249259Sdim Res = *it; 174249259Sdim Res->claim(); 175249259Sdim } 176249259Sdim } 177249259Sdim 178249259Sdim return Res; 179249259Sdim} 180249259Sdim 181249259SdimArg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1, 182249259Sdim OptSpecifier Id2, OptSpecifier Id3, 183249259Sdim OptSpecifier Id4, OptSpecifier Id5, 184249259Sdim OptSpecifier Id6, OptSpecifier Id7) const { 185249259Sdim Arg *Res = 0; 186249259Sdim for (const_iterator it = begin(), ie = end(); it != ie; ++it) { 187249259Sdim if ((*it)->getOption().matches(Id0) || 188249259Sdim (*it)->getOption().matches(Id1) || 189249259Sdim (*it)->getOption().matches(Id2) || 190249259Sdim (*it)->getOption().matches(Id3) || 191249259Sdim (*it)->getOption().matches(Id4) || 192249259Sdim (*it)->getOption().matches(Id5) || 193249259Sdim (*it)->getOption().matches(Id6) || 194249259Sdim (*it)->getOption().matches(Id7)) { 195249259Sdim Res = *it; 196249259Sdim Res->claim(); 197249259Sdim } 198249259Sdim } 199249259Sdim 200249259Sdim return Res; 201249259Sdim} 202249259Sdim 203249259Sdimbool ArgList::hasFlag(OptSpecifier Pos, OptSpecifier Neg, bool Default) const { 204249259Sdim if (Arg *A = getLastArg(Pos, Neg)) 205249259Sdim return A->getOption().matches(Pos); 206249259Sdim return Default; 207249259Sdim} 208249259Sdim 209263509Sdimbool ArgList::hasFlag(OptSpecifier Pos, OptSpecifier PosAlias, OptSpecifier Neg, 210263509Sdim bool Default) const { 211263509Sdim if (Arg *A = getLastArg(Pos, PosAlias, Neg)) 212263509Sdim return A->getOption().matches(Pos) || A->getOption().matches(PosAlias); 213263509Sdim return Default; 214263509Sdim} 215263509Sdim 216249259SdimStringRef ArgList::getLastArgValue(OptSpecifier Id, 217249259Sdim StringRef Default) const { 218249259Sdim if (Arg *A = getLastArg(Id)) 219249259Sdim return A->getValue(); 220249259Sdim return Default; 221249259Sdim} 222249259Sdim 223249259Sdimstd::vector<std::string> ArgList::getAllArgValues(OptSpecifier Id) const { 224249259Sdim SmallVector<const char *, 16> Values; 225249259Sdim AddAllArgValues(Values, Id); 226249259Sdim return std::vector<std::string>(Values.begin(), Values.end()); 227249259Sdim} 228249259Sdim 229249259Sdimvoid ArgList::AddLastArg(ArgStringList &Output, OptSpecifier Id) const { 230249259Sdim if (Arg *A = getLastArg(Id)) { 231249259Sdim A->claim(); 232249259Sdim A->render(*this, Output); 233249259Sdim } 234249259Sdim} 235249259Sdim 236263509Sdimvoid ArgList::AddLastArg(ArgStringList &Output, OptSpecifier Id0, 237263509Sdim OptSpecifier Id1) const { 238263509Sdim if (Arg *A = getLastArg(Id0, Id1)) { 239263509Sdim A->claim(); 240263509Sdim A->render(*this, Output); 241263509Sdim } 242263509Sdim} 243263509Sdim 244249259Sdimvoid ArgList::AddAllArgs(ArgStringList &Output, OptSpecifier Id0, 245249259Sdim OptSpecifier Id1, OptSpecifier Id2) const { 246249259Sdim for (arg_iterator it = filtered_begin(Id0, Id1, Id2), 247249259Sdim ie = filtered_end(); it != ie; ++it) { 248249259Sdim (*it)->claim(); 249249259Sdim (*it)->render(*this, Output); 250249259Sdim } 251249259Sdim} 252249259Sdim 253249259Sdimvoid ArgList::AddAllArgValues(ArgStringList &Output, OptSpecifier Id0, 254249259Sdim OptSpecifier Id1, OptSpecifier Id2) const { 255249259Sdim for (arg_iterator it = filtered_begin(Id0, Id1, Id2), 256249259Sdim ie = filtered_end(); it != ie; ++it) { 257249259Sdim (*it)->claim(); 258249259Sdim for (unsigned i = 0, e = (*it)->getNumValues(); i != e; ++i) 259249259Sdim Output.push_back((*it)->getValue(i)); 260249259Sdim } 261249259Sdim} 262249259Sdim 263249259Sdimvoid ArgList::AddAllArgsTranslated(ArgStringList &Output, OptSpecifier Id0, 264249259Sdim const char *Translation, 265249259Sdim bool Joined) const { 266249259Sdim for (arg_iterator it = filtered_begin(Id0), 267249259Sdim ie = filtered_end(); it != ie; ++it) { 268249259Sdim (*it)->claim(); 269249259Sdim 270249259Sdim if (Joined) { 271249259Sdim Output.push_back(MakeArgString(StringRef(Translation) + 272249259Sdim (*it)->getValue(0))); 273249259Sdim } else { 274249259Sdim Output.push_back(Translation); 275249259Sdim Output.push_back((*it)->getValue(0)); 276249259Sdim } 277249259Sdim } 278249259Sdim} 279249259Sdim 280249259Sdimvoid ArgList::ClaimAllArgs(OptSpecifier Id0) const { 281249259Sdim for (arg_iterator it = filtered_begin(Id0), 282249259Sdim ie = filtered_end(); it != ie; ++it) 283249259Sdim (*it)->claim(); 284249259Sdim} 285249259Sdim 286249259Sdimvoid ArgList::ClaimAllArgs() const { 287249259Sdim for (const_iterator it = begin(), ie = end(); it != ie; ++it) 288249259Sdim if (!(*it)->isClaimed()) 289249259Sdim (*it)->claim(); 290249259Sdim} 291249259Sdim 292249259Sdimconst char *ArgList::MakeArgString(const Twine &T) const { 293249259Sdim SmallString<256> Str; 294249259Sdim T.toVector(Str); 295249259Sdim return MakeArgString(Str.str()); 296249259Sdim} 297249259Sdim 298249259Sdimconst char *ArgList::GetOrMakeJoinedArgString(unsigned Index, 299249259Sdim StringRef LHS, 300249259Sdim StringRef RHS) const { 301249259Sdim StringRef Cur = getArgString(Index); 302249259Sdim if (Cur.size() == LHS.size() + RHS.size() && 303249259Sdim Cur.startswith(LHS) && Cur.endswith(RHS)) 304249259Sdim return Cur.data(); 305249259Sdim 306249259Sdim return MakeArgString(LHS + RHS); 307249259Sdim} 308249259Sdim 309249259Sdim// 310249259Sdim 311249259SdimInputArgList::InputArgList(const char* const *ArgBegin, 312249259Sdim const char* const *ArgEnd) 313249259Sdim : NumInputArgStrings(ArgEnd - ArgBegin) { 314249259Sdim ArgStrings.append(ArgBegin, ArgEnd); 315249259Sdim} 316249259Sdim 317249259SdimInputArgList::~InputArgList() { 318249259Sdim // An InputArgList always owns its arguments. 319249259Sdim for (iterator it = begin(), ie = end(); it != ie; ++it) 320249259Sdim delete *it; 321249259Sdim} 322249259Sdim 323249259Sdimunsigned InputArgList::MakeIndex(StringRef String0) const { 324249259Sdim unsigned Index = ArgStrings.size(); 325249259Sdim 326249259Sdim // Tuck away so we have a reliable const char *. 327249259Sdim SynthesizedStrings.push_back(String0); 328249259Sdim ArgStrings.push_back(SynthesizedStrings.back().c_str()); 329249259Sdim 330249259Sdim return Index; 331249259Sdim} 332249259Sdim 333249259Sdimunsigned InputArgList::MakeIndex(StringRef String0, 334249259Sdim StringRef String1) const { 335249259Sdim unsigned Index0 = MakeIndex(String0); 336249259Sdim unsigned Index1 = MakeIndex(String1); 337249259Sdim assert(Index0 + 1 == Index1 && "Unexpected non-consecutive indices!"); 338249259Sdim (void) Index1; 339249259Sdim return Index0; 340249259Sdim} 341249259Sdim 342249259Sdimconst char *InputArgList::MakeArgString(StringRef Str) const { 343249259Sdim return getArgString(MakeIndex(Str)); 344249259Sdim} 345249259Sdim 346249259Sdim// 347249259Sdim 348249259SdimDerivedArgList::DerivedArgList(const InputArgList &_BaseArgs) 349249259Sdim : BaseArgs(_BaseArgs) { 350249259Sdim} 351249259Sdim 352249259SdimDerivedArgList::~DerivedArgList() { 353249259Sdim // We only own the arguments we explicitly synthesized. 354249259Sdim for (iterator it = SynthesizedArgs.begin(), ie = SynthesizedArgs.end(); 355249259Sdim it != ie; ++it) 356249259Sdim delete *it; 357249259Sdim} 358249259Sdim 359249259Sdimconst char *DerivedArgList::MakeArgString(StringRef Str) const { 360249259Sdim return BaseArgs.MakeArgString(Str); 361249259Sdim} 362249259Sdim 363249259SdimArg *DerivedArgList::MakeFlagArg(const Arg *BaseArg, const Option Opt) const { 364249259Sdim Arg *A = new Arg(Opt, ArgList::MakeArgString(Twine(Opt.getPrefix()) + 365249259Sdim Twine(Opt.getName())), 366249259Sdim BaseArgs.MakeIndex(Opt.getName()), BaseArg); 367249259Sdim SynthesizedArgs.push_back(A); 368249259Sdim return A; 369249259Sdim} 370249259Sdim 371249259SdimArg *DerivedArgList::MakePositionalArg(const Arg *BaseArg, const Option Opt, 372249259Sdim StringRef Value) const { 373249259Sdim unsigned Index = BaseArgs.MakeIndex(Value); 374249259Sdim Arg *A = new Arg(Opt, ArgList::MakeArgString(Twine(Opt.getPrefix()) + 375249259Sdim Twine(Opt.getName())), 376249259Sdim Index, BaseArgs.getArgString(Index), BaseArg); 377249259Sdim SynthesizedArgs.push_back(A); 378249259Sdim return A; 379249259Sdim} 380249259Sdim 381249259SdimArg *DerivedArgList::MakeSeparateArg(const Arg *BaseArg, const Option Opt, 382249259Sdim StringRef Value) const { 383249259Sdim unsigned Index = BaseArgs.MakeIndex(Opt.getName(), Value); 384249259Sdim Arg *A = new Arg(Opt, ArgList::MakeArgString(Twine(Opt.getPrefix()) + 385249259Sdim Twine(Opt.getName())), 386249259Sdim Index, BaseArgs.getArgString(Index + 1), BaseArg); 387249259Sdim SynthesizedArgs.push_back(A); 388249259Sdim return A; 389249259Sdim} 390249259Sdim 391249259SdimArg *DerivedArgList::MakeJoinedArg(const Arg *BaseArg, const Option Opt, 392249259Sdim StringRef Value) const { 393249259Sdim unsigned Index = BaseArgs.MakeIndex(Opt.getName().str() + Value.str()); 394249259Sdim Arg *A = new Arg(Opt, ArgList::MakeArgString(Twine(Opt.getPrefix()) + 395249259Sdim Twine(Opt.getName())), Index, 396249259Sdim BaseArgs.getArgString(Index) + Opt.getName().size(), 397249259Sdim BaseArg); 398249259Sdim SynthesizedArgs.push_back(A); 399249259Sdim return A; 400249259Sdim} 401