//===--- 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/DriverDiagnostic.h"
#include "clang/Driver/Option.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/raw_ostream.h"

using namespace clang;
using namespace clang::driver;

void arg_iterator::SkipToNextArg() {
  for (; Current != Args.end(); ++Current) {
    // Done if there are no filters.
    if (!Id0.isValid())
      break;

    // Otherwise require a match.
    const Option &O = (*Current)->getOption();
    if (O.matches(Id0) ||
        (Id1.isValid() && O.matches(Id1)) ||
        (Id2.isValid() && O.matches(Id2)))
      break;
  }
}

//

ArgList::ArgList() {
}

ArgList::~ArgList() {
}

void ArgList::append(Arg *A) {
  Args.push_back(A);
}

void ArgList::eraseArg(OptSpecifier Id) {
  for (iterator it = begin(), ie = end(); it != ie; ) {
    if ((*it)->getOption().matches(Id)) {
      it = Args.erase(it);
      ie = end();
    } else {
      ++it;
    }
  }
}

Arg *ArgList::getLastArgNoClaim(OptSpecifier Id) const {
  // FIXME: Make search efficient?
  for (const_reverse_iterator it = rbegin(), ie = rend(); it != ie; ++it)
    if ((*it)->getOption().matches(Id))
      return *it;
  return 0;
}

Arg *ArgList::getLastArg(OptSpecifier Id) const {
  Arg *Res = 0;
  for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
    if ((*it)->getOption().matches(Id)) {
      Res = *it;
      Res->claim();
    }
  }

  return Res;
}

Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1) const {
  Arg *Res = 0;
  for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
    if ((*it)->getOption().matches(Id0) ||
        (*it)->getOption().matches(Id1)) {
      Res = *it;
      Res->claim();
    }
  }

  return Res;
}

Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1,
                         OptSpecifier Id2) const {
  Arg *Res = 0;
  for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
    if ((*it)->getOption().matches(Id0) ||
        (*it)->getOption().matches(Id1) ||
        (*it)->getOption().matches(Id2)) {
      Res = *it;
      Res->claim();
    }
  }

  return Res;
}

Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1,
                         OptSpecifier Id2, OptSpecifier Id3) const {
  Arg *Res = 0;
  for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
    if ((*it)->getOption().matches(Id0) ||
        (*it)->getOption().matches(Id1) ||
        (*it)->getOption().matches(Id2) ||
        (*it)->getOption().matches(Id3)) {
      Res = *it;
      Res->claim();
    }
  }

  return Res;
}

Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1,
                         OptSpecifier Id2, OptSpecifier Id3,
                         OptSpecifier Id4) const {
  Arg *Res = 0;
  for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
    if ((*it)->getOption().matches(Id0) ||
        (*it)->getOption().matches(Id1) ||
        (*it)->getOption().matches(Id2) ||
        (*it)->getOption().matches(Id3) ||
        (*it)->getOption().matches(Id4)) {
      Res = *it;
      Res->claim();
    }
  }

  return Res;
}

Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1,
                         OptSpecifier Id2, OptSpecifier Id3,
                         OptSpecifier Id4, OptSpecifier Id5) const {
  Arg *Res = 0;
  for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
    if ((*it)->getOption().matches(Id0) ||
        (*it)->getOption().matches(Id1) ||
        (*it)->getOption().matches(Id2) ||
        (*it)->getOption().matches(Id3) ||
        (*it)->getOption().matches(Id4) ||
        (*it)->getOption().matches(Id5)) {
      Res = *it;
      Res->claim();
    }
  }

  return Res;
}

Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1,
                         OptSpecifier Id2, OptSpecifier Id3,
                         OptSpecifier Id4, OptSpecifier Id5,
                         OptSpecifier Id6) const {
  Arg *Res = 0;
  for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
    if ((*it)->getOption().matches(Id0) ||
        (*it)->getOption().matches(Id1) ||
        (*it)->getOption().matches(Id2) ||
        (*it)->getOption().matches(Id3) ||
        (*it)->getOption().matches(Id4) ||
        (*it)->getOption().matches(Id5) ||
        (*it)->getOption().matches(Id6)) {
      Res = *it;
      Res->claim();
    }
  }

  return Res;
}

Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1,
                         OptSpecifier Id2, OptSpecifier Id3,
                         OptSpecifier Id4, OptSpecifier Id5,
                         OptSpecifier Id6, OptSpecifier Id7) const {
  Arg *Res = 0;
  for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
    if ((*it)->getOption().matches(Id0) ||
        (*it)->getOption().matches(Id1) ||
        (*it)->getOption().matches(Id2) ||
        (*it)->getOption().matches(Id3) ||
        (*it)->getOption().matches(Id4) ||
        (*it)->getOption().matches(Id5) ||
        (*it)->getOption().matches(Id6) ||
        (*it)->getOption().matches(Id7)) {
      Res = *it;
      Res->claim();
    }
  }

  return Res;
}

bool ArgList::hasFlag(OptSpecifier Pos, OptSpecifier Neg, bool Default) const {
  if (Arg *A = getLastArg(Pos, Neg))
    return A->getOption().matches(Pos);
  return Default;
}

StringRef ArgList::getLastArgValue(OptSpecifier Id,
                                         StringRef Default) const {
  if (Arg *A = getLastArg(Id))
    return A->getValue();
  return Default;
}

int ArgList::getLastArgIntValue(OptSpecifier Id, int Default,
                                clang::DiagnosticsEngine *Diags) const {
  int Res = Default;

  if (Arg *A = getLastArg(Id)) {
    if (StringRef(A->getValue()).getAsInteger(10, Res)) {
      if (Diags)
        Diags->Report(diag::err_drv_invalid_int_value)
          << A->getAsString(*this) << A->getValue();
    }
  }

  return Res;
}

std::vector<std::string> ArgList::getAllArgValues(OptSpecifier Id) const {
  SmallVector<const char *, 16> Values;
  AddAllArgValues(Values, Id);
  return std::vector<std::string>(Values.begin(), Values.end());
}

void ArgList::AddLastArg(ArgStringList &Output, OptSpecifier Id) const {
  if (Arg *A = getLastArg(Id)) {
    A->claim();
    A->render(*this, Output);
  }
}

void ArgList::AddAllArgs(ArgStringList &Output, OptSpecifier Id0,
                         OptSpecifier Id1, OptSpecifier Id2) const {
  for (arg_iterator it = filtered_begin(Id0, Id1, Id2),
         ie = filtered_end(); it != ie; ++it) {
    (*it)->claim();
    (*it)->render(*this, Output);
  }
}

void ArgList::AddAllArgValues(ArgStringList &Output, OptSpecifier Id0,
                              OptSpecifier Id1, OptSpecifier Id2) const {
  for (arg_iterator it = filtered_begin(Id0, Id1, Id2),
         ie = filtered_end(); it != ie; ++it) {
    (*it)->claim();
    for (unsigned i = 0, e = (*it)->getNumValues(); i != e; ++i)
      Output.push_back((*it)->getValue(i));
  }
}

void ArgList::AddAllArgsTranslated(ArgStringList &Output, OptSpecifier Id0,
                                   const char *Translation,
                                   bool Joined) const {
  for (arg_iterator it = filtered_begin(Id0),
         ie = filtered_end(); it != ie; ++it) {
    (*it)->claim();

    if (Joined) {
      Output.push_back(MakeArgString(StringRef(Translation) +
                                     (*it)->getValue(0)));
    } else {
      Output.push_back(Translation);
      Output.push_back((*it)->getValue(0));
    }
  }
}

void ArgList::ClaimAllArgs(OptSpecifier Id0) const {
  for (arg_iterator it = filtered_begin(Id0),
         ie = filtered_end(); it != ie; ++it)
    (*it)->claim();
}

void ArgList::ClaimAllArgs() const {
  for (const_iterator it = begin(), ie = end(); it != ie; ++it)
    if (!(*it)->isClaimed())
      (*it)->claim();
}

const char *ArgList::MakeArgString(const Twine &T) const {
  SmallString<256> Str;
  T.toVector(Str);
  return MakeArgString(Str.str());
}

const char *ArgList::GetOrMakeJoinedArgString(unsigned Index,
                                              StringRef LHS,
                                              StringRef RHS) const {
  StringRef Cur = getArgString(Index);
  if (Cur.size() == LHS.size() + RHS.size() &&
      Cur.startswith(LHS) && Cur.endswith(RHS))
    return Cur.data();

  return MakeArgString(LHS + RHS);
}

void ArgList::dump() {
  llvm::errs() << "ArgList:";
  for (iterator it = begin(), ie = end(); it != ie; ++it) {
    llvm::errs() << " " << (*it)->getSpelling();
  }
  llvm::errs() << "\n";
}

//

InputArgList::InputArgList(const char* const *ArgBegin,
                           const char* const *ArgEnd)
  : 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(StringRef 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(StringRef String0,
                                 StringRef 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(StringRef Str) const {
  return getArgString(MakeIndex(Str));
}

//

DerivedArgList::DerivedArgList(const InputArgList &_BaseArgs)
  : BaseArgs(_BaseArgs) {
}

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(StringRef Str) const {
  return BaseArgs.MakeArgString(Str);
}

Arg *DerivedArgList::MakeFlagArg(const Arg *BaseArg, const Option Opt) const {
  Arg *A = new Arg(Opt, ArgList::MakeArgString(Twine(Opt.getPrefix()) +
                                               Twine(Opt.getName())),
                   BaseArgs.MakeIndex(Opt.getName()), BaseArg);
  SynthesizedArgs.push_back(A);
  return A;
}

Arg *DerivedArgList::MakePositionalArg(const Arg *BaseArg, const Option Opt,
                                       StringRef Value) const {
  unsigned Index = BaseArgs.MakeIndex(Value);
  Arg *A = new Arg(Opt, ArgList::MakeArgString(Twine(Opt.getPrefix()) +
                                               Twine(Opt.getName())),
                   Index, BaseArgs.getArgString(Index), BaseArg);
  SynthesizedArgs.push_back(A);
  return A;
}

Arg *DerivedArgList::MakeSeparateArg(const Arg *BaseArg, const Option Opt,
                                     StringRef Value) const {
  unsigned Index = BaseArgs.MakeIndex(Opt.getName(), Value);
  Arg *A = new Arg(Opt, ArgList::MakeArgString(Twine(Opt.getPrefix()) +
                                               Twine(Opt.getName())),
                   Index, BaseArgs.getArgString(Index + 1), BaseArg);
  SynthesizedArgs.push_back(A);
  return A;
}

Arg *DerivedArgList::MakeJoinedArg(const Arg *BaseArg, const Option Opt,
                                   StringRef Value) const {
  unsigned Index = BaseArgs.MakeIndex(Opt.getName().str() + Value.str());
  Arg *A = new Arg(Opt, ArgList::MakeArgString(Twine(Opt.getPrefix()) +
                                               Twine(Opt.getName())), Index,
                   BaseArgs.getArgString(Index) + Opt.getName().size(),
                   BaseArg);
  SynthesizedArgs.push_back(A);
  return A;
}
