//===- LLVMCConfigurationEmitter.cpp - Generate LLVMC config ----*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open
// Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This tablegen backend is responsible for emitting LLVMC configuration code.
//
//===----------------------------------------------------------------------===//

#include "LLVMCConfigurationEmitter.h"
#include "Record.h"

#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringSet.h"

#include <algorithm>
#include <cassert>
#include <functional>
#include <stdexcept>
#include <string>
#include <typeinfo>


using namespace llvm;

namespace {

//===----------------------------------------------------------------------===//
/// Typedefs

typedef std::vector<Record*> RecordVector;
typedef std::vector<const DagInit*> DagVector;
typedef std::vector<std::string> StrVector;

//===----------------------------------------------------------------------===//
/// Constants

// Indentation.
const unsigned TabWidth = 4;
const unsigned Indent1  = TabWidth*1;
const unsigned Indent2  = TabWidth*2;
const unsigned Indent3  = TabWidth*3;
const unsigned Indent4  = TabWidth*4;

// Default help string.
const char * const DefaultHelpString = "NO HELP MESSAGE PROVIDED";

// Name for the "sink" option.
const char * const SinkOptionName = "SinkOption";

//===----------------------------------------------------------------------===//
/// Helper functions

/// Id - An 'identity' function object.
struct Id {
  template<typename T0>
  void operator()(const T0&) const {
  }
  template<typename T0, typename T1>
  void operator()(const T0&, const T1&) const {
  }
  template<typename T0, typename T1, typename T2>
  void operator()(const T0&, const T1&, const T2&) const {
  }
};

int InitPtrToInt(const Init* ptr) {
  const IntInit& val = dynamic_cast<const IntInit&>(*ptr);
  return val.getValue();
}

const std::string& InitPtrToString(const Init* ptr) {
  const StringInit& val = dynamic_cast<const StringInit&>(*ptr);
  return val.getValue();
}

const ListInit& InitPtrToList(const Init* ptr) {
  const ListInit& val = dynamic_cast<const ListInit&>(*ptr);
  return val;
}

const DagInit& InitPtrToDag(const Init* ptr) {
  const DagInit& val = dynamic_cast<const DagInit&>(*ptr);
  return val;
}

const std::string GetOperatorName(const DagInit& D) {
  return D.getOperator()->getAsString();
}

/// CheckBooleanConstant - Check that the provided value is a boolean constant.
void CheckBooleanConstant(const Init* I) {
  const DefInit& val = dynamic_cast<const DefInit&>(*I);
  const std::string& str = val.getAsString();

  if (str != "true" && str != "false") {
    throw "Incorrect boolean value: '" + str +
      "': must be either 'true' or 'false'";
  }
}

// CheckNumberOfArguments - Ensure that the number of args in d is
// greater than or equal to min_arguments, otherwise throw an exception.
void CheckNumberOfArguments (const DagInit& d, unsigned minArgs) {
  if (d.getNumArgs() < minArgs)
    throw GetOperatorName(d) + ": too few arguments!";
}

// EscapeVariableName - Escape commas and other symbols not allowed
// in the C++ variable names. Makes it possible to use options named
// like "Wa," (useful for prefix options).
std::string EscapeVariableName (const std::string& Var) {
  std::string ret;
  for (unsigned i = 0; i != Var.size(); ++i) {
    char cur_char = Var[i];
    if (cur_char == ',') {
      ret += "_comma_";
    }
    else if (cur_char == '+') {
      ret += "_plus_";
    }
    else if (cur_char == '-') {
      ret += "_dash_";
    }
    else {
      ret.push_back(cur_char);
    }
  }
  return ret;
}

/// EscapeQuotes - Replace '"' with '\"'.
std::string EscapeQuotes (const std::string& Var) {
  std::string ret;
  for (unsigned i = 0; i != Var.size(); ++i) {
    char cur_char = Var[i];
    if (cur_char == '"') {
      ret += "\\\"";
    }
    else {
      ret.push_back(cur_char);
    }
  }
  return ret;
}

/// OneOf - Does the input string contain this character?
bool OneOf(const char* lst, char c) {
  while (*lst) {
    if (*lst++ == c)
      return true;
  }
  return false;
}

template <class I, class S>
void CheckedIncrement(I& P, I E, S ErrorString) {
  ++P;
  if (P == E)
    throw ErrorString;
}

//===----------------------------------------------------------------------===//
/// Back-end specific code


/// OptionType - One of six different option types. See the
/// documentation for detailed description of differences.
namespace OptionType {

  enum OptionType { Alias, Switch, SwitchList,
                    Parameter, ParameterList, Prefix, PrefixList };

  bool IsAlias(OptionType t) {
    return (t == Alias);
  }

  bool IsList (OptionType t) {
    return (t == SwitchList || t == ParameterList || t == PrefixList);
  }

  bool IsSwitch (OptionType t) {
    return (t == Switch);
  }

  bool IsSwitchList (OptionType t) {
    return (t == SwitchList);
  }

  bool IsParameter (OptionType t) {
    return (t == Parameter || t == Prefix);
  }

}

OptionType::OptionType stringToOptionType(const std::string& T) {
  if (T == "alias_option")
    return OptionType::Alias;
  else if (T == "switch_option")
    return OptionType::Switch;
  else if (T == "switch_list_option")
    return OptionType::SwitchList;
  else if (T == "parameter_option")
    return OptionType::Parameter;
  else if (T == "parameter_list_option")
    return OptionType::ParameterList;
  else if (T == "prefix_option")
    return OptionType::Prefix;
  else if (T == "prefix_list_option")
    return OptionType::PrefixList;
  else
    throw "Unknown option type: " + T + '!';
}

namespace OptionDescriptionFlags {
  enum OptionDescriptionFlags { Required = 0x1, Hidden = 0x2,
                                ReallyHidden = 0x4, OneOrMore = 0x8,
                                Optional = 0x10, CommaSeparated = 0x20,
                                ForwardNotSplit = 0x40, ZeroOrMore = 0x80 };
}

/// OptionDescription - Represents data contained in a single
/// OptionList entry.
struct OptionDescription {
  OptionType::OptionType Type;
  std::string Name;
  unsigned Flags;
  std::string Help;
  unsigned MultiVal;
  Init* InitVal;

  OptionDescription(OptionType::OptionType t = OptionType::Switch,
                    const std::string& n = "",
                    const std::string& h = DefaultHelpString)
    : Type(t), Name(n), Flags(0x0), Help(h), MultiVal(1), InitVal(0)
  {}

  /// GenTypeDeclaration - Returns the C++ variable type of this
  /// option.
  const char* GenTypeDeclaration() const;

  /// GenVariableName - Returns the variable name used in the
  /// generated C++ code.
  std::string GenVariableName() const
  { return "autogenerated::" + GenOptionType() + EscapeVariableName(Name); }

  /// GenPlainVariableName - Returns the variable name without the namespace
  /// prefix.
  std::string GenPlainVariableName() const
  { return GenOptionType() + EscapeVariableName(Name); }

  /// Merge - Merge two option descriptions.
  void Merge (const OptionDescription& other);

  /// CheckConsistency - Check that the flags are consistent.
  void CheckConsistency() const;

  // Misc convenient getters/setters.

  bool isAlias() const;

  bool isMultiVal() const;

  bool isCommaSeparated() const;
  void setCommaSeparated();

  bool isForwardNotSplit() const;
  void setForwardNotSplit();

  bool isRequired() const;
  void setRequired();

  bool isOneOrMore() const;
  void setOneOrMore();

  bool isZeroOrMore() const;
  void setZeroOrMore();

  bool isOptional() const;
  void setOptional();

  bool isHidden() const;
  void setHidden();

  bool isReallyHidden() const;
  void setReallyHidden();

  bool isSwitch() const
  { return OptionType::IsSwitch(this->Type); }

  bool isSwitchList() const
  { return OptionType::IsSwitchList(this->Type); }

  bool isParameter() const
  { return OptionType::IsParameter(this->Type); }

  bool isList() const
  { return OptionType::IsList(this->Type); }

  bool isParameterList() const
  { return (OptionType::IsList(this->Type)
            && !OptionType::IsSwitchList(this->Type)); }

private:

  // GenOptionType - Helper function used by GenVariableName().
  std::string GenOptionType() const;
};

void OptionDescription::CheckConsistency() const {
  unsigned i = 0;

  i += this->isRequired();
  i += this->isOptional();
  i += this->isOneOrMore();
  i += this->isZeroOrMore();

  if (i > 1) {
    throw "Only one of (required), (optional), (one_or_more) or "
      "(zero_or_more) properties is allowed!";
  }
}

void OptionDescription::Merge (const OptionDescription& other)
{
  if (other.Type != Type)
    throw "Conflicting definitions for the option " + Name + "!";

  if (Help == other.Help || Help == DefaultHelpString)
    Help = other.Help;
  else if (other.Help != DefaultHelpString) {
    llvm::errs() << "Warning: several different help strings"
      " defined for option " + Name + "\n";
  }

  Flags |= other.Flags;
}

bool OptionDescription::isAlias() const {
  return OptionType::IsAlias(this->Type);
}

bool OptionDescription::isMultiVal() const {
  return MultiVal > 1;
}

bool OptionDescription::isCommaSeparated() const {
  return Flags & OptionDescriptionFlags::CommaSeparated;
}
void OptionDescription::setCommaSeparated() {
  Flags |= OptionDescriptionFlags::CommaSeparated;
}

bool OptionDescription::isForwardNotSplit() const {
  return Flags & OptionDescriptionFlags::ForwardNotSplit;
}
void OptionDescription::setForwardNotSplit() {
  Flags |= OptionDescriptionFlags::ForwardNotSplit;
}

bool OptionDescription::isRequired() const {
  return Flags & OptionDescriptionFlags::Required;
}
void OptionDescription::setRequired() {
  Flags |= OptionDescriptionFlags::Required;
}

bool OptionDescription::isOneOrMore() const {
  return Flags & OptionDescriptionFlags::OneOrMore;
}
void OptionDescription::setOneOrMore() {
  Flags |= OptionDescriptionFlags::OneOrMore;
}

bool OptionDescription::isZeroOrMore() const {
  return Flags & OptionDescriptionFlags::ZeroOrMore;
}
void OptionDescription::setZeroOrMore() {
  Flags |= OptionDescriptionFlags::ZeroOrMore;
}

bool OptionDescription::isOptional() const {
  return Flags & OptionDescriptionFlags::Optional;
}
void OptionDescription::setOptional() {
  Flags |= OptionDescriptionFlags::Optional;
}

bool OptionDescription::isHidden() const {
  return Flags & OptionDescriptionFlags::Hidden;
}
void OptionDescription::setHidden() {
  Flags |= OptionDescriptionFlags::Hidden;
}

bool OptionDescription::isReallyHidden() const {
  return Flags & OptionDescriptionFlags::ReallyHidden;
}
void OptionDescription::setReallyHidden() {
  Flags |= OptionDescriptionFlags::ReallyHidden;
}

const char* OptionDescription::GenTypeDeclaration() const {
  switch (Type) {
  case OptionType::Alias:
    return "cl::alias";
  case OptionType::PrefixList:
  case OptionType::ParameterList:
    return "cl::list<std::string>";
  case OptionType::Switch:
    return "cl::opt<bool>";
  case OptionType::SwitchList:
    return "cl::list<bool>";
  case OptionType::Parameter:
  case OptionType::Prefix:
  default:
    return "cl::opt<std::string>";
  }
}

std::string OptionDescription::GenOptionType() const {
  switch (Type) {
  case OptionType::Alias:
    return "Alias_";
  case OptionType::PrefixList:
  case OptionType::ParameterList:
    return "List_";
  case OptionType::Switch:
    return "Switch_";
  case OptionType::SwitchList:
    return "SwitchList_";
  case OptionType::Prefix:
  case OptionType::Parameter:
  default:
    return "Parameter_";
  }
}

/// OptionDescriptions - An OptionDescription array plus some helper
/// functions.
class OptionDescriptions {
  typedef StringMap<OptionDescription> container_type;

  /// Descriptions - A list of OptionDescriptions.
  container_type Descriptions;

public:
  /// FindOption - exception-throwing wrapper for find().
  const OptionDescription& FindOption(const std::string& OptName) const;

  // Wrappers for FindOption that throw an exception in case the option has a
  // wrong type.
  const OptionDescription& FindSwitch(const std::string& OptName) const;
  const OptionDescription& FindParameter(const std::string& OptName) const;
  const OptionDescription& FindParameterList(const std::string& OptName) const;
  const OptionDescription&
  FindListOrParameter(const std::string& OptName) const;
  const OptionDescription&
  FindParameterListOrParameter(const std::string& OptName) const;

  /// insertDescription - Insert new OptionDescription into
  /// OptionDescriptions list
  void InsertDescription (const OptionDescription& o);

  // Support for STL-style iteration
  typedef container_type::const_iterator const_iterator;
  const_iterator begin() const { return Descriptions.begin(); }
  const_iterator end() const { return Descriptions.end(); }
};

const OptionDescription&
OptionDescriptions::FindOption(const std::string& OptName) const {
  const_iterator I = Descriptions.find(OptName);
  if (I != Descriptions.end())
    return I->second;
  else
    throw OptName + ": no such option!";
}

const OptionDescription&
OptionDescriptions::FindSwitch(const std::string& OptName) const {
  const OptionDescription& OptDesc = this->FindOption(OptName);
  if (!OptDesc.isSwitch())
    throw OptName + ": incorrect option type - should be a switch!";
  return OptDesc;
}

const OptionDescription&
OptionDescriptions::FindParameterList(const std::string& OptName) const {
  const OptionDescription& OptDesc = this->FindOption(OptName);
  if (!OptDesc.isList() || OptDesc.isSwitchList())
    throw OptName + ": incorrect option type - should be a parameter list!";
  return OptDesc;
}

const OptionDescription&
OptionDescriptions::FindParameter(const std::string& OptName) const {
  const OptionDescription& OptDesc = this->FindOption(OptName);
  if (!OptDesc.isParameter())
    throw OptName + ": incorrect option type - should be a parameter!";
  return OptDesc;
}

const OptionDescription&
OptionDescriptions::FindListOrParameter(const std::string& OptName) const {
  const OptionDescription& OptDesc = this->FindOption(OptName);
  if (!OptDesc.isList() && !OptDesc.isParameter())
    throw OptName
      + ": incorrect option type - should be a list or parameter!";
  return OptDesc;
}

const OptionDescription&
OptionDescriptions::FindParameterListOrParameter
(const std::string& OptName) const {
  const OptionDescription& OptDesc = this->FindOption(OptName);
  if ((!OptDesc.isList() && !OptDesc.isParameter()) || OptDesc.isSwitchList())
    throw OptName
      + ": incorrect option type - should be a parameter list or parameter!";
  return OptDesc;
}

void OptionDescriptions::InsertDescription (const OptionDescription& o) {
  container_type::iterator I = Descriptions.find(o.Name);
  if (I != Descriptions.end()) {
    OptionDescription& D = I->second;
    D.Merge(o);
  }
  else {
    Descriptions[o.Name] = o;
  }
}

/// HandlerTable - A base class for function objects implemented as
/// 'tables of handlers'.
template <typename Handler>
class HandlerTable {
protected:
  // Implementation details.

  /// HandlerMap - A map from property names to property handlers
  typedef StringMap<Handler> HandlerMap;

  static HandlerMap Handlers_;
  static bool staticMembersInitialized_;

public:

  Handler GetHandler (const std::string& HandlerName) const {
    typename HandlerMap::iterator method = Handlers_.find(HandlerName);

    if (method != Handlers_.end()) {
      Handler h = method->second;
      return h;
    }
    else {
      throw "No handler found for property " + HandlerName + "!";
    }
  }

  void AddHandler(const char* Property, Handler H) {
    Handlers_[Property] = H;
  }

};

template <class Handler, class FunctionObject>
Handler GetHandler(FunctionObject* Obj, const DagInit& Dag) {
  const std::string& HandlerName = GetOperatorName(Dag);
  return Obj->GetHandler(HandlerName);
}

template <class FunctionObject>
void InvokeDagInitHandler(FunctionObject* Obj, Init* I) {
  typedef void (FunctionObject::*Handler) (const DagInit&);

  const DagInit& Dag = InitPtrToDag(I);
  Handler h = GetHandler<Handler>(Obj, Dag);

  ((Obj)->*(h))(Dag);
}

template <class FunctionObject>
void InvokeDagInitHandler(const FunctionObject* const Obj,
                          const Init* I, unsigned IndentLevel, raw_ostream& O)
{
  typedef void (FunctionObject::*Handler)
    (const DagInit&, unsigned IndentLevel, raw_ostream& O) const;

  const DagInit& Dag = InitPtrToDag(I);
  Handler h = GetHandler<Handler>(Obj, Dag);

  ((Obj)->*(h))(Dag, IndentLevel, O);
}

template <typename H>
typename HandlerTable<H>::HandlerMap HandlerTable<H>::Handlers_;

template <typename H>
bool HandlerTable<H>::staticMembersInitialized_ = false;


/// CollectOptionProperties - Function object for iterating over an
/// option property list.
class CollectOptionProperties;
typedef void (CollectOptionProperties::* CollectOptionPropertiesHandler)
(const DagInit&);

class CollectOptionProperties
: public HandlerTable<CollectOptionPropertiesHandler>
{
private:

  /// optDescs_ - OptionDescriptions table. This is where the
  /// information is stored.
  OptionDescription& optDesc_;

public:

  explicit CollectOptionProperties(OptionDescription& OD)
    : optDesc_(OD)
  {
    if (!staticMembersInitialized_) {
      AddHandler("help", &CollectOptionProperties::onHelp);
      AddHandler("hidden", &CollectOptionProperties::onHidden);
      AddHandler("init", &CollectOptionProperties::onInit);
      AddHandler("multi_val", &CollectOptionProperties::onMultiVal);
      AddHandler("one_or_more", &CollectOptionProperties::onOneOrMore);
      AddHandler("zero_or_more", &CollectOptionProperties::onZeroOrMore);
      AddHandler("really_hidden", &CollectOptionProperties::onReallyHidden);
      AddHandler("required", &CollectOptionProperties::onRequired);
      AddHandler("optional", &CollectOptionProperties::onOptional);
      AddHandler("comma_separated", &CollectOptionProperties::onCommaSeparated);
      AddHandler("forward_not_split",
                 &CollectOptionProperties::onForwardNotSplit);

      staticMembersInitialized_ = true;
    }
  }

  /// operator() - Just forwards to the corresponding property
  /// handler.
  void operator() (Init* I) {
    InvokeDagInitHandler(this, I);
  }

private:

  /// Option property handlers --
  /// Methods that handle option properties such as (help) or (hidden).

  void onHelp (const DagInit& d) {
    CheckNumberOfArguments(d, 1);
    optDesc_.Help = EscapeQuotes(InitPtrToString(d.getArg(0)));
  }

  void onHidden (const DagInit& d) {
    CheckNumberOfArguments(d, 0);
    optDesc_.setHidden();
  }

  void onReallyHidden (const DagInit& d) {
    CheckNumberOfArguments(d, 0);
    optDesc_.setReallyHidden();
  }

  void onCommaSeparated (const DagInit& d) {
    CheckNumberOfArguments(d, 0);
    if (!optDesc_.isParameterList())
      throw "'comma_separated' is valid only on parameter list options!";
    optDesc_.setCommaSeparated();
  }

  void onForwardNotSplit (const DagInit& d) {
    CheckNumberOfArguments(d, 0);
    if (!optDesc_.isParameter())
      throw "'forward_not_split' is valid only for parameter options!";
    optDesc_.setForwardNotSplit();
  }

  void onRequired (const DagInit& d) {
    CheckNumberOfArguments(d, 0);

    optDesc_.setRequired();
    optDesc_.CheckConsistency();
  }

  void onInit (const DagInit& d) {
    CheckNumberOfArguments(d, 1);
    Init* i = d.getArg(0);
    const std::string& str = i->getAsString();

    bool correct = optDesc_.isParameter() && dynamic_cast<StringInit*>(i);
    correct |= (optDesc_.isSwitch() && (str == "true" || str == "false"));

    if (!correct)
      throw "Incorrect usage of the 'init' option property!";

    optDesc_.InitVal = i;
  }

  void onOneOrMore (const DagInit& d) {
    CheckNumberOfArguments(d, 0);

    optDesc_.setOneOrMore();
    optDesc_.CheckConsistency();
  }

  void onZeroOrMore (const DagInit& d) {
    CheckNumberOfArguments(d, 0);

    if (optDesc_.isList())
      llvm::errs() << "Warning: specifying the 'zero_or_more' property "
        "on a list option has no effect.\n";

    optDesc_.setZeroOrMore();
    optDesc_.CheckConsistency();
  }

  void onOptional (const DagInit& d) {
    CheckNumberOfArguments(d, 0);

    if (!optDesc_.isList())
      llvm::errs() << "Warning: specifying the 'optional' property"
        "on a non-list option has no effect.\n";

    optDesc_.setOptional();
    optDesc_.CheckConsistency();
  }

  void onMultiVal (const DagInit& d) {
    CheckNumberOfArguments(d, 1);
    int val = InitPtrToInt(d.getArg(0));
    if (val < 2)
      throw "Error in the 'multi_val' property: "
        "the value must be greater than 1!";
    if (!optDesc_.isParameterList())
      throw "The multi_val property is valid only on list options!";
    optDesc_.MultiVal = val;
  }

};

/// AddOption - A function object that is applied to every option
/// description. Used by CollectOptionDescriptions.
class AddOption {
private:
  OptionDescriptions& OptDescs_;

public:
  explicit AddOption(OptionDescriptions& OD) : OptDescs_(OD)
  {}

  void operator()(const Init* i) {
    const DagInit& d = InitPtrToDag(i);
    CheckNumberOfArguments(d, 1);

    const OptionType::OptionType Type =
      stringToOptionType(GetOperatorName(d));
    const std::string& Name = InitPtrToString(d.getArg(0));

    OptionDescription OD(Type, Name);

    CheckNumberOfArguments(d, 2);

    // Alias option store the aliased option name in the 'Help' field and do not
    // have any properties.
    if (OD.isAlias()) {
      OD.Help = InitPtrToString(d.getArg(1));
    }
    else {
      processOptionProperties(d, OD);
    }

    // Switch options are ZeroOrMore by default.
    if (OD.isSwitch()) {
      if (!(OD.isOptional() || OD.isOneOrMore() || OD.isRequired()))
        OD.setZeroOrMore();
    }

    OptDescs_.InsertDescription(OD);
  }

private:
  /// processOptionProperties - Go through the list of option
  /// properties and call a corresponding handler for each.
  static void processOptionProperties (const DagInit& d, OptionDescription& o) {
    CheckNumberOfArguments(d, 2);
    DagInit::const_arg_iterator B = d.arg_begin();
    // Skip the first argument: it's always the option name.
    ++B;
    std::for_each(B, d.arg_end(), CollectOptionProperties(o));
  }

};

/// CollectOptionDescriptions - Collects option properties from all
/// OptionLists.
void CollectOptionDescriptions (const RecordVector& V,
                                OptionDescriptions& OptDescs)
{
  // For every OptionList:
  for (RecordVector::const_iterator B = V.begin(), E = V.end(); B!=E; ++B)
  {
    // Throws an exception if the value does not exist.
    ListInit* PropList = (*B)->getValueAsListInit("options");

    // For every option description in this list: invoke AddOption.
    std::for_each(PropList->begin(), PropList->end(), AddOption(OptDescs));
  }
}

// Tool information record

namespace ToolFlags {
  enum ToolFlags { Join = 0x1, Sink = 0x2 };
}

struct ToolDescription : public RefCountedBase<ToolDescription> {
  std::string Name;
  Init* CmdLine;
  Init* Actions;
  StrVector InLanguage;
  std::string InFileOption;
  std::string OutFileOption;
  StrVector OutLanguage;
  std::string OutputSuffix;
  unsigned Flags;
  const Init* OnEmpty;

  // Various boolean properties
  void setSink()      { Flags |= ToolFlags::Sink; }
  bool isSink() const { return Flags & ToolFlags::Sink; }
  void setJoin()      { Flags |= ToolFlags::Join; }
  bool isJoin() const { return Flags & ToolFlags::Join; }

  // Default ctor here is needed because StringMap can only store
  // DefaultConstructible objects
  ToolDescription (const std::string &n = "")
    : Name(n), CmdLine(0), Actions(0), OutFileOption("-o"),
      Flags(0), OnEmpty(0)
  {}
};

/// ToolDescriptions - A list of Tool information records.
typedef std::vector<IntrusiveRefCntPtr<ToolDescription> > ToolDescriptions;


/// CollectToolProperties - Function object for iterating over a list of
/// tool property records.

class CollectToolProperties;
typedef void (CollectToolProperties::* CollectToolPropertiesHandler)
(const DagInit&);

class CollectToolProperties : public HandlerTable<CollectToolPropertiesHandler>
{
private:

  /// toolDesc_ - Properties of the current Tool. This is where the
  /// information is stored.
  ToolDescription& toolDesc_;

public:

  explicit CollectToolProperties (ToolDescription& d)
    : toolDesc_(d)
  {
    if (!staticMembersInitialized_) {

      AddHandler("actions", &CollectToolProperties::onActions);
      AddHandler("command", &CollectToolProperties::onCommand);
      AddHandler("in_language", &CollectToolProperties::onInLanguage);
      AddHandler("join", &CollectToolProperties::onJoin);
      AddHandler("out_language", &CollectToolProperties::onOutLanguage);

      AddHandler("out_file_option", &CollectToolProperties::onOutFileOption);
      AddHandler("in_file_option", &CollectToolProperties::onInFileOption);

      AddHandler("output_suffix", &CollectToolProperties::onOutputSuffix);
      AddHandler("sink", &CollectToolProperties::onSink);
      AddHandler("works_on_empty", &CollectToolProperties::onWorksOnEmpty);

      staticMembersInitialized_ = true;
    }
  }

  void operator() (Init* I) {
    InvokeDagInitHandler(this, I);
  }

private:

  /// Property handlers --
  /// Functions that extract information about tool properties from
  /// DAG representation.

  void onActions (const DagInit& d) {
    CheckNumberOfArguments(d, 1);
    Init* Case = d.getArg(0);
    if (typeid(*Case) != typeid(DagInit) ||
        GetOperatorName(static_cast<DagInit&>(*Case)) != "case")
      throw "The argument to (actions) should be a 'case' construct!";
    toolDesc_.Actions = Case;
  }

  void onCommand (const DagInit& d) {
    CheckNumberOfArguments(d, 1);
    toolDesc_.CmdLine = d.getArg(0);
  }

  /// onInOutLanguage - Common implementation of on{In,Out}Language().
  void onInOutLanguage (const DagInit& d, StrVector& OutVec) {
    CheckNumberOfArguments(d, 1);

    // Copy strings to the output vector.
    for (unsigned i = 0, NumArgs = d.getNumArgs(); i < NumArgs; ++i) {
      OutVec.push_back(InitPtrToString(d.getArg(i)));
    }

    // Remove duplicates.
    std::sort(OutVec.begin(), OutVec.end());
    StrVector::iterator newE = std::unique(OutVec.begin(), OutVec.end());
    OutVec.erase(newE, OutVec.end());
  }


  void onInLanguage (const DagInit& d) {
    this->onInOutLanguage(d, toolDesc_.InLanguage);
  }

  void onJoin (const DagInit& d) {
    CheckNumberOfArguments(d, 0);
    toolDesc_.setJoin();
  }

  void onOutLanguage (const DagInit& d) {
    this->onInOutLanguage(d, toolDesc_.OutLanguage);
  }

  void onOutFileOption (const DagInit& d) {
    CheckNumberOfArguments(d, 1);
    toolDesc_.OutFileOption = InitPtrToString(d.getArg(0));
  }

  void onInFileOption (const DagInit& d) {
    CheckNumberOfArguments(d, 1);
    toolDesc_.InFileOption = InitPtrToString(d.getArg(0));
  }

  void onOutputSuffix (const DagInit& d) {
    CheckNumberOfArguments(d, 1);
    toolDesc_.OutputSuffix = InitPtrToString(d.getArg(0));
  }

  void onSink (const DagInit& d) {
    CheckNumberOfArguments(d, 0);
    toolDesc_.setSink();
  }

  void onWorksOnEmpty (const DagInit& d) {
    toolDesc_.OnEmpty = d.getArg(0);
  }

};

/// CollectToolDescriptions - Gather information about tool properties
/// from the parsed TableGen data (basically a wrapper for the
/// CollectToolProperties function object).
void CollectToolDescriptions (const RecordVector& Tools,
                              ToolDescriptions& ToolDescs)
{
  // Iterate over a properties list of every Tool definition
  for (RecordVector::const_iterator B = Tools.begin(),
         E = Tools.end(); B!=E; ++B) {
    const Record* T = *B;
    // Throws an exception if the value does not exist.
    ListInit* PropList = T->getValueAsListInit("properties");

    IntrusiveRefCntPtr<ToolDescription>
      ToolDesc(new ToolDescription(T->getName()));

    std::for_each(PropList->begin(), PropList->end(),
                  CollectToolProperties(*ToolDesc));
    ToolDescs.push_back(ToolDesc);
  }
}

/// FillInEdgeVector - Merge all compilation graph definitions into
/// one single edge list.
void FillInEdgeVector(const RecordVector& CompilationGraphs,
                      DagVector& Out) {
  for (RecordVector::const_iterator B = CompilationGraphs.begin(),
         E = CompilationGraphs.end(); B != E; ++B) {
    const ListInit* Edges = (*B)->getValueAsListInit("edges");

    for (ListInit::const_iterator B = Edges->begin(),
           E = Edges->end(); B != E; ++B) {
      Out.push_back(&InitPtrToDag(*B));
    }
  }
}

/// NotInGraph - Helper function object for FilterNotInGraph.
struct NotInGraph {
private:
  const llvm::StringSet<>& ToolsInGraph_;

public:
  NotInGraph(const llvm::StringSet<>& ToolsInGraph)
  : ToolsInGraph_(ToolsInGraph)
  {}

  bool operator()(const IntrusiveRefCntPtr<ToolDescription>& x) {
    return (ToolsInGraph_.count(x->Name) == 0);
  }
};

/// FilterNotInGraph - Filter out from ToolDescs all Tools not
/// mentioned in the compilation graph definition.
void FilterNotInGraph (const DagVector& EdgeVector,
                       ToolDescriptions& ToolDescs) {

  // List all tools mentioned in the graph.
  llvm::StringSet<> ToolsInGraph;

  for (DagVector::const_iterator B = EdgeVector.begin(),
         E = EdgeVector.end(); B != E; ++B) {

    const DagInit* Edge = *B;
    const std::string& NodeA = InitPtrToString(Edge->getArg(0));
    const std::string& NodeB = InitPtrToString(Edge->getArg(1));

    if (NodeA != "root")
      ToolsInGraph.insert(NodeA);
    ToolsInGraph.insert(NodeB);
  }

  // Filter ToolPropertiesList.
  ToolDescriptions::iterator new_end =
    std::remove_if(ToolDescs.begin(), ToolDescs.end(),
                   NotInGraph(ToolsInGraph));
  ToolDescs.erase(new_end, ToolDescs.end());
}

/// FillInToolToLang - Fills in two tables that map tool names to
/// input & output language names.  Helper function used by TypecheckGraph().
void FillInToolToLang (const ToolDescriptions& ToolDescs,
                       StringMap<StringSet<> >& ToolToInLang,
                       StringMap<StringSet<> >& ToolToOutLang) {
  for (ToolDescriptions::const_iterator B = ToolDescs.begin(),
         E = ToolDescs.end(); B != E; ++B) {
    const ToolDescription& D = *(*B);
    for (StrVector::const_iterator B = D.InLanguage.begin(),
           E = D.InLanguage.end(); B != E; ++B)
      ToolToInLang[D.Name].insert(*B);
    for (StrVector::const_iterator B = D.OutLanguage.begin(),
           E = D.OutLanguage.end(); B != E; ++B)
      ToolToOutLang[D.Name].insert(*B);
  }
}

/// Intersect - Is set intersection non-empty?
bool Intersect (const StringSet<>& S1, const StringSet<>& S2) {
  for (StringSet<>::const_iterator B = S1.begin(), E = S1.end(); B != E; ++B) {
    if (S2.count(B->first()) != 0)
      return true;
  }
  return false;
}

/// TypecheckGraph - Check that names for output and input languages
/// on all edges do match.
void TypecheckGraph (const DagVector& EdgeVector,
                     const ToolDescriptions& ToolDescs) {
  StringMap<StringSet<> > ToolToInLang;
  StringMap<StringSet<> > ToolToOutLang;

  FillInToolToLang(ToolDescs, ToolToInLang, ToolToOutLang);

  for (DagVector::const_iterator B = EdgeVector.begin(),
         E = EdgeVector.end(); B != E; ++B) {
    const DagInit* Edge = *B;
    const std::string& NodeA = InitPtrToString(Edge->getArg(0));
    const std::string& NodeB = InitPtrToString(Edge->getArg(1));
    StringMap<StringSet<> >::iterator IA = ToolToOutLang.find(NodeA);
    StringMap<StringSet<> >::iterator IB = ToolToInLang.find(NodeB);

    if (NodeB == "root")
      throw "Edges back to the root are not allowed!";

    if (NodeA != "root") {
      if (IA == ToolToOutLang.end())
        throw NodeA + ": no output language defined!";
      if (IB == ToolToInLang.end())
        throw NodeB + ": no input language defined!";

      if (!Intersect(IA->second, IB->second)) {
        throw "Edge " + NodeA + "->" + NodeB
          + ": output->input language mismatch";
      }
    }
  }
}

/// WalkCase - Walks the 'case' expression DAG and invokes
/// TestCallback on every test, and StatementCallback on every
/// statement. Handles 'case' nesting, but not the 'and' and 'or'
/// combinators (that is, they are passed directly to TestCallback).
/// TestCallback must have type 'void TestCallback(const DagInit*, unsigned
/// IndentLevel, bool FirstTest)'.
/// StatementCallback must have type 'void StatementCallback(const Init*,
/// unsigned IndentLevel)'.
template <typename F1, typename F2>
void WalkCase(const Init* Case, F1 TestCallback, F2 StatementCallback,
              unsigned IndentLevel = 0)
{
  const DagInit& d = InitPtrToDag(Case);

  // Error checks.
  if (GetOperatorName(d) != "case")
    throw "WalkCase should be invoked only on 'case' expressions!";

  if (d.getNumArgs() < 2)
    throw "There should be at least one clause in the 'case' expression:\n"
      + d.getAsString();

  // Main loop.
  bool even = false;
  const unsigned numArgs = d.getNumArgs();
  unsigned i = 1;
  for (DagInit::const_arg_iterator B = d.arg_begin(), E = d.arg_end();
       B != E; ++B) {
    Init* arg = *B;

    if (!even)
    {
      // Handle test.
      const DagInit& Test = InitPtrToDag(arg);

      if (GetOperatorName(Test) == "default" && (i+1 != numArgs))
        throw "The 'default' clause should be the last in the "
          "'case' construct!";
      if (i == numArgs)
        throw "Case construct handler: no corresponding action "
          "found for the test " + Test.getAsString() + '!';

      TestCallback(Test, IndentLevel, (i == 1));
    }
    else
    {
      if (dynamic_cast<DagInit*>(arg)
          && GetOperatorName(static_cast<DagInit&>(*arg)) == "case") {
        // Nested 'case'.
        WalkCase(arg, TestCallback, StatementCallback, IndentLevel + Indent1);
      }

      // Handle statement.
      StatementCallback(arg, IndentLevel);
    }

    ++i;
    even = !even;
  }
}

/// ExtractOptionNames - A helper function object used by
/// CheckForSuperfluousOptions() to walk the 'case' DAG.
class ExtractOptionNames {
  llvm::StringSet<>& OptionNames_;

  void processDag(const Init* Statement) {
    const DagInit& Stmt = InitPtrToDag(Statement);
    const std::string& ActionName = GetOperatorName(Stmt);
    if (ActionName == "forward" || ActionName == "forward_as" ||
        ActionName == "forward_value" ||
        ActionName == "forward_transformed_value" ||
        ActionName == "parameter_equals" || ActionName == "element_in_list") {
      CheckNumberOfArguments(Stmt, 1);

      Init* Arg = Stmt.getArg(0);
      if (typeid(*Arg) == typeid(StringInit))
        OptionNames_.insert(InitPtrToString(Arg));
    }
    else if (ActionName == "any_switch_on" || ActionName == "switch_on" ||
             ActionName == "any_not_empty" || ActionName == "any_empty" ||
             ActionName == "not_empty" || ActionName == "empty") {
      for (unsigned i = 0, NumArgs = Stmt.getNumArgs(); i < NumArgs; ++i) {
        Init* Arg = Stmt.getArg(i);
        if (typeid(*Arg) == typeid(StringInit))
          OptionNames_.insert(InitPtrToString(Arg));
      }
    }
    else if (ActionName == "and" || ActionName == "or" || ActionName == "not") {
      for (unsigned i = 0, NumArgs = Stmt.getNumArgs(); i < NumArgs; ++i) {
        this->processDag(Stmt.getArg(i));
      }
    }
  }

public:
  ExtractOptionNames(llvm::StringSet<>& OptionNames) : OptionNames_(OptionNames)
  {}

  void operator()(const Init* Statement) {
    // Statement is either a dag, or a list of dags.
    if (typeid(*Statement) == typeid(ListInit)) {
      const ListInit& DagList = *static_cast<const ListInit*>(Statement);
      for (ListInit::const_iterator B = DagList.begin(), E = DagList.end();
           B != E; ++B)
        this->processDag(*B);
    }
    else {
      this->processDag(Statement);
    }
  }

  void operator()(const DagInit& Test, unsigned, bool) {
    this->operator()(&Test);
  }
  void operator()(const Init* Statement, unsigned) {
    this->operator()(Statement);
  }
};

/// IsOptionalEdge - Validate that the 'optional_edge' has proper structure.
bool IsOptionalEdge (const DagInit& Edg) {
  return (GetOperatorName(Edg) == "optional_edge") && (Edg.getNumArgs() > 2);
}

/// CheckForSuperfluousOptions - Check that there are no side
/// effect-free options (specified only in the OptionList). Otherwise,
/// output a warning.
void CheckForSuperfluousOptions (const DagVector& EdgeVector,
                                 const ToolDescriptions& ToolDescs,
                                 const OptionDescriptions& OptDescs) {
  llvm::StringSet<> nonSuperfluousOptions;

  // Add all options mentioned in the ToolDesc.Actions to the set of
  // non-superfluous options.
  for (ToolDescriptions::const_iterator B = ToolDescs.begin(),
         E = ToolDescs.end(); B != E; ++B) {
    const ToolDescription& TD = *(*B);
    ExtractOptionNames Callback(nonSuperfluousOptions);
    if (TD.Actions)
      WalkCase(TD.Actions, Callback, Callback);
  }

  // Add all options mentioned in the 'case' clauses of the
  // OptionalEdges of the compilation graph to the set of
  // non-superfluous options.
  for (DagVector::const_iterator B = EdgeVector.begin(),
         E = EdgeVector.end(); B != E; ++B) {
    const DagInit& Edge = **B;
    if (IsOptionalEdge(Edge)) {
      const DagInit& Weight = InitPtrToDag(Edge.getArg(2));
      WalkCase(&Weight, ExtractOptionNames(nonSuperfluousOptions), Id());
    }
  }

  // Check that all options in OptDescs belong to the set of
  // non-superfluous options.
  for (OptionDescriptions::const_iterator B = OptDescs.begin(),
         E = OptDescs.end(); B != E; ++B) {
    const OptionDescription& Val = B->second;
    if (!nonSuperfluousOptions.count(Val.Name)
        && Val.Type != OptionType::Alias)
      llvm::errs() << "Warning: option '-" << Val.Name << "' has no effect! "
        "Probable cause: this option is specified only in the OptionList.\n";
  }
}

/// EmitCaseTest0Args - Helper function used by EmitCaseConstructHandler().
bool EmitCaseTest0Args(const std::string& TestName, raw_ostream& O) {
  if (TestName == "single_input_file") {
    O << "InputFilenames.size() == 1";
    return true;
  }
  else if (TestName == "multiple_input_files") {
    O << "InputFilenames.size() > 1";
    return true;
  }

  return false;
}

/// EmitMultipleArgumentTest - Helper function used by
/// EmitCaseTestMultipleArgs()
template <typename F>
void EmitMultipleArgumentTest(const DagInit& D, const char* LogicOp,
                              F Callback, raw_ostream& O)
{
  for (unsigned i = 0, NumArgs = D.getNumArgs(); i < NumArgs; ++i) {
    if (i != 0)
       O << ' ' << LogicOp << ' ';
    Callback(InitPtrToString(D.getArg(i)), O);
  }
}

// Callbacks for use with EmitMultipleArgumentTest

class EmitSwitchOn {
  const OptionDescriptions& OptDescs_;
public:
  EmitSwitchOn(const OptionDescriptions& OptDescs) : OptDescs_(OptDescs)
  {}

  void operator()(const std::string& OptName, raw_ostream& O) const {
    const OptionDescription& OptDesc = OptDescs_.FindSwitch(OptName);
    O << OptDesc.GenVariableName();
  }
};

class EmitEmptyTest {
  bool EmitNegate_;
  const OptionDescriptions& OptDescs_;
public:
  EmitEmptyTest(bool EmitNegate, const OptionDescriptions& OptDescs)
    : EmitNegate_(EmitNegate), OptDescs_(OptDescs)
  {}

  void operator()(const std::string& OptName, raw_ostream& O) const {
    const char* Neg = (EmitNegate_ ? "!" : "");
    if (OptName == "o") {
      O << Neg << "OutputFilename.empty()";
    }
    else if (OptName == "save-temps") {
      O << Neg << "(SaveTemps == SaveTempsEnum::Unset)";
    }
    else {
      const OptionDescription& OptDesc = OptDescs_.FindListOrParameter(OptName);
      O << Neg << OptDesc.GenVariableName() << ".empty()";
    }
  }
};


/// EmitCaseTestMultipleArgs - Helper function used by EmitCaseTest1Arg()
bool EmitCaseTestMultipleArgs (const std::string& TestName,
                               const DagInit& d,
                               const OptionDescriptions& OptDescs,
                               raw_ostream& O) {
  if (TestName == "any_switch_on") {
    EmitMultipleArgumentTest(d, "||", EmitSwitchOn(OptDescs), O);
    return true;
  }
  else if (TestName == "switch_on") {
    EmitMultipleArgumentTest(d, "&&", EmitSwitchOn(OptDescs), O);
    return true;
  }
  else if (TestName == "any_not_empty") {
    EmitMultipleArgumentTest(d, "||", EmitEmptyTest(true, OptDescs), O);
    return true;
  }
  else if (TestName == "any_empty") {
    EmitMultipleArgumentTest(d, "||", EmitEmptyTest(false, OptDescs), O);
    return true;
  }
  else if (TestName == "not_empty") {
    EmitMultipleArgumentTest(d, "&&", EmitEmptyTest(true, OptDescs), O);
    return true;
  }
  else if (TestName == "empty") {
    EmitMultipleArgumentTest(d, "&&", EmitEmptyTest(false, OptDescs), O);
    return true;
  }

  return false;
}

/// EmitCaseTest1Arg - Helper function used by EmitCaseTest1OrMoreArgs()
bool EmitCaseTest1Arg (const std::string& TestName,
                       const DagInit& d,
                       const OptionDescriptions& OptDescs,
                       raw_ostream& O) {
  const std::string& Arg = InitPtrToString(d.getArg(0));

  if (TestName == "input_languages_contain") {
    O << "InLangs.count(\"" << Arg << "\") != 0";
    return true;
  }
  else if (TestName == "in_language") {
    // This works only for single-argument Tool::GenerateAction. Join
    // tools can process several files in different languages simultaneously.

    // TODO: make this work with Edge::Weight (if possible).
    O << "LangMap.GetLanguage(inFile) == \"" << Arg << '\"';
    return true;
  }

  return false;
}

/// EmitCaseTest1OrMoreArgs - Helper function used by
/// EmitCaseConstructHandler()
bool EmitCaseTest1OrMoreArgs(const std::string& TestName,
                             const DagInit& d,
                             const OptionDescriptions& OptDescs,
                             raw_ostream& O) {
  CheckNumberOfArguments(d, 1);
  return EmitCaseTest1Arg(TestName, d, OptDescs, O) ||
    EmitCaseTestMultipleArgs(TestName, d, OptDescs, O);
}

/// EmitCaseTest2Args - Helper function used by EmitCaseConstructHandler().
bool EmitCaseTest2Args(const std::string& TestName,
                       const DagInit& d,
                       unsigned IndentLevel,
                       const OptionDescriptions& OptDescs,
                       raw_ostream& O) {
  CheckNumberOfArguments(d, 2);
  const std::string& OptName = InitPtrToString(d.getArg(0));
  const std::string& OptArg = InitPtrToString(d.getArg(1));

  if (TestName == "parameter_equals") {
    const OptionDescription& OptDesc = OptDescs.FindParameter(OptName);
    O << OptDesc.GenVariableName() << " == \"" << OptArg << "\"";
    return true;
  }
  else if (TestName == "element_in_list") {
    const OptionDescription& OptDesc = OptDescs.FindParameterList(OptName);
    const std::string& VarName = OptDesc.GenVariableName();
    O << "std::find(" << VarName << ".begin(),\n";
    O.indent(IndentLevel + Indent1)
      << VarName << ".end(), \""
      << OptArg << "\") != " << VarName << ".end()";
    return true;
  }

  return false;
}

// Forward declaration.
// EmitLogicalOperationTest and EmitCaseTest are mutually recursive.
void EmitCaseTest(const DagInit& d, unsigned IndentLevel,
                  const OptionDescriptions& OptDescs,
                  raw_ostream& O);

/// EmitLogicalOperationTest - Helper function used by
/// EmitCaseConstructHandler.
void EmitLogicalOperationTest(const DagInit& d, const char* LogicOp,
                              unsigned IndentLevel,
                              const OptionDescriptions& OptDescs,
                              raw_ostream& O) {
  O << '(';
  for (unsigned i = 0, NumArgs = d.getNumArgs(); i < NumArgs; ++i) {
    const DagInit& InnerTest = InitPtrToDag(d.getArg(i));
    EmitCaseTest(InnerTest, IndentLevel, OptDescs, O);
    if (i != NumArgs - 1) {
      O << ")\n";
      O.indent(IndentLevel + Indent1) << ' ' << LogicOp << " (";
    }
    else {
      O << ')';
    }
  }
}

void EmitLogicalNot(const DagInit& d, unsigned IndentLevel,
                    const OptionDescriptions& OptDescs, raw_ostream& O)
{
  CheckNumberOfArguments(d, 1);
  const DagInit& InnerTest = InitPtrToDag(d.getArg(0));
  O << "! (";
  EmitCaseTest(InnerTest, IndentLevel, OptDescs, O);
  O << ")";
}

/// EmitCaseTest - Helper function used by EmitCaseConstructHandler.
void EmitCaseTest(const DagInit& d, unsigned IndentLevel,
                  const OptionDescriptions& OptDescs,
                  raw_ostream& O) {
  const std::string& TestName = GetOperatorName(d);

  if (TestName == "and")
    EmitLogicalOperationTest(d, "&&", IndentLevel, OptDescs, O);
  else if (TestName == "or")
    EmitLogicalOperationTest(d, "||", IndentLevel, OptDescs, O);
  else if (TestName == "not")
    EmitLogicalNot(d, IndentLevel, OptDescs, O);
  else if (EmitCaseTest0Args(TestName, O))
    return;
  else if (EmitCaseTest1OrMoreArgs(TestName, d, OptDescs, O))
    return;
  else if (EmitCaseTest2Args(TestName, d, IndentLevel, OptDescs, O))
    return;
  else
    throw "Unknown test '" + TestName + "' used in the 'case' construct!";
}


/// EmitCaseTestCallback - Callback used by EmitCaseConstructHandler.
class EmitCaseTestCallback {
  bool EmitElseIf_;
  const OptionDescriptions& OptDescs_;
  raw_ostream& O_;
public:

  EmitCaseTestCallback(bool EmitElseIf,
                       const OptionDescriptions& OptDescs, raw_ostream& O)
    : EmitElseIf_(EmitElseIf), OptDescs_(OptDescs), O_(O)
  {}

  void operator()(const DagInit& Test, unsigned IndentLevel, bool FirstTest)
  {
    if (GetOperatorName(Test) == "default") {
      O_.indent(IndentLevel) << "else {\n";
    }
    else {
      O_.indent(IndentLevel)
        << ((!FirstTest && EmitElseIf_) ? "else if (" : "if (");
      EmitCaseTest(Test, IndentLevel, OptDescs_, O_);
      O_ << ") {\n";
    }
  }
};

/// EmitCaseStatementCallback - Callback used by EmitCaseConstructHandler.
template <typename F>
class EmitCaseStatementCallback {
  F Callback_;
  raw_ostream& O_;
public:

  EmitCaseStatementCallback(F Callback, raw_ostream& O)
    : Callback_(Callback), O_(O)
  {}

  void operator() (const Init* Statement, unsigned IndentLevel) {
    // Is this a nested 'case'?
    bool IsCase = dynamic_cast<const DagInit*>(Statement) &&
      GetOperatorName(static_cast<const DagInit&>(*Statement)) == "case";

    // If so, ignore it, it is handled by our caller, WalkCase.
    if (!IsCase) {
      if (typeid(*Statement) == typeid(ListInit)) {
        const ListInit& DagList = *static_cast<const ListInit*>(Statement);
        for (ListInit::const_iterator B = DagList.begin(), E = DagList.end();
             B != E; ++B)
          Callback_(*B, (IndentLevel + Indent1), O_);
      }
      else {
        Callback_(Statement, (IndentLevel + Indent1), O_);
      }
    }
    O_.indent(IndentLevel) << "}\n";
  }

};

/// EmitCaseConstructHandler - Emit code that handles the 'case'
/// construct. Takes a function object that should emit code for every case
/// clause. Implemented on top of WalkCase.
/// Callback's type is void F(const Init* Statement, unsigned IndentLevel,
/// raw_ostream& O).
/// EmitElseIf parameter controls the type of condition that is emitted ('if
/// (..) {..} else if (..) {} .. else {..}' vs. 'if (..) {..} if(..)  {..}
/// .. else {..}').
template <typename F>
void EmitCaseConstructHandler(const Init* Case, unsigned IndentLevel,
                              F Callback, bool EmitElseIf,
                              const OptionDescriptions& OptDescs,
                              raw_ostream& O) {
  WalkCase(Case, EmitCaseTestCallback(EmitElseIf, OptDescs, O),
           EmitCaseStatementCallback<F>(Callback, O), IndentLevel);
}

/// TokenizeCmdLine - converts from
/// "$CALL(HookName, 'Arg1', 'Arg2')/path -arg1 -arg2" to
/// ["$CALL(", "HookName", "Arg1", "Arg2", ")/path", "-arg1", "-arg2"].
void TokenizeCmdLine(const std::string& CmdLine, StrVector& Out) {
  const char* Delimiters = " \t\n\v\f\r";
  enum TokenizerState
  { Normal, SpecialCommand, InsideSpecialCommand, InsideQuotationMarks }
  cur_st  = Normal;

  if (CmdLine.empty())
    return;
  Out.push_back("");

  std::string::size_type B = CmdLine.find_first_not_of(Delimiters),
    E = CmdLine.size();

  for (; B != E; ++B) {
    char cur_ch = CmdLine[B];

    switch (cur_st) {
    case Normal:
      if (cur_ch == '$') {
        cur_st = SpecialCommand;
        break;
      }
      if (OneOf(Delimiters, cur_ch)) {
        // Skip whitespace
        B = CmdLine.find_first_not_of(Delimiters, B);
        if (B == std::string::npos) {
          B = E-1;
          continue;
        }
        --B;
        Out.push_back("");
        continue;
      }
      break;


    case SpecialCommand:
      if (OneOf(Delimiters, cur_ch)) {
        cur_st = Normal;
        Out.push_back("");
        continue;
      }
      if (cur_ch == '(') {
        Out.push_back("");
        cur_st = InsideSpecialCommand;
        continue;
      }
      break;

    case InsideSpecialCommand:
      if (OneOf(Delimiters, cur_ch)) {
        continue;
      }
      if (cur_ch == '\'') {
        cur_st = InsideQuotationMarks;
        Out.push_back("");
        continue;
      }
      if (cur_ch == ')') {
        cur_st = Normal;
        Out.push_back("");
      }
      if (cur_ch == ',') {
        continue;
      }

      break;

    case InsideQuotationMarks:
      if (cur_ch == '\'') {
        cur_st = InsideSpecialCommand;
        continue;
      }
      break;
    }

    Out.back().push_back(cur_ch);
  }
}

/// SubstituteCall - Given "$CALL(HookName, [Arg1 [, Arg2 [...]]])", output
/// "hooks::HookName([Arg1 [, Arg2 [, ...]]])". Helper function used by
/// SubstituteSpecialCommands().
StrVector::const_iterator
SubstituteCall (StrVector::const_iterator Pos,
                StrVector::const_iterator End,
                bool IsJoin, raw_ostream& O)
{
  const char* errorMessage = "Syntax error in $CALL invocation!";
  CheckedIncrement(Pos, End, errorMessage);
  const std::string& CmdName = *Pos;

  if (CmdName == ")")
    throw "$CALL invocation: empty argument list!";

  O << "hooks::";
  O << CmdName << "(";


  bool firstIteration = true;
  while (true) {
    CheckedIncrement(Pos, End, errorMessage);
    const std::string& Arg = *Pos;
    assert(Arg.size() != 0);

    if (Arg[0] == ')')
      break;

    if (firstIteration)
      firstIteration = false;
    else
      O << ", ";

    if (Arg == "$INFILE") {
      if (IsJoin)
        throw "$CALL(Hook, $INFILE) can't be used with a Join tool!";
      else
        O << "inFile.c_str()";
    }
    else {
      O << '"' << Arg << '"';
    }
  }

  O << ')';

  return Pos;
}

/// SubstituteEnv - Given '$ENV(VAR_NAME)', output 'getenv("VAR_NAME")'. Helper
/// function used by SubstituteSpecialCommands().
StrVector::const_iterator
SubstituteEnv (StrVector::const_iterator Pos,
               StrVector::const_iterator End, raw_ostream& O)
{
  const char* errorMessage = "Syntax error in $ENV invocation!";
  CheckedIncrement(Pos, End, errorMessage);
  const std::string& EnvName = *Pos;

  if (EnvName == ")")
    throw "$ENV invocation: empty argument list!";

  O << "checkCString(std::getenv(\"";
  O << EnvName;
  O << "\"))";

  CheckedIncrement(Pos, End, errorMessage);

  return Pos;
}

/// SubstituteSpecialCommands - Given an invocation of $CALL or $ENV, output
/// handler code. Helper function used by EmitCmdLineVecFill().
StrVector::const_iterator
SubstituteSpecialCommands (StrVector::const_iterator Pos,
                           StrVector::const_iterator End,
                           bool IsJoin, raw_ostream& O)
{

  const std::string& cmd = *Pos;

  // Perform substitution.
  if (cmd == "$CALL") {
    Pos = SubstituteCall(Pos, End, IsJoin, O);
  }
  else if (cmd == "$ENV") {
    Pos = SubstituteEnv(Pos, End, O);
  }
  else {
    throw "Unknown special command: " + cmd;
  }

  // Handle '$CMD(ARG)/additional/text'.
  const std::string& Leftover = *Pos;
  assert(Leftover.at(0) == ')');
  if (Leftover.size() != 1)
    O << " + std::string(\"" << (Leftover.c_str() + 1) << "\")";

  return Pos;
}

/// EmitCmdLineVecFill - Emit code that fills in the command line
/// vector. Helper function used by EmitGenerateActionMethod().
void EmitCmdLineVecFill(const Init* CmdLine, const std::string& ToolName,
                        bool IsJoin, unsigned IndentLevel,
                        raw_ostream& O) {
  StrVector StrVec;
  TokenizeCmdLine(InitPtrToString(CmdLine), StrVec);

  if (StrVec.empty())
    throw "Tool '" + ToolName + "' has empty command line!";

  StrVector::const_iterator B = StrVec.begin(), E = StrVec.end();

  // Emit the command itself.
  assert(!StrVec[0].empty());
  O.indent(IndentLevel) << "cmd = ";
  if (StrVec[0][0] == '$') {
    B = SubstituteSpecialCommands(B, E, IsJoin, O);
    ++B;
  }
  else {
    O << '"' << StrVec[0] << '"';
    ++B;
  }
  O << ";\n";

  // Go through the command arguments.
  assert(B <= E);
  for (; B != E; ++B) {
    const std::string& cmd = *B;

    assert(!cmd.empty());
    O.indent(IndentLevel);

    if (cmd.at(0) == '$') {
      O << "vec.push_back(std::make_pair(0, ";
      B = SubstituteSpecialCommands(B, E, IsJoin, O);
      O << "));\n";
    }
    else {
      O << "vec.push_back(std::make_pair(0, \"" << cmd << "\"));\n";
    }
  }

}

/// EmitForEachListElementCycleHeader - Emit common code for iterating through
/// all elements of a list. Helper function used by
/// EmitForwardOptionPropertyHandlingCode.
void EmitForEachListElementCycleHeader (const OptionDescription& D,
                                        unsigned IndentLevel,
                                        raw_ostream& O) {
  unsigned IndentLevel1 = IndentLevel + Indent1;

  O.indent(IndentLevel)
    << "for (" << D.GenTypeDeclaration()
    << "::iterator B = " << D.GenVariableName() << ".begin(),\n";
  O.indent(IndentLevel)
    << "E = " << D.GenVariableName() << ".end(); B != E;) {\n";
  O.indent(IndentLevel1) << "unsigned pos = " << D.GenVariableName()
                         << ".getPosition(B - " << D.GenVariableName()
                         << ".begin());\n";
}

/// EmitForwardOptionPropertyHandlingCode - Helper function used to
/// implement EmitActionHandler. Emits code for
/// handling the (forward) and (forward_as) option properties.
void EmitForwardOptionPropertyHandlingCode (const OptionDescription& D,
                                            unsigned IndentLevel,
                                            const std::string& NewName,
                                            raw_ostream& O) {
  const std::string& Name = NewName.empty()
    ? ("-" + D.Name)
    : NewName;
  unsigned IndentLevel1 = IndentLevel + Indent1;

  switch (D.Type) {
  case OptionType::Switch:
    O.indent(IndentLevel)
      << "vec.push_back(std::make_pair(" << D.GenVariableName()
      << ".getPosition(), \"" << Name << "\"));\n";
    break;
  case OptionType::Parameter:
    O.indent(IndentLevel) << "vec.push_back(std::make_pair("
                          << D.GenVariableName()
                          <<".getPosition(), \"" << Name;

    if (!D.isForwardNotSplit()) {
      O << "\"));\n";
      O.indent(IndentLevel) << "vec.push_back(std::make_pair("
                            << D.GenVariableName() << ".getPosition(), "
                            << D.GenVariableName() << "));\n";
    }
    else {
      O << "=\" + " << D.GenVariableName() << "));\n";
    }
    break;
  case OptionType::Prefix:
    O.indent(IndentLevel) << "vec.push_back(std::make_pair("
                          << D.GenVariableName() << ".getPosition(), \""
                          << Name << "\" + "
                          << D.GenVariableName() << "));\n";
    break;
  case OptionType::PrefixList:
    EmitForEachListElementCycleHeader(D, IndentLevel, O);
    O.indent(IndentLevel1) << "vec.push_back(std::make_pair(pos, \""
                           << Name << "\" + " << "*B));\n";
    O.indent(IndentLevel1) << "++B;\n";

    for (int i = 1, j = D.MultiVal; i < j; ++i) {
      O.indent(IndentLevel1) << "vec.push_back(std::make_pair(pos, *B));\n";
      O.indent(IndentLevel1) << "++B;\n";
    }

    O.indent(IndentLevel) << "}\n";
    break;
  case OptionType::ParameterList:
    EmitForEachListElementCycleHeader(D, IndentLevel, O);
    O.indent(IndentLevel1) << "vec.push_back(std::make_pair(pos, \""
                           << Name << "\"));\n";

    for (int i = 0, j = D.MultiVal; i < j; ++i) {
      O.indent(IndentLevel1) << "vec.push_back(std::make_pair(pos, *B));\n";
      O.indent(IndentLevel1) << "++B;\n";
    }

    O.indent(IndentLevel) << "}\n";
    break;
  case OptionType::SwitchList:
    EmitForEachListElementCycleHeader(D, IndentLevel, O);
    O.indent(IndentLevel1) << "vec.push_back(std::make_pair(pos, \""
                           << Name << "\"));\n";
    O.indent(IndentLevel1) << "++B;\n";
    O.indent(IndentLevel) << "}\n";
    break;
  case OptionType::Alias:
  default:
    throw "Aliases are not allowed in tool option descriptions!";
  }
}

/// ActionHandlingCallbackBase - Base class of EmitActionHandlersCallback and
/// EmitPreprocessOptionsCallback.
struct ActionHandlingCallbackBase
{

  void onErrorDag(const DagInit& d,
                  unsigned IndentLevel, raw_ostream& O) const
  {
    O.indent(IndentLevel)
      << "PrintError(\""
      << (d.getNumArgs() >= 1 ? InitPtrToString(d.getArg(0)) : "Unknown error!")
      << "\");\n";
    O.indent(IndentLevel) << "return 1;\n";
  }

  void onWarningDag(const DagInit& d,
                    unsigned IndentLevel, raw_ostream& O) const
  {
    CheckNumberOfArguments(d, 1);
    O.indent(IndentLevel) << "llvm::errs() << \""
                          << InitPtrToString(d.getArg(0)) << "\";\n";
  }

};

/// EmitActionHandlersCallback - Emit code that handles actions. Used by
/// EmitGenerateActionMethod() as an argument to EmitCaseConstructHandler().
class EmitActionHandlersCallback;

typedef void (EmitActionHandlersCallback::* EmitActionHandlersCallbackHandler)
(const DagInit&, unsigned, raw_ostream&) const;

class EmitActionHandlersCallback :
  public ActionHandlingCallbackBase,
  public HandlerTable<EmitActionHandlersCallbackHandler>
{
  typedef EmitActionHandlersCallbackHandler Handler;

  const OptionDescriptions& OptDescs;

  /// EmitHookInvocation - Common code for hook invocation from actions. Used by
  /// onAppendCmd and onOutputSuffix.
  void EmitHookInvocation(const std::string& Str,
                          const char* BlockOpen, const char* BlockClose,
                          unsigned IndentLevel, raw_ostream& O) const
  {
    StrVector Out;
    TokenizeCmdLine(Str, Out);

    for (StrVector::const_iterator B = Out.begin(), E = Out.end();
         B != E; ++B) {
      const std::string& cmd = *B;

      O.indent(IndentLevel) << BlockOpen;

      if (cmd.at(0) == '$')
        B = SubstituteSpecialCommands(B, E,  /* IsJoin = */ true, O);
      else
        O << '"' << cmd << '"';

      O << BlockClose;
    }
  }

  void onAppendCmd (const DagInit& Dag,
                    unsigned IndentLevel, raw_ostream& O) const
  {
    CheckNumberOfArguments(Dag, 1);
    this->EmitHookInvocation(InitPtrToString(Dag.getArg(0)),
                             "vec.push_back(std::make_pair(65536, ", "));\n",
                             IndentLevel, O);
  }

  void onForward (const DagInit& Dag,
                  unsigned IndentLevel, raw_ostream& O) const
  {
    CheckNumberOfArguments(Dag, 1);
    const std::string& Name = InitPtrToString(Dag.getArg(0));
    EmitForwardOptionPropertyHandlingCode(OptDescs.FindOption(Name),
                                          IndentLevel, "", O);
  }

  void onForwardAs (const DagInit& Dag,
                    unsigned IndentLevel, raw_ostream& O) const
  {
    CheckNumberOfArguments(Dag, 2);
    const std::string& Name = InitPtrToString(Dag.getArg(0));
    const std::string& NewName = InitPtrToString(Dag.getArg(1));
    EmitForwardOptionPropertyHandlingCode(OptDescs.FindOption(Name),
                                          IndentLevel, NewName, O);
  }

  void onForwardValue (const DagInit& Dag,
                       unsigned IndentLevel, raw_ostream& O) const
  {
    CheckNumberOfArguments(Dag, 1);
    const std::string& Name = InitPtrToString(Dag.getArg(0));
    const OptionDescription& D = OptDescs.FindParameterListOrParameter(Name);

    if (D.isSwitchList()) {
      throw std::runtime_error
        ("forward_value is not allowed with switch_list");
    }

    if (D.isParameter()) {
      O.indent(IndentLevel) << "vec.push_back(std::make_pair("
                            << D.GenVariableName() << ".getPosition(), "
                            << D.GenVariableName() << "));\n";
    }
    else {
      O.indent(IndentLevel) << "for (" << D.GenTypeDeclaration()
                            << "::iterator B = " << D.GenVariableName()
                            << ".begin(), \n";
      O.indent(IndentLevel + Indent1) << " E = " << D.GenVariableName()
                                      << ".end(); B != E; ++B)\n";
      O.indent(IndentLevel) << "{\n";
      O.indent(IndentLevel + Indent1)
        << "unsigned pos = " << D.GenVariableName()
        << ".getPosition(B - " << D.GenVariableName()
        << ".begin());\n";
      O.indent(IndentLevel + Indent1)
        << "vec.push_back(std::make_pair(pos, *B));\n";
      O.indent(IndentLevel) << "}\n";
    }
  }

  void onForwardTransformedValue (const DagInit& Dag,
                                  unsigned IndentLevel, raw_ostream& O) const
  {
    CheckNumberOfArguments(Dag, 2);
    const std::string& Name = InitPtrToString(Dag.getArg(0));
    const std::string& Hook = InitPtrToString(Dag.getArg(1));
    const OptionDescription& D = OptDescs.FindParameterListOrParameter(Name);

    O.indent(IndentLevel) << "vec.push_back(std::make_pair("
                          << D.GenVariableName() << ".getPosition("
                          << (D.isList() ? "0" : "") << "), "
                          << "hooks::" << Hook << "(" << D.GenVariableName()
                          << (D.isParameter() ? ".c_str()" : "") << ")));\n";
  }

  void onNoOutFile (const DagInit& Dag,
                    unsigned IndentLevel, raw_ostream& O) const
  {
    CheckNumberOfArguments(Dag, 0);
    O.indent(IndentLevel) << "no_out_file = true;\n";
  }

  void onOutputSuffix (const DagInit& Dag,
                       unsigned IndentLevel, raw_ostream& O) const
  {
    CheckNumberOfArguments(Dag, 1);
    this->EmitHookInvocation(InitPtrToString(Dag.getArg(0)),
                             "output_suffix = ", ";\n", IndentLevel, O);
  }

  void onStopCompilation (const DagInit& Dag,
                          unsigned IndentLevel, raw_ostream& O) const
  {
    O.indent(IndentLevel) << "stop_compilation = true;\n";
  }


  void onUnpackValues (const DagInit& Dag,
                       unsigned IndentLevel, raw_ostream& O) const
  {
    throw "'unpack_values' is deprecated. "
      "Use 'comma_separated' + 'forward_value' instead!";
  }

 public:

  explicit EmitActionHandlersCallback(const OptionDescriptions& OD)
    : OptDescs(OD)
  {
    if (!staticMembersInitialized_) {
      AddHandler("error", &EmitActionHandlersCallback::onErrorDag);
      AddHandler("warning", &EmitActionHandlersCallback::onWarningDag);
      AddHandler("append_cmd", &EmitActionHandlersCallback::onAppendCmd);
      AddHandler("forward", &EmitActionHandlersCallback::onForward);
      AddHandler("forward_as", &EmitActionHandlersCallback::onForwardAs);
      AddHandler("forward_value", &EmitActionHandlersCallback::onForwardValue);
      AddHandler("forward_transformed_value",
                 &EmitActionHandlersCallback::onForwardTransformedValue);
      AddHandler("no_out_file",
                 &EmitActionHandlersCallback::onNoOutFile);
      AddHandler("output_suffix", &EmitActionHandlersCallback::onOutputSuffix);
      AddHandler("stop_compilation",
                 &EmitActionHandlersCallback::onStopCompilation);
      AddHandler("unpack_values",
                 &EmitActionHandlersCallback::onUnpackValues);


      staticMembersInitialized_ = true;
    }
  }

  void operator()(const Init* I,
                  unsigned IndentLevel, raw_ostream& O) const
  {
    InvokeDagInitHandler(this, I, IndentLevel, O);
  }
};

void EmitGenerateActionMethodHeader(const ToolDescription& D,
                                    bool IsJoin, bool Naked,
                                    raw_ostream& O)
{
  O.indent(Indent1) << "int GenerateAction(Action& Out,\n";

  if (IsJoin)
    O.indent(Indent2) << "const PathVector& inFiles,\n";
  else
    O.indent(Indent2) << "const sys::Path& inFile,\n";

  O.indent(Indent2) << "const bool HasChildren,\n";
  O.indent(Indent2) << "const llvm::sys::Path& TempDir,\n";
  O.indent(Indent2) << "const InputLanguagesSet& InLangs,\n";
  O.indent(Indent2) << "const LanguageMap& LangMap) const\n";
  O.indent(Indent1) << "{\n";

  if (!Naked) {
    O.indent(Indent2) << "std::string cmd;\n";
    O.indent(Indent2) << "std::string out_file;\n";
    O.indent(Indent2)
      << "std::vector<std::pair<unsigned, std::string> > vec;\n";
    O.indent(Indent2) << "bool stop_compilation = !HasChildren;\n";
    O.indent(Indent2) << "bool no_out_file = false;\n";
    O.indent(Indent2) << "std::string output_suffix(\""
                      << D.OutputSuffix << "\");\n";
  }
}

// EmitGenerateActionMethod - Emit either a normal or a "join" version of the
// Tool::GenerateAction() method.
void EmitGenerateActionMethod (const ToolDescription& D,
                               const OptionDescriptions& OptDescs,
                               bool IsJoin, raw_ostream& O) {

  EmitGenerateActionMethodHeader(D, IsJoin, /* Naked = */ false, O);

  if (!D.CmdLine)
    throw "Tool " + D.Name + " has no cmd_line property!";

  // Process the 'command' property.
  O << '\n';
  EmitCmdLineVecFill(D.CmdLine, D.Name, IsJoin, Indent2, O);
  O << '\n';

  // Process the 'actions' list of this tool.
  if (D.Actions)
    EmitCaseConstructHandler(D.Actions, Indent2,
                             EmitActionHandlersCallback(OptDescs),
                             false, OptDescs, O);
  O << '\n';

  // Input file (s)
  if (!D.InFileOption.empty()) {
    O.indent(Indent2)
      << "vec.push_back(std::make_pair(InputFilenames.getPosition(0), \""
      << D.InFileOption << "\");\n";
  }

  if (IsJoin) {
    O.indent(Indent2)
      << "for (PathVector::const_iterator B = inFiles.begin(),\n";
    O.indent(Indent3) << "E = inFiles.end(); B != E; ++B)\n";
    O.indent(Indent2) << "{\n";
    O.indent(Indent3) << "vec.push_back(std::make_pair("
                      << "InputFilenames.getPosition(B - inFiles.begin()), "
                      << "B->str()));\n";
    O.indent(Indent2) << "}\n";
  }
  else {
    O.indent(Indent2) << "vec.push_back(std::make_pair("
                      << "InputFilenames.getPosition(0), inFile.str()));\n";
  }

  // Output file
  O.indent(Indent2) << "if (!no_out_file) {\n";
  if (!D.OutFileOption.empty())
    O.indent(Indent3) << "vec.push_back(std::make_pair(65536, \""
                      << D.OutFileOption << "\"));\n";

  O.indent(Indent3) << "out_file = this->OutFilename("
                    << (IsJoin ? "sys::Path(),\n" : "inFile,\n");
  O.indent(Indent4) <<
    "TempDir, stop_compilation, output_suffix.c_str()).str();\n\n";
  O.indent(Indent3) << "vec.push_back(std::make_pair(65536, out_file));\n";

  O.indent(Indent2) << "}\n\n";

  // Handle the Sink property.
  std::string SinkOption("autogenerated::");
  SinkOption += SinkOptionName;
  if (D.isSink()) {
    O.indent(Indent2) << "if (!" << SinkOption << ".empty()) {\n";
    O.indent(Indent3) << "for (cl::list<std::string>::iterator B = "
                      << SinkOption << ".begin(), E = " << SinkOption
                      << ".end(); B != E; ++B)\n";
    O.indent(Indent4) << "vec.push_back(std::make_pair(" << SinkOption
                      << ".getPosition(B - " << SinkOption
                      <<  ".begin()), *B));\n";
    O.indent(Indent2) << "}\n";
  }

  O.indent(Indent2) << "Out.Construct(cmd, this->SortArgs(vec), "
                    << "stop_compilation, out_file);\n";
  O.indent(Indent2) << "return 0;\n";
  O.indent(Indent1) << "}\n\n";
}

/// EmitGenerateActionMethods - Emit two GenerateAction() methods for
/// a given Tool class.
void EmitGenerateActionMethods (const ToolDescription& ToolDesc,
                                const OptionDescriptions& OptDescs,
                                raw_ostream& O) {
  if (!ToolDesc.isJoin()) {
    EmitGenerateActionMethodHeader(ToolDesc, /* IsJoin = */ true,
                                   /* Naked = */ true, O);
    O.indent(Indent2) << "PrintError(\"" << ToolDesc.Name
                      << " is not a Join tool!\");\n";
    O.indent(Indent2) << "return -1;\n";
    O.indent(Indent1) << "}\n\n";
  }
  else {
    EmitGenerateActionMethod(ToolDesc, OptDescs, true, O);
  }

  EmitGenerateActionMethod(ToolDesc, OptDescs, false, O);
}

/// EmitInOutLanguageMethods - Emit the [Input,Output]Language()
/// methods for a given Tool class.
void EmitInOutLanguageMethods (const ToolDescription& D, raw_ostream& O) {
  O.indent(Indent1) << "const char** InputLanguages() const {\n";
  O.indent(Indent2) << "return InputLanguages_;\n";
  O.indent(Indent1) << "}\n\n";

  O.indent(Indent1) << "const char** OutputLanguages() const {\n";
  O.indent(Indent2) << "return OutputLanguages_;\n";
  O.indent(Indent1) << "}\n\n";
}

/// EmitNameMethod - Emit the Name() method for a given Tool class.
void EmitNameMethod (const ToolDescription& D, raw_ostream& O) {
  O.indent(Indent1) << "const char* Name() const {\n";
  O.indent(Indent2) << "return \"" << D.Name << "\";\n";
  O.indent(Indent1) << "}\n\n";
}

/// EmitIsJoinMethod - Emit the IsJoin() method for a given Tool
/// class.
void EmitIsJoinMethod (const ToolDescription& D, raw_ostream& O) {
  O.indent(Indent1) << "bool IsJoin() const {\n";
  if (D.isJoin())
    O.indent(Indent2) << "return true;\n";
  else
    O.indent(Indent2) << "return false;\n";
  O.indent(Indent1) << "}\n\n";
}

/// EmitWorksOnEmptyCallback - Callback used by EmitWorksOnEmptyMethod in
/// conjunction with EmitCaseConstructHandler.
void EmitWorksOnEmptyCallback (const Init* Value,
                               unsigned IndentLevel, raw_ostream& O) {
  CheckBooleanConstant(Value);
  O.indent(IndentLevel) << "return " << Value->getAsString() << ";\n";
}

/// EmitWorksOnEmptyMethod - Emit the WorksOnEmpty() method for a given Tool
/// class.
void EmitWorksOnEmptyMethod (const ToolDescription& D,
                             const OptionDescriptions& OptDescs,
                             raw_ostream& O)
{
  O.indent(Indent1) << "bool WorksOnEmpty() const {\n";
  if (D.OnEmpty == 0)
    O.indent(Indent2) << "return false;\n";
  else
    EmitCaseConstructHandler(D.OnEmpty, Indent2, EmitWorksOnEmptyCallback,
                             /*EmitElseIf = */ true, OptDescs, O);
  O.indent(Indent1) << "}\n\n";
}

/// EmitStrArray - Emit definition of a 'const char**' static member
/// variable. Helper used by EmitStaticMemberDefinitions();
void EmitStrArray(const std::string& Name, const std::string& VarName,
                  const StrVector& StrVec, raw_ostream& O) {
  O << "const char* " << Name << "::" << VarName << "[] = {";
  for (StrVector::const_iterator B = StrVec.begin(), E = StrVec.end();
       B != E; ++B)
    O << '\"' << *B << "\", ";
  O << "0};\n";
}

/// EmitStaticMemberDefinitions - Emit static member definitions for a
/// given Tool class.
void EmitStaticMemberDefinitions(const ToolDescription& D, raw_ostream& O) {
  if (D.InLanguage.empty())
    throw "Tool " + D.Name + " has no 'in_language' property!";
  if (D.OutLanguage.empty())
    throw "Tool " + D.Name + " has no 'out_language' property!";

  EmitStrArray(D.Name, "InputLanguages_", D.InLanguage, O);
  EmitStrArray(D.Name, "OutputLanguages_", D.OutLanguage, O);
  O << '\n';
}

/// EmitToolClassDefinition - Emit a Tool class definition.
void EmitToolClassDefinition (const ToolDescription& D,
                              const OptionDescriptions& OptDescs,
                              raw_ostream& O) {
  if (D.Name == "root")
    return;

  // Header
  O << "class " << D.Name << " : public ";
  if (D.isJoin())
    O << "JoinTool";
  else
    O << "Tool";

  O << " {\nprivate:\n";
  O.indent(Indent1) << "static const char* InputLanguages_[];\n";
  O.indent(Indent1) << "static const char* OutputLanguages_[];\n\n";

  O << "public:\n";
  EmitNameMethod(D, O);
  EmitInOutLanguageMethods(D, O);
  EmitIsJoinMethod(D, O);
  EmitWorksOnEmptyMethod(D, OptDescs, O);
  EmitGenerateActionMethods(D, OptDescs, O);

  // Close class definition
  O << "};\n";

  EmitStaticMemberDefinitions(D, O);

}

/// EmitOptionDefinitions - Iterate over a list of option descriptions
/// and emit registration code.
void EmitOptionDefinitions (const OptionDescriptions& descs,
                            bool HasSink, raw_ostream& O)
{
  std::vector<OptionDescription> Aliases;

  // Emit static cl::Option variables.
  for (OptionDescriptions::const_iterator B = descs.begin(),
         E = descs.end(); B!=E; ++B) {
    const OptionDescription& val = B->second;

    if (val.Type == OptionType::Alias) {
      Aliases.push_back(val);
      continue;
    }

    O << val.GenTypeDeclaration() << ' '
      << val.GenPlainVariableName();

    O << "(\"" << val.Name << "\"\n";

    if (val.Type == OptionType::Prefix || val.Type == OptionType::PrefixList)
      O << ", cl::Prefix";

    if (val.isRequired()) {
      if (val.isList() && !val.isMultiVal())
        O << ", cl::OneOrMore";
      else
        O << ", cl::Required";
    }

    if (val.isOptional())
        O << ", cl::Optional";

    if (val.isOneOrMore())
        O << ", cl::OneOrMore";

    if (val.isZeroOrMore())
        O << ", cl::ZeroOrMore";

    if (val.isReallyHidden())
      O << ", cl::ReallyHidden";
    else if (val.isHidden())
      O << ", cl::Hidden";

    if (val.isCommaSeparated())
      O << ", cl::CommaSeparated";

    if (val.MultiVal > 1)
      O << ", cl::multi_val(" << val.MultiVal << ')';

    if (val.InitVal) {
      const std::string& str = val.InitVal->getAsString();
      O << ", cl::init(" << str << ')';
    }

    if (!val.Help.empty())
      O << ", cl::desc(\"" << val.Help << "\")";

    O << ");\n\n";
  }

  // Emit the aliases (they should go after all the 'proper' options).
  for (std::vector<OptionDescription>::const_iterator
         B = Aliases.begin(), E = Aliases.end(); B != E; ++B) {
    const OptionDescription& val = *B;

    O << val.GenTypeDeclaration() << ' '
      << val.GenPlainVariableName()
      << "(\"" << val.Name << '\"';

    const OptionDescription& D = descs.FindOption(val.Help);
    O << ", cl::aliasopt(" << D.GenVariableName() << ")";

    O << ", cl::desc(\"" << "An alias for -" + val.Help  << "\"));\n";
  }

  // Emit the sink option.
  if (HasSink)
    O << "cl::list<std::string> " << SinkOptionName << "(cl::Sink);\n";

  O << '\n';
}

/// EmitPreprocessOptionsCallback - Helper function passed to
/// EmitCaseConstructHandler() by EmitPreprocessOptions().

class EmitPreprocessOptionsCallback;

typedef void
(EmitPreprocessOptionsCallback::* EmitPreprocessOptionsCallbackHandler)
(const DagInit&, unsigned, raw_ostream&) const;

class EmitPreprocessOptionsCallback :
  public ActionHandlingCallbackBase,
  public HandlerTable<EmitPreprocessOptionsCallbackHandler>
{
  typedef EmitPreprocessOptionsCallbackHandler Handler;
  typedef void
  (EmitPreprocessOptionsCallback::* HandlerImpl)
  (const Init*, unsigned, raw_ostream&) const;

  const OptionDescriptions& OptDescs_;

  void onEachArgument(const DagInit& d, HandlerImpl h,
                      unsigned IndentLevel, raw_ostream& O) const
  {
    CheckNumberOfArguments(d, 1);

    for (unsigned i = 0, NumArgs = d.getNumArgs(); i < NumArgs; ++i) {
      ((this)->*(h))(d.getArg(i), IndentLevel, O);
    }
  }

  void onUnsetOptionImpl(const Init* I,
                         unsigned IndentLevel, raw_ostream& O) const
  {
    const std::string& OptName = InitPtrToString(I);
    const OptionDescription& OptDesc = OptDescs_.FindOption(OptName);

    if (OptDesc.isSwitch()) {
      O.indent(IndentLevel) << OptDesc.GenVariableName() << " = false;\n";
    }
    else if (OptDesc.isParameter()) {
      O.indent(IndentLevel) << OptDesc.GenVariableName() << " = \"\";\n";
    }
    else if (OptDesc.isList()) {
      O.indent(IndentLevel) << OptDesc.GenVariableName() << ".clear();\n";
    }
    else {
      throw "Can't apply 'unset_option' to alias option '" + OptName + "'!";
    }
  }

  void onUnsetOption(const DagInit& d,
                     unsigned IndentLevel, raw_ostream& O) const
  {
    this->onEachArgument(d, &EmitPreprocessOptionsCallback::onUnsetOptionImpl,
                         IndentLevel, O);
  }

  void onSetOptionImpl(const DagInit& D,
                       unsigned IndentLevel, raw_ostream& O) const {
    CheckNumberOfArguments(D, 2);

    const std::string& OptName = InitPtrToString(D.getArg(0));
    const OptionDescription& OptDesc = OptDescs_.FindOption(OptName);
    const Init* Value = D.getArg(1);

    if (OptDesc.isList()) {
      const ListInit& List = InitPtrToList(Value);

      O.indent(IndentLevel) << OptDesc.GenVariableName() << ".clear();\n";
      for (ListInit::const_iterator B = List.begin(), E = List.end();
           B != E; ++B) {
        const Init* CurElem = *B;
        if (OptDesc.isSwitchList())
          CheckBooleanConstant(CurElem);

        O.indent(IndentLevel)
          << OptDesc.GenVariableName() << ".push_back(\""
          << (OptDesc.isSwitchList() ? CurElem->getAsString()
              : InitPtrToString(CurElem))
          << "\");\n";
      }
    }
    else if (OptDesc.isSwitch()) {
      CheckBooleanConstant(Value);
      O.indent(IndentLevel) << OptDesc.GenVariableName()
                            << " = " << Value->getAsString() << ";\n";
    }
    else if (OptDesc.isParameter()) {
      const std::string& Str = InitPtrToString(Value);
      O.indent(IndentLevel) << OptDesc.GenVariableName()
                            << " = \"" << Str << "\";\n";
    }
    else {
      throw "Can't apply 'set_option' to alias option '" + OptName + "'!";
    }
  }

  void onSetSwitch(const Init* I,
                   unsigned IndentLevel, raw_ostream& O) const {
    const std::string& OptName = InitPtrToString(I);
    const OptionDescription& OptDesc = OptDescs_.FindOption(OptName);

    if (OptDesc.isSwitch())
      O.indent(IndentLevel) << OptDesc.GenVariableName() << " = true;\n";
    else
      throw "set_option: -" + OptName + " is not a switch option!";
  }

  void onSetOption(const DagInit& d,
                   unsigned IndentLevel, raw_ostream& O) const
  {
    CheckNumberOfArguments(d, 1);

    // 2-argument form: (set_option "A", true), (set_option "B", "C"),
    // (set_option "D", ["E", "F"])
    if (d.getNumArgs() == 2) {
      const OptionDescription& OptDesc =
        OptDescs_.FindOption(InitPtrToString(d.getArg(0)));
      const Init* Opt2 = d.getArg(1);

      if (!OptDesc.isSwitch() || typeid(*Opt2) != typeid(StringInit)) {
        this->onSetOptionImpl(d, IndentLevel, O);
        return;
      }
    }

    // Multiple argument form: (set_option "A"), (set_option "B", "C", "D")
    this->onEachArgument(d, &EmitPreprocessOptionsCallback::onSetSwitch,
                         IndentLevel, O);
  }

public:

  EmitPreprocessOptionsCallback(const OptionDescriptions& OptDescs)
  : OptDescs_(OptDescs)
  {
    if (!staticMembersInitialized_) {
      AddHandler("error", &EmitPreprocessOptionsCallback::onErrorDag);
      AddHandler("warning", &EmitPreprocessOptionsCallback::onWarningDag);
      AddHandler("unset_option", &EmitPreprocessOptionsCallback::onUnsetOption);
      AddHandler("set_option", &EmitPreprocessOptionsCallback::onSetOption);

      staticMembersInitialized_ = true;
    }
  }

  void operator()(const Init* I,
                  unsigned IndentLevel, raw_ostream& O) const
  {
    InvokeDagInitHandler(this, I, IndentLevel, O);
  }

};

/// EmitPreprocessOptions - Emit the PreprocessOptions() function.
void EmitPreprocessOptions (const RecordKeeper& Records,
                            const OptionDescriptions& OptDecs, raw_ostream& O)
{
  O << "int PreprocessOptions () {\n";

  const RecordVector& OptionPreprocessors =
    Records.getAllDerivedDefinitions("OptionPreprocessor");

  for (RecordVector::const_iterator B = OptionPreprocessors.begin(),
         E = OptionPreprocessors.end(); B!=E; ++B) {
    DagInit* Case = (*B)->getValueAsDag("preprocessor");
    EmitCaseConstructHandler(Case, Indent1,
                             EmitPreprocessOptionsCallback(OptDecs),
                             false, OptDecs, O);
  }

  O << '\n';
  O.indent(Indent1) << "return 0;\n";
  O << "}\n\n";
}

class DoEmitPopulateLanguageMap;
typedef void (DoEmitPopulateLanguageMap::* DoEmitPopulateLanguageMapHandler)
(const DagInit& D);

class DoEmitPopulateLanguageMap
: public HandlerTable<DoEmitPopulateLanguageMapHandler>
{
private:
  raw_ostream& O_;

public:

  explicit DoEmitPopulateLanguageMap (raw_ostream& O) : O_(O) {
    if (!staticMembersInitialized_) {
      AddHandler("lang_to_suffixes",
                 &DoEmitPopulateLanguageMap::onLangToSuffixes);

      staticMembersInitialized_ = true;
    }
  }

  void operator() (Init* I) {
    InvokeDagInitHandler(this, I);
  }

private:

  void onLangToSuffixes (const DagInit& d) {
    CheckNumberOfArguments(d, 2);

    const std::string& Lang = InitPtrToString(d.getArg(0));
    Init* Suffixes = d.getArg(1);

    // Second argument to lang_to_suffixes is either a single string...
    if (typeid(*Suffixes) == typeid(StringInit)) {
      O_.indent(Indent1) << "langMap[\"" << InitPtrToString(Suffixes)
                         << "\"] = \"" << Lang << "\";\n";
    }
    // ...or a list of strings.
    else {
      const ListInit& Lst = InitPtrToList(Suffixes);
      assert(Lst.size() != 0);
      for (ListInit::const_iterator B = Lst.begin(), E = Lst.end();
           B != E; ++B) {
        O_.indent(Indent1) << "langMap[\"" << InitPtrToString(*B)
                           << "\"] = \"" << Lang << "\";\n";
      }
    }
  }

};

/// EmitPopulateLanguageMap - Emit the PopulateLanguageMap() function.
void EmitPopulateLanguageMap (const RecordKeeper& Records, raw_ostream& O)
{
  O << "int PopulateLanguageMap (LanguageMap& langMap) {\n";

  // For each LanguageMap:
  const RecordVector& LangMaps =
    Records.getAllDerivedDefinitions("LanguageMap");

  // Call DoEmitPopulateLanguageMap.
  for (RecordVector::const_iterator B = LangMaps.begin(),
         E = LangMaps.end(); B!=E; ++B) {
    ListInit* LangMap = (*B)->getValueAsListInit("map");
    std::for_each(LangMap->begin(), LangMap->end(),
                  DoEmitPopulateLanguageMap(O));
  }

  O << '\n';
  O.indent(Indent1) << "return 0;\n";
  O << "}\n\n";
}

/// EmitEdgePropertyHandlerCallback - Emits code that handles edge
/// properties. Helper function passed to EmitCaseConstructHandler() by
/// EmitEdgeClass().
void EmitEdgePropertyHandlerCallback (const Init* i, unsigned IndentLevel,
                                      raw_ostream& O) {
  const DagInit& d = InitPtrToDag(i);
  const std::string& OpName = GetOperatorName(d);

  if (OpName == "inc_weight") {
    O.indent(IndentLevel) << "ret += ";
  }
  else if (OpName == "error") {
    CheckNumberOfArguments(d, 1);
    O.indent(IndentLevel) << "PrintError(\""
                          << InitPtrToString(d.getArg(0))
                          << "\");\n";
    O.indent(IndentLevel) << "return -1;\n";
    return;
  }
  else {
    throw "Unknown operator in edge properties list: '" + OpName + "'!"
      "\nOnly 'inc_weight', 'dec_weight' and 'error' are allowed.";
  }

  if (d.getNumArgs() > 0)
    O << InitPtrToInt(d.getArg(0)) << ";\n";
  else
    O << "2;\n";

}

/// EmitEdgeClass - Emit a single Edge# class.
void EmitEdgeClass (unsigned N, const std::string& Target,
                    const DagInit& Case, const OptionDescriptions& OptDescs,
                    raw_ostream& O) {

  // Class constructor.
  O << "class Edge" << N << ": public Edge {\n"
    << "public:\n";
  O.indent(Indent1) << "Edge" << N << "() : Edge(\"" << Target
                    << "\") {}\n\n";

  // Function Weight().
  O.indent(Indent1)
    << "int Weight(const InputLanguagesSet& InLangs) const {\n";
  O.indent(Indent2) << "unsigned ret = 0;\n";

  // Handle the 'case' construct.
  EmitCaseConstructHandler(&Case, Indent2, EmitEdgePropertyHandlerCallback,
                           false, OptDescs, O);

  O.indent(Indent2) << "return ret;\n";
  O.indent(Indent1) << "}\n\n};\n\n";
}

/// EmitEdgeClasses - Emit Edge* classes that represent graph edges.
void EmitEdgeClasses (const DagVector& EdgeVector,
                      const OptionDescriptions& OptDescs,
                      raw_ostream& O) {
  int i = 0;
  for (DagVector::const_iterator B = EdgeVector.begin(),
         E = EdgeVector.end(); B != E; ++B) {
    const DagInit& Edge = **B;
    const std::string& Name = GetOperatorName(Edge);

    if (Name == "optional_edge") {
      assert(IsOptionalEdge(Edge));
      const std::string& NodeB = InitPtrToString(Edge.getArg(1));

      const DagInit& Weight = InitPtrToDag(Edge.getArg(2));
      EmitEdgeClass(i, NodeB, Weight, OptDescs, O);
    }
    else if (Name != "edge") {
      throw "Unknown edge class: '" + Name + "'!";
    }

    ++i;
  }
}

/// EmitPopulateCompilationGraph - Emit the PopulateCompilationGraph() function.
void EmitPopulateCompilationGraph (const DagVector& EdgeVector,
                                   const ToolDescriptions& ToolDescs,
                                   raw_ostream& O)
{
  O << "int PopulateCompilationGraph (CompilationGraph& G) {\n";

  for (ToolDescriptions::const_iterator B = ToolDescs.begin(),
         E = ToolDescs.end(); B != E; ++B)
    O.indent(Indent1) << "G.insertNode(new " << (*B)->Name << "());\n";

  O << '\n';

  // Insert edges.

  int i = 0;
  for (DagVector::const_iterator B = EdgeVector.begin(),
         E = EdgeVector.end(); B != E; ++B) {
    const DagInit& Edge = **B;
    const std::string& NodeA = InitPtrToString(Edge.getArg(0));
    const std::string& NodeB = InitPtrToString(Edge.getArg(1));

    O.indent(Indent1) << "if (int ret = G.insertEdge(\"" << NodeA << "\", ";

    if (IsOptionalEdge(Edge))
      O << "new Edge" << i << "()";
    else
      O << "new SimpleEdge(\"" << NodeB << "\")";

    O << "))\n";
    O.indent(Indent2) << "return ret;\n";

    ++i;
  }

  O << '\n';
  O.indent(Indent1) << "return 0;\n";
  O << "}\n\n";
}

/// HookInfo - Information about the hook type and number of arguments.
struct HookInfo {

  // A hook can either have a single parameter of type std::vector<std::string>,
  // or NumArgs parameters of type const char*.
  enum HookType { ListHook, ArgHook };

  HookType Type;
  unsigned NumArgs;

  HookInfo() : Type(ArgHook), NumArgs(1)
  {}

  HookInfo(HookType T) : Type(T), NumArgs(1)
  {}

  HookInfo(unsigned N) : Type(ArgHook), NumArgs(N)
  {}
};

typedef llvm::StringMap<HookInfo> HookInfoMap;

/// ExtractHookNames - Extract the hook names from all instances of
/// $CALL(HookName) in the provided command line string/action. Helper
/// function used by FillInHookNames().
class ExtractHookNames {
  HookInfoMap& HookNames_;
  const OptionDescriptions& OptDescs_;
public:
  ExtractHookNames(HookInfoMap& HookNames, const OptionDescriptions& OptDescs)
    : HookNames_(HookNames), OptDescs_(OptDescs)
  {}

  void onAction (const DagInit& Dag) {
    const std::string& Name = GetOperatorName(Dag);

    if (Name == "forward_transformed_value") {
      CheckNumberOfArguments(Dag, 2);
      const std::string& OptName = InitPtrToString(Dag.getArg(0));
      const std::string& HookName = InitPtrToString(Dag.getArg(1));
      const OptionDescription& D =
        OptDescs_.FindParameterListOrParameter(OptName);

      HookNames_[HookName] = HookInfo(D.isList() ? HookInfo::ListHook
                                      : HookInfo::ArgHook);
    }
    else if (Name == "append_cmd" || Name == "output_suffix") {
      CheckNumberOfArguments(Dag, 1);
      this->onCmdLine(InitPtrToString(Dag.getArg(0)));
    }
  }

  void onCmdLine(const std::string& Cmd) {
    StrVector cmds;
    TokenizeCmdLine(Cmd, cmds);

    for (StrVector::const_iterator B = cmds.begin(), E = cmds.end();
         B != E; ++B) {
      const std::string& cmd = *B;

      if (cmd == "$CALL") {
        unsigned NumArgs = 0;
        CheckedIncrement(B, E, "Syntax error in $CALL invocation!");
        const std::string& HookName = *B;

        if (HookName.at(0) == ')')
          throw "$CALL invoked with no arguments!";

        while (++B != E && B->at(0) != ')') {
          ++NumArgs;
        }

        HookInfoMap::const_iterator H = HookNames_.find(HookName);

        if (H != HookNames_.end() && H->second.NumArgs != NumArgs &&
            H->second.Type != HookInfo::ArgHook)
          throw "Overloading of hooks is not allowed. Overloaded hook: "
            + HookName;
        else
          HookNames_[HookName] = HookInfo(NumArgs);
      }
    }
  }

  void operator()(const Init* Arg) {

    // We're invoked on an action (either a dag or a dag list).
    if (typeid(*Arg) == typeid(DagInit)) {
      const DagInit& Dag = InitPtrToDag(Arg);
      this->onAction(Dag);
      return;
    }
    else if (typeid(*Arg) == typeid(ListInit)) {
      const ListInit& List = InitPtrToList(Arg);
      for (ListInit::const_iterator B = List.begin(), E = List.end(); B != E;
           ++B) {
        const DagInit& Dag = InitPtrToDag(*B);
        this->onAction(Dag);
      }
      return;
    }

    // We're invoked on a command line string.
    this->onCmdLine(InitPtrToString(Arg));
  }

  void operator()(const Init* Statement, unsigned) {
    this->operator()(Statement);
  }
};

/// FillInHookNames - Actually extract the hook names from all command
/// line strings. Helper function used by EmitHookDeclarations().
void FillInHookNames(const ToolDescriptions& ToolDescs,
                     const OptionDescriptions& OptDescs,
                     HookInfoMap& HookNames)
{
  // For all tool descriptions:
  for (ToolDescriptions::const_iterator B = ToolDescs.begin(),
         E = ToolDescs.end(); B != E; ++B) {
    const ToolDescription& D = *(*B);

    // Look for 'forward_transformed_value' in 'actions'.
    if (D.Actions)
      WalkCase(D.Actions, Id(), ExtractHookNames(HookNames, OptDescs));

    // Look for hook invocations in 'cmd_line'.
    if (!D.CmdLine)
      continue;
    if (dynamic_cast<StringInit*>(D.CmdLine))
      // This is a string.
      ExtractHookNames(HookNames, OptDescs).operator()(D.CmdLine);
    else
      // This is a 'case' construct.
      WalkCase(D.CmdLine, Id(), ExtractHookNames(HookNames, OptDescs));
  }
}

/// EmitHookDeclarations - Parse CmdLine fields of all the tool
/// property records and emit hook function declaration for each
/// instance of $CALL(HookName).
void EmitHookDeclarations(const ToolDescriptions& ToolDescs,
                          const OptionDescriptions& OptDescs, raw_ostream& O) {
  HookInfoMap HookNames;

  FillInHookNames(ToolDescs, OptDescs, HookNames);
  if (HookNames.empty())
    return;

  for (HookInfoMap::const_iterator B = HookNames.begin(),
         E = HookNames.end(); B != E; ++B) {
    const char* HookName = B->first();
    const HookInfo& Info = B->second;

    O.indent(Indent1) << "std::string " << HookName << "(";

    if (Info.Type == HookInfo::ArgHook) {
      for (unsigned i = 0, j = Info.NumArgs; i < j; ++i) {
        O << "const char* Arg" << i << (i+1 == j ? "" : ", ");
      }
    }
    else {
      O << "const std::vector<std::string>& Arg";
    }

    O <<");\n";
  }
}

/// EmitIncludes - Emit necessary #include directives and some
/// additional declarations.
void EmitIncludes(raw_ostream& O) {
  O << "#include \"llvm/CompilerDriver/BuiltinOptions.h\"\n"
    << "#include \"llvm/CompilerDriver/CompilationGraph.h\"\n"
    << "#include \"llvm/CompilerDriver/Error.h\"\n"
    << "#include \"llvm/CompilerDriver/Tool.h\"\n\n"

    << "#include \"llvm/Support/CommandLine.h\"\n"
    << "#include \"llvm/Support/raw_ostream.h\"\n\n"

    << "#include <algorithm>\n"
    << "#include <cstdlib>\n"
    << "#include <iterator>\n"
    << "#include <stdexcept>\n\n"

    << "using namespace llvm;\n"
    << "using namespace llvmc;\n\n"

    << "inline const char* checkCString(const char* s)\n"
    << "{ return s == NULL ? \"\" : s; }\n\n";
}


/// DriverData - Holds all information about the driver.
struct DriverData {
  OptionDescriptions OptDescs;
  ToolDescriptions ToolDescs;
  DagVector Edges;
  bool HasSink;
};

/// HasSink - Go through the list of tool descriptions and check if
/// there are any with the 'sink' property set.
bool HasSink(const ToolDescriptions& ToolDescs) {
  for (ToolDescriptions::const_iterator B = ToolDescs.begin(),
         E = ToolDescs.end(); B != E; ++B)
    if ((*B)->isSink())
      return true;

  return false;
}

/// CollectDriverData - Collect compilation graph edges, tool properties and
/// option properties from the parse tree.
void CollectDriverData (const RecordKeeper& Records, DriverData& Data) {
  // Collect option properties.
  const RecordVector& OptionLists =
    Records.getAllDerivedDefinitions("OptionList");
  CollectOptionDescriptions(OptionLists, Data.OptDescs);

  // Collect tool properties.
  const RecordVector& Tools = Records.getAllDerivedDefinitions("Tool");
  CollectToolDescriptions(Tools, Data.ToolDescs);
  Data.HasSink = HasSink(Data.ToolDescs);

  // Collect compilation graph edges.
  const RecordVector& CompilationGraphs =
    Records.getAllDerivedDefinitions("CompilationGraph");
  FillInEdgeVector(CompilationGraphs, Data.Edges);
}

/// CheckDriverData - Perform some sanity checks on the collected data.
void CheckDriverData(DriverData& Data) {
  // Filter out all tools not mentioned in the compilation graph.
  FilterNotInGraph(Data.Edges, Data.ToolDescs);

  // Typecheck the compilation graph.
  TypecheckGraph(Data.Edges, Data.ToolDescs);

  // Check that there are no options without side effects (specified
  // only in the OptionList).
  CheckForSuperfluousOptions(Data.Edges, Data.ToolDescs, Data.OptDescs);
}

void EmitDriverCode(const DriverData& Data, 
                    raw_ostream& O, RecordKeeper &Records) {
  // Emit file header.
  EmitIncludes(O);

  // Emit global option registration code.
  O << "namespace llvmc {\n"
    << "namespace autogenerated {\n\n";
  EmitOptionDefinitions(Data.OptDescs, Data.HasSink, O);
  O << "} // End namespace autogenerated.\n"
    << "} // End namespace llvmc.\n\n";

  // Emit hook declarations.
  O << "namespace hooks {\n";
  EmitHookDeclarations(Data.ToolDescs, Data.OptDescs, O);
  O << "} // End namespace hooks.\n\n";

  O << "namespace {\n\n";
  O << "using namespace llvmc::autogenerated;\n\n";

  // Emit Tool classes.
  for (ToolDescriptions::const_iterator B = Data.ToolDescs.begin(),
         E = Data.ToolDescs.end(); B!=E; ++B)
    EmitToolClassDefinition(*(*B), Data.OptDescs, O);

  // Emit Edge# classes.
  EmitEdgeClasses(Data.Edges, Data.OptDescs, O);

  O << "} // End anonymous namespace.\n\n";

  O << "namespace llvmc {\n";
  O << "namespace autogenerated {\n\n";

  // Emit PreprocessOptions() function.
  EmitPreprocessOptions(Records, Data.OptDescs, O);

  // Emit PopulateLanguageMap() function
  // (language map maps from file extensions to language names).
  EmitPopulateLanguageMap(Records, O);

  // Emit PopulateCompilationGraph() function.
  EmitPopulateCompilationGraph(Data.Edges, Data.ToolDescs, O);

  O << "} // End namespace autogenerated.\n";
  O << "} // End namespace llvmc.\n\n";

  // EOF
}


// End of anonymous namespace
}

/// run - The back-end entry point.
void LLVMCConfigurationEmitter::run (raw_ostream &O) {
  try {
    DriverData Data;

    CollectDriverData(Records, Data);
    CheckDriverData(Data);

    this->EmitSourceFileHeader("llvmc-based driver: auto-generated code", O);
    EmitDriverCode(Data, O, Records);

  } catch (std::exception& Error) {
    throw Error.what() + std::string(" - usually this means a syntax error.");
  }
}
