//===--- ArgList.h - Argument List Management ----------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef CLANG_DRIVER_ARGLIST_H_
#define CLANG_DRIVER_ARGLIST_H_

#include "clang/Driver/OptSpecifier.h"
#include "clang/Driver/Util.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"

#include <list>
#include <string>
#include <vector>

namespace llvm {
  class Twine;
}

namespace clang {
  class Diagnostic;

namespace driver {
  class Arg;
  class ArgList;
  class Option;

  /// arg_iterator - Iterates through arguments stored inside an ArgList.
  class arg_iterator {
    /// The current argument.
    llvm::SmallVectorImpl<Arg*>::const_iterator Current;

    /// The argument list we are iterating over.
    const ArgList &Args;

    /// Optional filters on the arguments which will be match. Most clients
    /// should never want to iterate over arguments without filters, so we won't
    /// bother to factor this into two separate iterator implementations.
    //
    // FIXME: Make efficient; the idea is to provide efficient iteration over
    // all arguments which match a particular id and then just provide an
    // iterator combinator which takes multiple iterators which can be
    // efficiently compared and returns them in order.
    OptSpecifier Id0, Id1, Id2;

    void SkipToNextArg();

  public:
    typedef Arg * const *                 value_type;
    typedef Arg * const &                 reference;
    typedef Arg * const *                 pointer;
    typedef std::forward_iterator_tag   iterator_category;
    typedef std::ptrdiff_t              difference_type;

    arg_iterator(llvm::SmallVectorImpl<Arg*>::const_iterator it,
                 const ArgList &_Args, OptSpecifier _Id0 = 0U,
                 OptSpecifier _Id1 = 0U, OptSpecifier _Id2 = 0U)
      : Current(it), Args(_Args), Id0(_Id0), Id1(_Id1), Id2(_Id2) {
      SkipToNextArg();
    }

    operator const Arg*() { return *Current; }
    reference operator*() const { return *Current; }
    pointer operator->() const { return Current; }

    arg_iterator &operator++() {
      ++Current;
      SkipToNextArg();
      return *this;
    }

    arg_iterator operator++(int) {
      arg_iterator tmp(*this);
      ++(*this);
      return tmp;
    }

    friend bool operator==(arg_iterator LHS, arg_iterator RHS) {
      return LHS.Current == RHS.Current;
    }
    friend bool operator!=(arg_iterator LHS, arg_iterator RHS) {
      return !(LHS == RHS);
    }
  };

  /// ArgList - Ordered collection of driver arguments.
  ///
  /// The ArgList class manages a list of Arg instances as well as
  /// auxiliary data and convenience methods to allow Tools to quickly
  /// check for the presence of Arg instances for a particular Option
  /// and to iterate over groups of arguments.
  class ArgList {
  private:
    ArgList(const ArgList &); // DO NOT IMPLEMENT
    void operator=(const ArgList &); // DO NOT IMPLEMENT

  public:
    typedef llvm::SmallVector<Arg*, 16> arglist_type;
    typedef arglist_type::iterator iterator;
    typedef arglist_type::const_iterator const_iterator;
    typedef arglist_type::reverse_iterator reverse_iterator;
    typedef arglist_type::const_reverse_iterator const_reverse_iterator;

  private:
    /// The internal list of arguments.
    arglist_type Args;

  protected:
    ArgList();

  public:
    virtual ~ArgList();

    /// @name Arg Access
    /// @{

    /// append - Append \arg A to the arg list.
    void append(Arg *A);

    arglist_type &getArgs() { return Args; }
    const arglist_type &getArgs() const { return Args; }

    unsigned size() const { return Args.size(); }

    /// @}
    /// @name Arg Iteration
    /// @{

    iterator begin() { return Args.begin(); }
    iterator end() { return Args.end(); }

    reverse_iterator rbegin() { return Args.rbegin(); }
    reverse_iterator rend() { return Args.rend(); }

    const_iterator begin() const { return Args.begin(); }
    const_iterator end() const { return Args.end(); }

    const_reverse_iterator rbegin() const { return Args.rbegin(); }
    const_reverse_iterator rend() const { return Args.rend(); }

    arg_iterator filtered_begin(OptSpecifier Id0 = 0U, OptSpecifier Id1 = 0U,
                                OptSpecifier Id2 = 0U) const {
      return arg_iterator(Args.begin(), *this, Id0, Id1, Id2);
    }
    arg_iterator filtered_end() const {
      return arg_iterator(Args.end(), *this);
    }

    /// @}
    /// @name Arg Access
    /// @{

    /// hasArg - Does the arg list contain any option matching \arg Id.
    ///
    /// \arg Claim Whether the argument should be claimed, if it exists.
    bool hasArgNoClaim(OptSpecifier Id) const {
      return getLastArgNoClaim(Id) != 0;
    }
    bool hasArg(OptSpecifier Id) const {
      return getLastArg(Id) != 0;
    }
    bool hasArg(OptSpecifier Id0, OptSpecifier Id1) const {
      return getLastArg(Id0, Id1) != 0;
    }
    bool hasArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2) const {
      return getLastArg(Id0, Id1, Id2) != 0;
    }

    /// getLastArg - Return the last argument matching \arg Id, or null.
    ///
    /// \arg Claim Whether the argument should be claimed, if it exists.
    Arg *getLastArgNoClaim(OptSpecifier Id) const;
    Arg *getLastArg(OptSpecifier Id) const;
    Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1) const;
    Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2) const;
    Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2,
                    OptSpecifier Id3) const;

    /// getArgString - Return the input argument string at \arg Index.
    virtual const char *getArgString(unsigned Index) const = 0;

    /// getNumInputArgStrings - Return the number of original argument strings,
    /// which are guaranteed to be the first strings in the argument string
    /// list.
    virtual unsigned getNumInputArgStrings() const = 0;

    /// @}
    /// @name Argument Lookup Utilities
    /// @{

    /// getLastArgValue - Return the value of the last argument, or a default.
    llvm::StringRef getLastArgValue(OptSpecifier Id,
                                    llvm::StringRef Default = "") const;

    /// getLastArgValue - Return the value of the last argument as an integer,
    /// or a default. Emits an error if the argument is given, but non-integral.
    int getLastArgIntValue(OptSpecifier Id, int Default,
                           Diagnostic &Diags) const;

    /// getAllArgValues - Get the values of all instances of the given argument
    /// as strings.
    std::vector<std::string> getAllArgValues(OptSpecifier Id) const;

    /// @}
    /// @name Translation Utilities
    /// @{

    /// hasFlag - Given an option \arg Pos and its negative form \arg
    /// Neg, return true if the option is present, false if the
    /// negation is present, and \arg Default if neither option is
    /// given. If both the option and its negation are present, the
    /// last one wins.
    bool hasFlag(OptSpecifier Pos, OptSpecifier Neg, bool Default=true) const;

    /// AddLastArg - Render only the last argument match \arg Id0, if
    /// present.
    void AddLastArg(ArgStringList &Output, OptSpecifier Id0) const;

    /// AddAllArgs - Render all arguments matching the given ids.
    void AddAllArgs(ArgStringList &Output, OptSpecifier Id0,
                    OptSpecifier Id1 = 0U, OptSpecifier Id2 = 0U) const;

    /// AddAllArgValues - Render the argument values of all arguments
    /// matching the given ids.
    void AddAllArgValues(ArgStringList &Output, OptSpecifier Id0,
                         OptSpecifier Id1 = 0U, OptSpecifier Id2 = 0U) const;

    /// AddAllArgsTranslated - Render all the arguments matching the
    /// given ids, but forced to separate args and using the provided
    /// name instead of the first option value.
    ///
    /// \param Joined - If true, render the argument as joined with
    /// the option specifier.
    void AddAllArgsTranslated(ArgStringList &Output, OptSpecifier Id0,
                              const char *Translation,
                              bool Joined = false) const;

    /// ClaimAllArgs - Claim all arguments which match the given
    /// option id.
    void ClaimAllArgs(OptSpecifier Id0) const;

    /// @}
    /// @name Arg Synthesis
    /// @{

    /// MakeArgString - Construct a constant string pointer whose
    /// lifetime will match that of the ArgList.
    virtual const char *MakeArgString(llvm::StringRef Str) const = 0;
    const char *MakeArgString(const char *Str) const {
      return MakeArgString(llvm::StringRef(Str));
    }
    const char *MakeArgString(std::string Str) const {
      return MakeArgString(llvm::StringRef(Str));
    }
    const char *MakeArgString(const llvm::Twine &Str) const;

    /// \brief Create an arg string for (\arg LHS + \arg RHS), reusing the
    /// string at \arg Index if possible.
    const char *GetOrMakeJoinedArgString(unsigned Index, llvm::StringRef LHS,
                                         llvm::StringRef RHS) const;

    /// @}
  };

  class InputArgList : public ArgList  {
  private:
    /// List of argument strings used by the contained Args.
    ///
    /// This is mutable since we treat the ArgList as being the list
    /// of Args, and allow routines to add new strings (to have a
    /// convenient place to store the memory) via MakeIndex.
    mutable ArgStringList ArgStrings;

    /// Strings for synthesized arguments.
    ///
    /// This is mutable since we treat the ArgList as being the list
    /// of Args, and allow routines to add new strings (to have a
    /// convenient place to store the memory) via MakeIndex.
    mutable std::list<std::string> SynthesizedStrings;

    /// The number of original input argument strings.
    unsigned NumInputArgStrings;

  public:
    InputArgList(const char **ArgBegin, const char **ArgEnd);
    ~InputArgList();

    virtual const char *getArgString(unsigned Index) const {
      return ArgStrings[Index];
    }

    virtual unsigned getNumInputArgStrings() const {
      return NumInputArgStrings;
    }

    /// @name Arg Synthesis
    /// @{

  public:
    /// MakeIndex - Get an index for the given string(s).
    unsigned MakeIndex(llvm::StringRef String0) const;
    unsigned MakeIndex(llvm::StringRef String0, llvm::StringRef String1) const;

    virtual const char *MakeArgString(llvm::StringRef Str) const;

    /// @}
  };

  /// DerivedArgList - An ordered collection of driver arguments,
  /// whose storage may be in another argument list.
  class DerivedArgList : public ArgList {
    const InputArgList &BaseArgs;

    /// The list of arguments we synthesized.
    mutable arglist_type SynthesizedArgs;

  public:
    /// Construct a new derived arg list from \arg BaseArgs.
    DerivedArgList(const InputArgList &BaseArgs);
    ~DerivedArgList();

    virtual const char *getArgString(unsigned Index) const {
      return BaseArgs.getArgString(Index);
    }

    virtual unsigned getNumInputArgStrings() const {
      return BaseArgs.getNumInputArgStrings();
    }

    const InputArgList &getBaseArgs() const {
      return BaseArgs;
    }

    /// @name Arg Synthesis
    /// @{

    /// AddSynthesizedArg - Add a argument to the list of synthesized arguments
    /// (to be freed).
    void AddSynthesizedArg(Arg *A) {
      SynthesizedArgs.push_back(A);
    }

    virtual const char *MakeArgString(llvm::StringRef Str) const;

    /// AddFlagArg - Construct a new FlagArg for the given option \arg Id and
    /// append it to the argument list.
    void AddFlagArg(const Arg *BaseArg, const Option *Opt) {
      append(MakeFlagArg(BaseArg, Opt));
    }

    /// AddPositionalArg - Construct a new Positional arg for the given option
    /// \arg Id, with the provided \arg Value and append it to the argument
    /// list.
    void AddPositionalArg(const Arg *BaseArg, const Option *Opt,
                          llvm::StringRef Value) {
      append(MakePositionalArg(BaseArg, Opt, Value));
    }


    /// AddSeparateArg - Construct a new Positional arg for the given option
    /// \arg Id, with the provided \arg Value and append it to the argument
    /// list.
    void AddSeparateArg(const Arg *BaseArg, const Option *Opt,
                        llvm::StringRef Value) {
      append(MakeSeparateArg(BaseArg, Opt, Value));
    }


    /// AddJoinedArg - Construct a new Positional arg for the given option \arg
    /// Id, with the provided \arg Value and append it to the argument list.
    void AddJoinedArg(const Arg *BaseArg, const Option *Opt,
                      llvm::StringRef Value) {
      append(MakeJoinedArg(BaseArg, Opt, Value));
    }


    /// MakeFlagArg - Construct a new FlagArg for the given option
    /// \arg Id.
    Arg *MakeFlagArg(const Arg *BaseArg, const Option *Opt) const;

    /// MakePositionalArg - Construct a new Positional arg for the
    /// given option \arg Id, with the provided \arg Value.
    Arg *MakePositionalArg(const Arg *BaseArg, const Option *Opt,
                           llvm::StringRef Value) const;

    /// MakeSeparateArg - Construct a new Positional arg for the
    /// given option \arg Id, with the provided \arg Value.
    Arg *MakeSeparateArg(const Arg *BaseArg, const Option *Opt,
                         llvm::StringRef Value) const;

    /// MakeJoinedArg - Construct a new Positional arg for the
    /// given option \arg Id, with the provided \arg Value.
    Arg *MakeJoinedArg(const Arg *BaseArg, const Option *Opt,
                       llvm::StringRef Value) const;

    /// @}
  };

} // end namespace driver
} // end namespace clang

#endif
