| //===--- ArgList.cpp - Argument List Management -------------------------*-===// | 
 | // | 
 | //                     The LLVM Compiler Infrastructure | 
 | // | 
 | // This file is distributed under the University of Illinois Open Source | 
 | // License. See LICENSE.TXT for details. | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | #include "clang/Driver/ArgList.h" | 
 | #include "clang/Driver/Arg.h" | 
 | #include "clang/Driver/Option.h" | 
 |  | 
 | using namespace clang::driver; | 
 |  | 
 | ArgList::ArgList(arglist_type &_Args) : Args(_Args) { | 
 | } | 
 |  | 
 | ArgList::~ArgList() { | 
 | } | 
 |  | 
 | void ArgList::append(Arg *A) { | 
 |   Args.push_back(A); | 
 | } | 
 |  | 
 | Arg *ArgList::getLastArg(options::ID Id, bool Claim) const { | 
 |   // FIXME: Make search efficient? | 
 |   for (const_reverse_iterator it = rbegin(), ie = rend(); it != ie; ++it) { | 
 |     if ((*it)->getOption().matches(Id)) { | 
 |       if (Claim) (*it)->claim(); | 
 |       return *it; | 
 |     } | 
 |   } | 
 |    | 
 |   return 0; | 
 | } | 
 |  | 
 | Arg *ArgList::getLastArg(options::ID Id0, options::ID Id1, bool Claim) const { | 
 |   Arg *Res, *A0 = getLastArg(Id0, false), *A1 = getLastArg(Id1, false); | 
 |    | 
 |   if (A0 && A1) | 
 |     Res = A0->getIndex() > A1->getIndex() ? A0 : A1; | 
 |   else | 
 |     Res = A0 ? A0 : A1; | 
 |  | 
 |   if (Claim && Res) | 
 |     Res->claim(); | 
 |  | 
 |   return Res; | 
 | } | 
 |  | 
 | bool ArgList::hasFlag(options::ID Pos, options::ID Neg, bool Default) const { | 
 |   if (Arg *A = getLastArg(Pos, Neg)) | 
 |     return A->getOption().matches(Pos); | 
 |   return Default; | 
 | } | 
 |  | 
 | void ArgList::AddLastArg(ArgStringList &Output, options::ID Id) const { | 
 |   if (Arg *A = getLastArg(Id)) { | 
 |     A->claim(); | 
 |     A->render(*this, Output); | 
 |   } | 
 | } | 
 |  | 
 | void ArgList::AddAllArgs(ArgStringList &Output, options::ID Id0) const { | 
 |   // FIXME: Make fast. | 
 |   for (const_iterator it = begin(), ie = end(); it != ie; ++it) { | 
 |     const Arg *A = *it; | 
 |     if (A->getOption().matches(Id0)) { | 
 |       A->claim(); | 
 |       A->render(*this, Output); | 
 |     } | 
 |   } | 
 | } | 
 |  | 
 | void ArgList::AddAllArgs(ArgStringList &Output, options::ID Id0,  | 
 |                          options::ID Id1) const { | 
 |   // FIXME: Make fast. | 
 |   for (const_iterator it = begin(), ie = end(); it != ie; ++it) { | 
 |     const Arg *A = *it; | 
 |     if (A->getOption().matches(Id0) || A->getOption().matches(Id1)) { | 
 |       A->claim(); | 
 |       A->render(*this, Output); | 
 |     } | 
 |   } | 
 | } | 
 |  | 
 | void ArgList::AddAllArgs(ArgStringList &Output, options::ID Id0,  | 
 |                          options::ID Id1, options::ID Id2) const { | 
 |   // FIXME: Make fast. | 
 |   for (const_iterator it = begin(), ie = end(); it != ie; ++it) { | 
 |     const Arg *A = *it; | 
 |     if (A->getOption().matches(Id0) || A->getOption().matches(Id1) || | 
 |         A->getOption().matches(Id2)) { | 
 |       A->claim(); | 
 |       A->render(*this, Output); | 
 |     } | 
 |   } | 
 | } | 
 |  | 
 | void ArgList::AddAllArgValues(ArgStringList &Output, options::ID Id0) const { | 
 |   // FIXME: Make fast. | 
 |   for (const_iterator it = begin(), ie = end(); it != ie; ++it) { | 
 |     const Arg *A = *it; | 
 |     if (A->getOption().matches(Id0)) { | 
 |       A->claim(); | 
 |       for (unsigned i = 0, e = A->getNumValues(); i != e; ++i) | 
 |         Output.push_back(A->getValue(*this, i)); | 
 |     } | 
 |   } | 
 | } | 
 |  | 
 | void ArgList::AddAllArgValues(ArgStringList &Output, options::ID Id0,  | 
 |                               options::ID Id1) const { | 
 |   // FIXME: Make fast. | 
 |   for (const_iterator it = begin(), ie = end(); it != ie; ++it) { | 
 |     const Arg *A = *it; | 
 |     if (A->getOption().matches(Id0) || A->getOption().matches(Id1)) { | 
 |       A->claim(); | 
 |       for (unsigned i = 0, e = A->getNumValues(); i != e; ++i) | 
 |         Output.push_back(A->getValue(*this, i)); | 
 |     } | 
 |   } | 
 | } | 
 |  | 
 | void ArgList::AddAllArgsTranslated(ArgStringList &Output, options::ID Id0, | 
 |                                    const char *Translation, | 
 |                                    bool Joined) const { | 
 |   // FIXME: Make fast. | 
 |   for (const_iterator it = begin(), ie = end(); it != ie; ++it) { | 
 |     const Arg *A = *it; | 
 |     if (A->getOption().matches(Id0)) { | 
 |       A->claim(); | 
 |  | 
 |       if (Joined) { | 
 |         std::string Value = Translation; | 
 |         Value += A->getValue(*this, 0); | 
 |         Output.push_back(MakeArgString(Value.c_str())); | 
 |       } else { | 
 |         Output.push_back(Translation); | 
 |         Output.push_back(A->getValue(*this, 0)); | 
 |       } | 
 |     } | 
 |   } | 
 | } | 
 |  | 
 | void ArgList::ClaimAllArgs(options::ID Id0) const { | 
 |   // FIXME: Make fast. | 
 |   for (const_iterator it = begin(), ie = end(); it != ie; ++it) { | 
 |     const Arg *A = *it; | 
 |     if (A->getOption().matches(Id0)) | 
 |       A->claim(); | 
 |   } | 
 | } | 
 |  | 
 | // | 
 |  | 
 | InputArgList::InputArgList(const char **ArgBegin, const char **ArgEnd)  | 
 |   : ArgList(ActualArgs), NumInputArgStrings(ArgEnd - ArgBegin)  | 
 | { | 
 |   ArgStrings.append(ArgBegin, ArgEnd); | 
 | } | 
 |  | 
 | InputArgList::~InputArgList() { | 
 |   // An InputArgList always owns its arguments. | 
 |   for (iterator it = begin(), ie = end(); it != ie; ++it) | 
 |     delete *it; | 
 | } | 
 |  | 
 | unsigned InputArgList::MakeIndex(const char *String0) const { | 
 |   unsigned Index = ArgStrings.size(); | 
 |  | 
 |   // Tuck away so we have a reliable const char *. | 
 |   SynthesizedStrings.push_back(String0); | 
 |   ArgStrings.push_back(SynthesizedStrings.back().c_str()); | 
 |  | 
 |   return Index; | 
 | } | 
 |  | 
 | unsigned InputArgList::MakeIndex(const char *String0,  | 
 |                                  const char *String1) const { | 
 |   unsigned Index0 = MakeIndex(String0); | 
 |   unsigned Index1 = MakeIndex(String1); | 
 |   assert(Index0 + 1 == Index1 && "Unexpected non-consecutive indices!"); | 
 |   (void) Index1; | 
 |   return Index0; | 
 | } | 
 |  | 
 | const char *InputArgList::MakeArgString(const char *Str) const { | 
 |   return getArgString(MakeIndex(Str)); | 
 | } | 
 |  | 
 | // | 
 |  | 
 | DerivedArgList::DerivedArgList(InputArgList &_BaseArgs, bool _OnlyProxy) | 
 |   : ArgList(_OnlyProxy ? _BaseArgs.getArgs() : ActualArgs), | 
 |     BaseArgs(_BaseArgs), OnlyProxy(_OnlyProxy) | 
 | { | 
 | } | 
 |  | 
 | DerivedArgList::~DerivedArgList() { | 
 |   // We only own the arguments we explicitly synthesized. | 
 |   for (iterator it = SynthesizedArgs.begin(), ie = SynthesizedArgs.end();  | 
 |        it != ie; ++it) | 
 |     delete *it; | 
 | } | 
 |  | 
 | const char *DerivedArgList::MakeArgString(const char *Str) const { | 
 |   return BaseArgs.MakeArgString(Str); | 
 | } | 
 |  | 
 | Arg *DerivedArgList::MakeFlagArg(const Arg *BaseArg, const Option *Opt) const { | 
 |   return new FlagArg(Opt, BaseArgs.MakeIndex(Opt->getName()), BaseArg); | 
 | } | 
 |  | 
 | Arg *DerivedArgList::MakePositionalArg(const Arg *BaseArg, const Option *Opt,  | 
 |                                        const char *Value) const { | 
 |   return new PositionalArg(Opt, BaseArgs.MakeIndex(Value), BaseArg); | 
 | } | 
 |  | 
 | Arg *DerivedArgList::MakeSeparateArg(const Arg *BaseArg, const Option *Opt,  | 
 |                                      const char *Value) const { | 
 |   return new SeparateArg(Opt, BaseArgs.MakeIndex(Opt->getName(), Value), 1,  | 
 |                          BaseArg); | 
 | } | 
 |  | 
 | Arg *DerivedArgList::MakeJoinedArg(const Arg *BaseArg, const Option *Opt,  | 
 |                                    const char *Value) const { | 
 |   std::string Joined(Opt->getName()); | 
 |   Joined += Value; | 
 |   return new JoinedArg(Opt, BaseArgs.MakeIndex(Joined.c_str()), BaseArg); | 
 | } |