Re: [cmake-developers] [PATCH v3 5/7] For consoles output on Windows use our own std::streambuf

2016-07-06 Thread Dāvis Mosāns
2016-07-07 1:36 GMT+03:00 Mike Gelfand :
> On 07/07/2016 12:42 AM, clin...@elemtech.com wrote:
>> From what I remember, WriteConsoleW doesn't support redirection to a
>> file or pipe.  I don't see an alternative in the patch for the case
>> where stdout is not attached to the console.
> The SO thread I pointed at actually contained a check for whether
> corresponding stream is linked to terminal or not. Replacing stream
> buffers unconditionally is not right.
>

Sorry, I missed this... Will fix.

2016-07-07 2:21 GMT+03:00 Mike Gelfand :
> Just a small nore: as I failed to mention this before, the approach
> taken in this patch will lead to messages to be printed to stdout and
> stderr in CMake's internal encoding (UTF-8?) when ConsoleBuf is not
> used, i.e. 1) on non-Windows and 2) on Windows with one or another
> stream redirected to file/pipe (considering corresponding check is in
> place). Seems to be the case anyway now, but maybe something to think about.
>

I know this, it always have been the case and with this patch I fix only
output to console because currently it would output internal encoding
which is unreadable for non-ASCII because console expects different codepage.

As for encoding used for files it doesn't matter because we use same one
for both writing and reading. It would matter if other applications would
want to read it. And because it's set as UTF-8 it should work fine.

> On 07/06/2016 10:12 PM, Dāvis Mosāns wrote:
>> --- a/Source/cmakemain.cxx
>> +++ b/Source/cmakemain.cxx
>> @@ -171,6 +189,16 @@ int main(int ac, char const* const* av)
>>  #ifdef CMAKE_BUILD_WITH_CMAKE
>>cmDynamicLoader::FlushCache();
>>  #endif
>> +#if defined(_WIN32)
>> +  if (cbufio) {
>> +delete cbufio;
>> +std::cout.rdbuf(coutbuf);
>> +  }
>> +  if (cbuferr) {
>> +delete cbuferr;
>> +std::cerr.rdbuf(cerrbuf);
>> +  }
>> +#endif
>>return ret;
>>  }
>>
> If exception was thrown in the beginning of main (as it seems you expect
> one there), `coutbuf` and/or `cerrbuf` could be nullptr, and passing
> nullptr here will fail.

coutbuf can be null only if

cbufio = new cmsys::ConsoleBuf();

threw an exception in which case cbufio will be null and so it won't be set
here. And same for cerrbuf, it will be set if cbuferr is set in which case it
means there weren't any exception. While I think it's not needed, I can
add check for it and set rdbuf only when not null.

>
>> +this->setg((char_type *)m_ibuffer.data(), (char_type 
>> *)m_ibuffer.data(), (char_type *)m_ibuffer.data() + m_ibuffer.size());
>> +this->setp((char_type *)m_obuffer.data(), (char_type 
>> *)m_obuffer.data() + m_obuffer.size());
> This pattern over and over again. Needs to be put into separate member
> function, otherwise some day someone will mix "i" and "o" and wonder why
> doesn't it work.
>
> Also, I don't see that many calls to set(g|p) in that SO snipped, are
> they all really needed?
>

There aren't really that many calls, we set both once in constructor,
both once in sync and setg twice (differently) in underflow, because
two cases:

"The function may update gptr, egptr and eback pointers to define the
location of newly loaded data (if any). On failure, the function ensures
that either gptr() == nullptr or gptr() == egptr"

from http://en.cppreference.com/w/cpp/io/basic_streambuf/underflow
-- 

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

Re: [cmake-developers] [PATCH v3 5/7] For consoles output on Windows use our own std::streambuf

2016-07-06 Thread Mike Gelfand
On 07/07/2016 12:42 AM, clin...@elemtech.com wrote:
> From what I remember, WriteConsoleW doesn't support redirection to a
> file or pipe.  I don't see an alternative in the patch for the case
> where stdout is not attached to the console.
The SO thread I pointed at actually contained a check for whether
corresponding stream is linked to terminal or not. Replacing stream
buffers unconditionally is not right.

Regards,
Mike
-- 

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


Re: [cmake-developers] [PATCH v3 5/7] For consoles output on Windows use our own std::streambuf

2016-07-06 Thread clinton
From what I remember, WriteConsoleW doesn't support redirection to a file or pipe.  I don't see an alternative in the patch for the case where stdout is not attached to the console.
Clint

-- 

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

[cmake-developers] [PATCH v3 5/7] For consoles output on Windows use our own std::streambuf

2016-07-06 Thread Dāvis Mosāns
Currently Microsoft's C++ libraries implementation of std::cout/cerr
can't output Unicode characters but only ASCII or ANSI if locale is set
so we implement and use our own ConsoleBuf which can output Unicode
characters to console and it doesn't matter what locale or console's
codepage is set.
---
 CMakeLists.txt |   1 +
 Source/cmakemain.cxx   |  28 +
 Source/kwsys/CMakeLists.txt|   6 +-
 Source/kwsys/ConsoleBuf.hxx.in | 131 +
 bootstrap  |   1 +
 5 files changed, 166 insertions(+), 1 deletion(-)
 create mode 100644 Source/kwsys/ConsoleBuf.hxx.in

diff --git a/CMakeLists.txt b/CMakeLists.txt
index ae5990e..792b5a5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -258,6 +258,7 @@ macro (CMAKE_BUILD_UTILITIES)
   set(KWSYS_USE_MD5 1)
   set(KWSYS_USE_Process 1)
   set(KWSYS_USE_CommandLineArguments 1)
+  set(KWSYS_USE_ConsoleBuf 1)
   set(KWSYS_HEADER_ROOT ${CMake_BINARY_DIR}/Source)
   set(KWSYS_INSTALL_DOC_DIR "${CMAKE_DOC_DIR}")
   add_subdirectory(Source/kwsys)
diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx
index 521a5bf..2002e4b 100644
--- a/Source/cmakemain.cxx
+++ b/Source/cmakemain.cxx
@@ -26,6 +26,7 @@
 #include "cmake.h"
 #include "cmcmd.h"
 #include 
+#include 
 
 #ifdef CMAKE_BUILD_WITH_CMAKE
 static const char* cmDocumentationName[][2] = {
@@ -153,6 +154,23 @@ static void cmakemainProgressCallback(const char* m, float 
prog,
 
 int main(int ac, char const* const* av)
 {
+#if defined(_WIN32)
+  // Replace streambuf so we can output Unicode to console
+  cmsys::ConsoleBuf *cbufio = CM_NULLPTR;
+  cmsys::ConsoleBuf *cbuferr = CM_NULLPTR;
+  std::streambuf *coutbuf = CM_NULLPTR;
+  std::streambuf *cerrbuf = CM_NULLPTR;
+  try {
+cbufio = new cmsys::ConsoleBuf();
+coutbuf = std::cout.rdbuf(cbufio);
+cbuferr = new cmsys::ConsoleBuf(true);
+cerrbuf = std::cerr.rdbuf(cbuferr);
+  } catch (const std::system_error& ex) {
+std::cerr << "Failed to create ConsoleBuf!" << std::endl
+  << "Error code: " << ex.code() << std::endl
+  << ex.what() << std::endl;
+  };
+#endif
   cmsys::Encoding::CommandLineArguments args =
 cmsys::Encoding::CommandLineArguments::Main(ac, av);
   ac = args.argc();
@@ -171,6 +189,16 @@ int main(int ac, char const* const* av)
 #ifdef CMAKE_BUILD_WITH_CMAKE
   cmDynamicLoader::FlushCache();
 #endif
+#if defined(_WIN32)
+  if (cbufio) {
+delete cbufio;
+std::cout.rdbuf(coutbuf);
+  }
+  if (cbuferr) {
+delete cbuferr;
+std::cerr.rdbuf(cerrbuf);
+  }
+#endif
   return ret;
 }
 
diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt
index 65203c0..33a97e6 100644
--- a/Source/kwsys/CMakeLists.txt
+++ b/Source/kwsys/CMakeLists.txt
@@ -123,6 +123,7 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
   SET(KWSYS_USE_FStream 1)
   SET(KWSYS_USE_String 1)
   SET(KWSYS_USE_SystemInformation 1)
+  SET(KWSYS_USE_ConsoleBuf 1)
 ENDIF()
 
 # Enforce component dependencies.
@@ -154,6 +155,9 @@ ENDIF()
 IF(KWSYS_USE_FStream)
   SET(KWSYS_USE_Encoding 1)
 ENDIF()
+IF(KWSYS_USE_ConsoleBuf)
+  SET(KWSYS_USE_Encoding 1)
+ENDIF()
 
 # Setup the large file support default.
 IF(KWSYS_LFS_DISABLE)
@@ -668,7 +672,7 @@ SET(KWSYS_HXX_FILES Configure String
 # Add selected C++ classes.
 SET(cppclasses
   Directory DynamicLoader Encoding Glob RegularExpression SystemTools
-  CommandLineArguments IOStream FStream SystemInformation
+  CommandLineArguments IOStream FStream SystemInformation ConsoleBuf
   )
 FOREACH(cpp ${cppclasses})
   IF(KWSYS_USE_${cpp})
diff --git a/Source/kwsys/ConsoleBuf.hxx.in b/Source/kwsys/ConsoleBuf.hxx.in
new file mode 100644
index 000..90adc03
--- /dev/null
+++ b/Source/kwsys/ConsoleBuf.hxx.in
@@ -0,0 +1,131 @@
+/*
+  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@_ConsoleBuf_hxx
+#define @KWSYS_NAMESPACE@_ConsoleBuf_hxx
+
+#include <@KWSYS_NAMESPACE@/Configure.hxx>
+#include <@KWSYS_NAMESPACE@/Encoding.hxx>
+#include 
+
+namespace @KWSYS_NAMESPACE@
+{
+#if defined(_WIN32)
+
+  template>
+  class @KWSYS_NAMESPACE@_EXPORT BasicConsoleBuf : public 
std::basic_streambuf {
+public:
+  typedef typename Traits::int_type int_type;
+  typedef typename Traits::char_type char_type;
+
+  BasicConsoleBuf(const bool err = false) {
+m_hInput = ::GetStdHandle(STD_INPUT_HANDLE);
+if (m_hInput == INVALID_HANDLE_VALUE) {
+  throw