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 209249259SdimStringRef ArgList::getLastArgValue(OptSpecifier Id, 210249259Sdim StringRef Default) const { 211249259Sdim if (Arg *A = getLastArg(Id)) 212249259Sdim return A->getValue(); 213249259Sdim return Default; 214249259Sdim} 215249259Sdim 216249259Sdimstd::vector<std::string> ArgList::getAllArgValues(OptSpecifier Id) const { 217249259Sdim SmallVector<const char *, 16> Values; 218249259Sdim AddAllArgValues(Values, Id); 219249259Sdim return std::vector<std::string>(Values.begin(), Values.end()); 220249259Sdim} 221249259Sdim 222249259Sdimvoid ArgList::AddLastArg(ArgStringList &Output, OptSpecifier Id) const { 223249259Sdim if (Arg *A = getLastArg(Id)) { 224249259Sdim A->claim(); 225249259Sdim A->render(*this, Output); 226249259Sdim } 227249259Sdim} 228249259Sdim 229249259Sdimvoid ArgList::AddAllArgs(ArgStringList &Output, OptSpecifier Id0, 230249259Sdim OptSpecifier Id1, OptSpecifier Id2) const { 231249259Sdim for (arg_iterator it = filtered_begin(Id0, Id1, Id2), 232249259Sdim ie = filtered_end(); it != ie; ++it) { 233249259Sdim (*it)->claim(); 234249259Sdim (*it)->render(*this, Output); 235249259Sdim } 236249259Sdim} 237249259Sdim 238249259Sdimvoid ArgList::AddAllArgValues(ArgStringList &Output, OptSpecifier Id0, 239249259Sdim OptSpecifier Id1, OptSpecifier Id2) const { 240249259Sdim for (arg_iterator it = filtered_begin(Id0, Id1, Id2), 241249259Sdim ie = filtered_end(); it != ie; ++it) { 242249259Sdim (*it)->claim(); 243249259Sdim for (unsigned i = 0, e = (*it)->getNumValues(); i != e; ++i) 244249259Sdim Output.push_back((*it)->getValue(i)); 245249259Sdim } 246249259Sdim} 247249259Sdim 248249259Sdimvoid ArgList::AddAllArgsTranslated(ArgStringList &Output, OptSpecifier Id0, 249249259Sdim const char *Translation, 250249259Sdim bool Joined) const { 251249259Sdim for (arg_iterator it = filtered_begin(Id0), 252249259Sdim ie = filtered_end(); it != ie; ++it) { 253249259Sdim (*it)->claim(); 254249259Sdim 255249259Sdim if (Joined) { 256249259Sdim Output.push_back(MakeArgString(StringRef(Translation) + 257249259Sdim (*it)->getValue(0))); 258249259Sdim } else { 259249259Sdim Output.push_back(Translation); 260249259Sdim Output.push_back((*it)->getValue(0)); 261249259Sdim } 262249259Sdim } 263249259Sdim} 264249259Sdim 265249259Sdimvoid ArgList::ClaimAllArgs(OptSpecifier Id0) const { 266249259Sdim for (arg_iterator it = filtered_begin(Id0), 267249259Sdim ie = filtered_end(); it != ie; ++it) 268249259Sdim (*it)->claim(); 269249259Sdim} 270249259Sdim 271249259Sdimvoid ArgList::ClaimAllArgs() const { 272249259Sdim for (const_iterator it = begin(), ie = end(); it != ie; ++it) 273249259Sdim if (!(*it)->isClaimed()) 274249259Sdim (*it)->claim(); 275249259Sdim} 276249259Sdim 277249259Sdimconst char *ArgList::MakeArgString(const Twine &T) const { 278249259Sdim SmallString<256> Str; 279249259Sdim T.toVector(Str); 280249259Sdim return MakeArgString(Str.str()); 281249259Sdim} 282249259Sdim 283249259Sdimconst char *ArgList::GetOrMakeJoinedArgString(unsigned Index, 284249259Sdim StringRef LHS, 285249259Sdim StringRef RHS) const { 286249259Sdim StringRef Cur = getArgString(Index); 287249259Sdim if (Cur.size() == LHS.size() + RHS.size() && 288249259Sdim Cur.startswith(LHS) && Cur.endswith(RHS)) 289249259Sdim return Cur.data(); 290249259Sdim 291249259Sdim return MakeArgString(LHS + RHS); 292249259Sdim} 293249259Sdim 294249259Sdim// 295249259Sdim 296249259SdimInputArgList::InputArgList(const char* const *ArgBegin, 297249259Sdim const char* const *ArgEnd) 298249259Sdim : NumInputArgStrings(ArgEnd - ArgBegin) { 299249259Sdim ArgStrings.append(ArgBegin, ArgEnd); 300249259Sdim} 301249259Sdim 302249259SdimInputArgList::~InputArgList() { 303249259Sdim // An InputArgList always owns its arguments. 304249259Sdim for (iterator it = begin(), ie = end(); it != ie; ++it) 305249259Sdim delete *it; 306249259Sdim} 307249259Sdim 308249259Sdimunsigned InputArgList::MakeIndex(StringRef String0) const { 309249259Sdim unsigned Index = ArgStrings.size(); 310249259Sdim 311249259Sdim // Tuck away so we have a reliable const char *. 312249259Sdim SynthesizedStrings.push_back(String0); 313249259Sdim ArgStrings.push_back(SynthesizedStrings.back().c_str()); 314249259Sdim 315249259Sdim return Index; 316249259Sdim} 317249259Sdim 318249259Sdimunsigned InputArgList::MakeIndex(StringRef String0, 319249259Sdim StringRef String1) const { 320249259Sdim unsigned Index0 = MakeIndex(String0); 321249259Sdim unsigned Index1 = MakeIndex(String1); 322249259Sdim assert(Index0 + 1 == Index1 && "Unexpected non-consecutive indices!"); 323249259Sdim (void) Index1; 324249259Sdim return Index0; 325249259Sdim} 326249259Sdim 327249259Sdimconst char *InputArgList::MakeArgString(StringRef Str) const { 328249259Sdim return getArgString(MakeIndex(Str)); 329249259Sdim} 330249259Sdim 331249259Sdim// 332249259Sdim 333249259SdimDerivedArgList::DerivedArgList(const InputArgList &_BaseArgs) 334249259Sdim : BaseArgs(_BaseArgs) { 335249259Sdim} 336249259Sdim 337249259SdimDerivedArgList::~DerivedArgList() { 338249259Sdim // We only own the arguments we explicitly synthesized. 339249259Sdim for (iterator it = SynthesizedArgs.begin(), ie = SynthesizedArgs.end(); 340249259Sdim it != ie; ++it) 341249259Sdim delete *it; 342249259Sdim} 343249259Sdim 344249259Sdimconst char *DerivedArgList::MakeArgString(StringRef Str) const { 345249259Sdim return BaseArgs.MakeArgString(Str); 346249259Sdim} 347249259Sdim 348249259SdimArg *DerivedArgList::MakeFlagArg(const Arg *BaseArg, const Option Opt) const { 349249259Sdim Arg *A = new Arg(Opt, ArgList::MakeArgString(Twine(Opt.getPrefix()) + 350249259Sdim Twine(Opt.getName())), 351249259Sdim BaseArgs.MakeIndex(Opt.getName()), BaseArg); 352249259Sdim SynthesizedArgs.push_back(A); 353249259Sdim return A; 354249259Sdim} 355249259Sdim 356249259SdimArg *DerivedArgList::MakePositionalArg(const Arg *BaseArg, const Option Opt, 357249259Sdim StringRef Value) const { 358249259Sdim unsigned Index = BaseArgs.MakeIndex(Value); 359249259Sdim Arg *A = new Arg(Opt, ArgList::MakeArgString(Twine(Opt.getPrefix()) + 360249259Sdim Twine(Opt.getName())), 361249259Sdim Index, BaseArgs.getArgString(Index), BaseArg); 362249259Sdim SynthesizedArgs.push_back(A); 363249259Sdim return A; 364249259Sdim} 365249259Sdim 366249259SdimArg *DerivedArgList::MakeSeparateArg(const Arg *BaseArg, const Option Opt, 367249259Sdim StringRef Value) const { 368249259Sdim unsigned Index = BaseArgs.MakeIndex(Opt.getName(), Value); 369249259Sdim Arg *A = new Arg(Opt, ArgList::MakeArgString(Twine(Opt.getPrefix()) + 370249259Sdim Twine(Opt.getName())), 371249259Sdim Index, BaseArgs.getArgString(Index + 1), BaseArg); 372249259Sdim SynthesizedArgs.push_back(A); 373249259Sdim return A; 374249259Sdim} 375249259Sdim 376249259SdimArg *DerivedArgList::MakeJoinedArg(const Arg *BaseArg, const Option Opt, 377249259Sdim StringRef Value) const { 378249259Sdim unsigned Index = BaseArgs.MakeIndex(Opt.getName().str() + Value.str()); 379249259Sdim Arg *A = new Arg(Opt, ArgList::MakeArgString(Twine(Opt.getPrefix()) + 380249259Sdim Twine(Opt.getName())), Index, 381249259Sdim BaseArgs.getArgString(Index) + Opt.getName().size(), 382249259Sdim BaseArg); 383249259Sdim SynthesizedArgs.push_back(A); 384249259Sdim return A; 385249259Sdim} 386