//===- 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;
}

// apply is needed because C++'s syntax doesn't let us construct a function
// object and call it in the same statement.
template<typename F, typename T0>
void apply(F Fun, T0& Arg0) {
  return Fun(Arg0);
}

template<typename F, typename T0, typename T1>
void apply(F Fun, T0& Arg0, T1& Arg1) {
  return Fun(Arg0, Arg1);
}

//===----------------------------------------------------------------------===//
/// 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);

    if (OD.isAlias()) {
      // Aliases store the aliased option name in the 'Help' field.
      OD.Help = InitPtrToString(d.getArg(1));
    }
    else {
      processOptionProperties(d, OD);
    }

    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:
    // collect the information and
    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;
  std::string 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);
  }

  void onInLanguage (const DagInit& d) {
    CheckNumberOfArguments(d, 1);
    Init* arg = d.getArg(0);

    // Find out the argument's type.
    if (typeid(*arg) == typeid(StringInit)) {
      // It's a string.
      toolDesc_.InLanguage.push_back(InitPtrToString(arg));
    }
    else {
      // It's a list.
      const ListInit& lst = InitPtrToList(arg);
      StrVector& out = toolDesc_.InLanguage;

      // Copy strings to the output vector.
      for (ListInit::const_iterator B = lst.begin(), E = lst.end();
           B != E; ++B) {
        out.push_back(InitPtrToString(*B));
      }

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

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

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

  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) languages.  Helper function used by TypecheckGraph().
void FillInToolToLang (const ToolDescriptions& ToolDescs,
                       StringMap<StringSet<> >& ToolToInLang,
                       StringMap<std::string>& 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);
    ToolToOutLang[D.Name] = D.OutLanguage;
  }
}

/// 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<std::string> ToolToOutLang;

  FillInToolToLang(ToolDescs, ToolToInLang, ToolToOutLang);
  StringMap<std::string>::iterator IAE = ToolToOutLang.end();
  StringMap<StringSet<> >::iterator IBE = ToolToInLang.end();

  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<std::string>::iterator IA = ToolToOutLang.find(NodeA);
    StringMap<StringSet<> >::iterator IB = ToolToInLang.find(NodeB);

    if (NodeA != "root") {
      if (IA != IAE && IB != IBE && IB->second.count(IA->second) == 0)
        throw "Edge " + NodeA + "->" + NodeB
          + ": output->input language mismatch";
    }

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

/// 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 == "switch_on" || ActionName == "any_switch_on" ||
        ActionName == "parameter_equals" ||
        ActionName == "element_in_list" || ActionName == "not_empty" ||
        ActionName == "empty") {
      CheckNumberOfArguments(Stmt, 1);

      Init* Arg = Stmt.getArg(0);
      if (typeid(*Arg) == typeid(StringInit)) {
        const std::string& Name = InitPtrToString(Arg);
        OptionNames_.insert(Name);
      }
      else {
        // It's a list.
        const ListInit& List = InitPtrToList(Arg);
        for (ListInit::const_iterator B = List.begin(), E = List.end();
             B != E; ++B) {
          const std::string& Name = InitPtrToString(*B);
          OptionNames_.insert(Name);
        }
      }
    }
    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) {
    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;
}

/// EmitListTest - Helper function used by EmitCaseTest1ArgList().
template <typename F>
void EmitListTest(const ListInit& L, const char* LogicOp,
                  F Callback, raw_ostream& O)
{
  // This is a lot like EmitLogicalOperationTest, but works on ListInits instead
  // of Dags...
  bool isFirst = true;
  for (ListInit::const_iterator B = L.begin(), E = L.end(); B != E; ++B) {
    if (isFirst)
      isFirst = false;
    else
      O << ' ' << LogicOp << ' ';
    Callback(InitPtrToString(*B), O);
  }
}

// Callbacks for use with EmitListTest.

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()";
    }
  }
};


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

  if (TestName == "any_switch_on") {
    EmitListTest(L, "||", EmitSwitchOn(OptDescs), O);
    return true;
  }
  else if (TestName == "switch_on") {
    EmitListTest(L, "&&", EmitSwitchOn(OptDescs), O);
    return true;
  }
  else if (TestName == "any_not_empty") {
    EmitListTest(L, "||", EmitEmptyTest(true, OptDescs), O);
    return true;
  }
  else if (TestName == "any_empty") {
    EmitListTest(L, "||", EmitEmptyTest(false, OptDescs), O);
    return true;
  }
  else if (TestName == "not_empty") {
    EmitListTest(L, "&&", EmitEmptyTest(true, OptDescs), O);
    return true;
  }
  else if (TestName == "empty") {
    EmitListTest(L, "&&", EmitEmptyTest(false, OptDescs), O);
    return true;
  }

  return false;
}

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

  if (TestName == "switch_on") {
    apply(EmitSwitchOn(OptDescs), OptName, O);
    return true;
  }
  else if (TestName == "input_languages_contain") {
    O << "InLangs.count(\"" << OptName << "\") != 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) == \"" << OptName << '\"';
    return true;
  }
  else if (TestName == "not_empty" || TestName == "empty") {
    bool EmitNegate = (TestName == "not_empty");
    apply(EmitEmptyTest(EmitNegate, OptDescs), OptName, O);
    return true;
  }

  return false;
}

/// EmitCaseTest1Arg - Helper function used by EmitCaseConstructHandler();
bool EmitCaseTest1Arg(const std::string& TestName,
                      const DagInit& d,
                      const OptionDescriptions& OptDescs,
                      raw_ostream& O) {
  CheckNumberOfArguments(d, 1);
  if (typeid(*d.getArg(0)) == typeid(ListInit))
    return EmitCaseTest1ArgList(TestName, d, OptDescs, O);
  else
    return EmitCaseTest1ArgStr(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 j = 0, NumArgs = d.getNumArgs(); j < NumArgs; ++j) {
    const DagInit& InnerTest = InitPtrToDag(d.getArg(j));
    EmitCaseTest(InnerTest, IndentLevel, OptDescs, O);
    if (j != 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 (EmitCaseTest1Arg(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) {

    // Ignore nested 'case' DAG.
    if (!(dynamic_cast<const DagInit*>(Statement) &&
          GetOperatorName(static_cast<const DagInit&>(*Statement)) == "case")) {
      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";

  if (D.OutLanguage.empty())
    throw "Tool " + D.Name + " has no 'out_language' property!";

  O.indent(Indent1) << "const char* OutputLanguage() const {\n";
  O.indent(Indent2) << "return \"" << D.OutLanguage << "\";\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";
}

/// 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!";

  O << "const char* " << D.Name << "::InputLanguages_[] = {";
  for (StrVector::const_iterator B = D.InLanguage.begin(),
         E = D.InLanguage.end(); B != E; ++B)
    O << '\"' << *B << "\", ";
  O << "0};\n\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\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 onListOrDag(const DagInit& d, HandlerImpl h,
                   unsigned IndentLevel, raw_ostream& O) const
  {
    CheckNumberOfArguments(d, 1);
    const Init* I = d.getArg(0);

    // If I is a list, apply h to each element.
    if (typeid(*I) == typeid(ListInit)) {
      const ListInit& L = *static_cast<const ListInit*>(I);
      for (ListInit::const_iterator B = L.begin(), E = L.end(); B != E; ++B)
        ((this)->*(h))(*B, IndentLevel, O);
    }
    // Otherwise, apply h to I.
    else {
      ((this)->*(h))(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->onListOrDag(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 Init* Value = d.getArg(1);
    const OptionDescription& OptDesc = OptDescs_.FindOption(OptName);

    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);

    // Two arguments: (set_option "parameter", VALUE), where VALUE can be a
    // boolean, a string or a string list.
    if (d.getNumArgs() > 1)
      this->onSetOptionImpl(d, IndentLevel, O);
    // One argument: (set_option "switch")
    // or (set_option ["switch1", "switch2", ...])
    else
      this->onListOrDag(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 LangMap:
  const RecordVector& LangMaps =
    Records.getAllDerivedDefinitions("LanguageMap");

  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.
    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) {
  // 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);

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