ENH: add missing file
This commit is contained in:
parent
bb7b27e417
commit
7950b99d9d
288
Source/CTest/cmProcess.cxx
Normal file
288
Source/CTest/cmProcess.cxx
Normal file
@ -0,0 +1,288 @@
|
||||
/*=========================================================================
|
||||
|
||||
Program: CMake - Cross-Platform Makefile Generator
|
||||
Module: $RCSfile$
|
||||
Language: C++
|
||||
Date: $Date$
|
||||
Version: $Revision$
|
||||
|
||||
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;
|
||||
|
||||
}
|
73
Source/CTest/cmProcess.h
Normal file
73
Source/CTest/cmProcess.h
Normal file
@ -0,0 +1,73 @@
|
||||
/*=========================================================================
|
||||
|
||||
Program: CMake - Cross-Platform Makefile Generator
|
||||
Module: $RCSfile$
|
||||
Language: C++
|
||||
Date: $Date$
|
||||
Version: $Revision$
|
||||
|
||||
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
|
Loading…
x
Reference in New Issue
Block a user