/*============================================================================
  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 "cmLoadCacheCommand.h"

#include <cmsys/RegularExpression.hxx>

// cmLoadCacheCommand
bool cmLoadCacheCommand
::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
{
  if (args.size()< 1)
    {
    this->SetError("called with wrong number of arguments.");
    }

  if(args.size() >= 2 && args[1] == "READ_WITH_PREFIX")
    {
    return this->ReadWithPrefix(args);
    }
  
  // Cache entries to be excluded from the import list.
  // If this set is empty, all cache entries are brought in
  // and they can not be overridden.
  bool excludeFiles=false;
  unsigned int i;
  std::set<cmStdString> excludes;

  for(i=0; i<args.size(); i++)
    {
    if (excludeFiles)
      {
      excludes.insert(args[i]);
      }
    if (args[i] == "EXCLUDE")
      {
      excludeFiles=true;
      }
    if (excludeFiles && (args[i] == "INCLUDE_INTERNALS"))
      {
      break;
      }
    }

  // Internal cache entries to be imported.
  // If this set is empty, no internal cache entries are
  // brought in.
  bool includeFiles=false;
  std::set<cmStdString> includes;

  for(i=0; i<args.size(); i++)
    {
    if (includeFiles)
      {
      includes.insert(args[i]);
      }
    if (args[i] == "INCLUDE_INTERNALS")
      {
      includeFiles=true;
      }
    if (includeFiles && (args[i] == "EXCLUDE"))
      {
      break;
      }
    }

  // Loop over each build directory listed in the arguments.  Each
  // directory has a cache file.
  for(i=0; i<args.size(); i++)
    {
    if ((args[i] == "EXCLUDE") || (args[i] == "INCLUDE_INTERNALS"))
      {
      break;
      }
    this->Makefile->GetCacheManager()->LoadCache(args[i].c_str(), false,
                                             excludes, includes);
    }


  return true;
}

//----------------------------------------------------------------------------
bool cmLoadCacheCommand::ReadWithPrefix(std::vector<std::string> const& args)
{
  // Make sure we have a prefix.
  if(args.size() < 3)
    {
    this->SetError("READ_WITH_PREFIX form must specify a prefix.");
    return false;
    }
  
  // Make sure the cache file exists.
  std::string cacheFile = args[0]+"/CMakeCache.txt";
  if(!cmSystemTools::FileExists(cacheFile.c_str()))
    {
    std::string e = "Cannot load cache file from " + cacheFile;
    this->SetError(e.c_str());
    return false;
    }
  
  // Prepare the table of variables to read.
  this->Prefix = args[2];
  for(unsigned int i=3; i < args.size(); ++i)
    {
    this->VariablesToRead.insert(args[i]);
    }
  
  // Read the cache file.
  std::ifstream fin(cacheFile.c_str());  
  
  // This is a big hack read loop to overcome a buggy ifstream
  // implementation on HP-UX.  This should work on all platforms even
  // for small buffer sizes.
  const int bufferSize = 4096;
  char buffer[bufferSize];  
  std::string line;
  while(fin)
    {
    // Read a block of the file.
    fin.read(buffer, bufferSize);
    if(fin.gcount())
      {
      // Parse for newlines directly.
      const char* i = buffer;
      const char* end = buffer+fin.gcount();
      while(i != end)
        {
        const char* begin = i;
        while(i != end && *i != '\n') { ++i; }
        if(i == begin || *(i-1) != '\r')
          {
          // Include this portion of the line.
          line += std::string(begin, i-begin);
          }
        else
          {
          // Include this portion of the line.
          // Don't include the \r in a \r\n pair.
          line += std::string(begin, i-1-begin);
          }
        if(i != end)
          {
          // Completed a line.
          this->CheckLine(line.c_str());
          line = "";
          
          // Skip the newline character.
          ++i;
          }
        }
      }
    }
  if(line.length())
    {
    // Partial last line.
    this->CheckLine(line.c_str());
    }
  
  return true;
}

//----------------------------------------------------------------------------
void cmLoadCacheCommand::CheckLine(const char* line)
{
  // Check one line of the cache file.
  std::string var;
  std::string value;
  if(this->ParseEntry(line, var, value))
    {
    // Found a real entry.  See if this one was requested.
    if(this->VariablesToRead.find(var) != this->VariablesToRead.end())
      {
      // This was requested.  Set this variable locally with the given
      // prefix.
      var = this->Prefix + var;
      if(value.length())
        {
        this->Makefile->AddDefinition(var.c_str(), value.c_str());
        }
      else
        {
        this->Makefile->RemoveDefinition(var.c_str());
        }
      }
    }
}

//----------------------------------------------------------------------------
bool cmLoadCacheCommand::ParseEntry(const char* entry, std::string& var,
                                    std::string& value)
{
  // input line is:         key:type=value
  cmsys::RegularExpression reg("^([^:]*):([^=]*)=(.*[^\t ]|[\t ]*)[\t ]*$");
  // input line is:         "key":type=value
  cmsys::RegularExpression 
    regQuoted("^\"([^\"]*)\":([^=]*)=(.*[^\t ]|[\t ]*)[\t ]*$");
  bool flag = false;
  if(regQuoted.find(entry))
    {
    var = regQuoted.match(1);
    value = regQuoted.match(3);
    flag = true;
    }
  else if (reg.find(entry))
    {
    var = reg.match(1);
    value = reg.match(3);
    flag = true;
    }

  // if value is enclosed in single quotes ('foo') then remove them
  // it is used to enclose trailing space or tab
  if (flag && 
      value.size() >= 2 &&
      value[0] == '\'' && 
      value[value.size() - 1] == '\'') 
    {
    value = value.substr(1, value.size() - 2);
    }
  return flag;
}
