text: //===--- Job.h - Commands to Execute ----------------------------*- C++ -*-===//
  //
  //                     The LLVM Compiler Infrastructure
  //
  // This file is distributed under the University of Illinois Open Source
  // License. See LICENSE.TXT for details.
  //
  //===----------------------------------------------------------------------===//
  
  #ifndef LLVM_CLANG_DRIVER_JOB_H
  #define LLVM_CLANG_DRIVER_JOB_H
  
  #include "clang/Basic/LLVM.h"
  #include "llvm/ADT/ArrayRef.h"
  #include "llvm/ADT/SmallVector.h"
  #include "llvm/ADT/iterator.h"
  #include "llvm/Option/Option.h"
  #include <memory>
  
  namespace llvm {
    class raw_ostream;
  }
  
  namespace clang {
  namespace driver {
  class Action;
  class Command;
  class Tool;
  class InputInfo;
  
  // Re-export this as clang::driver::ArgStringList.
  using llvm::opt::ArgStringList;
  
  struct CrashReportInfo {
    StringRef Filename;
    StringRef VFSPath;
  
    CrashReportInfo(StringRef Filename, StringRef VFSPath)
        : Filename(Filename), VFSPath(VFSPath) {}
  };
  
  /// Command - An executable path/name and argument vector to
  /// execute.
  class Command {
    /// Source - The action which caused the creation of this job.
    const Action &Source;
  
    /// Tool - The tool which caused the creation of this job.
    const Tool &Creator;
  
    /// The executable to run.
    const char *Executable;
  
    /// The list of program arguments (not including the implicit first
    /// argument, which will be the executable).
    llvm::opt::ArgStringList Arguments;
  
    /// The list of program arguments which are inputs.
    llvm::opt::ArgStringList InputFilenames;
  
    /// Response file name, if this command is set to use one, or nullptr
    /// otherwise
    const char *ResponseFile;
  
    /// The input file list in case we need to emit a file list instead of a
    /// proper response file
    llvm::opt::ArgStringList InputFileList;
  
    /// String storage if we need to create a new argument to specify a response
    /// file
    std::string ResponseFileFlag;
  
    /// See Command::setEnvironment
    std::vector<const char *> Environment;
  
    /// When a response file is needed, we try to put most arguments in an
    /// exclusive file, while others remains as regular command line arguments.
    /// This functions fills a vector with the regular command line arguments,
    /// argv, excluding the ones passed in a response file.
    void buildArgvForResponseFile(llvm::SmallVectorImpl<const char *> &Out) const;
  
    /// Encodes an array of C strings into a single string separated by whitespace.
    /// This function will also put in quotes arguments that have whitespaces and
    /// will escape the regular backslashes (used in Windows paths) and quotes.
    /// The results are the contents of a response file, written into a raw_ostream.
    void writeResponseFile(raw_ostream &OS) const;
  
  public:
    Command(const Action &Source, const Tool &Creator, const char *Executable,
            const llvm::opt::ArgStringList &Arguments,
            ArrayRef<InputInfo> Inputs);
    // FIXME: This really shouldn't be copyable, but is currently copied in some
    // error handling in Driver::generateCompilationDiagnostics.
    Command(const Command &) = default;
    virtual ~Command() {}
  
    virtual void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote,
                       CrashReportInfo *CrashInfo = nullptr) const;
  
    virtual int Execute(ArrayRef<Optional<StringRef>> Redirects,
                        std::string *ErrMsg, bool *ExecutionFailed) const;
  
    /// getSource - Return the Action which caused the creation of this job.
    const Action &getSource() const { return Source; }
  
    /// getCreator - Return the Tool which caused the creation of this job.
    const Tool &getCreator() const { return Creator; }
  
    /// Set to pass arguments via a response file when launching the command
    void setResponseFile(const char *FileName);
  
    /// Set an input file list, necessary if we need to use a response file but
    /// the tool being called only supports input files lists.
    void setInputFileList(llvm::opt::ArgStringList List) {
      InputFileList = std::move(List);
    }
  
    /// \brief Sets the environment to be used by the new process.
    /// \param NewEnvironment An array of environment variables.
    /// \remark If the environment remains unset, then the environment
    ///         from the parent process will be used.
    void setEnvironment(llvm::ArrayRef<const char *> NewEnvironment);
  
    const char *getExecutable() const { return Executable; }
  
    const llvm::opt::ArgStringList &getArguments() const { return Arguments; }
  
    /// Print a command argument, and optionally quote it.
    static void printArg(llvm::raw_ostream &OS, StringRef Arg, bool Quote);
  };
  
  /// Like Command, but with a fallback which is executed in case
  /// the primary command crashes.
  class FallbackCommand : public Command {
  public:
    FallbackCommand(const Action &Source_, const Tool &Creator_,
                    const char *Executable_, const ArgStringList &Arguments_,
                    ArrayRef<InputInfo> Inputs,
                    std::unique_ptr<Command> Fallback_);
  
    void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote,
               CrashReportInfo *CrashInfo = nullptr) const override;
  
    int Execute(ArrayRef<Optional<StringRef>> Redirects, std::string *ErrMsg,
                bool *ExecutionFailed) const override;
  
  private:
    std::unique_ptr<Command> Fallback;
  };
  
  /// Like Command, but always pretends that the wrapped command succeeded.
  class ForceSuccessCommand : public Command {
  public:
    ForceSuccessCommand(const Action &Source_, const Tool &Creator_,
                        const char *Executable_, const ArgStringList &Arguments_,
                        ArrayRef<InputInfo> Inputs);
  
    void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote,
               CrashReportInfo *CrashInfo = nullptr) const override;
  
    int Execute(ArrayRef<Optional<StringRef>> Redirects, std::string *ErrMsg,
                bool *ExecutionFailed) const override;
  };
  
  /// JobList - A sequence of jobs to perform.
  class JobList {
  public:
    typedef SmallVector<std::unique_ptr<Command>, 4> list_type;
    typedef list_type::size_type size_type;
    typedef llvm::pointee_iterator<list_type::iterator> iterator;
    typedef llvm::pointee_iterator<list_type::const_iterator> const_iterator;
  
  private:
    list_type Jobs;
  
  public:
    void Print(llvm::raw_ostream &OS, const char *Terminator,
               bool Quote, CrashReportInfo *CrashInfo = nullptr) const;
  
    /// Add a job to the list (taking ownership).
    void addJob(std::unique_ptr<Command> J) { Jobs.push_back(std::move(J)); }
  
    /// Clear the job list.
    void clear();
  
    const list_type &getJobs() const { return Jobs; }
  
    bool empty() const { return Jobs.empty(); }
    size_type size() const { return Jobs.size(); }
    iterator begin() { return Jobs.begin(); }
    const_iterator begin() const { return Jobs.begin(); }
    iterator end() { return Jobs.end(); }
    const_iterator end() const { return Jobs.end(); }
  };
  
  } // end namespace driver
  } // end namespace clang
  
  #endif
  