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

#include <cmsys/auto_ptr.hxx>

bool cmForEachFunctionBlocker::
IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf,
                  cmExecutionStatus &inStatus)
{
  if (!cmSystemTools::Strucmp(lff.Name.c_str(),"foreach"))
    {
    // record the number of nested foreach commands
    this->Depth++;
    }
  else if (!cmSystemTools::Strucmp(lff.Name.c_str(),"endforeach"))
    {
    // if this is the endofreach for this statement
    if (!this->Depth)
      {
      // Remove the function blocker for this scope or bail.
      cmsys::auto_ptr<cmFunctionBlocker>
        fb(mf.RemoveFunctionBlocker(this, lff));
      if(!fb.get()) { return false; }

      // at end of for each execute recorded commands
      // store the old value
      std::string oldDef;
      if (mf.GetDefinition(this->Args[0].c_str()))
        {
        oldDef = mf.GetDefinition(this->Args[0].c_str());
        }
      std::vector<std::string>::const_iterator j = this->Args.begin();
      ++j;

      std::string tmps;
      cmListFileArgument arg;
      for( ; j != this->Args.end(); ++j)
        {
        // set the variable to the loop value
        mf.AddDefinition(this->Args[0].c_str(),j->c_str());
        // Invoke all the functions that were collected in the block.
        cmExecutionStatus status;
        for(unsigned int c = 0; c < this->Functions.size(); ++c)
          {
          status.Clear();
          mf.ExecuteCommand(this->Functions[c],status);
          if (status.GetReturnInvoked())
            {
            inStatus.SetReturnInvoked(true);
            // restore the variable to its prior value
            mf.AddDefinition(this->Args[0].c_str(),oldDef.c_str());
            return true;
            }
          if (status.GetBreakInvoked())
            {
            // restore the variable to its prior value
            mf.AddDefinition(this->Args[0].c_str(),oldDef.c_str());
            return true;
            }
          if(cmSystemTools::GetFatalErrorOccured() )
            {
            return true;
            }
          }
        }
      // restore the variable to its prior value
      mf.AddDefinition(this->Args[0].c_str(),oldDef.c_str());
      return true;
      }
    else
      {
      // close out a nested foreach
      this->Depth--;
      }
    }

  // record the command
  this->Functions.push_back(lff);

  // always return true
  return true;
}

bool cmForEachFunctionBlocker::
ShouldRemove(const cmListFileFunction& lff, cmMakefile& mf)
{
  if(!cmSystemTools::Strucmp(lff.Name.c_str(),"endforeach"))
    {
    std::vector<std::string> expandedArguments;
    mf.ExpandArguments(lff.Arguments, expandedArguments);
    // if the endforeach has arguments then make sure
    // they match the begin foreach arguments
    if ((expandedArguments.empty() ||
         (expandedArguments[0] == this->Args[0])))
      {
      return true;
      }
    }
  return false;
}

bool cmForEachCommand
::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
{
  if(args.size() < 1)
    {
    this->SetError("called with incorrect number of arguments");
    return false;
    }
  if(args.size() > 1 && args[1] == "IN")
    {
    return this->HandleInMode(args);
    }

  // create a function blocker
  cmForEachFunctionBlocker *f = new cmForEachFunctionBlocker();
  if ( args.size() > 1 )
    {
    if ( args[1] == "RANGE" )
      {
      int start = 0;
      int stop = 0;
      int step = 0;
      if ( args.size() == 3 )
        {
        stop = atoi(args[2].c_str());
        }
      if ( args.size() == 4 )
        {
        start = atoi(args[2].c_str());
        stop = atoi(args[3].c_str());
        }
      if ( args.size() == 5 )
        {
        start = atoi(args[2].c_str());
        stop = atoi(args[3].c_str());
        step = atoi(args[4].c_str());
        }
      if ( step == 0 )
        {
        if ( start > stop )
          {
          step = -1;
          }
        else
          {
          step = 1;
          }
        }
      if (
        (start > stop && step > 0) ||
        (start < stop && step < 0) ||
        step == 0
        )
        {
        cmOStringStream str;
        str << "called with incorrect range specification: start ";
        str << start << ", stop " << stop << ", step " << step;
        this->SetError(str.str().c_str());
        return false;
        }
      std::vector<std::string> range;
      char buffer[100];
      range.push_back(args[0]);
      int cc;
      for ( cc = start; ; cc += step )
        {
        if ( (step > 0 && cc > stop) || (step < 0 && cc < stop) )
          {
          break;
          }
        sprintf(buffer, "%d", cc);
        range.push_back(buffer);
        if ( cc == stop )
          {
          break;
          }
        }
      f->Args = range;
      }
    else
      {
      f->Args = args;
      }
    }
  else
    {
    f->Args = args;
    }
  this->Makefile->AddFunctionBlocker(f);

  return true;
}

//----------------------------------------------------------------------------
bool cmForEachCommand::HandleInMode(std::vector<std::string> const& args)
{
  cmsys::auto_ptr<cmForEachFunctionBlocker> f(new cmForEachFunctionBlocker());
  f->Args.push_back(args[0]);

  enum Doing { DoingNone, DoingLists, DoingItems };
  Doing doing = DoingNone;
  for(unsigned int i=2; i < args.size(); ++i)
    {
    if(doing == DoingItems)
      {
      f->Args.push_back(args[i]);
      }
    else if(args[i] == "LISTS")
      {
      doing = DoingLists;
      }
    else if(args[i] == "ITEMS")
      {
      doing = DoingItems;
      }
    else if(doing == DoingLists)
      {
      const char* value = this->Makefile->GetDefinition(args[i].c_str());
      if(value && *value)
        {
        cmSystemTools::ExpandListArgument(value, f->Args, true);
        }
      }
    else
      {
      cmOStringStream e;
      e << "Unknown argument:\n" << "  " << args[i] << "\n";
      this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
      return true;
      }
    }

  this->Makefile->AddFunctionBlocker(f.release()); // TODO: pass auto_ptr
  return true;
}
