/*============================================================================
  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 <cmProcess.h>
#include <cmSystemTools.h>

cmProcess::cmProcess()
{
  this->Process = 0;
  this->Timeout = 0;
  this->TotalTime = 0;
  this->ExitValue = 0;
  this->Id = 0;
  this->StartTime = 0;
}

cmProcess::~cmProcess()
{
  cmsysProcess_Delete(this->Process);
}
void cmProcess::SetCommand(const char* command)
{
  this->Command = command;
}

void cmProcess::SetCommandArguments(std::vector<std::string> const& args)
{
  this->Arguments = args;
}

bool cmProcess::StartProcess()
{
  if(this->Command.size() == 0)
    {
    return false;
    }
  this->StartTime = cmSystemTools::GetTime();
  this->ProcessArgs.clear();
  // put the command as arg0
  this->ProcessArgs.push_back(this->Command.c_str());
  // now put the command arguments in
  for(std::vector<std::string>::iterator i = this->Arguments.begin();
      i != this->Arguments.end(); ++i)
    {
    this->ProcessArgs.push_back(i->c_str());
    }
  this->ProcessArgs.push_back(0); // null terminate the list
  this->Process = cmsysProcess_New();
  cmsysProcess_SetCommand(this->Process, &*this->ProcessArgs.begin());
  if(this->WorkingDirectory.size())
    {
    cmsysProcess_SetWorkingDirectory(this->Process,
                                     this->WorkingDirectory.c_str());
    }
  cmsysProcess_SetTimeout(this->Process, this->Timeout);
  cmsysProcess_Execute(this->Process);
  return (cmsysProcess_GetState(this->Process)
          == cmsysProcess_State_Executing);
}

//----------------------------------------------------------------------------
bool cmProcess::Buffer::GetLine(std::string& line)
{
  // Scan for the next newline.
  for(size_type sz = this->size(); this->Last != sz; ++this->Last)
    {
    if((*this)[this->Last] == '\n' || (*this)[this->Last] == '\0')
      {
      // Extract the range first..last as a line.
      const char* text = &*this->begin() + this->First;
      size_type length = this->Last - this->First;
      while(length && text[length-1] == '\r')
        {
        length --;
        }
      line.assign(text, length);

      // Start a new range for the next line.
      ++this->Last;
      this->First = Last;

      // Return the line extracted.
      return true;
      }
    }

  // Available data have been exhausted without a newline.
  if(this->First != 0)
    {
    // Move the partial line to the beginning of the buffer.
    this->erase(this->begin(), this->begin() + this->First);
    this->First = 0;
    this->Last = this->size();
    }
  return false;
}

//----------------------------------------------------------------------------
bool cmProcess::Buffer::GetLast(std::string& line)
{
  // Return the partial last line, if any.
  if(!this->empty())
    {
    line.assign(&*this->begin(), this->size());
    this->First = this->Last = 0;
    this->clear();
    return true;
    }
  return false;
}

//----------------------------------------------------------------------------
int cmProcess::GetNextOutputLine(std::string& line, double timeout)
{
  for(;;)
    {
    // Look for lines already buffered.
    if(this->StdOut.GetLine(line))
      {
      return cmsysProcess_Pipe_STDOUT;
      }
    else if(this->StdErr.GetLine(line))
      {
      return cmsysProcess_Pipe_STDERR;
      }

    // Check for more data from the process.
    char* data;
    int length;
    int p = cmsysProcess_WaitForData(this->Process, &data, &length, &timeout);
    if(p == cmsysProcess_Pipe_Timeout)
      {
      return cmsysProcess_Pipe_Timeout;
      }
    else if(p == cmsysProcess_Pipe_STDOUT)
      {
      this->StdOut.insert(this->StdOut.end(), data, data+length);
      }
    else if(p == cmsysProcess_Pipe_STDERR)
      {
      this->StdErr.insert(this->StdErr.end(), data, data+length);
      }
    else // p == cmsysProcess_Pipe_None
      {
      // The process will provide no more data.
      break;
      }
    }

  // Look for partial last lines.
  if(this->StdOut.GetLast(line))
    {
    return cmsysProcess_Pipe_STDOUT;
    }
  else if(this->StdErr.GetLast(line))
    {
    return cmsysProcess_Pipe_STDERR;
    }

  // No more data.  Wait for process exit.
  if(!cmsysProcess_WaitForExit(this->Process, &timeout))
    {
    return cmsysProcess_Pipe_Timeout;
    }

  // Record exit information.
  this->ExitValue = cmsysProcess_GetExitValue(this->Process);
  this->TotalTime = cmSystemTools::GetTime() - this->StartTime;
  // Because of a processor clock scew the runtime may become slightly
  // negative. If someone changed the system clock while the process was
  // running this may be even more. Make sure not to report a negative
  // duration here.
  if (this->TotalTime <= 0.0)
    {
    this->TotalTime = 0.0;
    }
  //  std::cerr << "Time to run: " << this->TotalTime << "\n";
  return cmsysProcess_Pipe_None;
}

// return the process status
int cmProcess::GetProcessStatus()
{
  if(!this->Process)
    {
    return cmsysProcess_State_Exited;
    }
  return cmsysProcess_GetState(this->Process);
}

int cmProcess::ReportStatus()
{
  int result = 1;
  switch(cmsysProcess_GetState(this->Process))
    {
    case cmsysProcess_State_Starting:
      {
      std::cerr << "cmProcess: Never started "
           << this->Command << " process.\n";
      } break;
    case cmsysProcess_State_Error:
      {
      std::cerr << "cmProcess: Error executing " << this->Command
                << " process: "
                << cmsysProcess_GetErrorString(this->Process)
                << "\n";
      } break;
    case cmsysProcess_State_Exception:
      {
      std::cerr << "cmProcess: " << this->Command
                      << " process exited with an exception: ";
      switch(cmsysProcess_GetExitException(this->Process))
        {
        case cmsysProcess_Exception_None:
          {
          std::cerr << "None";
          } break;
        case cmsysProcess_Exception_Fault:
          {
          std::cerr << "Segmentation fault";
          } break;
        case cmsysProcess_Exception_Illegal:
          {
          std::cerr << "Illegal instruction";
          } break;
        case cmsysProcess_Exception_Interrupt:
          {
          std::cerr << "Interrupted by user";
          } break;
        case cmsysProcess_Exception_Numerical:
          {
          std::cerr << "Numerical exception";
          } break;
        case cmsysProcess_Exception_Other:
          {
          std::cerr << "Unknown";
          } break;
        }
      std::cerr << "\n";
      } break;
    case cmsysProcess_State_Executing:
      {
      std::cerr << "cmProcess: Never terminated " <<
        this->Command << " process.\n";
      } break;
    case cmsysProcess_State_Exited:
      {
      result = cmsysProcess_GetExitValue(this->Process);
      std::cerr << "cmProcess: " << this->Command
                << " process exited with code "
                << result << "\n";
      } break;
    case cmsysProcess_State_Expired:
      {
      std::cerr << "cmProcess: killed " << this->Command
                << " process due to timeout.\n";
      } break;
    case cmsysProcess_State_Killed:
      {
      std::cerr << "cmProcess: killed " << this->Command << " process.\n";
      } break;
    }
  return result;

}


int cmProcess::GetExitException()
{
  return cmsysProcess_GetExitException(this->Process);
}
