Typically Windows applications (eg. MSVC compiler) use current console's codepage for output to pipes so we need to encode that to internally used encoding (KWSYS_ENCODING_DEFAULT_CODEPAGE). --- Source/cmExecProgramCommand.cxx | 1 + Source/cmExecuteProcessCommand.cxx | 1 + Source/cmProcessTools.cxx | 2 ++ Source/cmSystemTools.cxx | 3 +++ Source/kwsys/CMakeLists.txt | 2 ++ Source/kwsys/Process.h.in | 13 +++++++++++++ Source/kwsys/ProcessUNIX.c | 6 ++++++ Source/kwsys/ProcessWin32.c | 33 ++++++++++++++++++++++++++++++++- Source/kwsys/SystemInformation.cxx | 1 + 9 files changed, 61 insertions(+), 1 deletion(-)
diff --git a/Source/cmExecProgramCommand.cxx b/Source/cmExecProgramCommand.cxx index 58bbc31..92b89fc 100644 --- a/Source/cmExecProgramCommand.cxx +++ b/Source/cmExecProgramCommand.cxx @@ -220,6 +220,7 @@ bool cmExecProgramCommand::RunCommand(const char* command, std::string& output, char* data; int p; while ((p = cmsysProcess_WaitForData(cp, &data, &length, CM_NULLPTR), p)) { + cmsysProcess_DecodeTextOutput(cp, &data, &length); if (p == cmsysProcess_Pipe_STDOUT || p == cmsysProcess_Pipe_STDERR) { if (verbose) { cmSystemTools::Stdout(data, length); diff --git a/Source/cmExecuteProcessCommand.cxx b/Source/cmExecuteProcessCommand.cxx index d97b25f..b13fb2e 100644 --- a/Source/cmExecuteProcessCommand.cxx +++ b/Source/cmExecuteProcessCommand.cxx @@ -229,6 +229,7 @@ bool cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args, char* data; int p; while ((p = cmsysProcess_WaitForData(cp, &data, &length, CM_NULLPTR), p)) { + cmsysProcess_DecodeTextOutput(cp, &data, &length); // Put the output in the right place. if (p == cmsysProcess_Pipe_STDOUT && !output_quiet) { if (output_variable.empty()) { diff --git a/Source/cmProcessTools.cxx b/Source/cmProcessTools.cxx index 34b8df2..8ab8070 100644 --- a/Source/cmProcessTools.cxx +++ b/Source/cmProcessTools.cxx @@ -23,10 +23,12 @@ void cmProcessTools::RunProcess(struct cmsysProcess_s* cp, OutputParser* out, while ((out || err) && (p = cmsysProcess_WaitForData(cp, &data, &length, CM_NULLPTR), p)) { if (out && p == cmsysProcess_Pipe_STDOUT) { + cmsysProcess_DecodeTextOutput(cp, &data, &length); if (!out->Process(data, length)) { out = CM_NULLPTR; } } else if (err && p == cmsysProcess_Pipe_STDERR) { + cmsysProcess_DecodeTextOutput(cp, &data, &length); if (!err->Process(data, length)) { err = CM_NULLPTR; } diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 9740ef7..aeb5471 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -616,6 +616,7 @@ bool cmSystemTools::RunSingleCommand(std::vector<std::string> const& command, (captureStdOut || captureStdErr || outputflag != OUTPUT_NONE)) { while ((pipe = cmsysProcess_WaitForData(cp, &data, &length, CM_NULLPTR)) > 0) { + cmsysProcess_DecodeTextOutput(cp, &data, &length); // Translate NULL characters in the output into valid text. // Visual Studio 7 puts these characters in the output of its // build process. @@ -1689,11 +1690,13 @@ int cmSystemTools::WaitForLine(cmsysProcess* process, std::string& line, return pipe; } else if (pipe == cmsysProcess_Pipe_STDOUT) { // Append to the stdout buffer. + cmsysProcess_DecodeTextOutput(process, &data, &length); std::vector<char>::size_type size = out.size(); out.insert(out.end(), data, data + length); outiter = out.begin() + size; } else if (pipe == cmsysProcess_Pipe_STDERR) { // Append to the stderr buffer. + cmsysProcess_DecodeTextOutput(process, &data, &length); std::vector<char>::size_type size = err.size(); err.insert(err.end(), data, data + length); erriter = err.begin() + size; diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt index 39b03b3..65203c0 100644 --- a/Source/kwsys/CMakeLists.txt +++ b/Source/kwsys/CMakeLists.txt @@ -708,6 +708,8 @@ IF(KWSYS_USE_Process) IF(NOT UNIX) # Use the Windows implementation. SET(KWSYS_C_SRCS ${KWSYS_C_SRCS} ProcessWin32.c) + SET_PROPERTY(SOURCE ProcessWin32.c APPEND PROPERTY COMPILE_DEFINITIONS + KWSYS_ENCODING_DEFAULT_CODEPAGE=${KWSYS_ENCODING_DEFAULT_CODEPAGE}) ELSE() # Use the UNIX implementation. SET(KWSYS_C_SRCS ${KWSYS_C_SRCS} ProcessUNIX.c) diff --git a/Source/kwsys/Process.h.in b/Source/kwsys/Process.h.in index 96563a2..0c79b47 100644 --- a/Source/kwsys/Process.h.in +++ b/Source/kwsys/Process.h.in @@ -67,6 +67,7 @@ # define kwsysProcess_Execute kwsys_ns(Process_Execute) # define kwsysProcess_Disown kwsys_ns(Process_Disown) # define kwsysProcess_WaitForData kwsys_ns(Process_WaitForData) +# define kwsysProcess_DecodeTextOutput kwsys_ns(Process_DecodeTextOutput) # define kwsysProcess_Pipes_e kwsys_ns(Process_Pipes_e) # define kwsysProcess_Pipe_None kwsys_ns(Process_Pipe_None) # define kwsysProcess_Pipe_STDIN kwsys_ns(Process_Pipe_STDIN) @@ -356,6 +357,18 @@ enum kwsysProcess_Pipes_e }; /** + * Decode pipe's text output from external encoding to internal. + * + * data = Must be a pointer to the same data buffer that WaitForData + returned. + * length = Pointer to the length of data, also must be same as returned + * from WaitForData. + * + * Returns 1 if data was succesfully decoded or 0 in case of error. + */ +kwsysEXPORT int kwsysProcess_DecodeTextOutput(kwsysProcess* cp, char** data, int* length); + +/** * Block until the child process terminates or the given timeout * expires. If no process is running, returns immediatly. The * argument is: diff --git a/Source/kwsys/ProcessUNIX.c b/Source/kwsys/ProcessUNIX.c index b577982..a357b22 100644 --- a/Source/kwsys/ProcessUNIX.c +++ b/Source/kwsys/ProcessUNIX.c @@ -1187,6 +1187,12 @@ int kwsysProcess_WaitForData(kwsysProcess* cp, char** data, int* length, } /*--------------------------------------------------------------------------*/ +int kwsysProcess_DecodeTextOutput(kwsysProcess* cp, char** data, int* length) +{ + return 1; +} + +/*--------------------------------------------------------------------------*/ static int kwsysProcessWaitForPipe(kwsysProcess* cp, char** data, int* length, kwsysProcessWaitData* wd) { diff --git a/Source/kwsys/ProcessWin32.c b/Source/kwsys/ProcessWin32.c index 2b93e69..6424969 100644 --- a/Source/kwsys/ProcessWin32.c +++ b/Source/kwsys/ProcessWin32.c @@ -69,6 +69,7 @@ a UNIX-style select system call. /* The maximum amount to read from a pipe at a time. */ #define KWSYSPE_PIPE_BUFFER_SIZE 1024 +#define KWSYSPE_PIPE_ACTUAL_BUFFER_SIZE (KWSYSPE_PIPE_BUFFER_SIZE * 2) /* Debug output macro. */ #if 0 @@ -181,7 +182,7 @@ struct kwsysProcessPipeData_s /* ------------- Data managed per call to Execute ------------- */ /* Buffer for data read in this pipe's thread. */ - char DataBuffer[KWSYSPE_PIPE_BUFFER_SIZE]; + char DataBuffer[KWSYSPE_PIPE_ACTUAL_BUFFER_SIZE]; /* The length of the data stored in the buffer. */ DWORD DataLength; @@ -319,6 +320,9 @@ struct kwsysProcess_s /* Own handles for the child's ends of the pipes in the parent process. Used temporarily during process creation. */ HANDLE PipeChildStd[3]; + + /* Console's active codepage */ + UINT codepage; }; /*--------------------------------------------------------------------------*/ @@ -1645,6 +1649,28 @@ void kwsysProcessPipeThreadReadPipe(kwsysProcess* cp, kwsysProcessPipeData* td) } /*--------------------------------------------------------------------------*/ +int kwsysProcess_DecodeTextOutput(kwsysProcess* cp, char** data, int* length) +{ + int success = 1; + if (cp && data && length && *length > 0 && + cp->codepage != KWSYS_ENCODING_DEFAULT_CODEPAGE) { + success = 0; + const int wlength = MultiByteToWideChar(cp->codepage, 0, *data, *length, NULL, 0); + wchar_t* wdata = malloc(wlength * sizeof(wchar_t)); + int r = MultiByteToWideChar(cp->codepage, 0, *data, *length, wdata, wlength); + if (r > 0) { + r = WideCharToMultiByte(KWSYS_ENCODING_DEFAULT_CODEPAGE, 0, wdata, wlength, *data, KWSYSPE_PIPE_ACTUAL_BUFFER_SIZE, NULL, NULL); + if (r > 0) { + *length = r; + success = 1; + } + } + free(wdata); + } + return success; +} + +/*--------------------------------------------------------------------------*/ /* Function executed for each pipe's thread. Argument is a pointer to @@ -1761,6 +1787,11 @@ int kwsysProcessInitialize(kwsysProcess* cp) } } + cp->codepage = GetConsoleCP(); + if (!cp->codepage) { + cp->codepage = GetACP(); + } + return 1; } diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx index c84d71f..f3e5a50 100644 --- a/Source/kwsys/SystemInformation.cxx +++ b/Source/kwsys/SystemInformation.cxx @@ -4637,6 +4637,7 @@ std::string SystemInformationImplementation::RunProcess(std::vector<const char*> while( ( static_cast<void>(pipe = kwsysProcess_WaitForData(gp,&data,&length,&timeout)), (pipe == kwsysProcess_Pipe_STDOUT || pipe == kwsysProcess_Pipe_STDERR) ) ) // wait for 1s { + kwsysProcess_DecodeTextOutput(gp, &data, &length); buffer.append(data, length); } kwsysProcess_WaitForExit(gp, 0); -- 2.9.0 -- Powered by www.kitware.com Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Kitware offers various services to support the CMake community. For more information on each offering, please visit: CMake Support: http://cmake.org/cmake/help/support.html CMake Consulting: http://cmake.org/cmake/help/consulting.html CMake Training Courses: http://cmake.org/cmake/help/training.html Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Follow this link to subscribe/unsubscribe: http://public.kitware.com/mailman/listinfo/cmake-developers