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    |  3 ++
 Source/cmExecuteProcessCommand.cxx | 11 ++++-
 Source/cmProcessTools.cxx          |  9 +++-
 Source/cmSystemTools.cxx           | 11 ++++-
 Source/kwsys/CMakeLists.txt        |  2 +-
 Source/kwsys/ProcessOutput.hxx.in  | 94 ++++++++++++++++++++++++++++++++++++++
 Source/kwsys/SystemInformation.cxx |  4 ++
 bootstrap                          |  1 +
 8 files changed, 128 insertions(+), 7 deletions(-)
 create mode 100644 Source/kwsys/ProcessOutput.hxx.in

diff --git a/Source/cmExecProgramCommand.cxx b/Source/cmExecProgramCommand.cxx
index 58bbc31..217cda1 100644
--- a/Source/cmExecProgramCommand.cxx
+++ b/Source/cmExecProgramCommand.cxx
@@ -14,6 +14,7 @@
 #include "cmSystemTools.h"
 
 #include <cmsys/Process.h>
+#include <cmsys/ProcessOutput.hxx>
 
 // cmExecProgramCommand
 bool cmExecProgramCommand::InitialPass(std::vector<std::string> const& args,
@@ -219,6 +220,7 @@ bool cmExecProgramCommand::RunCommand(const char* command, 
std::string& output,
   int length;
   char* data;
   int p;
+  cmsys::ProcessOutput processOutput;
   while ((p = cmsysProcess_WaitForData(cp, &data, &length, CM_NULLPTR), p)) {
     if (p == cmsysProcess_Pipe_STDOUT || p == cmsysProcess_Pipe_STDERR) {
       if (verbose) {
@@ -230,6 +232,7 @@ bool cmExecProgramCommand::RunCommand(const char* command, 
std::string& output,
 
   // All output has been read.  Wait for the process to exit.
   cmsysProcess_WaitForExit(cp, CM_NULLPTR);
+  processOutput.DecodeText(output, output);
 
   // Check the result of running the process.
   std::string msg;
diff --git a/Source/cmExecuteProcessCommand.cxx 
b/Source/cmExecuteProcessCommand.cxx
index d97b25f..bdefa8b 100644
--- a/Source/cmExecuteProcessCommand.cxx
+++ b/Source/cmExecuteProcessCommand.cxx
@@ -14,6 +14,7 @@
 #include "cmSystemTools.h"
 
 #include <cmsys/Process.h>
+#include <cmsys/ProcessOutput.hxx>
 
 #include <ctype.h> /* isspace */
 
@@ -228,17 +229,21 @@ bool 
cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args,
   int length;
   char* data;
   int p;
+  cmsys::ProcessOutput processOutput;
+  std::string strdata;
   while ((p = cmsysProcess_WaitForData(cp, &data, &length, CM_NULLPTR), p)) {
     // Put the output in the right place.
     if (p == cmsysProcess_Pipe_STDOUT && !output_quiet) {
       if (output_variable.empty()) {
-        cmSystemTools::Stdout(data, length);
+        processOutput.DecodeText(data, length, strdata);
+        cmSystemTools::Stdout(strdata.c_str(), strdata.size());
       } else {
         cmExecuteProcessCommandAppend(tempOutput, data, length);
       }
     } else if (p == cmsysProcess_Pipe_STDERR && !error_quiet) {
       if (error_variable.empty()) {
-        cmSystemTools::Stderr(data, length);
+        processOutput.DecodeText(data, length, strdata);
+        cmSystemTools::Stderr(strdata.c_str(), strdata.size());
       } else {
         cmExecuteProcessCommandAppend(tempError, data, length);
       }
@@ -247,6 +252,8 @@ bool 
cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args,
 
   // All output has been read.  Wait for the process to exit.
   cmsysProcess_WaitForExit(cp, CM_NULLPTR);
+  processOutput.DecodeText(tempOutput, tempOutput);
+  processOutput.DecodeText(tempError, tempError);
 
   // Fix the text in the output strings.
   cmExecuteProcessCommandFixText(tempOutput, output_strip_trailing_whitespace);
diff --git a/Source/cmProcessTools.cxx b/Source/cmProcessTools.cxx
index 34b8df2..fdfa276 100644
--- a/Source/cmProcessTools.cxx
+++ b/Source/cmProcessTools.cxx
@@ -12,6 +12,7 @@
 #include "cmProcessTools.h"
 
 #include <cmsys/Process.h>
+#include <cmsys/ProcessOutput.hxx>
 
 void cmProcessTools::RunProcess(struct cmsysProcess_s* cp, OutputParser* out,
                                 OutputParser* err)
@@ -20,14 +21,18 @@ void cmProcessTools::RunProcess(struct cmsysProcess_s* cp, 
OutputParser* out,
   char* data = CM_NULLPTR;
   int length = 0;
   int p;
+  cmsys::ProcessOutput processOutput;
+  std::string strdata;
   while ((out || err) &&
          (p = cmsysProcess_WaitForData(cp, &data, &length, CM_NULLPTR), p)) {
     if (out && p == cmsysProcess_Pipe_STDOUT) {
-      if (!out->Process(data, length)) {
+      processOutput.DecodeText(data, length, strdata);
+      if (!out->Process(strdata.c_str(), int(strdata.size()))) {
         out = CM_NULLPTR;
       }
     } else if (err && p == cmsysProcess_Pipe_STDERR) {
-      if (!err->Process(data, length)) {
+      processOutput.DecodeText(data, length, strdata);
+      if (!err->Process(strdata.c_str(), int(strdata.size()))) {
         err = CM_NULLPTR;
       }
     }
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 9740ef7..ca92646 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -26,6 +26,7 @@
 #include <cmsys/Glob.hxx>
 #include <cmsys/RegularExpression.hxx>
 #include <cmsys/System.h>
+#include <cmsys/ProcessOutput.hxx>
 #if defined(CMAKE_BUILD_WITH_CMAKE)
 #include "cmArchiveWrite.h"
 #include "cmLocale.h"
@@ -612,6 +613,8 @@ bool 
cmSystemTools::RunSingleCommand(std::vector<std::string> const& command,
   char* data;
   int length;
   int pipe;
+  cmsys::ProcessOutput processOutput;
+  std::string strdata;
   if (outputflag != OUTPUT_PASSTHROUGH &&
       (captureStdOut || captureStdErr || outputflag != OUTPUT_NONE)) {
     while ((pipe = cmsysProcess_WaitForData(cp, &data, &length, CM_NULLPTR)) >
@@ -627,14 +630,16 @@ bool 
cmSystemTools::RunSingleCommand(std::vector<std::string> const& command,
 
       if (pipe == cmsysProcess_Pipe_STDOUT) {
         if (outputflag != OUTPUT_NONE) {
-          cmSystemTools::Stdout(data, length);
+          processOutput.DecodeText(data, length, strdata);
+          cmSystemTools::Stdout(strdata.c_str(), strdata.size());
         }
         if (captureStdOut) {
           tempStdOut.insert(tempStdOut.end(), data, data + length);
         }
       } else if (pipe == cmsysProcess_Pipe_STDERR) {
         if (outputflag != OUTPUT_NONE) {
-          cmSystemTools::Stderr(data, length);
+          processOutput.DecodeText(data, length, strdata);
+          cmSystemTools::Stderr(strdata.c_str(), strdata.size());
         }
         if (captureStdErr) {
           tempStdErr.insert(tempStdErr.end(), data, data + length);
@@ -646,9 +651,11 @@ bool 
cmSystemTools::RunSingleCommand(std::vector<std::string> const& command,
   cmsysProcess_WaitForExit(cp, CM_NULLPTR);
   if (captureStdOut) {
     captureStdOut->assign(tempStdOut.begin(), tempStdOut.end());
+    processOutput.DecodeText(*captureStdOut, *captureStdOut);
   }
   if (captureStdErr) {
     captureStdErr->assign(tempStdErr.begin(), tempStdErr.end());
+    processOutput.DecodeText(*captureStdErr, *captureStdErr);
   }
 
   bool result = true;
diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt
index 87f6048..5fce50f 100644
--- a/Source/kwsys/CMakeLists.txt
+++ b/Source/kwsys/CMakeLists.txt
@@ -666,7 +666,7 @@ ENDIF()
 # selected components.  Initialize with required components.
 SET(KWSYS_CLASSES)
 SET(KWSYS_H_FILES Configure SharedForward)
-SET(KWSYS_HXX_FILES Configure String
+SET(KWSYS_HXX_FILES Configure String ProcessOutput
   hashtable hash_fun hash_map hash_set
   )
 
diff --git a/Source/kwsys/ProcessOutput.hxx.in 
b/Source/kwsys/ProcessOutput.hxx.in
new file mode 100644
index 0000000..a662bed
--- /dev/null
+++ b/Source/kwsys/ProcessOutput.hxx.in
@@ -0,0 +1,94 @@
+/*============================================================================
+  KWSys - Kitware System Library
+  Copyright 2000-2016 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.
+============================================================================*/
+#ifndef @KWSYS_NAMESPACE@_ProcessOutput_hxx
+#define @KWSYS_NAMESPACE@_ProcessOutput_hxx
+
+#include <string>
+#include <vector>
+#if defined(_WIN32)
+#  ifndef WIN32_LEAN_AND_MEAN
+#    define WIN32_LEAN_AND_MEAN 1
+#  endif
+#  include <windows.h>
+#endif
+
+namespace @KWSYS_NAMESPACE@
+{
+  class ProcessOutput
+  {
+    public:
+#if defined(_WIN32)
+      static const UINT defaultCodepage = @KWSYS_ENCODING_DEFAULT_CODEPAGE@;
+#endif
+      ProcessOutput()
+      {
+#if defined(_WIN32)
+        codepage = GetConsoleCP();
+        if (!codepage) {
+          codepage = GetACP();
+        }
+#endif
+      }
+
+      ~ProcessOutput()
+      {
+      }
+
+      bool DecodeText(std::string raw, std::string& decoded)
+      {
+        bool success = true;
+        decoded = raw;
+#if defined(_WIN32)
+        if (raw.size() > 0 && codepage != defaultCodepage) {
+          success = false;
+          const int wlength = MultiByteToWideChar(codepage, 0, raw.c_str(), 
int(raw.size()), NULL, 0);
+          wchar_t* wdata = new wchar_t[wlength];
+          int r = MultiByteToWideChar(codepage, 0, raw.c_str(), 
int(raw.size()), wdata, wlength);
+          if (r > 0) {
+            int length = WideCharToMultiByte(defaultCodepage, 0, wdata, 
wlength, NULL, 0, NULL, NULL);
+            char *data = new char[length + 1];
+            r = WideCharToMultiByte(defaultCodepage, 0, wdata, wlength, data, 
length, NULL, NULL);
+            if (r > 0) {
+              data[length] = '\0';
+              decoded = data;
+              success = true;
+            }
+            delete[] data;
+          }
+          delete[] wdata;
+        }
+#endif
+        return success;
+      }
+
+      bool DecodeText(const char* data, size_t length, std::string& decoded)
+      {
+        return DecodeText(std::string(data, length), decoded);
+      }
+
+      bool DecodeText(std::vector<char> raw, std::vector<char>& decoded)
+      {
+         std::string str;
+         const bool success = DecodeText(std::string(raw.begin(), raw.end()), 
str);
+         decoded.assign(str.begin(), str.end());
+         return success;
+      }
+
+    private:
+#if defined(_WIN32)
+      UINT codepage;
+#endif
+  };
+}
+
+#endif
+
diff --git a/Source/kwsys/SystemInformation.cxx 
b/Source/kwsys/SystemInformation.cxx
index 81fb2f9..d5495de 100644
--- a/Source/kwsys/SystemInformation.cxx
+++ b/Source/kwsys/SystemInformation.cxx
@@ -37,12 +37,14 @@
 #include "kwsysPrivate.h"
 #include KWSYS_HEADER(SystemInformation.hxx)
 #include KWSYS_HEADER(Process.h)
+#include KWSYS_HEADER(ProcessOutput.hxx)
 
 // Work-around CMake dependency scanning limitation.  This must
 // duplicate the above list of headers.
 #if 0
 # include "SystemInformation.hxx.in"
 # include "Process.h.in"
+# include "ProcessOutput.hxx.in"
 #endif
 
 #include <iostream>
@@ -4631,6 +4633,7 @@ std::string 
SystemInformationImplementation::RunProcess(std::vector<const char*>
   int length;
   double timeout = 255;
   int pipe; // pipe id as returned by kwsysProcess_WaitForData()
+  ProcessOutput processOutput;
 
   while( ( static_cast<void>(pipe = 
kwsysProcess_WaitForData(gp,&data,&length,&timeout)),
            (pipe == kwsysProcess_Pipe_STDOUT || pipe == 
kwsysProcess_Pipe_STDERR) ) ) // wait for 1s
@@ -4638,6 +4641,7 @@ std::string 
SystemInformationImplementation::RunProcess(std::vector<const char*>
       buffer.append(data, length);
     }
   kwsysProcess_WaitForExit(gp, 0);
+  processOutput.DecodeText(buffer, buffer);
 
   int result = 0;
   switch(kwsysProcess_GetState(gp))
diff --git a/bootstrap b/bootstrap
index 742fa2b..aa7307d 100755
--- a/bootstrap
+++ b/bootstrap
@@ -371,6 +371,7 @@ KWSYS_FILES="\
   FStream.hxx \
   Glob.hxx \
   Process.h \
+  ProcessOutput.hxx \
   RegularExpression.hxx \
   String.h \
   String.hxx \
-- 
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

Reply via email to