[Cmake-commits] [cmake-commits] hoffman committed cmProcess.cxx NONE 1.1 cmProcess.h NONE 1.1

cmake-commits at cmake.org cmake-commits at cmake.org
Thu Jul 3 09:49:51 EDT 2008


Update of /cvsroot/CMake/CMake/Source/CTest
In directory public:/mounts/ram/cvs-serv20273

Added Files:
	cmProcess.cxx cmProcess.h 
Log Message:
ENH: add missing file


--- NEW FILE: cmProcess.cxx ---
/*=========================================================================

  Program:   CMake - Cross-Platform Makefile Generator
  Module:    $RCSfile: cmProcess.cxx,v $
  Language:  C++
  Date:      $Date: 2008-07-03 13:49:48 $
  Version:   $Revision: 1.1 $

  Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
  See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include <cmProcess.h>
#include <iostream>

cmProcess::cmProcess()
{
  this->Process = 0;
  this->Timeout = 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->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_SetOption(this->Process, cmsysProcess_Option_HideWindow, 1);
  cmsysProcess_SetTimeout(this->Process, this->Timeout);
  cmsysProcess_Execute(this->Process);
  return (cmsysProcess_GetState(this->Process)
          == cmsysProcess_State_Executing);
}
  
// return true if there is a new line of data
// return false if there is no new data
int cmProcess::CheckOutput(double timeout, 
                            std::string& stdOutLine,
                            std::string& stdErrLine)
{
  stdOutLine = "";
  stdErrLine = "";
  std::vector<char>::iterator outiter = 
    this->StdOutBuffer.begin();
  std::vector<char>::iterator erriter = 
    this->StdErrorBuffer.begin();
  while(1)
    {
    // Check for a newline in stdout.
    for(;outiter != this->StdOutBuffer.end(); ++outiter)
      {
      if((*outiter == '\r') && ((outiter+1) == this->StdOutBuffer.end()))
        {
        break;
        }
      else if(*outiter == '\n' || *outiter == '\0')
        {
        int length = outiter-this->StdOutBuffer.begin();
        if(length > 1 && *(outiter-1) == '\r')
          {
          --length;
          }
        if(length > 0)
          {
          stdOutLine.append(&this->StdOutBuffer[0], length);
          }
        this->StdOutBuffer.erase(this->StdOutBuffer.begin(), outiter+1);
        this->LastOutputPipe = cmsysProcess_Pipe_STDOUT;
        return  this->LastOutputPipe;;
        }
      }

    // Check for a newline in stderr.
    for(;erriter != this->StdErrorBuffer.end(); ++erriter)
      {
      if((*erriter == '\r') && ((erriter+1) == this->StdErrorBuffer.end()))
        {
        break;
        }
      else if(*erriter == '\n' || *erriter == '\0')
        {
        int length = erriter-this->StdErrorBuffer.begin();
        if(length > 1 && *(erriter-1) == '\r')
          {
          --length;
          }
        if(length > 0)
          {
          stdErrLine.append(&this->StdErrorBuffer[0], length);
          }
        this->StdErrorBuffer.erase(this->StdErrorBuffer.begin(), erriter+1);
        this->LastOutputPipe = cmsysProcess_Pipe_STDERR;
        return this->LastOutputPipe;
        }
      }

    // No newlines found.  Wait for more data from the process.
    int length;
    char* data;
    int pipe = cmsysProcess_WaitForData(this->Process, &data, 
                                        &length, &timeout);
    if(pipe == cmsysProcess_Pipe_Timeout)
      {
      // Timeout has been exceeded.
      this->LastOutputPipe = pipe;
      return pipe;
      }
    else if(pipe == cmsysProcess_Pipe_STDOUT)
      {
      // Append to the stdout buffer.
      std::vector<char>::size_type size = this->StdOutBuffer.size();
      this->StdOutBuffer.insert(this->StdOutBuffer.end(), data, data+length);
      outiter = this->StdOutBuffer.begin()+size;
      }
    else if(pipe == cmsysProcess_Pipe_STDERR)
      {
      // Append to the stderr buffer.
      std::vector<char>::size_type size = this->StdErrorBuffer.size();
      this->StdErrorBuffer.insert(this->StdErrorBuffer.end(),
                                  data, data+length);
      erriter = this->StdErrorBuffer.begin()+size;
      }
    else if(pipe == cmsysProcess_Pipe_None)
      {
      // Both stdout and stderr pipes have broken.  Return leftover data.
      if(!this->StdOutBuffer.empty())
        {
        stdOutLine.append(&this->StdOutBuffer[0],
                          outiter-this->StdOutBuffer.begin());
        this->StdOutBuffer.erase(this->StdOutBuffer.begin(),
                                 this->StdOutBuffer.end());
        this->LastOutputPipe = cmsysProcess_Pipe_STDOUT;
        return this->LastOutputPipe;
        }
      else if(!this->StdErrorBuffer.empty())
        {
        stdErrLine.append(&this->StdErrorBuffer[0],
                          erriter-this->StdErrorBuffer.begin());
        this->StdErrorBuffer.erase(this->StdErrorBuffer.begin(), 
                                   this->StdErrorBuffer.end());
        this->LastOutputPipe = cmsysProcess_Pipe_STDERR;
        return this->LastOutputPipe;
        }
      else
        {
        this->LastOutputPipe = cmsysProcess_Pipe_None;
        return this->LastOutputPipe;
        }
      }
    }
}


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

// return true if the process is running
bool cmProcess::IsRunning()
{
  int status = this->GetProcessStatus();
  if(status == cmsysProcess_State_Executing )
    {
    if(this->LastOutputPipe != 0)
      {
      return true;
      }
    }
  // if the process is done, then wait for it to exit
  cmsysProcess_WaitForExit(this->Process, 0);
  this->ExitValue = cmsysProcess_GetExitValue(this->Process);
  return false;
}


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;

}

--- NEW FILE: cmProcess.h ---
/*=========================================================================

  Program:   CMake - Cross-Platform Makefile Generator
  Module:    $RCSfile: cmProcess.h,v $
  Language:  C++
  Date:      $Date: 2008-07-03 13:49:49 $
  Version:   $Revision: 1.1 $

  Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
  See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#ifndef cmProcess_h
#define cmProcess_h

#include <set>
#include <map>
#include <string>
#include <vector>
#include <cmsys/Process.h>


/** \class cmProcess
 * \brief run a process with c++
 *
 * cmProcess wraps the kwsys process stuff in a c++ class.
 */
class cmProcess 
{
public:
  cmProcess();
  ~cmProcess();
  const char* GetCommand() { return this->Command.c_str();}
  void SetCommand(const char* command);
  void SetCommandArguments(std::vector<std::string> const& arg);
  void SetWorkingDirectory(const char* dir) { this->WorkingDirectory = dir;}
  void SetTimeout(double t) { this->Timeout = t;}
  // Return true if the process starts
  bool StartProcess();
  
  // return process state
  int CheckOutput(double timeout, 
                  std::string& stdOutLine,
                  std::string& stdErrLine);
  // return the process status
  int GetProcessStatus();
  // return true if the process is running
  bool IsRunning();
  // Report the status of the program 
  int ReportStatus();
  int GetId() { return this->Id; }
  void SetId(int id) { this->Id = id;}
  int GetExitValue() { return this->ExitValue;}
private:
  int LastOutputPipe;
  double Timeout;
  cmsysProcess* Process;
  std::vector<char> StdErrorBuffer;
  std::vector<char> StdOutBuffer;
  std::string Command;
  std::string WorkingDirectory;
  std::vector<std::string> Arguments;
  std::vector<const char*> ProcessArgs;
  std::string Output;
  int Id;
  int ExitValue;
};

#endif



More information about the Cmake-commits mailing list