/*============================================================================
  CMake - Cross Platform Makefile Generator
  Copyright 2000-2009 Kitware, Inc., Insight Software Consortium

  Distributed under the OSI-approved BSD License (the "License");
  see accompanying file Copyright.txt for details.

  This software is distributed WITHOUT ANY WARRANTY; without even the
  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  See the License for more information.
============================================================================*/
#include "cmMakefile.h"
#include "cmVersion.h"
#include "cmCommand.h"
#include "cmSourceFile.h"
#include "cmSourceFileLocation.h"
#include "cmSystemTools.h"
#include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h"
#include "cmCommands.h"
#include "cmCacheManager.h"
#include "cmFunctionBlocker.h"
#include "cmListFileCache.h"
#include "cmCommandArgumentParserHelper.h"
#include "cmTest.h"
#ifdef CMAKE_BUILD_WITH_CMAKE
#  include "cmVariableWatch.h"
#endif
#include "cmInstallGenerator.h"
#include "cmTestGenerator.h"
#include "cmDefinitions.h"
#include "cmake.h"
#include <stdlib.h> // required for atoi

#include <cmsys/RegularExpression.hxx>

#include <cmsys/auto_ptr.hxx>

#include <stack>
#include <ctype.h> // for isspace

class cmMakefile::Internals
{
public:
  std::stack<cmDefinitions, std::list<cmDefinitions> > VarStack;
};

// default is not to be building executables
cmMakefile::cmMakefile(): Internal(new Internals)
{
  this->Internal->VarStack.push(cmDefinitions());

  // Setup the default include file regular expression (match everything).
  this->IncludeFileRegularExpression = "^.*$";
  // Setup the default include complaint regular expression (match nothing).
  this->ComplainFileRegularExpression = "^$";
  // Source and header file extensions that we can handle

  // Set up a list of source and header extensions
  // these are used to find files when the extension
  // is not given
  // The "c" extension MUST precede the "C" extension.
  this->SourceFileExtensions.push_back( "c" );
  this->SourceFileExtensions.push_back( "C" );

  this->SourceFileExtensions.push_back( "c++" );
  this->SourceFileExtensions.push_back( "cc" );
  this->SourceFileExtensions.push_back( "cpp" );
  this->SourceFileExtensions.push_back( "cxx" );
  this->SourceFileExtensions.push_back( "m" );
  this->SourceFileExtensions.push_back( "M" );
  this->SourceFileExtensions.push_back( "mm" );

  this->HeaderFileExtensions.push_back( "h" );
  this->HeaderFileExtensions.push_back( "hh" );
  this->HeaderFileExtensions.push_back( "h++" );
  this->HeaderFileExtensions.push_back( "hm" );
  this->HeaderFileExtensions.push_back( "hpp" );
  this->HeaderFileExtensions.push_back( "hxx" );
  this->HeaderFileExtensions.push_back( "in" );
  this->HeaderFileExtensions.push_back( "txx" );

  this->DefineFlags = " ";
  this->LocalGenerator = 0;

  this->AddDefaultDefinitions();
  this->Initialize();
  this->PreOrder = false;
}

cmMakefile::cmMakefile(const cmMakefile& mf): Internal(new Internals)
{
  this->Internal->VarStack.push(mf.Internal->VarStack.top().Closure());

  this->Prefix = mf.Prefix;
  this->AuxSourceDirectories = mf.AuxSourceDirectories;
  this->cmStartDirectory = mf.cmStartDirectory;
  this->StartOutputDirectory = mf.StartOutputDirectory;
  this->cmHomeDirectory = mf.cmHomeDirectory;
  this->HomeOutputDirectory = mf.HomeOutputDirectory;
  this->cmCurrentListFile = mf.cmCurrentListFile;
  this->ProjectName = mf.ProjectName;
  this->Targets = mf.Targets;
  this->SourceFiles = mf.SourceFiles;
  this->Tests = mf.Tests;
  this->IncludeDirectories = mf.IncludeDirectories;
  this->LinkDirectories = mf.LinkDirectories;
  this->SystemIncludeDirectories = mf.SystemIncludeDirectories;
  this->ListFiles = mf.ListFiles;
  this->OutputFiles = mf.OutputFiles;
  this->LinkLibraries = mf.LinkLibraries;
  this->InstallGenerators = mf.InstallGenerators;
  this->TestGenerators = mf.TestGenerators;
  this->IncludeFileRegularExpression = mf.IncludeFileRegularExpression;
  this->ComplainFileRegularExpression = mf.ComplainFileRegularExpression;
  this->SourceFileExtensions = mf.SourceFileExtensions;
  this->HeaderFileExtensions = mf.HeaderFileExtensions;
  this->DefineFlags = mf.DefineFlags;
  this->DefineFlagsOrig = mf.DefineFlagsOrig;

#if defined(CMAKE_BUILD_WITH_CMAKE)
  this->SourceGroups = mf.SourceGroups;
#endif

  this->LocalGenerator = mf.LocalGenerator;
  this->FunctionBlockers = mf.FunctionBlockers;
  this->DataMap = mf.DataMap;
  this->MacrosMap = mf.MacrosMap;
  this->SubDirectoryOrder = mf.SubDirectoryOrder;
  this->Properties = mf.Properties;
  this->PreOrder = mf.PreOrder;
  this->ListFileStack = mf.ListFileStack;
  this->Initialize();
}

//----------------------------------------------------------------------------
void cmMakefile::Initialize()
{
  this->cmDefineRegex.compile("#cmakedefine[ \t]+([A-Za-z_0-9]*)");
  this->cmDefine01Regex.compile("#cmakedefine01[ \t]+([A-Za-z_0-9]*)");
  this->cmAtVarRegex.compile("(@[A-Za-z_0-9/.+-]+@)");

  // Enter a policy level for this directory.
  this->PushPolicy();

  // Protect the directory-level policies.
  this->PushPolicyBarrier();

  // By default the check is not done.  It is enabled by
  // cmListFileCache in the top level if necessary.
  this->CheckCMP0000 = false;
}

unsigned int cmMakefile::GetCacheMajorVersion()
{
  return this->GetCacheManager()->GetCacheMajorVersion();
}

unsigned int cmMakefile::GetCacheMinorVersion()
{
  return this->GetCacheManager()->GetCacheMinorVersion();
}

bool cmMakefile::NeedCacheCompatibility(int major, int minor)
{
  return this->GetCacheManager()->NeedCacheCompatibility(major, minor);
}

cmMakefile::~cmMakefile()
{
  for(std::vector<cmInstallGenerator*>::iterator
        i = this->InstallGenerators.begin();
      i != this->InstallGenerators.end(); ++i)
    {
    delete *i;
    }
  for(std::vector<cmTestGenerator*>::iterator
        i = this->TestGenerators.begin();
      i != this->TestGenerators.end(); ++i)
    {
    delete *i;
    }
  for(std::vector<cmSourceFile*>::iterator i = this->SourceFiles.begin();
      i != this->SourceFiles.end(); ++i)
    {
    delete *i;
    }
  for(std::map<cmStdString, cmTest*>::iterator i = this->Tests.begin();
      i != this->Tests.end(); ++i)
    {
    delete i->second;
    }
  for(std::vector<cmTarget*>::iterator
        i = this->ImportedTargetsOwned.begin();
      i != this->ImportedTargetsOwned.end(); ++i)
    {
    delete *i;
    }
  for(unsigned int i=0; i < this->UsedCommands.size(); i++)
    {
    delete this->UsedCommands[i];
    }
  for(DataMapType::const_iterator d = this->DataMap.begin();
      d != this->DataMap.end(); ++d)
    {
    if(d->second)
      {
      delete d->second;
      }
    }
  std::vector<cmFunctionBlocker*>::iterator pos;
  for (pos = this->FunctionBlockers.begin();
       pos != this->FunctionBlockers.end(); ++pos)
    {
    cmFunctionBlocker* b = *pos;
    delete b;
    }
  this->FunctionBlockers.clear();
  if (this->PolicyStack.size() != 1)
  {
    cmSystemTools::Error("Internal CMake Error, Policy Stack has not been"
      " popped properly");
  }
}

void cmMakefile::PrintStringVector(const char* s,
                                   const std::vector<std::string>& v) const
{
  std::cout << s << ": ( \n";
  for(std::vector<std::string>::const_iterator i = v.begin();
      i != v.end(); ++i)
    {
    std::cout << (*i).c_str() << " ";
    }
  std::cout << " )\n";
}

void cmMakefile
::PrintStringVector(const char* s,
                    const std::vector<std::pair<cmStdString, bool> >& v) const
{
  std::cout << s << ": ( \n";
  for(std::vector<std::pair<cmStdString, bool> >::const_iterator i
        = v.begin(); i != v.end(); ++i)
    {
    std::cout << i->first.c_str() << " " << i->second;
    }
  std::cout << " )\n";
}


// call print on all the classes in the makefile
void cmMakefile::Print()
{
  // print the class lists
  std::cout << "classes:\n";

  std::cout << " this->Targets: ";
  for (cmTargets::iterator l = this->Targets.begin();
       l != this->Targets.end(); l++)
    {
    std::cout << l->first << std::endl;
    }

  std::cout << " this->StartOutputDirectory; " <<
    this->StartOutputDirectory.c_str() << std::endl;
  std::cout << " this->HomeOutputDirectory; " <<
    this->HomeOutputDirectory.c_str() << std::endl;
  std::cout << " this->cmStartDirectory; " <<
    this->cmStartDirectory.c_str() << std::endl;
  std::cout << " this->cmHomeDirectory; " <<
    this->cmHomeDirectory.c_str() << std::endl;
  std::cout << " this->ProjectName; "
            <<  this->ProjectName.c_str() << std::endl;
  this->PrintStringVector("this->IncludeDirectories;",
                          this->IncludeDirectories);
  this->PrintStringVector("this->LinkDirectories", this->LinkDirectories);
#if defined(CMAKE_BUILD_WITH_CMAKE)
  for( std::vector<cmSourceGroup>::const_iterator i =
         this->SourceGroups.begin(); i != this->SourceGroups.end(); ++i)
    {
    std::cout << "Source Group: " << i->GetName() << std::endl;
    }
#endif
}

bool cmMakefile::CommandExists(const char* name) const
{
  return this->GetCMakeInstance()->CommandExists(name);
}


//----------------------------------------------------------------------------
void cmMakefile::IssueMessage(cmake::MessageType t,
                              std::string const& text) const
{
  // Collect context information.
  cmListFileBacktrace backtrace;
  if(!this->CallStack.empty())
    {
    if((t == cmake::FATAL_ERROR) || (t == cmake::INTERNAL_ERROR))
      {
      this->CallStack.back().Status->SetNestedError(true);
      }
    this->GetBacktrace(backtrace);
    }
  else
    {
    cmListFileContext lfc;
    if(this->ListFileStack.empty())
      {
      // We are not processing the project.  Add the directory-level context.
      lfc.FilePath = this->GetCurrentDirectory();
      lfc.FilePath += "/CMakeLists.txt";
      }
    else
      {
      // We are processing the project but are not currently executing a
      // command.  Add whatever context information we have.
      lfc.FilePath = this->ListFileStack.back();
      }
    lfc.Line = 0;
    if(!this->GetCMakeInstance()->GetIsInTryCompile())
      {
      lfc.FilePath = this->LocalGenerator->Convert(lfc.FilePath.c_str(),
                                                   cmLocalGenerator::HOME);
      }
    backtrace.push_back(lfc);
    }

  // Issue the message.
  this->GetCMakeInstance()->IssueMessage(t, text, backtrace);
}

//----------------------------------------------------------------------------
bool cmMakefile::GetBacktrace(cmListFileBacktrace& backtrace) const
{
  if(this->CallStack.empty())
    {
    return false;
    }
  for(CallStackType::const_reverse_iterator i = this->CallStack.rbegin();
      i != this->CallStack.rend(); ++i)
    {
    cmListFileContext lfc = *(*i).Context;
    lfc.FilePath = this->LocalGenerator->Convert(lfc.FilePath.c_str(),
                                                 cmLocalGenerator::HOME);
    backtrace.push_back(lfc);
    }
  return true;
}

//----------------------------------------------------------------------------
bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff,
                                cmExecutionStatus &status)
{
  bool result = true;

  // quick return if blocked
  if(this->IsFunctionBlocked(lff,status))
    {
    // No error.
    return result;
    }
  
  std::string name = lff.Name;

  // Place this call on the call stack.
  cmMakefileCall stack_manager(this, lff, status);
  static_cast<void>(stack_manager);

  // Lookup the command prototype.
  if(cmCommand* proto = this->GetCMakeInstance()->GetCommand(name.c_str()))
    {
    // Clone the prototype.
    cmsys::auto_ptr<cmCommand> pcmd(proto->Clone());
    pcmd->SetMakefile(this);

    // Decide whether to invoke the command.
    if(pcmd->GetEnabled() && !cmSystemTools::GetFatalErrorOccured()  &&
       (!this->GetCMakeInstance()->GetScriptMode() || pcmd->IsScriptable()))
      {
      // if trace is one, print out invoke information
      if(this->GetCMakeInstance()->GetTrace())
        {
        cmOStringStream msg;
        msg << lff.FilePath << "(" << lff.Line << "):  ";
        msg << lff.Name << "(";
        for(std::vector<cmListFileArgument>::const_iterator i = 
              lff.Arguments.begin(); i != lff.Arguments.end(); ++i)
          {
          msg << i->Value;
          msg << " ";
          }
        msg << ")";
        cmSystemTools::Message(msg.str().c_str());
        }
      // Try invoking the command.
      if(!pcmd->InvokeInitialPass(lff.Arguments,status) ||
         status.GetNestedError())
        {
        if(!status.GetNestedError())
          {
          // The command invocation requested that we report an error.
          this->IssueMessage(cmake::FATAL_ERROR, pcmd->GetError());
          }
        result = false;
        if ( this->GetCMakeInstance()->GetScriptMode() )
          {
          cmSystemTools::SetFatalErrorOccured();
          }
        }
      else if(pcmd->HasFinalPass())
        {
        // use the command
        this->UsedCommands.push_back(pcmd.release());
        }
      }
    else if ( this->GetCMakeInstance()->GetScriptMode()
              && !pcmd->IsScriptable() )
      {
      std::string error = "Command ";
      error += pcmd->GetName();
      error += "() is not scriptable";
      this->IssueMessage(cmake::FATAL_ERROR, error);
      result = false;
      cmSystemTools::SetFatalErrorOccured();
      }
    }
  else
    {
    if(!cmSystemTools::GetFatalErrorOccured())
      {
      std::string error = "Unknown CMake command \"";
      error += lff.Name;
      error += "\".";
      this->IssueMessage(cmake::FATAL_ERROR, error);
      result = false;
      cmSystemTools::SetFatalErrorOccured();
      }
    }

  return result;
}

//----------------------------------------------------------------------------
class cmMakefile::IncludeScope
{
public:
  IncludeScope(cmMakefile* mf, const char* fname, bool noPolicyScope);
  ~IncludeScope();
  void Quiet() { this->ReportError = false; }
private:
  cmMakefile* Makefile;
  const char* File;
  bool NoPolicyScope;
  bool CheckCMP0011;
  bool ReportError;
  void EnforceCMP0011();
};

//----------------------------------------------------------------------------
cmMakefile::IncludeScope::IncludeScope(cmMakefile* mf, const char* fname,
                                       bool noPolicyScope):
  Makefile(mf), File(fname), NoPolicyScope(noPolicyScope),
  CheckCMP0011(false), ReportError(true)
{
  if(!this->NoPolicyScope)
    {
    // Check CMP0011 to determine the policy scope type.
    switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0011))
      {
      case cmPolicies::WARN:
        // We need to push a scope to detect whether the script sets
        // any policies that would affect the includer and therefore
        // requires a warning.  We use a weak scope to simulate OLD
        // behavior by allowing policy changes to affect the includer.
        this->Makefile->PushPolicy(true);
        this->CheckCMP0011 = true;
        break;
      case cmPolicies::OLD:
        // OLD behavior is to not push a scope at all.
        this->NoPolicyScope = true;
        break;
      case cmPolicies::REQUIRED_IF_USED:
      case cmPolicies::REQUIRED_ALWAYS:
        // We should never make this policy required, but we handle it
        // here just in case.
        this->CheckCMP0011 = true;
      case cmPolicies::NEW:
        // NEW behavior is to push a (strong) scope.
        this->Makefile->PushPolicy();
        break;
      }
    }

  // The included file cannot pop our policy scope.
  this->Makefile->PushPolicyBarrier();
}

//----------------------------------------------------------------------------
cmMakefile::IncludeScope::~IncludeScope()
{
  // Enforce matching policy scopes inside the included file.
  this->Makefile->PopPolicyBarrier(this->ReportError);

  if(!this->NoPolicyScope)
    {
    // If we need to enforce policy CMP0011 then the top entry is the
    // one we pushed above.  If the entry is empty, then the included
    // script did not set any policies that might affect the includer so
    // we do not need to enforce the policy.
    if(this->CheckCMP0011 && this->Makefile->PolicyStack.back().empty())
      {
      this->CheckCMP0011 = false;
      }

    // Pop the scope we pushed for the script.
    this->Makefile->PopPolicy();

    // We enforce the policy after the script's policy stack entry has
    // been removed.
    if(this->CheckCMP0011)
      {
      this->EnforceCMP0011();
      }
    }
}

//----------------------------------------------------------------------------
void cmMakefile::IncludeScope::EnforceCMP0011()
{
  // We check the setting of this policy again because the included
  // script might actually set this policy for its includer.
  cmPolicies* policies = this->Makefile->GetPolicies();
  switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0011))
    {
    case cmPolicies::WARN:
      // Warn because the user did not set this policy.
      {
      cmOStringStream w;
      w << policies->GetPolicyWarning(cmPolicies::CMP0011) << "\n"
        << "The included script\n  " << this->File << "\n"
        << "affects policy settings.  "
        << "CMake is implying the NO_POLICY_SCOPE option for compatibility, "
        << "so the effects are applied to the including context.";
      this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str());
      }
      break;
    case cmPolicies::REQUIRED_IF_USED:
    case cmPolicies::REQUIRED_ALWAYS:
      {
      cmOStringStream e;
      e << policies->GetRequiredPolicyError(cmPolicies::CMP0011) << "\n"
        << "The included script\n  " << this->File << "\n"
        << "affects policy settings, so it requires this policy to be set.";
      this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
      }
      break;
    case cmPolicies::OLD:
    case cmPolicies::NEW:
      // The script set this policy.  We assume the purpose of the
      // script is to initialize policies for its includer, and since
      // the policy is now set for later scripts, we do not warn.
      break;
    }
}

//----------------------------------------------------------------------------
// Parse the given CMakeLists.txt file executing all commands
//
bool cmMakefile::ReadListFile(const char* filename_in,
                              const char *external_in,
                              std::string* fullPath,
                              bool noPolicyScope)
{
  std::string currentParentFile
    = this->GetSafeDefinition("CMAKE_PARENT_LIST_FILE");
  std::string currentFile
    = this->GetSafeDefinition("CMAKE_CURRENT_LIST_FILE");
  this->AddDefinition("CMAKE_PARENT_LIST_FILE", filename_in);

  const char* external = 0;
  std::string external_abs;

  const char* filename = filename_in;
  std::string filename_abs;

  if (external_in)
    {
    external_abs =
      cmSystemTools::CollapseFullPath(external_in,
                                      this->cmStartDirectory.c_str());
    external = external_abs.c_str();
    if (filename_in)
      {
      filename_abs =
        cmSystemTools::CollapseFullPath(filename_in,
                                        this->cmStartDirectory.c_str());
      filename = filename_abs.c_str();
      }
    }

  // keep track of the current file being read
  if (filename)
    {
    if(this->cmCurrentListFile != filename)
      {
      this->cmCurrentListFile = filename;
      }
    }

  // Now read the input file
  const char *filenametoread= filename;

  if( external)
    {
    filenametoread= external;
    }

  this->AddDefinition("CMAKE_CURRENT_LIST_FILE", filenametoread);

  // try to see if the list file is the top most
  // list file for a project, and if it is, then it
  // must have a project command.   If there is not
  // one, then cmake will provide one via the
  // cmListFileCache class.
  bool requireProjectCommand = false;
  if(!external && this->cmStartDirectory == this->cmHomeDirectory)
    {
    if(cmSystemTools::LowerCase(
      cmSystemTools::GetFilenameName(filename)) == "cmakelists.txt")
      {
      requireProjectCommand = true;
      }
    }

  // push the listfile onto the stack
  this->ListFileStack.push_back(filenametoread);
  if(fullPath!=0)
    {
    *fullPath=filenametoread;
    }
  cmListFile cacheFile;
  if( !cacheFile.ParseFile(filenametoread, requireProjectCommand, this) )
    {
    // pop the listfile off the stack
    this->ListFileStack.pop_back();
    if(fullPath!=0)
      {
      *fullPath = "";
      }
    this->AddDefinition("CMAKE_PARENT_LIST_FILE", currentParentFile.c_str());
    this->AddDefinition("CMAKE_CURRENT_LIST_FILE", currentFile.c_str());
    return false;
    }
  // add this list file to the list of dependencies
  this->ListFiles.push_back( filenametoread);

  // Enforce balanced blocks (if/endif, function/endfunction, etc.).
  {
  LexicalPushPop lexScope(this);
  IncludeScope incScope(this, filenametoread, noPolicyScope);

  // Run the parsed commands.
  const size_t numberFunctions = cacheFile.Functions.size();
  for(size_t i =0; i < numberFunctions; ++i)
    {
    cmExecutionStatus status;
    this->ExecuteCommand(cacheFile.Functions[i],status);
    if(cmSystemTools::GetFatalErrorOccured())
      {
      // Exit early due to error.
      lexScope.Quiet();
      incScope.Quiet();
      break;
      }
    if(status.GetReturnInvoked())
      {
      // Exit early due to return command.
      break;
      }
    }
  }

  // If this is the directory-level CMakeLists.txt file then perform
  // some extra checks.
  if(this->ListFileStack.size() == 1)
    {
    this->EnforceDirectoryLevelRules();
    }

  this->AddDefinition("CMAKE_PARENT_LIST_FILE", currentParentFile.c_str());
  this->AddDefinition("CMAKE_CURRENT_LIST_FILE", currentFile.c_str());

  // pop the listfile off the stack
  this->ListFileStack.pop_back();

  return true;
}

//----------------------------------------------------------------------------
void cmMakefile::EnforceDirectoryLevelRules()
{
  // Diagnose a violation of CMP0000 if necessary.
  if(this->CheckCMP0000)
    {
    cmOStringStream msg;
    msg << "No cmake_minimum_required command is present.  "
        << "A line of code such as\n"
        << "  cmake_minimum_required(VERSION "
        << cmVersion::GetMajorVersion() << "."
        << cmVersion::GetMinorVersion()
        << ")\n"
        << "should be added at the top of the file.  "
        << "The version specified may be lower if you wish to "
        << "support older CMake versions for this project.  "
        << "For more information run "
        << "\"cmake --help-policy CMP0000\".";
    switch (this->GetPolicyStatus(cmPolicies::CMP0000))
      {
      case cmPolicies::WARN:
        // Warn because the user did not provide a mimimum required
        // version.
        this->IssueMessage(cmake::AUTHOR_WARNING, msg.str().c_str());
      case cmPolicies::OLD:
        // OLD behavior is to use policy version 2.4 set in
        // cmListFileCache.
        break;
      case cmPolicies::REQUIRED_IF_USED:
      case cmPolicies::REQUIRED_ALWAYS:
      case cmPolicies::NEW:
        // NEW behavior is to issue an error.
        this->IssueMessage(cmake::FATAL_ERROR, msg.str().c_str());
        cmSystemTools::SetFatalErrorOccured();
        return;
      }
    }
}

void cmMakefile::AddCommand(cmCommand* wg)
{
  this->GetCMakeInstance()->AddCommand(wg);
}

// Set the make file
void cmMakefile::SetLocalGenerator(cmLocalGenerator* lg)
{
  this->LocalGenerator = lg;
  // the source groups need to access the global generator
  // so don't create them until the lg is set
#if defined(CMAKE_BUILD_WITH_CMAKE)
  this->AddSourceGroup("", "^.*$");
  this->AddSourceGroup
    ("Source Files",
     "\\.(C|M|c|c\\+\\+|cc|cpp|cxx|f|f90|for|fpp"
     "|ftn|m|mm|rc|def|r|odl|idl|hpj|bat)$");
  this->AddSourceGroup("Header Files",
                       "\\.(h|hh|h\\+\\+|hm|hpp|hxx|in|txx|inl)$");
  this->AddSourceGroup("CMake Rules", "\\.rule$");
  this->AddSourceGroup("Resources", "\\.plist$");
#endif

}

bool cmMakefile::NeedBackwardsCompatibility(unsigned int major,
                                            unsigned int minor,
                                            unsigned int patch)
{
  if(this->LocalGenerator)
    {
    return
      this->LocalGenerator->NeedBackwardsCompatibility(major, minor, patch);
    }
  else
    {
    return false;
    }
}

void cmMakefile::FinalPass()
{
  // do all the variable expansions here
  this->ExpandVariables();

  // give all the commands a chance to do something
  // after the file has been parsed before generation
  for(std::vector<cmCommand*>::iterator i = this->UsedCommands.begin();
      i != this->UsedCommands.end(); ++i)
    {
    (*i)->FinalPass();
    }

}

// Generate the output file
void cmMakefile::ConfigureFinalPass()
{
  this->FinalPass();
  const char* oldValue
    = this->GetDefinition("CMAKE_BACKWARDS_COMPATIBILITY");
  if (oldValue && atof(oldValue) <= 1.2)
    {
    cmSystemTools::Error("You have requested backwards compatibility "
                         "with CMake version 1.2 or earlier. This version "
                         "of CMake only supports backwards compatibility "
                         "with CMake 1.4 or later. For compatibility with "
                         "1.2 or earlier please use CMake 2.0");
    }
  for (cmTargets::iterator l = this->Targets.begin();
       l != this->Targets.end(); l++)
    {
    l->second.FinishConfigure();
    }
}

//----------------------------------------------------------------------------
void
cmMakefile::AddCustomCommandToTarget(const char* target,
                                     const std::vector<std::string>& depends,
                                     const cmCustomCommandLines& commandLines,
                                     cmTarget::CustomCommandType type,
                                     const char* comment,
                                     const char* workingDir,
                                     bool escapeOldStyle)
{
  // Find the target to which to add the custom command.
  cmTargets::iterator ti = this->Targets.find(target);
  if(ti != this->Targets.end())
    {
    // Add the command to the appropriate build step for the target.
    std::vector<std::string> no_output;
    cmCustomCommand cc(no_output, depends, commandLines, comment, workingDir);
    cc.SetEscapeOldStyle(escapeOldStyle);
    cc.SetEscapeAllowMakeVars(true);
    switch(type)
      {
      case cmTarget::PRE_BUILD:
        ti->second.GetPreBuildCommands().push_back(cc);
        break;
      case cmTarget::PRE_LINK:
        ti->second.GetPreLinkCommands().push_back(cc);
        break;
      case cmTarget::POST_BUILD:
        ti->second.GetPostBuildCommands().push_back(cc);
        break;
      }
    }
}

//----------------------------------------------------------------------------
void
cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs,
                                     const std::vector<std::string>& depends,
                                     const char* main_dependency,
                                     const cmCustomCommandLines& commandLines,
                                     const char* comment,
                                     const char* workingDir,
                                     bool replace,
                                     bool escapeOldStyle)
{
  // Make sure there is at least one output.
  if(outputs.empty())
    {
    cmSystemTools::Error("Attempt to add a custom rule with no output!");
    return;
    }

  // Choose a source file on which to store the custom command.
  cmSourceFile* file = 0;
  if(main_dependency && main_dependency[0])
    {
    // The main dependency was specified.  Use it unless a different
    // custom command already used it.
    file = this->GetSource(main_dependency);
    if(file && file->GetCustomCommand() && !replace)
      {
      // The main dependency already has a custom command.
      if(commandLines == file->GetCustomCommand()->GetCommandLines())
        {
        // The existing custom command is identical.  Silently ignore
        // the duplicate.
        return;
        }
      else
        {
        // The existing custom command is different.  We need to
        // generate a rule file for this new command.
        file = 0;
        }
      }
    else
      {
      // The main dependency does not have a custom command or we are
      // allowed to replace it.  Use it to store the command.
      file = this->GetOrCreateSource(main_dependency);
      }
    }

  // Generate a rule file if the main dependency is not available.
  if(!file)
    {
    // Construct a rule file associated with the first output produced.
    std::string outName = outputs[0];
    outName += ".rule";
    // Check if the rule file already exists.
    file = this->GetSource(outName.c_str());
    if(file && file->GetCustomCommand() && !replace)
      {
      // The rule file already exists.
      if(commandLines != file->GetCustomCommand()->GetCommandLines())
        {
        cmSystemTools::Error("Attempt to add a custom rule to output \"",
                             outName.c_str(),
                             "\" which already has a custom rule.");
        }
      return;
      }

    // Create a cmSourceFile for the rule file.
    file = this->GetOrCreateSource(outName.c_str(), true);
    }

  // Always create the output sources and mark them generated.
  for(std::vector<std::string>::const_iterator o = outputs.begin();
      o != outputs.end(); ++o)
    {
    if(cmSourceFile* out = this->GetOrCreateSource(o->c_str(), true))
      {
      out->SetProperty("GENERATED", "1");
      }
    }

  // Construct a complete list of dependencies.
  std::vector<std::string> depends2(depends);
  if(main_dependency && main_dependency[0])
    {
    depends2.push_back(main_dependency);
    }

  // Attach the custom command to the file.
  if(file)
    {
    cmCustomCommand* cc =
      new cmCustomCommand(outputs, depends2, commandLines,
                          comment, workingDir);
    cc->SetEscapeOldStyle(escapeOldStyle);
    cc->SetEscapeAllowMakeVars(true);
    file->SetCustomCommand(cc);
    }
}

//----------------------------------------------------------------------------
void
cmMakefile::AddCustomCommandToOutput(const char* output,
                                     const std::vector<std::string>& depends,
                                     const char* main_dependency,
                                     const cmCustomCommandLines& commandLines,
                                     const char* comment,
                                     const char* workingDir,
                                     bool replace,
                                     bool escapeOldStyle)
{
  std::vector<std::string> outputs;
  outputs.push_back(output);
  this->AddCustomCommandToOutput(outputs, depends, main_dependency,
                                 commandLines, comment, workingDir,
                                 replace, escapeOldStyle);
}

//----------------------------------------------------------------------------
void
cmMakefile::AddCustomCommandOldStyle(const char* target,
                                     const std::vector<std::string>& outputs,
                                     const std::vector<std::string>& depends,
                                     const char* source,
                                     const cmCustomCommandLines& commandLines,
                                     const char* comment)
{
  // Translate the old-style signature to one of the new-style
  // signatures.
  if(strcmp(source, target) == 0)
    {
    // In the old-style signature if the source and target were the
    // same then it added a post-build rule to the target.  Preserve
    // this behavior.
    this->AddCustomCommandToTarget(target, depends, commandLines,
                                   cmTarget::POST_BUILD, comment, 0);
    return;
    }

  // Each output must get its own copy of this rule.
  cmsys::RegularExpression sourceFiles("\\.(C|M|c|c\\+\\+|cc|cpp|cxx|m|mm|"
                                       "rc|def|r|odl|idl|hpj|bat|h|h\\+\\+|"
                                       "hm|hpp|hxx|in|txx|inl)$");
  for(std::vector<std::string>::const_iterator oi = outputs.begin();
      oi != outputs.end(); ++oi)
    {
    // Get the name of this output.
    const char* output = oi->c_str();

    // Choose whether to use a main dependency.
    if(sourceFiles.find(source))
      {
      // The source looks like a real file.  Use it as the main dependency.
      this->AddCustomCommandToOutput(output, depends, source,
                                     commandLines, comment, 0);
      }
    else
      {
      // The source may not be a real file.  Do not use a main dependency.
      const char* no_main_dependency = 0;
      std::vector<std::string> depends2 = depends;
      depends2.push_back(source);
      this->AddCustomCommandToOutput(output, depends2, no_main_dependency,
                                     commandLines, comment, 0);
      }

    // If the rule was added to the source (and not a .rule file),
    // then add the source to the target to make sure the rule is
    // included.
    std::string sname = output;
    sname += ".rule";
    if(!this->GetSource(sname.c_str()))
      {
      if (this->Targets.find(target) != this->Targets.end())
        {
        this->Targets[target].AddSource(source);
        }
      else
        {
        cmSystemTools::Error("Attempt to add a custom rule to a target "
                             "that does not exist yet for target ", target);
        return;
        }
      }
    }
}

//----------------------------------------------------------------------------
void cmMakefile::AddUtilityCommand(const char* utilityName,
                                   bool excludeFromAll,
                                   const std::vector<std::string>& depends,
                                   const char* workingDirectory,
                                   const char* command,
                                   const char* arg1,
                                   const char* arg2,
                                   const char* arg3,
                                   const char* arg4)
{
  // Construct the command line for the custom command.
  cmCustomCommandLine commandLine;
  commandLine.push_back(command);
  if(arg1)
    {
    commandLine.push_back(arg1);
    }
  if(arg2)
    {
    commandLine.push_back(arg2);
    }
  if(arg3)
    {
    commandLine.push_back(arg3);
    }
  if(arg4)
    {
    commandLine.push_back(arg4);
    }
  cmCustomCommandLines commandLines;
  commandLines.push_back(commandLine);

  // Call the real signature of this method.
  this->AddUtilityCommand(utilityName, excludeFromAll, workingDirectory,
                          depends, commandLines);
}

//----------------------------------------------------------------------------
cmTarget*
cmMakefile::AddUtilityCommand(const char* utilityName,
                              bool excludeFromAll,
                              const char* workingDirectory,
                              const std::vector<std::string>& depends,
                              const cmCustomCommandLines& commandLines,
                              bool escapeOldStyle, const char* comment)
{
  // Create a target instance for this utility.
  cmTarget* target = this->AddNewTarget(cmTarget::UTILITY, utilityName);
  if (excludeFromAll)
    {
    target->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
    }
  if(!comment)
    {
    // Use an empty comment to avoid generation of default comment.
    comment = "";
    }

  // Store the custom command in the target.
  std::string force = this->GetStartOutputDirectory();
  force += cmake::GetCMakeFilesDirectory();
  force += "/";
  force += utilityName;
  const char* no_main_dependency = 0;
  bool no_replace = false;
  this->AddCustomCommandToOutput(force.c_str(), depends,
                                 no_main_dependency,
                                 commandLines, comment,
                                 workingDirectory, no_replace,
                                 escapeOldStyle);
  cmSourceFile* sf = target->AddSource(force.c_str());

  // The output is not actually created so mark it symbolic.
  if(sf)
    {
    sf->SetProperty("SYMBOLIC", "1");
    }
  else
    {
    cmSystemTools::Error("Could not get source file entry for ",
                         force.c_str());
    }
  return target;
}

void cmMakefile::AddDefineFlag(const char* flag)
{
  if (!flag)
    {
    return;
    }

  // Update the string used for the old DEFINITIONS property.
  this->AddDefineFlag(flag, this->DefineFlagsOrig);

  // If this is really a definition, update COMPILE_DEFINITIONS.
  if(this->ParseDefineFlag(flag, false))
    {
    return;
    }

  // Add this flag that does not look like a definition.
  this->AddDefineFlag(flag, this->DefineFlags);
}

void cmMakefile::AddDefineFlag(const char* flag, std::string& dflags)
{
  // remove any \n\r
  std::string ret = flag;
  std::string::size_type pos = 0;
  while((pos = ret.find('\n', pos)) != std::string::npos)
    {
    ret[pos] = ' ';
    pos++;
    }
  pos = 0;
  while((pos = ret.find('\r', pos)) != std::string::npos)
    {
    ret[pos] = ' ';
    pos++;
    }

  dflags += " ";
  dflags += ret;
}


void cmMakefile::RemoveDefineFlag(const char* flag)
{
  // Check the length of the flag to remove.
  std::string::size_type len = strlen(flag);
  if(len < 1)
    {
    return;
    }

  // Update the string used for the old DEFINITIONS property.
  this->RemoveDefineFlag(flag, len, this->DefineFlagsOrig);

  // If this is really a definition, update COMPILE_DEFINITIONS.
  if(this->ParseDefineFlag(flag, true))
    {
    return;
    }

  // Remove this flag that does not look like a definition.
  this->RemoveDefineFlag(flag, len, this->DefineFlags);
}

void cmMakefile::RemoveDefineFlag(const char* flag,
                                  std::string::size_type len,
                                  std::string& dflags)
{
  // Remove all instances of the flag that are surrounded by
  // whitespace or the beginning/end of the string.
  for(std::string::size_type lpos = dflags.find(flag, 0);
      lpos != std::string::npos; lpos = dflags.find(flag, lpos))
    {
    std::string::size_type rpos = lpos + len;
    if((lpos <= 0 || isspace(dflags[lpos-1])) &&
       (rpos >= dflags.size() || isspace(dflags[rpos])))
      {
      dflags.erase(lpos, len);
      }
    else
      {
      ++lpos;
      }
    }
}

bool cmMakefile::ParseDefineFlag(std::string const& def, bool remove)
{
  // Create a regular expression to match valid definitions.
  static cmsys::RegularExpression
    valid("^[-/]D[A-Za-z_][A-Za-z0-9_]*(=.*)?$");

  // Make sure the definition matches.
  if(!valid.find(def.c_str()))
    {
    return false;
    }

  // VS6 IDE does not support definition values with spaces in
  // combination with '"', '$', or ';'.
  if((strcmp(this->LocalGenerator->GetGlobalGenerator()->GetName(),
             "Visual Studio 6") == 0) &&
     (def.find(" ") != def.npos && def.find_first_of("\"$;") != def.npos))
    {
    return false;
    }

  // Definitions with non-trivial values require a policy check.
  static cmsys::RegularExpression
    trivial("^[-/]D[A-Za-z_][A-Za-z0-9_]*(=[A-Za-z0-9_.]+)?$");
  if(!trivial.find(def.c_str()))
    {
    // This definition has a non-trivial value.
    switch(this->GetPolicyStatus(cmPolicies::CMP0005))
      {
      case cmPolicies::WARN:
        this->IssueMessage(
          cmake::AUTHOR_WARNING,
          this->GetPolicies()->GetPolicyWarning(cmPolicies::CMP0005)
          );
      case cmPolicies::OLD:
        // OLD behavior is to not escape the value.  We should not
        // convert the definition to use the property.
        return false;
      case cmPolicies::REQUIRED_IF_USED:
      case cmPolicies::REQUIRED_ALWAYS:
        this->IssueMessage(
          cmake::FATAL_ERROR,
          this->GetPolicies()->GetRequiredPolicyError(cmPolicies::CMP0005)
          );
        return false;
      case cmPolicies::NEW:
        // NEW behavior is to escape the value.  Proceed to convert it
        // to an entry in the property.
        break;
      }
    }

  // Get the definition part after the flag.
  const char* define = def.c_str() + 2;

  if(remove)
    {
    if(const char* cdefs = this->GetProperty("COMPILE_DEFINITIONS"))
      {
      // Expand the list.
      std::vector<std::string> defs;
      cmSystemTools::ExpandListArgument(cdefs, defs);

      // Recompose the list without the definition.
      std::string ndefs;
      const char* sep = "";
      for(std::vector<std::string>::const_iterator di = defs.begin();
          di != defs.end(); ++di)
        {
        if(*di != define)
          {
          ndefs += sep;
          sep = ";";
          ndefs += *di;
          }
        }

      // Store the new list.
      this->SetProperty("COMPILE_DEFINITIONS", ndefs.c_str());
      }
    }
  else
    {
    // Append the definition to the directory property.
    this->AppendProperty("COMPILE_DEFINITIONS", define);
    }

  return true;
}

void cmMakefile::AddLinkLibrary(const char* lib,
                                cmTarget::LinkLibraryType llt)
{
  cmTarget::LibraryID tmp;
  tmp.first = lib;
  tmp.second = llt;
  this->LinkLibraries.push_back(tmp);
}

void cmMakefile::AddLinkLibraryForTarget(const char *target,
                                         const char* lib,
                                         cmTarget::LinkLibraryType llt)
{
  cmTargets::iterator i = this->Targets.find(target);
  if ( i != this->Targets.end())
    {
    cmTarget* tgt =
      this->GetCMakeInstance()->GetGlobalGenerator()->FindTarget(0,lib);
    if(tgt)
      {
      // CMake versions below 2.4 allowed linking to modules.
      bool allowModules = this->NeedBackwardsCompatibility(2,2);
      // if it is not a static or shared library then you can not link to it
      if(!((tgt->GetType() == cmTarget::STATIC_LIBRARY) ||
           (tgt->GetType() == cmTarget::SHARED_LIBRARY) ||
           tgt->IsExecutableWithExports()))
        {
        cmOStringStream e;
        e << "Target \"" << lib << "\" of type "
          << cmTarget::TargetTypeNames[static_cast<int>(tgt->GetType())]
          << " may not be linked into another target.  "
          << "One may link only to STATIC or SHARED libraries, or "
          << "to executables with the ENABLE_EXPORTS property set.";
        // in older versions of cmake linking to modules was allowed
        if( tgt->GetType() == cmTarget::MODULE_LIBRARY )
          {
          e << "\n"
            << "If you are developing a new project, re-organize it to avoid "
            << "linking to modules.  "
            << "If you are just trying to build an existing project, "
            << "set CMAKE_BACKWARDS_COMPATIBILITY to 2.2 or lower to allow "
            << "linking to modules.";
          }
        // if no modules are allowed then this is always an error
        if(!allowModules ||
           // if we allow modules but the type is not a module then it is
           // still an error
           (allowModules && tgt->GetType() != cmTarget::MODULE_LIBRARY))
          {
          this->IssueMessage(cmake::FATAL_ERROR, e.str().c_str());
          }
        }
      }
    i->second.AddLinkLibrary( *this, target, lib, llt );
    }
  else
    {
    cmOStringStream e;
    e << "Attempt to add link library \""
      << lib << "\" to target \""
      << target << "\" which is not built by this project.";
    cmSystemTools::Error(e.str().c_str());
    }
}

void cmMakefile::AddLinkDirectoryForTarget(const char *target,
                                           const char* d)
{
  cmTargets::iterator i = this->Targets.find(target);
  if ( i != this->Targets.end())
    {
    i->second.AddLinkDirectory( d );
    }
  else
    {
    cmSystemTools::Error
      ("Attempt to add link directories to non-existant target: ",
       target, " for directory ", d);
    }
}

void cmMakefile::AddLinkLibrary(const char* lib)
{
  this->AddLinkLibrary(lib,cmTarget::GENERAL);
}

void cmMakefile::AddLinkDirectory(const char* dir)
{
  // Don't add a link directory that is already present.  Yes, this
  // linear search results in n^2 behavior, but n won't be getting
  // much bigger than 20.  We cannot use a set because of order
  // dependency of the link search path.

  if(!dir)
    {
    return;
    }
  // remove trailing slashes
  if(dir[strlen(dir)-1] == '/')
    {
    std::string newdir = dir;
    newdir = newdir.substr(0, newdir.size()-1);
    if(std::find(this->LinkDirectories.begin(),
                 this->LinkDirectories.end(),
                 newdir.c_str()) == this->LinkDirectories.end())
      {
      this->LinkDirectories.push_back(newdir);
      }
    }
  else
    {
    if(std::find(this->LinkDirectories.begin(),
                 this->LinkDirectories.end(), dir)
       == this->LinkDirectories.end())
      {
      this->LinkDirectories.push_back(dir);
      }
    }
}

void cmMakefile::InitializeFromParent()
{
  cmMakefile *parent = this->LocalGenerator->GetParent()->GetMakefile();

  // Initialize definitions with the closure of the parent scope.
  this->Internal->VarStack.top() = parent->Internal->VarStack.top().Closure();

  // copy include paths
  this->IncludeDirectories = parent->IncludeDirectories;
  this->SystemIncludeDirectories = parent->SystemIncludeDirectories;

  // define flags
  this->DefineFlags = parent->DefineFlags;
  this->DefineFlagsOrig = parent->DefineFlagsOrig;

  // Include transform property.  There is no per-config version.
  {
  const char* prop = "IMPLICIT_DEPENDS_INCLUDE_TRANSFORM";
  this->SetProperty(prop, parent->GetProperty(prop));
  }

  // compile definitions property and per-config versions
  {
  this->SetProperty("COMPILE_DEFINITIONS",
                    parent->GetProperty("COMPILE_DEFINITIONS"));
  std::vector<std::string> configs;
  if(const char* configTypes =
     this->GetDefinition("CMAKE_CONFIGURATION_TYPES"))
    {
    cmSystemTools::ExpandListArgument(configTypes, configs);
    }
  else if(const char* buildType =
          this->GetDefinition("CMAKE_BUILD_TYPE"))
    {
    configs.push_back(buildType);
    }
  for(std::vector<std::string>::const_iterator ci = configs.begin();
      ci != configs.end(); ++ci)
    {
    std::string defPropName = "COMPILE_DEFINITIONS_";
    defPropName += cmSystemTools::UpperCase(*ci);
    this->SetProperty(defPropName.c_str(),
                      parent->GetProperty(defPropName.c_str()));
    }
  }

  // link libraries
  this->LinkLibraries = parent->LinkLibraries;

  // link directories
  this->LinkDirectories = parent->LinkDirectories;

  // the initial project name
  this->ProjectName = parent->ProjectName;

  // Copy include regular expressions.
  this->IncludeFileRegularExpression = parent->IncludeFileRegularExpression;
  this->ComplainFileRegularExpression = parent->ComplainFileRegularExpression;

  // Imported targets.
  this->ImportedTargets = parent->ImportedTargets;
}

void cmMakefile::ConfigureSubDirectory(cmLocalGenerator *lg2)
{
  // copy our variables from the child makefile
  lg2->GetMakefile()->InitializeFromParent();
  lg2->GetMakefile()->MakeStartDirectoriesCurrent();
  if (this->GetCMakeInstance()->GetDebugOutput())
    {
    std::string msg="   Entering             ";
    msg += lg2->GetMakefile()->GetCurrentDirectory();
    cmSystemTools::Message(msg.c_str());
    }
  // finally configure the subdir
  lg2->Configure();
  if (this->GetCMakeInstance()->GetDebugOutput())
    {
    std::string msg="   Returning to         ";
    msg += this->GetCurrentDirectory();
    cmSystemTools::Message(msg.c_str());
    }
}

void cmMakefile::AddSubDirectory(const char* sub,
                                 bool excludeFromAll, bool preorder)
{
  // the source path must be made full if it isn't already
  std::string srcPath = sub;
  if (!cmSystemTools::FileIsFullPath(srcPath.c_str()))
    {
    srcPath = this->GetCurrentDirectory();
    srcPath += "/";
    srcPath += sub;
    }

  // binary path must be made full if it isn't already
  std::string binPath = sub;
  if (!cmSystemTools::FileIsFullPath(binPath.c_str()))
    {
    binPath = this->GetCurrentOutputDirectory();
    binPath += "/";
    binPath += sub;
    }


  this->AddSubDirectory(srcPath.c_str(), binPath.c_str(),
                        excludeFromAll, preorder, false);
}


void cmMakefile::AddSubDirectory(const char* srcPath, const char *binPath,
                                 bool excludeFromAll, bool preorder,
                                 bool immediate)
{
  // Make sure the binary directory is unique.
  if(!this->EnforceUniqueDir(srcPath, binPath))
    {
    return;
    }

  // create a new local generator and set its parent
  cmLocalGenerator *lg2 =
    this->LocalGenerator->GetGlobalGenerator()->CreateLocalGenerator();
  lg2->SetParent(this->LocalGenerator);
  this->LocalGenerator->GetGlobalGenerator()->AddLocalGenerator(lg2);

  // set the subdirs start dirs
  lg2->GetMakefile()->SetStartDirectory(srcPath);
  lg2->GetMakefile()->SetStartOutputDirectory(binPath);
  if(excludeFromAll)
    {
    lg2->GetMakefile()->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
    }
  lg2->GetMakefile()->SetPreOrder(preorder);

  if (immediate)
    {
    this->ConfigureSubDirectory(lg2);
    }
}

void cmMakefile::AddIncludeDirectory(const char* inc, bool before)
{
  // if there is a newline then break it into multiple arguments
  if (!inc)
    {
    return;
    }

  // Don't add an include directory that is already present.  Yes,
  // this linear search results in n^2 behavior, but n won't be
  // getting much bigger than 20.  We cannot use a set because of
  // order dependency of the include path.
  std::vector<std::string>::iterator i =
    std::find(this->IncludeDirectories.begin(),
              this->IncludeDirectories.end(), inc);
  if(i == this->IncludeDirectories.end())
    {
    if (before)
      {
      // WARNING: this *is* expensive (linear time) since it's a vector
      this->IncludeDirectories.insert(this->IncludeDirectories.begin(), inc);
      }
    else
      {
      this->IncludeDirectories.push_back(inc);
      }
    }
  else
    {
    if(before)
      {
      // if this before and already in the path then remove it
      this->IncludeDirectories.erase(i);
      // WARNING: this *is* expensive (linear time) since it's a vector
      this->IncludeDirectories.insert(this->IncludeDirectories.begin(), inc);
      }
    }
}

//----------------------------------------------------------------------------
void cmMakefile::AddSystemIncludeDirectory(const char* dir)
{
  this->SystemIncludeDirectories.insert(dir);
}

//----------------------------------------------------------------------------
bool cmMakefile::IsSystemIncludeDirectory(const char* dir)
{
  return (this->SystemIncludeDirectories.find(dir) !=
          this->SystemIncludeDirectories.end());
}

void cmMakefile::AddDefinition(const char* name, const char* value)
{
  if (!value )
    {
    return;
    }

#ifdef CMAKE_STRICT
  if (this->GetCMakeInstance())
    {
    this->GetCMakeInstance()->
      RecordPropertyAccess(name,cmProperty::VARIABLE);
    }
#endif

  this->Internal->VarStack.top().Set(name, value);

#ifdef CMAKE_BUILD_WITH_CMAKE
  cmVariableWatch* vv = this->GetVariableWatch();
  if ( vv )
    {
    vv->VariableAccessed(name,
                         cmVariableWatch::VARIABLE_MODIFIED_ACCESS,
                         value,
                         this);
    }
#endif
}


void cmMakefile::AddCacheDefinition(const char* name, const char* value,
                                    const char* doc,
                                    cmCacheManager::CacheEntryType type,
                                    bool force)
{
  const char* val = value;
  cmCacheManager::CacheIterator it =
    this->GetCacheManager()->GetCacheIterator(name);
  if(!it.IsAtEnd() && (it.GetType() == cmCacheManager::UNINITIALIZED) &&
     it.Initialized())
    {
    // if this is not a force, then use the value from the cache
    // if it is a force, then use the value being passed in
    if(!force)
      {
      val = it.GetValue();
      }
    if ( type == cmCacheManager::PATH || type == cmCacheManager::FILEPATH )
      {
      std::vector<std::string>::size_type cc;
      std::vector<std::string> files;
      std::string nvalue = "";
      cmSystemTools::ExpandListArgument(val, files);
      for ( cc = 0; cc < files.size(); cc ++ )
        {
        if(!cmSystemTools::IsOff(files[cc].c_str()))
          {
          files[cc] = cmSystemTools::CollapseFullPath(files[cc].c_str());
          }
        if ( cc > 0 )
          {
          nvalue += ";";
          }
        nvalue += files[cc];
        }

      this->GetCacheManager()->AddCacheEntry(name, nvalue.c_str(), doc, type);
      val = it.GetValue();
      }

    }
  this->GetCacheManager()->AddCacheEntry(name, val, doc, type);
  // if there was a definition then remove it
  this->Internal->VarStack.top().Set(name, 0);
}


void cmMakefile::AddDefinition(const char* name, bool value)
{
  this->Internal->VarStack.top().Set(name, value? "ON" : "OFF");
#ifdef CMAKE_BUILD_WITH_CMAKE
  cmVariableWatch* vv = this->GetVariableWatch();
  if ( vv )
    {
    vv->VariableAccessed(name, cmVariableWatch::VARIABLE_MODIFIED_ACCESS,
      value?"ON":"OFF", this);
    }
#endif
}

void cmMakefile::RemoveDefinition(const char* name)
{
  this->Internal->VarStack.top().Set(name, 0);
#ifdef CMAKE_BUILD_WITH_CMAKE
  cmVariableWatch* vv = this->GetVariableWatch();
  if ( vv )
    {
    vv->VariableAccessed(name, cmVariableWatch::VARIABLE_REMOVED_ACCESS,
      0, this);
    }
#endif
}

void cmMakefile::RemoveCacheDefinition(const char* name)
{
  this->GetCacheManager()->RemoveCacheEntry(name);
}

void cmMakefile::SetProjectName(const char* p)
{
  this->ProjectName = p;
}


void cmMakefile::AddGlobalLinkInformation(const char* name, cmTarget& target)
{
  // for these targets do not add anything
  switch(target.GetType())
    {
    case cmTarget::UTILITY:
    case cmTarget::GLOBAL_TARGET:
      return;
    default:;
    }
  std::vector<std::string>::iterator j;
  for(j = this->LinkDirectories.begin();
      j != this->LinkDirectories.end(); ++j)
    {
    target.AddLinkDirectory(j->c_str());
    }
  target.MergeLinkLibraries( *this, name, this->LinkLibraries );
}


void cmMakefile::AddLibrary(const char* lname, cmTarget::TargetType type,
                            const std::vector<std::string> &srcs,
                            bool excludeFromAll)
{
  // wrong type ? default to STATIC
  if (    (type != cmTarget::STATIC_LIBRARY) 
       && (type != cmTarget::SHARED_LIBRARY) 
       && (type != cmTarget::MODULE_LIBRARY))
    {
    type = cmTarget::STATIC_LIBRARY;
    }

  cmTarget* target = this->AddNewTarget(type, lname);
  // Clear its dependencies. Otherwise, dependencies might persist
  // over changes in CMakeLists.txt, making the information stale and
  // hence useless.
  target->ClearDependencyInformation( *this, lname );
  if(excludeFromAll)
    {
    target->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
    }
  target->AddSources(srcs);
  this->AddGlobalLinkInformation(lname, *target);
}

cmTarget* cmMakefile::AddExecutable(const char *exeName,
                                    const std::vector<std::string> &srcs,
                                    bool excludeFromAll)
{
  cmTarget* target = this->AddNewTarget(cmTarget::EXECUTABLE, exeName);
  if(excludeFromAll)
    {
    target->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
    }
  target->AddSources(srcs);
  this->AddGlobalLinkInformation(exeName, *target);
  return target;
}

//----------------------------------------------------------------------------
cmTarget*
cmMakefile::AddNewTarget(cmTarget::TargetType type, const char* name)
{
  cmTargets::iterator it =
    this->Targets.insert(cmTargets::value_type(name, cmTarget())).first;
  cmTarget& target = it->second;
  target.SetType(type, name);
  target.SetMakefile(this);
  this->LocalGenerator->GetGlobalGenerator()->AddTarget(*it);
  return &it->second;
}

cmSourceFile *cmMakefile::GetSourceFileWithOutput(const char *cname)
{
  std::string name = cname;
  std::string out;

  // look through all the source files that have custom commands
  // and see if the custom command has the passed source file as an output
  // keep in mind the possible .rule extension that may be tacked on
  for(std::vector<cmSourceFile*>::const_iterator i =
        this->SourceFiles.begin(); i != this->SourceFiles.end(); ++i)
    {
    // does this source file have a custom command?
    if ((*i)->GetCustomCommand())
      {
      // is the output of the custom command match the source files name
      const std::vector<std::string>& outputs =
        (*i)->GetCustomCommand()->GetOutputs();
      for(std::vector<std::string>::const_iterator o = outputs.begin();
          o != outputs.end(); ++o)
        {
        out = *o;
        std::string::size_type pos = out.rfind(name);
        // If the output matches exactly
        if (pos != out.npos &&
            pos == out.size() - name.size() &&
            (pos ==0 || out[pos-1] == '/'))
          {
          return *i;
          }
        }
      }
    }

  // otherwise return NULL
  return 0;
}

#if defined(CMAKE_BUILD_WITH_CMAKE)
cmSourceGroup* cmMakefile::GetSourceGroup(const std::vector<std::string>&name)
{
  cmSourceGroup* sg = 0;

  // first look for source group starting with the same as the one we wants
  for (std::vector<cmSourceGroup>::iterator sgIt = this->SourceGroups.begin();
       sgIt != this->SourceGroups.end(); ++sgIt)

    {
    std::string sgName = sgIt->GetName();
    if(sgName == name[0])
      {
      sg = &(*sgIt);
      break;
      }
    }

  if(sg != 0)
    {
    // iterate through its children to find match source group
    for(unsigned int i=1; i<name.size(); ++i)
      {
      sg = sg->lookupChild(name[i].c_str());
      if(sg == 0)
        {
        break;
        }
      }
    }
  return sg;
}

 void cmMakefile::AddSourceGroup(const char* name,
                                 const char* regex)
{
  if (name)
    {
    std::vector<std::string> nameVector;
    nameVector.push_back(name);
    AddSourceGroup(nameVector, regex);
    }
}

void cmMakefile::AddSourceGroup(const std::vector<std::string>& name,
                                const char* regex)
{
  cmSourceGroup* sg = 0;
  std::vector<std::string> currentName;
  int i = 0;
  const int lastElement = static_cast<int>(name.size()-1);
  for(i=lastElement; i>=0; --i)
    {
    currentName.assign(name.begin(), name.begin()+i+1);
    sg = this->GetSourceGroup(currentName);
    if(sg != 0)
      {
      break;
      }
    }

  // i now contains the index of the last found component
  if(i==lastElement)
    {
    // group already exists, replace its regular expression
    if ( regex )
      {
      // We only want to set the regular expression.  If there are already
      // source files in the group, we don't want to remove them.
      sg->SetGroupRegex(regex);
      }
    return;
    }
  else if(i==-1)
    {
    // group does not exists nor belong to any existing group
    // add its first component
    this->SourceGroups.push_back(cmSourceGroup(name[0].c_str(), regex));
    sg = this->GetSourceGroup(currentName);
    i = 0; // last component found
    }

  // build the whole source group path
  const char* fullname = sg->GetFullName();
  cmGlobalGenerator* gg = this->LocalGenerator->GetGlobalGenerator();
  if(strlen(fullname))
    {
    std::string guidName = "SG_Filter_";
    guidName += fullname;
    gg->CreateGUID(guidName.c_str());
    }
  for(++i; i<=lastElement; ++i)
    {
    sg->AddChild(cmSourceGroup(name[i].c_str(), 0, sg->GetFullName()));
    sg = sg->lookupChild(name[i].c_str());
    fullname = sg->GetFullName();
    if(strlen(fullname))
      {
      std::string guidName = "SG_Filter_";
      guidName += fullname;
      gg->CreateGUID(guidName.c_str());
      }
    }

  sg->SetGroupRegex(regex);
}

#endif

void cmMakefile::AddExtraDirectory(const char* dir)
{
  this->AuxSourceDirectories.push_back(dir);
}


// expance CMAKE_BINARY_DIR and CMAKE_SOURCE_DIR in the
// include and library directories.

void cmMakefile::ExpandVariables()
{
  // Now expand variables in the include and link strings
  for(std::vector<std::string>::iterator d = this->IncludeDirectories.begin();
      d != this->IncludeDirectories.end(); ++d)
    {
    this->ExpandVariablesInString(*d, true, true);
    }
  for(std::vector<std::string>::iterator d = this->LinkDirectories.begin();
      d != this->LinkDirectories.end(); ++d)
    {
    this->ExpandVariablesInString(*d, true, true);
    }
  for(cmTarget::LinkLibraryVectorType::iterator l =
        this->LinkLibraries.begin();
      l != this->LinkLibraries.end(); ++l)
    {
    this->ExpandVariablesInString(l->first, true, true);
    }
}

bool cmMakefile::IsOn(const char* name) const
{
  const char* value = this->GetDefinition(name);
  return cmSystemTools::IsOn(value);
}

bool cmMakefile::IsSet(const char* name) const
{
  const char* value = this->GetDefinition(name);
  if ( !value )
    {
    return false;
    }

  if ( ! *value )
    {
    return false;
    }

  if ( cmSystemTools::IsNOTFOUND(value) )
    {
    return false;
    }

  return true;
}

bool cmMakefile::PlatformIs64Bit() const
{
  if(const char* sizeof_dptr = this->GetDefinition("CMAKE_SIZEOF_VOID_P"))
    {
    return atoi(sizeof_dptr) == 8;
    }
  return false;
}

bool cmMakefile::CanIWriteThisFile(const char* fileName)
{
  if ( !this->IsOn("CMAKE_DISABLE_SOURCE_CHANGES") )
    {
    return true;
    }
  // If we are doing an in-source build, than the test will always fail
  if ( cmSystemTools::SameFile(this->GetHomeDirectory(),
                               this->GetHomeOutputDirectory()) )
    {
    if ( this->IsOn("CMAKE_DISABLE_IN_SOURCE_BUILD") )
      {
      return false;
      }
    return true;
    }

  // Check if this is subdirectory of the source tree but not a
  // subdirectory of a build tree
  if ( cmSystemTools::IsSubDirectory(fileName,
      this->GetHomeDirectory()) &&
    !cmSystemTools::IsSubDirectory(fileName,
      this->GetHomeOutputDirectory()) )
    {
    return false;
    }
  return true;
}

const char* cmMakefile::GetRequiredDefinition(const char* name) const
{
  const char* ret = this->GetDefinition(name);
  if(!ret)
    {
    cmSystemTools::Error("Error required internal CMake variable not "
                         "set, cmake may be not be built correctly.\n",
                         "Missing variable is:\n",
                         name);
    return "";
    }
  return ret;
}

bool cmMakefile::IsDefinitionSet(const char* name) const
{
  const char* def = this->Internal->VarStack.top().Get(name);
  if(!def)
    {
    def = this->GetCacheManager()->GetCacheValue(name);
    }
#ifdef CMAKE_BUILD_WITH_CMAKE
  if(cmVariableWatch* vv = this->GetVariableWatch())
    {
    if(!def)
      {
      vv->VariableAccessed
        (name, cmVariableWatch::UNKNOWN_VARIABLE_DEFINED_ACCESS,
         def, this);
      }
    }
#endif
  return def?true:false;
}

const char* cmMakefile::GetDefinition(const char* name) const
{
#ifdef CMAKE_STRICT
  if (this->GetCMakeInstance())
    {
    this->GetCMakeInstance()->
      RecordPropertyAccess(name,cmProperty::VARIABLE);
    }
#endif
  const char* def = this->Internal->VarStack.top().Get(name);
  if(!def)
    {
    def = this->GetCacheManager()->GetCacheValue(name);
    }
#ifdef CMAKE_BUILD_WITH_CMAKE
  cmVariableWatch* vv = this->GetVariableWatch();
  if ( vv )
    {
    if ( def )
      {
      vv->VariableAccessed(name, cmVariableWatch::VARIABLE_READ_ACCESS,
        def, this);
      }
    else
      {
      // are unknown access allowed
      const char* allow = this->Internal->VarStack.top()
        .Get("CMAKE_ALLOW_UNKNOWN_VARIABLE_READ_ACCESS");
      if(cmSystemTools::IsOn(allow))
        {
        vv->VariableAccessed(name,
          cmVariableWatch::ALLOWED_UNKNOWN_VARIABLE_READ_ACCESS, def, this);
        }
      else
        {
        vv->VariableAccessed(name,
          cmVariableWatch::UNKNOWN_VARIABLE_READ_ACCESS, def, this);
        }
      }
    }
#endif
  return def;
}

const char* cmMakefile::GetSafeDefinition(const char* def) const
{
  const char* ret = this->GetDefinition(def);
  if(!ret)
    {
    return "";
    }
  return ret;
}

std::vector<std::string> cmMakefile
::GetDefinitions(int cacheonly /* = 0 */) const
{
  std::set<cmStdString> definitions;
  if ( !cacheonly )
    {
    definitions = this->Internal->VarStack.top().ClosureKeys();
    }
  cmCacheManager::CacheIterator cit =
    this->GetCacheManager()->GetCacheIterator();
  for ( cit.Begin(); !cit.IsAtEnd(); cit.Next() )
    {
    definitions.insert(cit.GetName());
    }

  std::vector<std::string> res;

  std::set<cmStdString>::iterator fit;
  for ( fit = definitions.begin(); fit != definitions.end(); fit ++ )
    {
    res.push_back(*fit);
    }
  return res;
}


const char *cmMakefile::ExpandVariablesInString(std::string& source)
{
  return this->ExpandVariablesInString(source, false, false);
}

const char *cmMakefile::ExpandVariablesInString(std::string& source,
                                                bool escapeQuotes,
                                                bool noEscapes,
                                                bool atOnly,
                                                const char* filename,
                                                long line,
                                                bool removeEmpty,
                                                bool replaceAt)
{
  if ( source.empty() || source.find_first_of("$@\\") == source.npos)
    {
    return source.c_str();
    }

  // Special-case the @ONLY mode.
  if(atOnly)
    {
    if(!noEscapes || !removeEmpty || !replaceAt)
      {
      // This case should never be called.  At-only is for
      // configure-file/string which always does no escapes.
      this->IssueMessage(cmake::INTERNAL_ERROR,
                         "ExpandVariablesInString @ONLY called "
                         "on something with escapes.");
      }

    // Store an original copy of the input.
    std::string input = source;

    // Start with empty output.
    source = "";

    // Look for one @VAR@ at a time.
    const char* in = input.c_str();
    while(this->cmAtVarRegex.find(in))
      {
      // Get the range of the string to replace.
      const char* first = in + this->cmAtVarRegex.start();
      const char* last =  in + this->cmAtVarRegex.end();

      // Store the unchanged part of the string now.
      source.append(in, first-in);

      // Lookup the definition of VAR.
      std::string var(first+1, last-first-2);
      if(const char* val = this->GetDefinition(var.c_str()))
        {
        // Store the value in the output escaping as requested.
        if(escapeQuotes)
          {
          source.append(cmSystemTools::EscapeQuotes(val));
          }
        else
          {
          source.append(val);
          }
        }

      // Continue looking for @VAR@ further along the string.
      in = last;
      }

    // Append the rest of the unchanged part of the string.
    source.append(in);

    return source.c_str();
    }

  // This method replaces ${VAR} and @VAR@ where VAR is looked up
  // with GetDefinition(), if not found in the map, nothing is expanded.
  // It also supports the $ENV{VAR} syntax where VAR is looked up in
  // the current environment variables.

  cmCommandArgumentParserHelper parser;
  parser.SetMakefile(this);
  parser.SetLineFile(line, filename);
  parser.SetEscapeQuotes(escapeQuotes);
  parser.SetNoEscapeMode(noEscapes);
  parser.SetReplaceAtSyntax(replaceAt);
  parser.SetRemoveEmpty(removeEmpty);
  int res = parser.ParseString(source.c_str(), 0);
  const char* emsg = parser.GetError();
  if ( res && !emsg[0] )
    {
    source = parser.GetResult();
    }
  else
    {
    // Construct the main error message.
    cmOStringStream error;
    error << "Syntax error in cmake code ";
    if(filename && line > 0)
      {
      // This filename and line number may be more specific than the
      // command context because one command invocation can have
      // arguments on multiple lines.
      error << "at\n"
            << "  " << filename << ":" << line << "\n";
      }
    error << "when parsing string\n"
          << "  " << source.c_str() << "\n";
    error << emsg;

    // If the parser failed ("res" is false) then this is a real
    // argument parsing error, so the policy applies.  Otherwise the
    // parser reported an error message without failing because the
    // helper implementation is unhappy, which has always reported an
    // error.
    cmake::MessageType mtype = cmake::FATAL_ERROR;
    if(!res)
      {
      // This is a real argument parsing error.  Use policy CMP0010 to
      // decide whether it is an error.
      switch(this->GetPolicyStatus(cmPolicies::CMP0010))
        {
        case cmPolicies::WARN:
          error << "\n"
                << (this->GetPolicies()
                    ->GetPolicyWarning(cmPolicies::CMP0010));
        case cmPolicies::OLD:
          // OLD behavior is to just warn and continue.
          mtype = cmake::AUTHOR_WARNING;
          break;
        case cmPolicies::REQUIRED_IF_USED:
        case cmPolicies::REQUIRED_ALWAYS:
          error << "\n"
                << (this->GetPolicies()
                    ->GetRequiredPolicyError(cmPolicies::CMP0010));
        case cmPolicies::NEW:
          // NEW behavior is to report the error.
          cmSystemTools::SetFatalErrorOccured();
          break;
        }
      }
    this->IssueMessage(mtype, error.str());
    }
  return source.c_str();
}

void cmMakefile::RemoveVariablesInString(std::string& source,
                                         bool atOnly) const
{
  if(!atOnly)
    {
    cmsys::RegularExpression var("(\\${[A-Za-z_0-9]*})");
    while (var.find(source))
      {
      source.erase(var.start(),var.end() - var.start());
      }
    }

  if(!atOnly)
    {
    cmsys::RegularExpression varb("(\\$ENV{[A-Za-z_0-9]*})");
    while (varb.find(source))
      {
      source.erase(varb.start(),varb.end() - varb.start());
      }
    }
  cmsys::RegularExpression var2("(@[A-Za-z_0-9]*@)");
  while (var2.find(source))
    {
    source.erase(var2.start(),var2.end() - var2.start());
    }
}

/**
 * Add the default definitions to the makefile.  These values must not
 * be dependent on anything that isn't known when this cmMakefile instance
 * is constructed.
 */
void cmMakefile::AddDefaultDefinitions()
{
/* Up to CMake 2.4 here only WIN32, UNIX and APPLE were set.
  With CMake must separate between target and host platform. In most cases
  the tests for WIN32, UNIX and APPLE will be for the target system, so an 
  additional set of variables for the host system is required ->
  CMAKE_HOST_WIN32, CMAKE_HOST_UNIX, CMAKE_HOST_APPLE.
  WIN32, UNIX and APPLE are now set in the platform files in 
  Modules/Platforms/.
  To keep cmake scripts (-P) and custom language and compiler modules
  working, these variables are still also set here in this place, but they
  will be reset in CMakeSystemSpecificInformation.cmake before the platform 
  files are executed. */
#if defined(_WIN32) || defined(__CYGWIN__)
  this->AddDefinition("WIN32", "1");
  this->AddDefinition("CMAKE_HOST_WIN32", "1");
#else
  this->AddDefinition("UNIX", "1");
  this->AddDefinition("CMAKE_HOST_UNIX", "1");
#endif
  // Cygwin is more like unix so enable the unix commands
#if defined(__CYGWIN__)
  this->AddDefinition("UNIX", "1");
  this->AddDefinition("CMAKE_HOST_UNIX", "1");
#endif
#if defined(__APPLE__)
  this->AddDefinition("APPLE", "1");
  this->AddDefinition("CMAKE_HOST_APPLE", "1");
#endif

  char temp[1024];
  sprintf(temp, "%d", cmVersion::GetMinorVersion());
  this->AddDefinition("CMAKE_MINOR_VERSION", temp);
  sprintf(temp, "%d", cmVersion::GetMajorVersion());
  this->AddDefinition("CMAKE_MAJOR_VERSION", temp);
  sprintf(temp, "%d", cmVersion::GetPatchVersion());
  this->AddDefinition("CMAKE_PATCH_VERSION", temp);
  sprintf(temp, "%u.%u.%u",
          cmVersion::GetMajorVersion(),
          cmVersion::GetMinorVersion(),
          cmVersion::GetPatchVersion());
  this->AddDefinition("CMAKE_VERSION", temp);

  this->AddDefinition("CMAKE_FILES_DIRECTORY",
                      cmake::GetCMakeFilesDirectory());
}

#if defined(CMAKE_BUILD_WITH_CMAKE)
/**
 * Find a source group whose regular expression matches the filename
 * part of the given source name.  Search backward through the list of
 * source groups, and take the first matching group found.  This way
 * non-inherited SOURCE_GROUP commands will have precedence over
 * inherited ones.
 */
cmSourceGroup&
cmMakefile::FindSourceGroup(const char* source,
                            std::vector<cmSourceGroup> &groups)
{
  // First search for a group that lists the file explicitly.
  for(std::vector<cmSourceGroup>::reverse_iterator sg = groups.rbegin();
      sg != groups.rend(); ++sg)
    {
    cmSourceGroup *result = sg->MatchChildrenFiles(source);
    if(result)
      {
      return *result;
      }
    }

  // Now search for a group whose regex matches the file.
  for(std::vector<cmSourceGroup>::reverse_iterator sg = groups.rbegin();
      sg != groups.rend(); ++sg)
    {
    cmSourceGroup *result = sg->MatchChildrenRegex(source);
    if(result)
      {
      return *result;
      }
    }


  // Shouldn't get here, but just in case, return the default group.
  return groups.front();
}
#endif

bool cmMakefile::IsFunctionBlocked(const cmListFileFunction& lff,
                                   cmExecutionStatus &status)
{
  // if there are no blockers get out of here
  if (this->FunctionBlockers.begin() == this->FunctionBlockers.end())
    {
    return false;
    }

  // loop over all function blockers to see if any block this command
  // evaluate in reverse, this is critical for balanced IF statements etc
  std::vector<cmFunctionBlocker*>::reverse_iterator pos;
  for (pos = this->FunctionBlockers.rbegin();
       pos != this->FunctionBlockers.rend(); ++pos)
    {
    if((*pos)->IsFunctionBlocked(lff, *this, status))
      {
      return true;
      }
    }

  return false;
}

//----------------------------------------------------------------------------
void cmMakefile::PushFunctionBlockerBarrier()
{
  this->FunctionBlockerBarriers.push_back(this->FunctionBlockers.size());
}

//----------------------------------------------------------------------------
void cmMakefile::PopFunctionBlockerBarrier(bool reportError)
{
  // Remove any extra entries pushed on the barrier.
  FunctionBlockersType::size_type barrier =
    this->FunctionBlockerBarriers.back();
  while(this->FunctionBlockers.size() > barrier)
    {
    cmsys::auto_ptr<cmFunctionBlocker> fb(this->FunctionBlockers.back());
    this->FunctionBlockers.pop_back();
    if(reportError)
      {
      // Report the context in which the unclosed block was opened.
      cmListFileContext const& lfc = fb->GetStartingContext();
      cmOStringStream e;
      e << "A logical block opening on the line\n"
        << "  " << lfc << "\n"
        << "is not closed.";
      this->IssueMessage(cmake::FATAL_ERROR, e.str());
      reportError = false;
      }
    }

  // Remove the barrier.
  this->FunctionBlockerBarriers.pop_back();
}

bool cmMakefile::ExpandArguments(
  std::vector<cmListFileArgument> const& inArgs,
  std::vector<std::string>& outArgs)
{
  std::vector<cmListFileArgument>::const_iterator i;
  std::string value;
  outArgs.reserve(inArgs.size());
  for(i = inArgs.begin(); i != inArgs.end(); ++i)
    {
    // Expand the variables in the argument.
    value = i->Value;
    this->ExpandVariablesInString(value, false, false, false,
                                  i->FilePath, i->Line,
                                  false, true);

    // If the argument is quoted, it should be one argument.
    // Otherwise, it may be a list of arguments.
    if(i->Quoted)
      {
      outArgs.push_back(value);
      }
    else
      {
      cmSystemTools::ExpandListArgument(value, outArgs);
      }
    }
  return !cmSystemTools::GetFatalErrorOccured();
}

//----------------------------------------------------------------------------
void cmMakefile::AddFunctionBlocker(cmFunctionBlocker* fb)
{
  if(!this->CallStack.empty())
    {
    // Record the context in which the blocker is created.
    fb->SetStartingContext(*(this->CallStack.back().Context));
    }

  this->FunctionBlockers.push_back(fb);
}

cmsys::auto_ptr<cmFunctionBlocker>
cmMakefile::RemoveFunctionBlocker(cmFunctionBlocker* fb,
                                  const cmListFileFunction& lff)
{
  // Find the function blocker stack barrier for the current scope.
  // We only remove a blocker whose index is not less than the barrier.
  FunctionBlockersType::size_type barrier = 0;
  if(!this->FunctionBlockerBarriers.empty())
    {
    barrier = this->FunctionBlockerBarriers.back();
    }

  // Search for the function blocker whose scope this command ends.
  for(FunctionBlockersType::size_type
        i = this->FunctionBlockers.size(); i > barrier; --i)
    {
    std::vector<cmFunctionBlocker*>::iterator pos =
      this->FunctionBlockers.begin() + (i - 1);
    if (*pos == fb)
      {
      // Warn if the arguments do not match, but always remove.
      if(!(*pos)->ShouldRemove(lff, *this))
        {
        cmListFileContext const& lfc = fb->GetStartingContext();
        cmOStringStream e;
        e << "A logical block opening on the line\n"
          << "  " << lfc << "\n"
          << "closes on the line\n"
          << "  " << lff << "\n"
          << "with mis-matching arguments.";
        this->IssueMessage(cmake::AUTHOR_WARNING, e.str());
        }
      cmFunctionBlocker* b = *pos;
      this->FunctionBlockers.erase(pos);
      return cmsys::auto_ptr<cmFunctionBlocker>(b);
      }
    }

  return cmsys::auto_ptr<cmFunctionBlocker>();
}

//----------------------------------------------------------------------------
cmMakefile::LexicalPushPop::LexicalPushPop(cmMakefile* mf):
  Makefile(mf), ReportError(true)
{
  this->Makefile->PushFunctionBlockerBarrier();
}

//----------------------------------------------------------------------------
cmMakefile::LexicalPushPop::~LexicalPushPop()
{
  this->Makefile->PopFunctionBlockerBarrier(this->ReportError);
}

void cmMakefile::SetHomeDirectory(const char* dir)
{
  this->cmHomeDirectory = dir;
  cmSystemTools::ConvertToUnixSlashes(this->cmHomeDirectory);
  this->AddDefinition("CMAKE_SOURCE_DIR", this->GetHomeDirectory());
  if ( !this->GetDefinition("CMAKE_CURRENT_SOURCE_DIR") )
    {
    this->AddDefinition("CMAKE_CURRENT_SOURCE_DIR", this->GetHomeDirectory());
    }
}

void cmMakefile::SetHomeOutputDirectory(const char* lib)
{
  this->HomeOutputDirectory = lib;
  cmSystemTools::ConvertToUnixSlashes(this->HomeOutputDirectory);
  this->AddDefinition("CMAKE_BINARY_DIR", this->GetHomeOutputDirectory());
  if ( !this->GetDefinition("CMAKE_CURRENT_BINARY_DIR") )
    {
    this->AddDefinition("CMAKE_CURRENT_BINARY_DIR",
                        this->GetHomeOutputDirectory());
    }
}


/**
 * Register the given cmData instance with its own name.
 */
void cmMakefile::RegisterData(cmData* data)
{
  std::string name = data->GetName();
  DataMapType::const_iterator d = this->DataMap.find(name);
  if((d != this->DataMap.end()) && (d->second != 0) && (d->second != data))
    {
    delete d->second;
    }
  this->DataMap[name] = data;
}


/**
 * Register the given cmData instance with the given name.  This can be used
 * to register a NULL pointer.
 */
void cmMakefile::RegisterData(const char* name, cmData* data)
{
  DataMapType::const_iterator d = this->DataMap.find(name);
  if((d != this->DataMap.end()) && (d->second != 0) && (d->second != data))
    {
    delete d->second;
    }
  this->DataMap[name] = data;
}


/**
 * Lookup a cmData instance previously registered with the given name.  If
 * the instance cannot be found, return NULL.
 */
cmData* cmMakefile::LookupData(const char* name) const
{
  DataMapType::const_iterator d = this->DataMap.find(name);
  if(d != this->DataMap.end())
    {
    return d->second;
    }
  else
    {
    return 0;
    }
}

//----------------------------------------------------------------------------
cmSourceFile* cmMakefile::GetSource(const char* sourceName)
{
  cmSourceFileLocation sfl(this, sourceName);
  for(std::vector<cmSourceFile*>::const_iterator
        sfi = this->SourceFiles.begin();
      sfi != this->SourceFiles.end(); ++sfi)
    {
    cmSourceFile* sf = *sfi;
    if(sf->Matches(sfl))
      {
      return sf;
      }
    }
  return 0;
}

//----------------------------------------------------------------------------
cmSourceFile* cmMakefile::GetOrCreateSource(const char* sourceName,
                                            bool generated)
{
  if(cmSourceFile* esf = this->GetSource(sourceName))
    {
    return esf;
    }
  else
    {
    cmSourceFile* sf = new cmSourceFile(this, sourceName);
    if(generated)
      {
      sf->SetProperty("GENERATED", "1");
      }
    this->SourceFiles.push_back(sf);
    return sf;
    }
}

void cmMakefile::EnableLanguage(std::vector<std::string> const &  lang, 
                               bool optional)
{
  this->AddDefinition("CMAKE_CFG_INTDIR",
                      this->LocalGenerator->GetGlobalGenerator()
                      ->GetCMakeCFGInitDirectory());
  this->LocalGenerator->GetGlobalGenerator()->EnableLanguage(lang, this, 
                                                             optional);
}

void cmMakefile::ExpandSourceListArguments(
  std::vector<std::string> const& arguments,
  std::vector<std::string>& newargs, unsigned int /* start */)
{
  // now expand the args
  unsigned int i;
  for(i = 0; i < arguments.size(); ++i)
    {
    // List expansion will have been done already.
    newargs.push_back(arguments[i]);
    }
}

int cmMakefile::TryCompile(const char *srcdir, const char *bindir,
                           const char *projectName, const char *targetName,
                           bool fast,
                           const std::vector<std::string> *cmakeArgs,
                           std::string *output)
{
  // does the binary directory exist ? If not create it...
  if (!cmSystemTools::FileIsDirectory(bindir))
    {
    cmSystemTools::MakeDirectory(bindir);
    }

  // change to the tests directory and run cmake
  // use the cmake object instead of calling cmake
  std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
  cmSystemTools::ChangeDirectory(bindir);

  // make sure the same generator is used
  // use this program as the cmake to be run, it should not
  // be run that way but the cmake object requires a vailid path
  std::string cmakeCommand = this->GetDefinition("CMAKE_COMMAND");
  cmake cm;
  cm.SetIsInTryCompile(true);
  cmGlobalGenerator *gg = cm.CreateGlobalGenerator
    (this->LocalGenerator->GetGlobalGenerator()->GetName());
  if (!gg)
    {
    cmSystemTools::Error(
      "Internal CMake error, TryCompile bad GlobalGenerator");
    // return to the original directory
    cmSystemTools::ChangeDirectory(cwd.c_str());
    return 1;
    }
  cm.SetGlobalGenerator(gg);

  // do a configure
  cm.SetHomeDirectory(srcdir);
  cm.SetHomeOutputDirectory(bindir);
  cm.SetStartDirectory(srcdir);
  cm.SetStartOutputDirectory(bindir);
  cm.SetCMakeCommand(cmakeCommand.c_str());
  cm.LoadCache();
  // if cmake args were provided then pass them in
  if (cmakeArgs)
    {
    cm.SetCacheArgs(*cmakeArgs);
    }
  // to save time we pass the EnableLanguage info directly
  gg->EnableLanguagesFromGenerator
    (this->LocalGenerator->GetGlobalGenerator());
  if(this->IsOn("CMAKE_SUPPRESS_DEVELOPER_WARNINGS"))
    {
    cm.AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_WARNINGS",
                     "TRUE", "", cmCacheManager::INTERNAL);
    }
  else
    {
    cm.AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_WARNINGS",
                     "FALSE", "", cmCacheManager::INTERNAL);
    }    
  if (cm.Configure() != 0)
    {
    cmSystemTools::Error(
      "Internal CMake error, TryCompile configure of cmake failed");
    // return to the original directory
    cmSystemTools::ChangeDirectory(cwd.c_str());
    return 1;
    }

  if (cm.Generate() != 0)
    {
    cmSystemTools::Error(
      "Internal CMake error, TryCompile generation of cmake failed");
    // return to the original directory
    cmSystemTools::ChangeDirectory(cwd.c_str());
    return 1;
    }

  // finally call the generator to actually build the resulting project
  int ret =
    this->LocalGenerator->GetGlobalGenerator()->TryCompile(srcdir,bindir,
                                                           projectName,
                                                           targetName,
                                                           fast,
                                                           output,
                                                           this);

  cmSystemTools::ChangeDirectory(cwd.c_str());
  return ret;
}

cmake *cmMakefile::GetCMakeInstance() const
{
  if ( this->LocalGenerator && this->LocalGenerator->GetGlobalGenerator() )
    {
    return this->LocalGenerator->GetGlobalGenerator()->GetCMakeInstance();
    }
  return 0;
}

#ifdef CMAKE_BUILD_WITH_CMAKE
cmVariableWatch *cmMakefile::GetVariableWatch() const
{
  if ( this->GetCMakeInstance() &&
       this->GetCMakeInstance()->GetVariableWatch() )
    {
    return this->GetCMakeInstance()->GetVariableWatch();
    }
  return 0;
}
#endif

void cmMakefile::AddMacro(const char* name, const char* signature)
{
  if ( !name || !signature )
    {
    return;
    }
  this->MacrosMap[name] = signature;
}

void cmMakefile::GetListOfMacros(std::string& macros)
{
  StringStringMap::iterator it;
  macros = "";
  int cc = 0;
  for ( it = this->MacrosMap.begin(); it != this->MacrosMap.end(); ++it )
    {
    if ( cc > 0 )
      {
      macros += ";";
      }
    macros += it->first;
    cc ++;
    }
}

cmCacheManager *cmMakefile::GetCacheManager() const
{
  return this->GetCMakeInstance()->GetCacheManager();
}

void cmMakefile::DisplayStatus(const char* message, float s)
{
  this->GetLocalGenerator()->GetGlobalGenerator()
    ->GetCMakeInstance()->UpdateProgress(message, s);
}

std::string cmMakefile::GetModulesFile(const char* filename)
{
  std::vector<std::string> modulePath;
  const char* def = this->GetDefinition("CMAKE_MODULE_PATH");
  if(def)
    {
    cmSystemTools::ExpandListArgument(def, modulePath);
    }

  // Also search in the standard modules location.
  def = this->GetDefinition("CMAKE_ROOT");
  if(def)
    {
    std::string rootModules = def;
    rootModules += "/Modules";
    modulePath.push_back(rootModules);
    }
  //std::string  Look through the possible module directories.
  for(std::vector<std::string>::iterator i = modulePath.begin();
      i != modulePath.end(); ++i)
    {
    std::string itempl = *i;
    cmSystemTools::ConvertToUnixSlashes(itempl);
    itempl += "/";
    itempl += filename;
    if(cmSystemTools::FileExists(itempl.c_str()))
      {
      return itempl;
      }
    }
  return "";
}

void cmMakefile::ConfigureString(const std::string& input,
                                 std::string& output, bool atOnly,
                                 bool escapeQuotes)
{
  // Split input to handle one line at a time.
  std::string::const_iterator lineStart = input.begin();
  while(lineStart != input.end())
    {
    // Find the end of this line.
    std::string::const_iterator lineEnd = lineStart;
    while(lineEnd != input.end() && *lineEnd != '\n')
      {
      ++lineEnd;
      }

    // Copy the line.
    std::string line(lineStart, lineEnd);

    // Skip the newline character.
    bool haveNewline = (lineEnd != input.end());
    if(haveNewline)
      {
      ++lineEnd;
      }

    // Replace #cmakedefine instances.
    if(this->cmDefineRegex.find(line))
      {
      const char* def =
        this->GetDefinition(this->cmDefineRegex.match(1).c_str());
      if(!cmSystemTools::IsOff(def))
        {
        cmSystemTools::ReplaceString(line, "#cmakedefine", "#define");
        output += line;
        }
      else
        {
        output += "/* #undef ";
        output += this->cmDefineRegex.match(1);
        output += " */";
        }
      }
    else if(this->cmDefine01Regex.find(line))
      {
      const char* def =
        this->GetDefinition(this->cmDefine01Regex.match(1).c_str());
      cmSystemTools::ReplaceString(line, "#cmakedefine01", "#define");
      output += line;
      if(!cmSystemTools::IsOff(def))
        {
        output += " 1";
        }
      else
        {
        output += " 0";
        }
      }
    else
      {
      output += line;
      }

    if(haveNewline)
      {
      output += "\n";
      }

    // Move to the next line.
    lineStart = lineEnd;
    }

  // Perform variable replacements.
  this->ExpandVariablesInString(output, escapeQuotes, true,
                                atOnly, 0, -1, true);
}

int cmMakefile::ConfigureFile(const char* infile, const char* outfile,
                              bool copyonly, bool atOnly, bool escapeQuotes)
{
  int res = 1;
  if ( !this->CanIWriteThisFile(outfile) )
    {
    cmSystemTools::Error("Attempt to write file: ",
                         outfile, " into a source directory.");
    return 0;
    }
  if ( !cmSystemTools::FileExists(infile) )
    {
    cmSystemTools::Error("File ", infile, " does not exist.");
    return 0;
    }
  std::string soutfile = outfile;
  std::string sinfile = infile;
  this->AddCMakeDependFile(infile);
  cmSystemTools::ConvertToUnixSlashes(soutfile);
  mode_t perm = 0;
  cmSystemTools::GetPermissions(sinfile.c_str(), perm);
  std::string::size_type pos = soutfile.rfind('/');
  if(pos != std::string::npos)
    {
    std::string path = soutfile.substr(0, pos);
    cmSystemTools::MakeDirectory(path.c_str());
    }

  if(copyonly)
    {
    if ( !cmSystemTools::CopyFileIfDifferent(sinfile.c_str(),
                                             soutfile.c_str()))
      {
      return 0;
      }
    }
  else
    {
    std::string tempOutputFile = soutfile;
    tempOutputFile += ".tmp";
    std::ofstream fout(tempOutputFile.c_str());
    if(!fout)
      {
      cmSystemTools::Error(
        "Could not open file for write in copy operation ",
        tempOutputFile.c_str());
      cmSystemTools::ReportLastSystemError("");
      return 0;
      }
    std::ifstream fin(sinfile.c_str());
    if(!fin)
      {
      cmSystemTools::Error("Could not open file for read in copy operation ",
                           sinfile.c_str());
      return 0;
      }

    // now copy input to output and expand variables in the
    // input file at the same time
    std::string inLine;
    std::string outLine;
    while( cmSystemTools::GetLineFromStream(fin, inLine) )
      {
      outLine = "";
      this->ConfigureString(inLine, outLine, atOnly, escapeQuotes);
      fout << outLine.c_str() << "\n";
      }
    // close the files before attempting to copy
    fin.close();
    fout.close();
    if ( !cmSystemTools::CopyFileIfDifferent(tempOutputFile.c_str(),
                                             soutfile.c_str()) )
      {
      res = 0;
      }
    else
      {
      cmSystemTools::SetPermissions(soutfile.c_str(), perm);
      }
    cmSystemTools::RemoveFile(tempOutputFile.c_str());
    }
  return res;
}

void cmMakefile::SetProperty(const char* prop, const char* value)
{
  if (!prop)
    {
    return;
    }
  
  // handle special props
  std::string propname = prop;
  if ( propname == "INCLUDE_DIRECTORIES" )
    {
    std::vector<std::string> varArgsExpanded;
    if(value)
      {
      cmSystemTools::ExpandListArgument(value, varArgsExpanded);
      }
    this->SetIncludeDirectories(varArgsExpanded);
    return;
    }

  if ( propname == "LINK_DIRECTORIES" )
    {
    std::vector<std::string> varArgsExpanded;
    if(value)
      {
      cmSystemTools::ExpandListArgument(value, varArgsExpanded);
      }
    this->SetLinkDirectories(varArgsExpanded);
    return;
    }
  
  if ( propname == "INCLUDE_REGULAR_EXPRESSION" )
    {
    this->SetIncludeRegularExpression(value);
    return;
    }

  if ( propname == "ADDITIONAL_MAKE_CLEAN_FILES" )
    {
    // This property is not inherrited
    if ( strcmp(this->GetCurrentDirectory(), 
                this->GetStartDirectory()) != 0 )
      {
      return;
      }
    }

  this->Properties.SetProperty(prop,value,cmProperty::DIRECTORY);
}

void cmMakefile::AppendProperty(const char* prop, const char* value)
{
  if (!prop)
    {
    return;
    }

  // handle special props
  std::string propname = prop;
  if ( propname == "INCLUDE_DIRECTORIES" )
    {
    std::vector<std::string> varArgsExpanded;
    cmSystemTools::ExpandListArgument(value, varArgsExpanded);
    for(std::vector<std::string>::const_iterator vi = varArgsExpanded.begin();
        vi != varArgsExpanded.end(); ++vi)
      {
      this->AddIncludeDirectory(vi->c_str());
      }
    return;
    }

  if ( propname == "LINK_DIRECTORIES" )
    {
    std::vector<std::string> varArgsExpanded;
    cmSystemTools::ExpandListArgument(value, varArgsExpanded);
    for(std::vector<std::string>::const_iterator vi = varArgsExpanded.begin();
        vi != varArgsExpanded.end(); ++vi)
      {
      this->AddLinkDirectory(vi->c_str());
      }
    return;
    }

  this->Properties.AppendProperty(prop,value,cmProperty::DIRECTORY);
}

const char *cmMakefile::GetPropertyOrDefinition(const char* prop)
{
  const char *ret = this->GetProperty(prop, cmProperty::DIRECTORY);
  if (!ret)
    {
    ret = this->GetDefinition(prop);
    }
  return ret;
}

const char *cmMakefile::GetProperty(const char* prop)
{
  return this->GetProperty(prop, cmProperty::DIRECTORY);
}

const char *cmMakefile::GetProperty(const char* prop,
                                    cmProperty::ScopeType scope)
{
  if(!prop)
    {
    return 0;
    }
  // watch for specific properties
  static std::string output;
  output = "";
  if (!strcmp("PARENT_DIRECTORY",prop))
    {
    if(cmLocalGenerator* plg = this->LocalGenerator->GetParent())
      {
      output = plg->GetMakefile()->GetStartDirectory();
      }
    return output.c_str();
    }
  else if (!strcmp("INCLUDE_REGULAR_EXPRESSION",prop) )
    {
    output = this->GetIncludeRegularExpression();
    return output.c_str();
    }
  else if (!strcmp("LISTFILE_STACK",prop))
    {
    for (std::deque<cmStdString>::iterator i = this->ListFileStack.begin();
         i != this->ListFileStack.end(); ++i)
      {
      if (i != this->ListFileStack.begin())
        {
        output += ";";
        }
      output += *i;
      }
    return output.c_str();
    }
  else if (!strcmp("VARIABLES",prop) || !strcmp("CACHE_VARIABLES",prop))
    {
    int cacheonly = 0;
    if ( !strcmp("CACHE_VARIABLES",prop) )
      {
      cacheonly = 1;
      }
    std::vector<std::string> vars = this->GetDefinitions(cacheonly);
    for (unsigned int cc = 0; cc < vars.size(); cc ++ )
      {
      if ( cc > 0 )
        {
        output += ";";
        }
      output += vars[cc];
      }
    return output.c_str();
    }
  else if (!strcmp("MACROS",prop))
    {
    this->GetListOfMacros(output);
    return output.c_str();
    }
  else if (!strcmp("DEFINITIONS",prop))
    { 
    output += this->DefineFlagsOrig;
    return output.c_str();
    }
  else if (!strcmp("INCLUDE_DIRECTORIES",prop) )
    {
    cmOStringStream str;
    for (std::vector<std::string>::const_iterator 
         it = this->GetIncludeDirectories().begin();
         it != this->GetIncludeDirectories().end();
         ++ it )
      {
      if ( it != this->GetIncludeDirectories().begin())
        {
        str << ";";
        }
      str << it->c_str();
      }
    output = str.str();
    return output.c_str();
    }
  else if (!strcmp("LINK_DIRECTORIES",prop))
    {
    cmOStringStream str;
    for (std::vector<std::string>::const_iterator 
         it = this->GetLinkDirectories().begin();
         it != this->GetLinkDirectories().end();
         ++ it )
      {
      if ( it != this->GetLinkDirectories().begin())
        {
        str << ";";
        }
      str << it->c_str();
      }
    output = str.str();
    return output.c_str();
    }

  bool chain = false;
  const char *retVal =
    this->Properties.GetPropertyValue(prop, scope, chain);
  if (chain)
    {
    if(this->LocalGenerator->GetParent())
      {
      return this->LocalGenerator->GetParent()->GetMakefile()->
        GetProperty(prop, scope);
      }
    return this->GetCMakeInstance()->GetProperty(prop,scope);
    }

  return retVal;
}

bool cmMakefile::GetPropertyAsBool(const char* prop)
{
  return cmSystemTools::IsOn(this->GetProperty(prop));
}

//----------------------------------------------------------------------------
const char* cmMakefile::GetFeature(const char* feature, const char* config)
{
  // TODO: Define accumulation policy for features (prepend, append, replace).
  // Currently we always replace.
  if(config && *config)
    {
    std::string featureConfig = feature;
    featureConfig += "_";
    featureConfig += cmSystemTools::UpperCase(config);
    if(const char* value = this->GetProperty(featureConfig.c_str()))
      {
      return value;
      }
    }
  if(const char* value = this->GetProperty(feature))
    {
    return value;
    }
  if(cmLocalGenerator* parent = this->LocalGenerator->GetParent())
    {
    return parent->GetMakefile()->GetFeature(feature, config);
    }
  return 0;
}

cmTarget* cmMakefile::FindTarget(const char* name)
{
  cmTargets& tgts = this->GetTargets();

  cmTargets::iterator i = tgts.find ( name );
  if ( i != tgts.end() )
    {
    return &i->second;
    }

  return 0;
}

//----------------------------------------------------------------------------
cmTest* cmMakefile::CreateTest(const char* testName)
{
  if ( !testName )
    {
    return 0;
    }
  cmTest* test = this->GetTest(testName);
  if ( test )
    {
    return test;
    }
  test = new cmTest(this);
  test->SetName(testName);
  this->Tests[testName] = test;
  return test;
}

//----------------------------------------------------------------------------
cmTest* cmMakefile::GetTest(const char* testName) const
{
  if(testName)
    {
    std::map<cmStdString, cmTest*>::const_iterator
      mi = this->Tests.find(testName);
    if(mi != this->Tests.end())
      {
      return mi->second;
      }
    }
  return 0;
}

std::string cmMakefile::GetListFileStack()
{
  cmOStringStream tmp;
  size_t depth = this->ListFileStack.size();
  if (depth > 0)
    {
    std::deque<cmStdString>::iterator it = this->ListFileStack.end();
    do
      {
      if (depth != this->ListFileStack.size())
        {
        tmp << "\n                ";
        }
      --it;
      tmp << "[";
      tmp << depth;
      tmp << "]\t";
      tmp << *it;
      depth--;
      }
    while (it != this->ListFileStack.begin());
    }
  return tmp.str();
}


void cmMakefile::PushScope()
{
  cmDefinitions* parent = &this->Internal->VarStack.top();
  this->Internal->VarStack.push(cmDefinitions(parent));
}

void cmMakefile::PopScope()
{
  this->Internal->VarStack.pop();
}

void cmMakefile::RaiseScope(const char *var, const char *varDef)
{
  if (!var || !strlen(var))
    {
    return;
    }

  cmDefinitions& cur = this->Internal->VarStack.top();
  if(cmDefinitions* up = cur.GetParent())
    {
    // First localize the definition in the current scope.
    cur.Get(var);

    // Now update the definition in the parent scope.
    up->Set(var, varDef);
    }
  else if(cmLocalGenerator* plg = this->LocalGenerator->GetParent())
    {
    // Update the definition in the parent directory top scope.  This
    // directory's scope was initialized by the closure of the parent
    // scope, so we do not need to localize the definition first.
    cmMakefile* parent = plg->GetMakefile();
    parent->Internal->VarStack.top().Set(var, varDef);
    }
  else
    {
    cmOStringStream m;
    m << "Cannot set \"" << var << "\": current scope has no parent.";
    this->IssueMessage(cmake::AUTHOR_WARNING, m.str());
    }
}


// define properties
void cmMakefile::DefineProperties(cmake *cm)
{
  cm->DefineProperty
    ("ADDITIONAL_MAKE_CLEAN_FILES", cmProperty::DIRECTORY,
     "Additional files to clean during the make clean stage.",
     "A list of files that will be cleaned as a part of the "
     "\"make clean\" stage. ");

  cm->DefineProperty
    ("CLEAN_NO_CUSTOM", cmProperty::DIRECTORY,
     "Should the output of custom commands be left.",
     "If this is true then the outputs of custom commands for this "
     "directory will not be removed during the \"make clean\" stage. ");

  cm->DefineProperty
    ("LISTFILE_STACK", cmProperty::DIRECTORY,
     "The current stack of listfiles being processed.",
     "This property is mainly useful when trying to debug errors "
     "in your CMake scripts. It returns a list of what list files "
     "are currently being processed, in order. So if one listfile "
     "does an INCLUDE command then that is effectively pushing "
     "the included listfile onto the stack.", false);

  cm->DefineProperty
    ("TEST_INCLUDE_FILE", cmProperty::DIRECTORY,
     "A cmake file that will be included when ctest is run.",
     "If you specify TEST_INCLUDE_FILE, that file will be "
     "included and processed when ctest is run on the directory.");

  cm->DefineProperty
    ("COMPILE_DEFINITIONS", cmProperty::DIRECTORY,
     "Preprocessor definitions for compiling a directory's sources.",
     "The COMPILE_DEFINITIONS property may be set to a "
     "semicolon-separated list of preprocessor "
     "definitions using the syntax VAR or VAR=value.  Function-style "
     "definitions are not supported.  CMake will automatically escape "
     "the value correctly for the native build system (note that CMake "
     "language syntax may require escapes to specify some values).  "
     "This property may be set on a per-configuration basis using the name "
     "COMPILE_DEFINITIONS_<CONFIG> where <CONFIG> is an upper-case name "
     "(ex. \"COMPILE_DEFINITIONS_DEBUG\").  "
     "This property will be initialized in each directory by its value "
     "in the directory's parent.\n"
     "CMake will automatically drop some definitions that "
     "are not supported by the native build tool.  "
     "The VS6 IDE does not support definition values with spaces "
     "(but NMake does).\n"
     "Dislaimer: Most native build tools have poor support for escaping "
     "certain values.  CMake has work-arounds for many cases but some "
     "values may just not be possible to pass correctly.  If a value "
     "does not seem to be escaped correctly, do not attempt to "
     "work-around the problem by adding escape sequences to the value.  "
     "Your work-around may break in a future version of CMake that "
     "has improved escape support.  Instead consider defining the macro "
     "in a (configured) header file.  Then report the limitation.");

  cm->DefineProperty
    ("COMPILE_DEFINITIONS_<CONFIG>", cmProperty::DIRECTORY,
     "Per-configuration preprocessor definitions in a directory.",
     "This is the configuration-specific version of COMPILE_DEFINITIONS.  "
     "This property will be initialized in each directory by its value "
     "in the directory's parent.\n");

  cm->DefineProperty
    ("IMPLICIT_DEPENDS_INCLUDE_TRANSFORM", cmProperty::DIRECTORY,
     "Specify #include line transforms for dependencies in a directory.",
     "This property specifies rules to transform macro-like #include lines "
     "during implicit dependency scanning of C and C++ source files.  "
     "The list of rules must be semicolon-separated with each entry of "
     "the form \"A_MACRO(%)=value-with-%\" (the % must be literal).  "
     "During dependency scanning occurrences of A_MACRO(...) on #include "
     "lines will be replaced by the value given with the macro argument "
     "substituted for '%'.  For example, the entry\n"
     "  MYDIR(%)=<mydir/%>\n"
     "will convert lines of the form\n"
     "  #include MYDIR(myheader.h)\n"
     "to\n"
     "  #include <mydir/myheader.h>\n"
     "allowing the dependency to be followed.\n"
     "This property applies to sources in all targets within a directory.  "
     "The property value is initialized in each directory by its value "
     "in the directory's parent.");

  cm->DefineProperty
    ("EXCLUDE_FROM_ALL", cmProperty::DIRECTORY,
     "Exclude the directory from the all target of its parent.",
     "A property on a directory that indicates if its targets are excluded "
     "from the default build target. If it is not, then with a Makefile "
     "for example typing make will cause the targets to be built. "
     "The same concept applies to the default build of other generators.",
     false);

  cm->DefineProperty
    ("PARENT_DIRECTORY", cmProperty::DIRECTORY,
     "Source directory that added current subdirectory.",
     "This read-only property specifies the source directory that "
     "added the current source directory as a subdirectory of the build.  "
     "In the top-level directory the value is the empty-string.", false);

  cm->DefineProperty
    ("INCLUDE_REGULAR_EXPRESSION", cmProperty::DIRECTORY,
     "Include file scanning regular expression.",
     "This read-only property specifies the regular expression used "
     "during dependency scanning to match include files that should "
     "be followed.  See the include_regular_expression command.", false);

  cm->DefineProperty
    ("INTERPROCEDURAL_OPTIMIZATION", cmProperty::DIRECTORY,
     "Enable interprocedural optimization for targets in a directory.",
     "If set to true, enables interprocedural optimizations "
     "if they are known to be supported by the compiler.");

  cm->DefineProperty
    ("INTERPROCEDURAL_OPTIMIZATION_<CONFIG>", cmProperty::DIRECTORY,
     "Per-configuration interprocedural optimization for a directory.",
     "This is a per-configuration version of INTERPROCEDURAL_OPTIMIZATION.  "
     "If set, this property overrides the generic property "
     "for the named configuration.");

  cm->DefineProperty
    ("VARIABLES", cmProperty::DIRECTORY,
     "List of variables defined in the current directory.",
     "This read-only property specifies the list of CMake variables "
     "currently defined.  "
     "It is intended for debugging purposes.", false);

  cm->DefineProperty
    ("CACHE_VARIABLES", cmProperty::DIRECTORY,
     "List of cache variables available in the current directory.",
     "This read-only property specifies the list of CMake cache "
     "variables currently defined.  "
     "It is intended for debugging purposes.", false);

  cm->DefineProperty
    ("MACROS", cmProperty::DIRECTORY,
     "List of macro commands available in the current directory.",
     "This read-only property specifies the list of CMake macros "
     "currently defined.  "
     "It is intended for debugging purposes.  "
     "See the macro command.", false);

  cm->DefineProperty
    ("DEFINITIONS", cmProperty::DIRECTORY,
     "For CMake 2.4 compatibility only.  Use COMPILE_DEFINITIONS instead.",
     "This read-only property specifies the list of flags given so far "
     "to the add_definitions command.  "
     "It is intended for debugging purposes.  "
     "Use the COMPILE_DEFINITIONS instead.", false);

  cm->DefineProperty
    ("INCLUDE_DIRECTORIES", cmProperty::DIRECTORY,
     "List of preprocessor include file search directories.",
     "This read-only property specifies the list of directories given "
     "so far to the include_directories command.  "
     "It is intended for debugging purposes.", false);

  cm->DefineProperty
    ("LINK_DIRECTORIES", cmProperty::DIRECTORY,
     "List of linker search directories.",
     "This read-only property specifies the list of directories given "
     "so far to the link_directories command.  "
     "It is intended for debugging purposes.", false);

  cm->DefineProperty
    ("RULE_LAUNCH_COMPILE", cmProperty::DIRECTORY,
     "Specify a launcher for compile rules.",
     "See the global property of the same name for details.  "
     "This overrides the global property for a directory.",
     true);
  cm->DefineProperty
    ("RULE_LAUNCH_LINK", cmProperty::DIRECTORY,
     "Specify a launcher for link rules.",
     "See the global property of the same name for details.  "
     "This overrides the global property for a directory.",
     true);
  cm->DefineProperty
    ("RULE_LAUNCH_CUSTOM", cmProperty::DIRECTORY,
     "Specify a launcher for custom rules.",
     "See the global property of the same name for details.  "
     "This overrides the global property for a directory.",
     true);
}

//----------------------------------------------------------------------------
cmTarget*
cmMakefile::AddImportedTarget(const char* name, cmTarget::TargetType type)
{
  // Create the target.
  cmsys::auto_ptr<cmTarget> target(new cmTarget);
  target->SetType(type, name);
  target->SetMakefile(this);
  target->MarkAsImported();

  // Add to the set of available imported targets.
  this->ImportedTargets[name] = target.get();

  // Transfer ownership to this cmMakefile object.
  this->ImportedTargetsOwned.push_back(target.get());
  return target.release();
}

//----------------------------------------------------------------------------
cmTarget* cmMakefile::FindTargetToUse(const char* name)
{
  // Look for an imported target.  These take priority because they
  // are more local in scope and do not have to be globally unique.
  std::map<cmStdString, cmTarget*>::const_iterator
    imported = this->ImportedTargets.find(name);
  if(imported != this->ImportedTargets.end())
    {
    return imported->second;
    }

  // Look for a target built in this project.
  return this->LocalGenerator->GetGlobalGenerator()->FindTarget(0, name);
}

//----------------------------------------------------------------------------
bool cmMakefile::EnforceUniqueName(std::string const& name, std::string& msg,
                                   bool isCustom)
{
  if(cmTarget* existing = this->FindTargetToUse(name.c_str()))
    {
    // The name given conflicts with an existing target.  Produce an
    // error in a compatible way.
    if(existing->IsImported())
      {
      // Imported targets were not supported in previous versions.
      // This is new code, so we can make it an error.
      cmOStringStream e;
      e << "cannot create target \"" << name
        << "\" because an imported target with the same name already exists.";
      msg = e.str();
      return false;
      }
    else 
      {
      // target names must be globally unique
      switch (this->GetPolicyStatus(cmPolicies::CMP0002))
        {
        case cmPolicies::WARN:
          this->IssueMessage(cmake::AUTHOR_WARNING, this->GetPolicies()->
                             GetPolicyWarning(cmPolicies::CMP0002));
        case cmPolicies::OLD:
          return true;
        case cmPolicies::REQUIRED_IF_USED:
        case cmPolicies::REQUIRED_ALWAYS:
          this->IssueMessage(cmake::FATAL_ERROR,
            this->GetPolicies()->GetRequiredPolicyError(cmPolicies::CMP0002)
            );
          return true;
        case cmPolicies::NEW:
          break;
        }
      
      // The conflict is with a non-imported target.
      // Allow this if the user has requested support.
      cmake* cm =
        this->LocalGenerator->GetGlobalGenerator()->GetCMakeInstance();
      if(isCustom && existing->GetType() == cmTarget::UTILITY &&
         this != existing->GetMakefile() &&
         cm->GetPropertyAsBool("ALLOW_DUPLICATE_CUSTOM_TARGETS"))
        {
        return true;
        }

      // Produce an error that tells the user how to work around the
      // problem.
      cmOStringStream e;
      e << "cannot create target \"" << name
        << "\" because another target with the same name already exists.  "
        << "The existing target is ";
      switch(existing->GetType())
        {
        case cmTarget::EXECUTABLE:
          e << "an executable ";
          break;
        case cmTarget::STATIC_LIBRARY:
          e << "a static library ";
          break;
        case cmTarget::SHARED_LIBRARY:
          e << "a shared library ";
          break;
        case cmTarget::MODULE_LIBRARY:
          e << "a module library ";
          break;
        case cmTarget::UTILITY:
          e << "a custom target ";
          break;
        default: break;
        }
      e << "created in source directory \""
        << existing->GetMakefile()->GetCurrentDirectory() << "\".  "
        << "See documentation for policy CMP0002 for more details.";
      msg = e.str();
      return false;
      }
    }
  return true;
}

//----------------------------------------------------------------------------
bool cmMakefile::EnforceUniqueDir(const char* srcPath, const char* binPath)
{
  // Make sure the binary directory is unique.
  cmGlobalGenerator* gg = this->LocalGenerator->GetGlobalGenerator();
  if(gg->BinaryDirectoryIsNew(binPath))
    {
    return true;
    }
  cmOStringStream e;
  switch (this->GetPolicyStatus(cmPolicies::CMP0013))
    {
    case cmPolicies::WARN:
      // Print the warning.
      e << this->GetPolicies()->GetPolicyWarning(cmPolicies::CMP0013)
        << "\n"
        << "The binary directory\n"
        << "  " << binPath << "\n"
        << "is already used to build a source directory.  "
        << "This command uses it to build source directory\n"
        << "  " << srcPath << "\n"
        << "which can generate conflicting build files.  "
        << "CMake does not support this use case but it used "
        << "to work accidentally and is being allowed for "
        << "compatibility.";
      this->IssueMessage(cmake::AUTHOR_WARNING, e.str());
    case cmPolicies::OLD:
      // OLD behavior does not warn.
      return true;
    case cmPolicies::REQUIRED_IF_USED:
    case cmPolicies::REQUIRED_ALWAYS:
      e << this->GetPolicies()->GetRequiredPolicyError(cmPolicies::CMP0013)
        << "\n";
    case cmPolicies::NEW:
      // NEW behavior prints the error.
      e << "The binary directory\n"
        << "  " << binPath << "\n"
        << "is already used to build a source directory.  "
        << "It cannot be used to build source directory\n"
        << "  " << srcPath << "\n"
        << "Specify a unique binary directory name.";
      this->IssueMessage(cmake::FATAL_ERROR, e.str());
      break;
    }

  return false;
}

//----------------------------------------------------------------------------
cmPolicies::PolicyStatus
cmMakefile::GetPolicyStatus(cmPolicies::PolicyID id)
{
  // Get the current setting of the policy.
  cmPolicies::PolicyStatus cur = this->GetPolicyStatusInternal(id);

  // If the policy is required to be set to NEW but is not, ignore the
  // current setting and tell the caller.
  if(cur != cmPolicies::NEW)
    {
    if(cur == cmPolicies::REQUIRED_ALWAYS ||
       cur == cmPolicies::REQUIRED_IF_USED)
      {
      return cur;
      }
    cmPolicies::PolicyStatus def = this->GetPolicies()->GetPolicyStatus(id);
    if(def == cmPolicies::REQUIRED_ALWAYS ||
       def == cmPolicies::REQUIRED_IF_USED)
      {
      return def;
      }
    }

  // The current setting is okay.
  return cur;
}

//----------------------------------------------------------------------------
cmPolicies::PolicyStatus
cmMakefile::GetPolicyStatusInternal(cmPolicies::PolicyID id)
{
  // Is the policy set in our stack?
  for(PolicyStackType::reverse_iterator psi = this->PolicyStack.rbegin();
      psi != this->PolicyStack.rend(); ++psi)
    {
    PolicyStackEntry::const_iterator pse = psi->find(id);
    if(pse != psi->end())
      {
      return pse->second;
      }
    }

  // If we have a parent directory, recurse up to it.
  if(this->LocalGenerator->GetParent())
    {
    cmMakefile* parent = this->LocalGenerator->GetParent()->GetMakefile();
    return parent->GetPolicyStatusInternal(id);
    }

  // The policy is not set.  Use the default for this CMake version.
  return this->GetPolicies()->GetPolicyStatus(id);
}

bool cmMakefile::SetPolicy(const char *id, 
                           cmPolicies::PolicyStatus status)
{
  cmPolicies::PolicyID pid;
  if (!this->GetPolicies()->GetPolicyID(id, /* out */ pid))
    {
    cmOStringStream e;
    e << "Policy \"" << id << "\" is not known to this version of CMake.";
    this->IssueMessage(cmake::FATAL_ERROR, e.str());
    return false;
    }
  return this->SetPolicy(pid,status);
}

//----------------------------------------------------------------------------
bool cmMakefile::SetPolicy(cmPolicies::PolicyID id,
                           cmPolicies::PolicyStatus status)
{
  // A REQUIRED_ALWAYS policy may be set only to NEW.
  if(status != cmPolicies::NEW &&
     this->GetPolicies()->GetPolicyStatus(id) ==
     cmPolicies::REQUIRED_ALWAYS)
    {
    std::string msg =
      this->GetPolicies()->GetRequiredAlwaysPolicyError(id);
    this->IssueMessage(cmake::FATAL_ERROR, msg.c_str());
    return false;
    }

  // Update the policy stack from the top to the top-most strong entry.
  bool previous_was_weak = true;
  for(PolicyStackType::reverse_iterator psi = this->PolicyStack.rbegin();
      previous_was_weak && psi != this->PolicyStack.rend(); ++psi)
    {
    (*psi)[id] = status;
    previous_was_weak = psi->Weak;
    }

  // Special hook for presenting compatibility variable as soon as
  // the user requests it.
  if(id == cmPolicies::CMP0001 &&
     (status == cmPolicies::WARN || status == cmPolicies::OLD))
    {
    if(!(this->GetCacheManager()
         ->GetCacheValue("CMAKE_BACKWARDS_COMPATIBILITY")))
      {
      // Set it to 2.4 because that is the last version where the
      // variable had meaning.
      this->AddCacheDefinition
        ("CMAKE_BACKWARDS_COMPATIBILITY", "2.4",
         "For backwards compatibility, what version of CMake "
         "commands and "
         "syntax should this version of CMake try to support.",
         cmCacheManager::STRING);
      }
    }

  return true;
}

//----------------------------------------------------------------------------
cmMakefile::PolicyPushPop::PolicyPushPop(cmMakefile* m, bool weak,
                                         cmPolicies::PolicyMap const& pm):
  Makefile(m), ReportError(true)
{
  this->Makefile->PushPolicy(weak, pm);
  this->Makefile->PushPolicyBarrier();
}

//----------------------------------------------------------------------------
cmMakefile::PolicyPushPop::~PolicyPushPop()
{
  this->Makefile->PopPolicyBarrier(this->ReportError);
  this->Makefile->PopPolicy();
}

//----------------------------------------------------------------------------
void cmMakefile::PushPolicy(bool weak, cmPolicies::PolicyMap const& pm)
{
  // Allocate a new stack entry.
  this->PolicyStack.push_back(PolicyStackEntry(pm, weak));
}

//----------------------------------------------------------------------------
void cmMakefile::PopPolicy()
{
  if(this->PolicyStack.size() > this->PolicyBarriers.back())
    {
    this->PolicyStack.pop_back();
    }
  else
    {
    this->IssueMessage(cmake::FATAL_ERROR,
                       "cmake_policy POP without matching PUSH");
    }
}

//----------------------------------------------------------------------------
void cmMakefile::PushPolicyBarrier()
{
  this->PolicyBarriers.push_back(this->PolicyStack.size());
}

//----------------------------------------------------------------------------
void cmMakefile::PopPolicyBarrier(bool reportError)
{
  // Remove any extra entries pushed on the barrier.
  PolicyStackType::size_type barrier = this->PolicyBarriers.back();
  while(this->PolicyStack.size() > barrier)
    {
    if(reportError)
      {
      this->IssueMessage(cmake::FATAL_ERROR,
                         "cmake_policy PUSH without matching POP");
      reportError = false;
      }
    this->PopPolicy();
    }

  // Remove the barrier.
  this->PolicyBarriers.pop_back();
}

bool cmMakefile::SetPolicyVersion(const char *version)
{
  return this->GetCMakeInstance()->GetPolicies()->
    ApplyPolicyVersion(this,version);
}

cmPolicies *cmMakefile::GetPolicies()
{ 
  if (!this->GetCMakeInstance())
  {
    return 0;
  }
  return this->GetCMakeInstance()->GetPolicies();
}

//----------------------------------------------------------------------------
void cmMakefile::RecordPolicies(cmPolicies::PolicyMap& pm)
{
  /* Record the setting of every policy.  */
  typedef cmPolicies::PolicyID PolicyID;
  for(PolicyID pid = cmPolicies::CMP0000;
      pid != cmPolicies::CMPCOUNT; pid = PolicyID(pid+1))
    {
    pm[pid] = this->GetPolicyStatus(pid);
    }
}
