diff options
Diffstat (limited to 'Source/CTest/cmProcess.cxx')
-rw-r--r-- | Source/CTest/cmProcess.cxx | 228 |
1 files changed, 83 insertions, 145 deletions
diff --git a/Source/CTest/cmProcess.cxx b/Source/CTest/cmProcess.cxx index de0fc9a..facd649 100644 --- a/Source/CTest/cmProcess.cxx +++ b/Source/CTest/cmProcess.cxx @@ -23,7 +23,6 @@ cmProcess::cmProcess() this->Process = 0; this->Timeout = 0; this->TotalTime = 0; - this->LastOutputPipe = cmsysProcess_Pipe_None; this->ExitValue = 0; this->Id = 0; this->StartTime = 0; @@ -74,153 +73,112 @@ bool cmProcess::StartProcess() == cmsysProcess_State_Executing); } -int cmProcess::GetNextOutputLine(std::string& stdOutLine, - std::string& stdErrLine, - bool& gotStdOut, - bool& gotStdErr, - bool running) +//---------------------------------------------------------------------------- +bool cmProcess::Buffer::GetLine(std::string& line) { - if(this->StdErrorBuffer.empty() && this->StdOutBuffer.empty()) + // Scan for the next newline. + for(size_type sz = this->size(); this->Last != sz; ++this->Last) { - return cmsysProcess_Pipe_Timeout; - } - stdOutLine = ""; - stdErrLine = ""; + if((*this)[this->Last] == '\n' || (*this)[this->Last] == '\0') + { + // Extract the range first..last as a line. + const char* data = &*this->begin() + this->First; + size_type length = this->Last - this->First; + length -= (length && data[length-1] == '\r')? 1:0; + line.assign(data, length); - this->LastOutputPipe = cmsysProcess_Pipe_Timeout; - std::vector<char>::iterator outiter = - this->StdOutBuffer.begin(); - std::vector<char>::iterator erriter = - this->StdErrorBuffer.begin(); + // Start a new range for the next line. + ++this->Last; + this->First = Last; - // 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; - gotStdOut = true; - break; + // Return the line extracted. + return true; } } - // Check for a newline in stderr. - for(;erriter != this->StdErrorBuffer.end(); ++erriter) + // Available data have been exhausted without a newline. + if(this->First != 0) { - 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; - gotStdErr = true; - break; - } + // 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; +} - if(!running && !gotStdErr && !gotStdOut) - { - //If process terminated with no newline, flush the buffer - if(!running) - { - if(!this->StdErrorBuffer.empty()) - { - gotStdErr = true; - stdErrLine.append(&this->StdErrorBuffer[0], - this->StdErrorBuffer.size()); - this->StdErrorBuffer.erase(this->StdErrorBuffer.begin(), - this->StdErrorBuffer.end()); - } - if(!this->StdOutBuffer.empty()) - { - gotStdOut = true; - stdOutLine.append(&this->StdOutBuffer[0], - this->StdOutBuffer.size()); - this->StdOutBuffer.erase(this->StdOutBuffer.begin(), - this->StdOutBuffer.end()); - } - return cmsysProcess_Pipe_None; - } +//---------------------------------------------------------------------------- +bool cmProcess::Buffer::GetLast(std::string& line) +{ + // Return the partial last line, if any. + if(!this->empty()) + { + line.assign(&*this->begin(), this->size()); + this->clear(); + return true; } - //If we get here, we have stuff waiting in the buffers, but no newline - return this->LastOutputPipe; + return false; } -// return true if there is a new line of data -// return false if there is no new data -bool cmProcess::CheckOutput(double timeout) -{ - // Wait for data from the process. - int length; - char* data; - while(1) +//---------------------------------------------------------------------------- +int cmProcess::GetNextOutputLine(std::string& line, double timeout) +{ + for(;;) { - int pipe = cmsysProcess_WaitForData(this->Process, &data, - &length, &timeout); - if(pipe == cmsysProcess_Pipe_Timeout) + // Look for lines already buffered. + if(this->StdOut.GetLine(line)) { - // Timeout has been exceeded. - this->LastOutputPipe = pipe; - return true; + return cmsysProcess_Pipe_STDOUT; } - else if(pipe == cmsysProcess_Pipe_STDOUT) + else if(this->StdErr.GetLine(line)) { - // Append to the stdout buffer. - this->StdOutBuffer.insert(this->StdOutBuffer.end(), data, data+length); - this->LastOutputPipe = pipe; + return cmsysProcess_Pipe_STDERR; } - else if(pipe == 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) { - // Append to the stderr buffer. - this->StdErrorBuffer.insert(this->StdErrorBuffer.end(), - data, data+length); - this->LastOutputPipe = pipe; + return cmsysProcess_Pipe_Timeout; } - else if(pipe == cmsysProcess_Pipe_None) + else if(p == cmsysProcess_Pipe_STDOUT) { - // Both stdout and stderr pipes have broken. Return leftover data. - if(!this->StdOutBuffer.empty()) - { - this->LastOutputPipe = cmsysProcess_Pipe_STDOUT; - return false; - } - else if(!this->StdErrorBuffer.empty()) - { - this->LastOutputPipe = cmsysProcess_Pipe_STDERR; - return false; - } - else - { - this->LastOutputPipe = cmsysProcess_Pipe_None; - return false; - } + 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; + // std::cerr << "Time to run: " << this->TotalTime << "\n"; + return cmsysProcess_Pipe_None; } // return the process status @@ -233,26 +191,6 @@ int cmProcess::GetProcessStatus() 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); - this->TotalTime = cmSystemTools::GetTime() - this->StartTime; -// std::cerr << "Time to run: " << this->TotalTime << "\n"; - return false; -} - - int cmProcess::ReportStatus() { int result = 1; |