//===- ArgList.cpp - Argument List Management -----------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "llvm/Option/ArgList.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/OptSpecifier.h"
#include "llvm/Option/OptTable.h"
#include "llvm/Option/Option.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <memory>
#include <string>
#include <vector>

using namespace llvm;
using namespace llvm::opt;

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

  // Update ranges for the option and all of its groups.
  for (Option O = A->getOption().getUnaliasedOption(); O.isValid();
       O = O.getGroup()) {
    auto &R =
        OptRanges.insert(std::make_pair(O.getID(), emptyRange())).first->second;
    R.first = std::min<unsigned>(R.first, Args.size() - 1);
    R.second = Args.size();
  }
}

void ArgList::eraseArg(OptSpecifier Id) {
  // Zero out the removed entries but keep them around so that we don't
  // need to invalidate OptRanges.
  for (Arg *const &A : filtered(Id)) {
    // Avoid the need for a non-const filtered iterator variant.
    Arg **ArgsBegin = Args.data();
    ArgsBegin[&A - ArgsBegin] = nullptr;
  }
  OptRanges.erase(Id.getID());
}

ArgList::OptRange
ArgList::getRange(std::initializer_list<OptSpecifier> Ids) const {
  OptRange R = emptyRange();
  for (auto Id : Ids) {
    auto I = OptRanges.find(Id.getID());
    if (I != OptRanges.end()) {
      R.first = std::min(R.first, I->second.first);
      R.second = std::max(R.second, I->second.second);
    }
  }
  // Map an empty {-1, 0} range to {0, 0} so it can be used to form iterators.
  if (R.first == -1u)
    R.first = 0;
  return R;
}

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

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

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

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

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::addOptInFlag(ArgStringList &Output, OptSpecifier Pos,
                           OptSpecifier Neg) const {
  if (Arg *A = getLastArg(Pos, Neg))
    if (A->getOption().matches(Pos))
      A->render(*this, Output);
}

void ArgList::AddAllArgsExcept(ArgStringList &Output,
                               ArrayRef<OptSpecifier> Ids,
                               ArrayRef<OptSpecifier> ExcludeIds) const {
  for (const Arg *Arg : *this) {
    bool Excluded = false;
    for (OptSpecifier Id : ExcludeIds) {
      if (Arg->getOption().matches(Id)) {
        Excluded = true;
        break;
      }
    }
    if (!Excluded) {
      for (OptSpecifier Id : Ids) {
        if (Arg->getOption().matches(Id)) {
          Arg->claim();
          Arg->render(*this, Output);
          break;
        }
      }
    }
  }
}

/// This is a nicer interface when you don't have a list of Ids to exclude.
void ArgList::addAllArgs(ArgStringList &Output,
                         ArrayRef<OptSpecifier> Ids) const {
  ArrayRef<OptSpecifier> Exclude = {};
  AddAllArgsExcept(Output, Ids, Exclude);
}

void ArgList::AddAllArgs(ArgStringList &Output, OptSpecifier Id0) const {
  for (auto *Arg : filtered(Id0)) {
    Arg->claim();
    Arg->render(*this, Output);
  }
}

void ArgList::AddAllArgValues(ArgStringList &Output, OptSpecifier Id0,
                              OptSpecifier Id1, OptSpecifier Id2) const {
  for (auto *Arg : filtered(Id0, Id1, Id2)) {
    Arg->claim();
    const auto &Values = Arg->getValues();
    Output.append(Values.begin(), Values.end());
  }
}

void ArgList::AddAllArgsTranslated(ArgStringList &Output, OptSpecifier Id0,
                                   const char *Translation,
                                   bool Joined) const {
  for (auto *Arg : filtered(Id0)) {
    Arg->claim();

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

void ArgList::ClaimAllArgs(OptSpecifier Id0) const {
  for (auto *Arg : filtered(Id0))
    Arg->claim();
}

void ArgList::ClaimAllArgs() const {
  for (auto *Arg : *this)
    if (!Arg->isClaimed())
      Arg->claim();
}

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

  return MakeArgString(LHS + RHS);
}

void ArgList::print(raw_ostream &O) const {
  for (Arg *A : *this) {
    O << "* ";
    A->print(O);
  }
}

#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD void ArgList::dump() const { print(dbgs()); }
#endif

StringRef ArgList::getSubCommand(
    ArrayRef<OptTable::SubCommand> AllSubCommands,
    std::function<void(ArrayRef<StringRef>)> HandleMultipleSubcommands,
    std::function<void(ArrayRef<StringRef>)> HandleOtherPositionals) const {

  SmallVector<StringRef, 4> SubCommands;
  SmallVector<StringRef, 4> OtherPositionals;
  for (const Arg *A : *this) {
    if (A->getOption().getKind() != Option::InputClass)
      continue;

    size_t OldSize = SubCommands.size();
    for (const OptTable::SubCommand &CMD : AllSubCommands) {
      if (StringRef(CMD.Name) == A->getValue())
        SubCommands.push_back(A->getValue());
    }

    if (SubCommands.size() == OldSize)
      OtherPositionals.push_back(A->getValue());
  }

  // Invoke callbacks if necessary.
  if (SubCommands.size() > 1) {
    HandleMultipleSubcommands(SubCommands);
    return {};
  }
  if (!OtherPositionals.empty())
    HandleOtherPositionals(OtherPositionals);

  if (SubCommands.size() == 1)
    return SubCommands.front();
  return {}; // No valid usage of subcommand found.
}

void InputArgList::releaseMemory() {
  // An InputArgList always owns its arguments.
  for (Arg *A : *this)
    delete A;
}

InputArgList::InputArgList(const char* const *ArgBegin,
                           const char* const *ArgEnd)
  : NumInputArgStrings(ArgEnd - ArgBegin) {
  ArgStrings.append(ArgBegin, ArgEnd);
}

unsigned InputArgList::MakeIndex(StringRef String0) const {
  unsigned Index = ArgStrings.size();

  // Tuck away so we have a reliable const char *.
  SynthesizedStrings.push_back(std::string(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::MakeArgStringRef(StringRef Str) const {
  return getArgString(MakeIndex(Str));
}

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

const char *DerivedArgList::MakeArgStringRef(StringRef Str) const {
  return BaseArgs.MakeArgString(Str);
}

void DerivedArgList::AddSynthesizedArg(Arg *A) {
  SynthesizedArgs.push_back(std::unique_ptr<Arg>(A));
}

Arg *DerivedArgList::MakeFlagArg(const Arg *BaseArg, const Option Opt) const {
  SynthesizedArgs.push_back(
      std::make_unique<Arg>(Opt, MakeArgString(Opt.getPrefix() + Opt.getName()),
                       BaseArgs.MakeIndex(Opt.getName()), BaseArg));
  return SynthesizedArgs.back().get();
}

Arg *DerivedArgList::MakePositionalArg(const Arg *BaseArg, const Option Opt,
                                       StringRef Value) const {
  unsigned Index = BaseArgs.MakeIndex(Value);
  SynthesizedArgs.push_back(
      std::make_unique<Arg>(Opt, MakeArgString(Opt.getPrefix() + Opt.getName()),
                       Index, BaseArgs.getArgString(Index), BaseArg));
  return SynthesizedArgs.back().get();
}

Arg *DerivedArgList::MakeSeparateArg(const Arg *BaseArg, const Option Opt,
                                     StringRef Value) const {
  unsigned Index = BaseArgs.MakeIndex(Opt.getName(), Value);
  SynthesizedArgs.push_back(
      std::make_unique<Arg>(Opt, MakeArgString(Opt.getPrefix() + Opt.getName()),
                       Index, BaseArgs.getArgString(Index + 1), BaseArg));
  return SynthesizedArgs.back().get();
}

Arg *DerivedArgList::MakeJoinedArg(const Arg *BaseArg, const Option Opt,
                                   StringRef Value) const {
  unsigned Index = BaseArgs.MakeIndex((Opt.getName() + Value).str());
  SynthesizedArgs.push_back(std::make_unique<Arg>(
      Opt, MakeArgString(Opt.getPrefix() + Opt.getName()), Index,
      BaseArgs.getArgString(Index) + Opt.getName().size(), BaseArg));
  return SynthesizedArgs.back().get();
}
