Browse Source

Merge branch 'upstream-kwsys' into update-kwsys

Brad King 12 years ago
parent
commit
f668112039

+ 52 - 6
Source/kwsys/CMakeLists.txt

@@ -115,6 +115,7 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
   SET(KWSYS_USE_Base64 1)
   SET(KWSYS_USE_Directory 1)
   SET(KWSYS_USE_DynamicLoader 1)
+  SET(KWSYS_USE_Encoding 1)
   SET(KWSYS_USE_Glob 1)
   SET(KWSYS_USE_MD5 1)
   SET(KWSYS_USE_Process 1)
@@ -125,6 +126,7 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
   SET(KWSYS_USE_FundamentalType 1)
   SET(KWSYS_USE_Terminal 1)
   SET(KWSYS_USE_IOStream 1)
+  SET(KWSYS_USE_FStream 1)
   SET(KWSYS_USE_String 1)
   SET(KWSYS_USE_SystemInformation 1)
   SET(KWSYS_USE_CPU 1)
@@ -133,18 +135,32 @@ ENDIF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
 # Enforce component dependencies.
 IF(KWSYS_USE_SystemTools)
   SET(KWSYS_USE_Directory 1)
+  SET(KWSYS_USE_FStream 1)
+  SET(KWSYS_USE_Encoding 1)
 ENDIF(KWSYS_USE_SystemTools)
 IF(KWSYS_USE_Glob)
   SET(KWSYS_USE_Directory 1)
   SET(KWSYS_USE_SystemTools 1)
   SET(KWSYS_USE_RegularExpression 1)
+  SET(KWSYS_USE_FStream 1)
+  SET(KWSYS_USE_Encoding 1)
 ENDIF(KWSYS_USE_Glob)
 IF(KWSYS_USE_Process)
   SET(KWSYS_USE_System 1)
+  SET(KWSYS_USE_Encoding 1)
 ENDIF(KWSYS_USE_Process)
 IF(KWSYS_USE_SystemInformation)
   SET(KWSYS_USE_Process 1)
 ENDIF(KWSYS_USE_SystemInformation)
+IF(KWSYS_USE_System)
+  SET(KWSYS_USE_Encoding 1)
+ENDIF(KWSYS_USE_System)
+IF(KWSYS_USE_Directory)
+  SET(KWSYS_USE_Encoding 1)
+ENDIF(KWSYS_USE_Directory)
+IF(KWSYS_USE_FStream)
+  SET(KWSYS_USE_Encoding 1)
+ENDIF(KWSYS_USE_FStream)
 
 # Setup the large file support default.
 IF(KWSYS_LFS_DISABLE)
@@ -153,6 +169,11 @@ ELSE(KWSYS_LFS_DISABLE)
   SET(KWSYS_LFS_REQUESTED 1)
 ENDIF(KWSYS_LFS_DISABLE)
 
+# Specify default 8 bit encoding for Windows
+IF(NOT KWSYS_ENCODING_DEFAULT_CODEPAGE)
+  SET(KWSYS_ENCODING_DEFAULT_CODEPAGE CP_ACP)
+ENDIF(NOT KWSYS_ENCODING_DEFAULT_CODEPAGE)
+
 # Enable testing if building standalone.
 IF(KWSYS_STANDALONE)
   INCLUDE(Dart)
@@ -509,6 +530,12 @@ IF(KWSYS_USE_FundamentalType)
     "Checking whether char is signed" DIRECT)
 ENDIF(KWSYS_USE_FundamentalType)
 
+IF(KWSYS_USE_Encoding)
+  # Look for type size helper macros.
+  KWSYS_PLATFORM_CXX_TEST(KWSYS_STL_HAS_WSTRING
+    "Checking whether wstring is available" DIRECT)
+ENDIF(KWSYS_USE_Encoding)
+
 IF(KWSYS_USE_IOStream)
   # Determine whether iostreams support long long.
   SET(KWSYS_PLATFORM_CXX_TEST_DEFINES
@@ -864,8 +891,8 @@ SET(KWSYS_HXX_FILES Configure String
 
 # Add selected C++ classes.
 SET(cppclasses
-  Directory DynamicLoader Glob RegularExpression SystemTools
-  CommandLineArguments IOStream SystemInformation
+  Directory DynamicLoader Encoding Glob RegularExpression SystemTools
+  CommandLineArguments IOStream FStream SystemInformation
   )
 FOREACH(cpp ${cppclasses})
   IF(KWSYS_USE_${cpp})
@@ -881,7 +908,7 @@ ENDFOREACH(cpp)
 
 # Add selected C components.
 FOREACH(c
-    Process Base64 FundamentalType MD5 Terminal System String CPU
+    Process Base64 Encoding FundamentalType MD5 Terminal System String CPU
     )
   IF(KWSYS_USE_${c})
     # Use the corresponding header file.
@@ -912,16 +939,24 @@ IF(KWSYS_USE_Process)
 ENDIF(KWSYS_USE_Process)
 
 # Add selected C sources.
-FOREACH(c Base64 MD5 Terminal System String)
+FOREACH(c Base64 Encoding MD5 Terminal System String)
   IF(KWSYS_USE_${c})
-    SET(KWSYS_C_SRCS ${KWSYS_C_SRCS} ${c}.c)
+    IF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${c}C.c)
+      LIST(APPEND KWSYS_C_SRCS ${c}C.c)
+    ELSE()
+      LIST(APPEND KWSYS_C_SRCS ${c}.c)
+    ENDIF()
   ENDIF(KWSYS_USE_${c})
 ENDFOREACH(c)
 
 # Configure headers of C++ classes and construct the list of sources.
 FOREACH(c ${KWSYS_CLASSES})
   # Add this source to the list of source files for the library.
-  SET(KWSYS_CXX_SRCS ${KWSYS_CXX_SRCS} ${c}.cxx)
+  IF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${c}CXX.cxx)
+    LIST(APPEND KWSYS_CXX_SRCS ${c}CXX.cxx)
+  ELSEIF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${c}.cxx)
+    LIST(APPEND KWSYS_CXX_SRCS ${c}.cxx)
+  ENDIF()
 
   # Configure the header for this class.
   CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/${c}.hxx.in ${KWSYS_HEADER_DIR}/${c}.hxx
@@ -1047,6 +1082,12 @@ IF(KWSYS_USE_String)
     COMPILE_FLAGS "-DKWSYS_STRING_C")
 ENDIF(KWSYS_USE_String)
 
+IF(KWSYS_USE_Encoding)
+  # Set default 8 bit encoding in "EndcodingC.c".
+  SET_PROPERTY(SOURCE EncodingC.c APPEND PROPERTY COMPILE_DEFINITIONS
+    KWSYS_ENCODING_DEFAULT_CODEPAGE=${KWSYS_ENCODING_DEFAULT_CODEPAGE})
+ENDIF(KWSYS_USE_Encoding)
+
 #-----------------------------------------------------------------------------
 # Setup testing if not being built as part of another project.
 IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
@@ -1090,6 +1131,11 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
       testCommandLineArguments
       testCommandLineArguments1
       )
+    IF(KWSYS_STL_HAS_WSTRING)
+      SET(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS}
+        testEncoding
+        )
+    ENDIF(KWSYS_STL_HAS_WSTRING)
     IF(KWSYS_USE_SystemInformation)
       SET(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS} testSystemInformation)
     ENDIF(KWSYS_USE_SystemInformation)

+ 4 - 0
Source/kwsys/Configure.hxx.in

@@ -36,6 +36,9 @@
 /* Whether STL is in std namespace.  */
 #define @KWSYS_NAMESPACE@_STL_HAVE_STD @KWSYS_STL_HAVE_STD@
 
+/* Whether wstring is available.  */
+#define @KWSYS_NAMESPACE@_STL_HAS_WSTRING @KWSYS_STL_HAS_WSTRING@
+
 /* Whether the STL string has operator<< for ostream.  */
 #define @KWSYS_NAMESPACE@_STL_STRING_HAVE_OSTREAM @KWSYS_STL_STRING_HAVE_OSTREAM@
 
@@ -170,6 +173,7 @@
 # define KWSYS_STL_HAS_ALLOCATOR_TEMPLATE @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_TEMPLATE
 # define KWSYS_STL_HAS_ALLOCATOR_NONTEMPLATE @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_NONTEMPLATE
 # define KWSYS_STL_HAS_ALLOCATOR_OBJECTS @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_OBJECTS
+# define KWSYS_STL_HAS_WSTRING          @KWSYS_NAMESPACE@_STL_HAS_WSTRING
 #endif
 
 #endif

+ 10 - 7
Source/kwsys/Directory.cxx

@@ -14,6 +14,8 @@
 
 #include KWSYS_HEADER(Configure.hxx)
 
+#include KWSYS_HEADER(Encoding.hxx)
+
 #include KWSYS_HEADER(stl/string)
 #include KWSYS_HEADER(stl/vector)
 
@@ -22,6 +24,7 @@
 #if 0
 # include "Directory.hxx.in"
 # include "Configure.hxx.in"
+# include "Encoding.hxx.in"
 # include "kwsys_stl.hxx.in"
 # include "kwsys_stl_string.hxx.in"
 # include "kwsys_stl_vector.hxx.in"
@@ -120,10 +123,10 @@ bool Directory::Load(const char* name)
     buf = new char[n + 2 + 1];
     sprintf(buf, "%s/*", name);
     }
-  struct _finddata_t data;      // data of current file
+  struct _wfinddata_t data;      // data of current file
 
   // Now put them into the file array
-  srchHandle = _findfirst(buf, &data);
+  srchHandle = _wfindfirst((wchar_t*)Encoding::ToWide(buf).c_str(), &data);
   delete [] buf;
 
   if ( srchHandle == -1 )
@@ -134,9 +137,9 @@ bool Directory::Load(const char* name)
   // Loop through names
   do
     {
-    this->Internal->Files.push_back(data.name);
+    this->Internal->Files.push_back(Encoding::ToNarrow(data.name));
     }
-  while ( _findnext(srchHandle, &data) != -1 );
+  while ( _wfindnext(srchHandle, &data) != -1 );
   this->Internal->Path = name;
   return _findclose(srchHandle) != -1;
 }
@@ -160,10 +163,10 @@ unsigned long Directory::GetNumberOfFilesInDirectory(const char* name)
     buf = new char[n + 2 + 1];
     sprintf(buf, "%s/*", name);
     }
-  struct _finddata_t data;      // data of current file
+  struct _wfinddata_t data;      // data of current file
 
   // Now put them into the file array
-  srchHandle = _findfirst(buf, &data);
+  srchHandle = _wfindfirst((wchar_t*)Encoding::ToWide(buf).c_str(), &data);
   delete [] buf;
 
   if ( srchHandle == -1 )
@@ -177,7 +180,7 @@ unsigned long Directory::GetNumberOfFilesInDirectory(const char* name)
     {
     count++;
     }
-  while ( _findnext(srchHandle, &data) != -1 );
+  while ( _wfindnext(srchHandle, &data) != -1 );
   _findclose(srchHandle);
   return count;
 }

+ 6 - 13
Source/kwsys/DynamicLoader.cxx

@@ -186,13 +186,12 @@ namespace KWSYS_NAMESPACE
 DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(const char* libname)
 {
   DynamicLoader::LibraryHandle lh;
-#ifdef UNICODE
-  wchar_t libn[MB_CUR_MAX];
-  mbstowcs(libn, libname, MB_CUR_MAX);
-  lh = LoadLibrary(libn);
-#else
-  lh = LoadLibrary(libname);
-#endif
+  int length = MultiByteToWideChar(CP_UTF8, 0, libname, -1, NULL, 0);
+  wchar_t* wchars = new wchar_t[length+1];
+  wchars[0] = '\0';
+  MultiByteToWideChar(CP_UTF8, 0, libname, -1, wchars, length);
+  lh = LoadLibraryW(wchars);
+  delete [] wchars;
   return lh;
 }
 
@@ -238,13 +237,7 @@ DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
 #else
   const char *rsym = sym;
 #endif
-#ifdef UNICODE
-  wchar_t wsym[MB_CUR_MAX];
-  mbstowcs(wsym, rsym, MB_CUR_MAX);
-  result = GetProcAddress(lib, wsym);
-#else
   result = (void*)GetProcAddress(lib, rsym);
-#endif
 #if defined(__BORLANDC__) || defined(__WATCOMC__)
   delete[] rsym;
 #endif

+ 79 - 0
Source/kwsys/Encoding.h.in

@@ -0,0 +1,79 @@
+/*============================================================================
+  KWSys - Kitware System Library
+  Copyright 2000-2009 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@_Encoding_h
+#define @KWSYS_NAMESPACE@_Encoding_h
+
+#include <@KWSYS_NAMESPACE@/Configure.h>
+#include <wchar.h>
+
+/* Redefine all public interface symbol names to be in the proper
+   namespace.  These macros are used internally to kwsys only, and are
+   not visible to user code.  Use kwsysHeaderDump.pl to reproduce
+   these macros after making changes to the interface.  */
+#if !defined(KWSYS_NAMESPACE)
+# define kwsys_ns(x) @KWSYS_NAMESPACE@##x
+# define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT
+#endif
+#if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
+# define kwsysEncoding         kwsys_ns(Encoding)
+# define kwsysEncoding_mbstowcs  kwsys_ns(Encoding_mbstowcs)
+# define kwsysEncoding_DupToWide  kwsys_ns(Encoding_DupToWide)
+# define kwsysEncoding_wcstombs  kwsys_ns(Encoding_wcstombs)
+# define kwsysEncoding_DupToNarrow kwsys_ns(Encoding_DupToNarrow)
+#endif
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+
+
+/* Convert a narrow string to a wide string.
+   On Windows, UTF-8 is assumed, and on other platforms,
+   the current locale is assumed.
+   */
+kwsysEXPORT size_t kwsysEncoding_mbstowcs(wchar_t* dest, const char* src, size_t n);
+
+/* Convert a narrow string to a wide string.
+   This can return NULL if the conversion fails. */
+kwsysEXPORT wchar_t* kwsysEncoding_DupToWide(const char* src);
+
+
+/* Convert a wide string to a narrow string.
+   On Windows, UTF-8 is assumed, and on other platforms,
+   the current locale is assumed. */
+kwsysEXPORT size_t kwsysEncoding_wcstombs(char* dest, const wchar_t* src, size_t n);
+
+/* Convert a wide string to a narrow string.
+   This can return NULL if the conversion fails. */
+kwsysEXPORT char* kwsysEncoding_DupToNarrow(const wchar_t* str);
+
+
+#if defined(__cplusplus)
+} /* extern "C" */
+#endif
+
+/* If we are building a kwsys .c or .cxx file, let it use these macros.
+   Otherwise, undefine them to keep the namespace clean.  */
+#if !defined(KWSYS_NAMESPACE)
+# undef kwsys_ns
+# undef kwsysEXPORT
+# if !defined(KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
+#  undef kwsysEncoding
+#  undef kwsysEncoding_mbstowcs
+#  undef kwsysEncoding_DupToWide
+#  undef kwsysEncoding_wcstombs
+#  undef kwsysEncoding_DupToNarrow
+# endif
+#endif
+
+#endif

+ 56 - 0
Source/kwsys/Encoding.hxx.in

@@ -0,0 +1,56 @@
+/*============================================================================
+  KWSys - Kitware System Library
+  Copyright 2000-2009 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@_Encoding_hxx
+#define @KWSYS_NAMESPACE@_Encoding_hxx
+
+#include <@KWSYS_NAMESPACE@/Configure.hxx>
+#include <@KWSYS_NAMESPACE@/stl/string>
+
+/* Define these macros temporarily to keep the code readable.  */
+#if !defined (KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
+# define kwsys_stl @KWSYS_NAMESPACE@_stl
+#endif
+
+namespace @KWSYS_NAMESPACE@
+{
+class @KWSYS_NAMESPACE@_EXPORT Encoding
+{
+public:
+  /**
+   * Convert between char and wchar_t
+   */
+
+#if @KWSYS_NAMESPACE@_STL_HAS_WSTRING
+
+  // Convert a narrow string to a wide string.
+  // On Windows, UTF-8 is assumed, and on other platforms,
+  // the current locale is assumed.
+  static kwsys_stl::wstring ToWide(const kwsys_stl::string& str);
+  static kwsys_stl::wstring ToWide(const char* str);
+
+  // Convert a wide string to a narrow string.
+  // On Windows, UTF-8 is assumed, and on other platforms,
+  // the current locale is assumed.
+  static kwsys_stl::string ToNarrow(const kwsys_stl::wstring& str);
+  static kwsys_stl::string ToNarrow(const wchar_t* str);
+
+#endif // @KWSYS_NAMESPACE@_STL_HAS_WSTRING
+
+}; // class Encoding
+} // namespace @KWSYS_NAMESPACE@
+
+/* Undefine temporary macros.  */
+#if !defined (KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
+# undef kwsys_stl
+#endif
+
+#endif

+ 79 - 0
Source/kwsys/EncodingC.c

@@ -0,0 +1,79 @@
+/*============================================================================
+  KWSys - Kitware System Library
+  Copyright 2000-2009 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.
+============================================================================*/
+#include "kwsysPrivate.h"
+#include KWSYS_HEADER(Encoding.h)
+
+/* Work-around CMake dependency scanning limitation.  This must
+   duplicate the above list of headers.  */
+#if 0
+# include "Encoding.h.in"
+#endif
+
+#include <stdlib.h>
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+size_t kwsysEncoding_mbstowcs(wchar_t* dest, const char* str, size_t n)
+{
+  if(str == 0)
+    {
+    return (size_t)-1;
+    }
+#ifdef _WIN32
+  return MultiByteToWideChar(KWSYS_ENCODING_DEFAULT_CODEPAGE, 0,
+                             str, -1, dest, (int)n) - 1;
+#else
+  return mbstowcs(dest, str, n);
+#endif
+}
+
+wchar_t* kwsysEncoding_DupToWide(const char* str)
+{
+  wchar_t* ret = NULL;
+  size_t length = kwsysEncoding_mbstowcs(NULL, str, 0) + 1;
+  if(length > 0)
+    {
+    ret = malloc((length)*sizeof(wchar_t));
+    ret[0] = 0;
+    kwsysEncoding_mbstowcs(ret, str, length);
+    }
+  return ret;
+}
+
+size_t kwsysEncoding_wcstombs(char* dest, const wchar_t* str, size_t n)
+{
+  if(str == 0)
+    {
+    return (size_t)-1;
+    }
+#ifdef _WIN32
+  return WideCharToMultiByte(KWSYS_ENCODING_DEFAULT_CODEPAGE, 0, str, -1,
+                             dest, (int)n, NULL, NULL) - 1;
+#else
+  return wcstombs(dest, str, n);
+#endif
+}
+
+char* kwsysEncoding_DupToNarrow(const wchar_t* str)
+{
+  char* ret = NULL;
+  size_t length = kwsysEncoding_wcstombs(0, str, 0);
+  if(length > 0)
+    {
+    ret = malloc(length);
+    ret[0] = 0;
+    kwsysEncoding_wcstombs(ret, str, length);
+    }
+  return ret;
+}

+ 88 - 0
Source/kwsys/EncodingCXX.cxx

@@ -0,0 +1,88 @@
+/*============================================================================
+  KWSys - Kitware System Library
+  Copyright 2000-2009 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.
+============================================================================*/
+
+#ifdef __osf__
+#  define _OSF_SOURCE
+#  define _POSIX_C_SOURCE 199506L
+#  define _XOPEN_SOURCE_EXTENDED
+#endif
+
+#include "kwsysPrivate.h"
+#include KWSYS_HEADER(Encoding.hxx)
+#include KWSYS_HEADER(Encoding.h)
+#include KWSYS_HEADER(stl/vector)
+
+// Work-around CMake dependency scanning limitation.  This must
+// duplicate the above list of headers.
+#if 0
+# include "Encoding.hxx.in"
+# include "Encoding.h.in"
+#endif
+
+#include <stdlib.h>
+
+#ifdef _MSC_VER
+# pragma warning (disable: 4786)
+#endif
+
+// Windows API.
+#if defined(_WIN32)
+# include <windows.h>
+#endif
+
+namespace KWSYS_NAMESPACE
+{
+
+#if KWSYS_STL_HAS_WSTRING
+
+kwsys_stl::wstring Encoding::ToWide(const kwsys_stl::string& str)
+{
+  return ToWide(str.c_str());
+}
+
+kwsys_stl::string Encoding::ToNarrow(const kwsys_stl::wstring& str)
+{
+  return ToNarrow(str.c_str());
+}
+
+kwsys_stl::wstring Encoding::ToWide(const char* cstr)
+{
+  kwsys_stl::wstring wstr;
+  size_t length = kwsysEncoding_mbstowcs(0, cstr, 0) + 1;
+  if(length > 0)
+    {
+    kwsys_stl::vector<wchar_t> wchars(length);
+    if(kwsysEncoding_mbstowcs(&wchars[0], cstr, length) > 0)
+      {
+      wstr = &wchars[0];
+      }
+    }
+  return wstr;
+}
+
+kwsys_stl::string Encoding::ToNarrow(const wchar_t* wcstr)
+{
+  kwsys_stl::string str;
+  size_t length = kwsysEncoding_wcstombs(0, wcstr, 0) + 1;
+  if(length > 0)
+    {
+    std::vector<char> chars(length);
+    if(kwsysEncoding_wcstombs(&chars[0], wcstr, length) > 0)
+      {
+      str = &chars[0];
+      }
+    }
+  return str;
+}
+#endif // KWSYS_STL_HAS_WSTRING
+
+} // namespace KWSYS_NAMESPACE

+ 172 - 0
Source/kwsys/FStream.hxx.in

@@ -0,0 +1,172 @@
+/*============================================================================
+  KWSys - Kitware System Library
+  Copyright 2000-2009 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@_FStream_hxx
+#define @KWSYS_NAMESPACE@_FStream_hxx
+
+#include <@KWSYS_NAMESPACE@/ios/fstream>
+#include <@KWSYS_NAMESPACE@/Encoding.hxx>
+
+namespace @KWSYS_NAMESPACE@
+{
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+  template<typename CharType,typename Traits>
+  class basic_filebuf : public std::basic_filebuf<CharType,Traits>
+  {
+    public:
+      typedef std::basic_filebuf<CharType,Traits> my_base_type;
+      basic_filebuf *open(char const *s,std::ios_base::openmode mode)
+      {
+        my_base_type::open(Encoding::ToWide(s).c_str(), mode);
+        return this;
+      }
+  };
+
+  template<typename CharType,typename Traits = std::char_traits<CharType> >
+  class basic_ifstream : public std::basic_istream<CharType,Traits>
+  {
+  public:
+    typedef basic_filebuf<CharType,Traits> internal_buffer_type;
+    typedef std::basic_istream<CharType,Traits> internal_stream_type;
+
+    basic_ifstream() : internal_stream_type(new internal_buffer_type())
+    {
+      buf_ = static_cast<internal_buffer_type *>(internal_stream_type::rdbuf());
+    }
+    explicit basic_ifstream(char const *file_name,
+                            std::ios_base::openmode mode = std::ios_base::in)
+      : internal_stream_type(new internal_buffer_type())
+    {
+      buf_ = static_cast<internal_buffer_type *>(internal_stream_type::rdbuf());
+      open(file_name,mode);
+    }
+    void open(char const *file_name,std::ios_base::openmode mode = std::ios_base::in)
+    {
+      if(!buf_->open(file_name,mode | std::ios_base::in))
+        {
+        this->setstate(std::ios_base::failbit);
+        }
+      else
+        {
+        this->clear();
+        }
+    }
+    bool is_open()
+    {
+      return buf_->is_open();
+    }
+    bool is_open() const
+    {
+      return buf_->is_open();
+    }
+    void close()
+    {
+      if(!buf_->close())
+        {
+        this->setstate(std::ios_base::failbit);
+        }
+      else
+      {
+        this->clear();
+      }
+    }
+
+    internal_buffer_type *rdbuf() const
+    {
+      return buf_.get();
+    }
+
+    ~basic_ifstream()
+    {
+      buf_->close();
+      delete buf_;
+    }
+
+  private:
+    internal_buffer_type* buf_;
+};
+
+template<typename CharType,typename Traits = std::char_traits<CharType> >
+class basic_ofstream : public std::basic_ostream<CharType,Traits>
+{
+  public:
+  typedef basic_filebuf<CharType,Traits> internal_buffer_type;
+  typedef std::basic_ostream<CharType,Traits> internal_stream_type;
+
+  basic_ofstream() : internal_stream_type(new internal_buffer_type())
+  {
+  buf_ = static_cast<internal_buffer_type *>(internal_stream_type::rdbuf());
+  }
+  explicit basic_ofstream(char const *file_name,std::ios_base::openmode mode = std::ios_base::out) :
+  internal_stream_type(new internal_buffer_type())
+  {
+    buf_ = static_cast<internal_buffer_type *>(internal_stream_type::rdbuf());
+    open(file_name,mode);
+  }
+  void open(char const *file_name,std::ios_base::openmode mode = std::ios_base::out)
+  {
+    if(!buf_->open(file_name,mode | std::ios_base::out))
+    {
+    this->setstate(std::ios_base::failbit);
+    }
+    else
+    {
+    this->clear();
+    }
+  }
+  bool is_open()
+  {
+    return buf_->is_open();
+  }
+  bool is_open() const
+  {
+    return buf_->is_open();
+  }
+  void close()
+  {
+    if(!buf_->close())
+      {
+      this->setstate(std::ios_base::failbit);
+      }
+    else
+      {
+      this->clear();
+      }
+  }
+
+  internal_buffer_type *rdbuf() const
+  {
+    return buf_.get();
+  }
+  ~basic_ofstream()
+  {
+    buf_->close();
+    delete buf_;
+  }
+
+  private:
+  internal_buffer_type* buf_;
+};
+
+  typedef basic_ifstream<char> ifstream;
+  typedef basic_ofstream<char> ofstream;
+
+#else
+  using @KWSYS_NAMESPACE@_ios_namespace::basic_filebuf;
+  using @KWSYS_NAMESPACE@_ios_namespace::ofstream;
+  using @KWSYS_NAMESPACE@_ios_namespace::ifstream;
+#endif
+
+}
+
+
+
+#endif

+ 49 - 29
Source/kwsys/ProcessWin32.c

@@ -12,12 +12,14 @@
 #include "kwsysPrivate.h"
 #include KWSYS_HEADER(Process.h)
 #include KWSYS_HEADER(System.h)
+#include KWSYS_HEADER(Encoding.h)
 
 /* Work-around CMake dependency scanning limitation.  This must
    duplicate the above list of headers.  */
 #if 0
 # include "Process.h.in"
 # include "System.h.in"
+# include "Encoding_c.h.in"
 #endif
 
 /*
@@ -88,9 +90,10 @@ typedef LARGE_INTEGER kwsysProcessTime;
 typedef struct kwsysProcessCreateInformation_s
 {
   /* Windows child startup control data.  */
-  STARTUPINFO StartupInfo;
+  STARTUPINFOW StartupInfo;
 } kwsysProcessCreateInformation;
 
+
 /*--------------------------------------------------------------------------*/
 typedef struct kwsysProcessPipeData_s kwsysProcessPipeData;
 static DWORD WINAPI kwsysProcessPipeThreadRead(LPVOID ptd);
@@ -197,14 +200,14 @@ struct kwsysProcess_s
   int State;
 
   /* The command lines to execute.  */
-  char** Commands;
+  wchar_t** Commands;
   int NumberOfCommands;
 
   /* The exit code of each command.  */
   DWORD* CommandExitCodes;
 
   /* The working directory for the child process.  */
-  char* WorkingDirectory;
+  wchar_t* WorkingDirectory;
 
   /* Whether to create the child as a detached process.  */
   int OptionDetach;
@@ -299,7 +302,7 @@ struct kwsysProcess_s
 
   /* Real working directory of our own process.  */
   DWORD RealWorkingDirectoryLength;
-  char* RealWorkingDirectory;
+  wchar_t* RealWorkingDirectory;
 };
 
 /*--------------------------------------------------------------------------*/
@@ -546,7 +549,7 @@ int kwsysProcess_SetCommand(kwsysProcess* cp, char const* const* command)
 int kwsysProcess_AddCommand(kwsysProcess* cp, char const* const* command)
 {
   int newNumberOfCommands;
-  char** newCommands;
+  wchar_t** newCommands;
 
   /* Make sure we have a command to add.  */
   if(!cp || !command || !*command)
@@ -554,9 +557,10 @@ int kwsysProcess_AddCommand(kwsysProcess* cp, char const* const* command)
     return 0;
     }
 
+
   /* Allocate a new array for command pointers.  */
   newNumberOfCommands = cp->NumberOfCommands + 1;
-  if(!(newCommands = (char**)malloc(sizeof(char*) * newNumberOfCommands)))
+  if(!(newCommands = (wchar_t**)malloc(sizeof(wchar_t*) * newNumberOfCommands)))
     {
     /* Out of memory.  */
     return 0;
@@ -585,8 +589,8 @@ int kwsysProcess_AddCommand(kwsysProcess* cp, char const* const* command)
   /* Allocate enough space for the command.  We do not need an extra
      byte for the terminating null because we allocated a space for
      the first argument that we will not use.  */
-  newCommands[cp->NumberOfCommands] = (char*)malloc(length);
-  if(!newCommands[cp->NumberOfCommands])
+  char* new_cmd = malloc(length);
+  if(!new_cmd)
     {
     /* Out of memory.  */
     free(newCommands);
@@ -595,9 +599,13 @@ int kwsysProcess_AddCommand(kwsysProcess* cp, char const* const* command)
 
   /* Construct the command line in the allocated buffer.  */
   kwsysProcessComputeCommandLine(cp, command,
-                                 newCommands[cp->NumberOfCommands]);
+                                 new_cmd);
+
+  newCommands[cp->NumberOfCommands] = kwsysEncoding_DupToWide(new_cmd);
+  free(new_cmd);
   }
 
+
   /* Save the new array of commands.  */
   free(cp->Commands);
   cp->Commands = newCommands;
@@ -633,22 +641,26 @@ int kwsysProcess_SetWorkingDirectory(kwsysProcess* cp, const char* dir)
     }
   if(dir && dir[0])
     {
+    wchar_t* wdir = kwsysEncoding_DupToWide(dir);
     /* We must convert the working directory to a full path.  */
-    DWORD length = GetFullPathName(dir, 0, 0, 0);
+    DWORD length = GetFullPathNameW(wdir, 0, 0, 0);
     if(length > 0)
       {
-      cp->WorkingDirectory = (char*)malloc(length);
-      if(!cp->WorkingDirectory)
+      wchar_t* work_dir = malloc(length*sizeof(wchar_t));
+      if(!work_dir)
         {
+        free(wdir);
         return 0;
         }
-      if(!GetFullPathName(dir, length, cp->WorkingDirectory, 0))
+      if(!GetFullPathNameW(wdir, length, work_dir, 0))
         {
-        free(cp->WorkingDirectory);
-        cp->WorkingDirectory = 0;
+        free(work_dir);
+        free(wdir);
         return 0;
         }
+      cp->WorkingDirectory = work_dir;
       }
+    free(wdir);
     }
   return 1;
 }
@@ -879,13 +891,13 @@ void kwsysProcess_Execute(kwsysProcess* cp)
      to make pipe file paths evaluate correctly.  */
   if(cp->WorkingDirectory)
     {
-    if(!GetCurrentDirectory(cp->RealWorkingDirectoryLength,
+    if(!GetCurrentDirectoryW(cp->RealWorkingDirectoryLength,
                             cp->RealWorkingDirectory))
       {
       kwsysProcessCleanup(cp, 1);
       return;
       }
-    SetCurrentDirectory(cp->WorkingDirectory);
+    SetCurrentDirectoryW(cp->WorkingDirectory);
     }
 
   /* Initialize startup info data.  */
@@ -1003,7 +1015,7 @@ void kwsysProcess_Execute(kwsysProcess* cp)
   /* Restore the working directory.  */
   if(cp->RealWorkingDirectory)
     {
-    SetCurrentDirectory(cp->RealWorkingDirectory);
+    SetCurrentDirectoryW(cp->RealWorkingDirectory);
     free(cp->RealWorkingDirectory);
     cp->RealWorkingDirectory = 0;
     }
@@ -1507,10 +1519,10 @@ int kwsysProcessInitialize(kwsysProcess* cp)
   /* Allocate space to save the real working directory of this process.  */
   if(cp->WorkingDirectory)
     {
-    cp->RealWorkingDirectoryLength = GetCurrentDirectory(0, 0);
+    cp->RealWorkingDirectoryLength = GetCurrentDirectoryW(0, 0);
     if(cp->RealWorkingDirectoryLength > 0)
       {
-      cp->RealWorkingDirectory = (char*)malloc(cp->RealWorkingDirectoryLength);
+      cp->RealWorkingDirectory = malloc(cp->RealWorkingDirectoryLength * sizeof(wchar_t));
       if(!cp->RealWorkingDirectory)
         {
         return 0;
@@ -1547,9 +1559,11 @@ int kwsysProcessCreate(kwsysProcess* cp, int index,
   else if(cp->PipeFileSTDIN)
     {
     /* Create a handle to read a file for stdin.  */
-    HANDLE fin = CreateFile(cp->PipeFileSTDIN, GENERIC_READ|GENERIC_WRITE,
+    wchar_t* wstdin = kwsysEncoding_DupToWide(cp->PipeFileSTDIN);
+    HANDLE fin = CreateFileW(wstdin, GENERIC_READ|GENERIC_WRITE,
                             FILE_SHARE_READ|FILE_SHARE_WRITE,
                             0, OPEN_EXISTING, 0, 0);
+    free(wstdin);
     if(fin == INVALID_HANDLE_VALUE)
       {
       return 0;
@@ -1655,7 +1669,7 @@ int kwsysProcessCreate(kwsysProcess* cp, int index,
 
   /* Create the child in a suspended state so we can wait until all
      children have been created before running any one.  */
-  if(!CreateProcess(0, cp->Commands[index], 0, 0, TRUE, CREATE_SUSPENDED, 0,
+  if(!CreateProcessW(0, cp->Commands[index], 0, 0, TRUE, CREATE_SUSPENDED, 0,
                     0, &si->StartupInfo, &cp->ProcessInformation[index]))
     {
     return 0;
@@ -1729,6 +1743,7 @@ void kwsysProcessDestroy(kwsysProcess* cp, int event)
 int kwsysProcessSetupOutputPipeFile(PHANDLE phandle, const char* name)
 {
   HANDLE fout;
+  wchar_t* wname;
   if(!name)
     {
     return 1;
@@ -1738,8 +1753,10 @@ int kwsysProcessSetupOutputPipeFile(PHANDLE phandle, const char* name)
   kwsysProcessCleanupHandle(phandle);
 
   /* Create a handle to write a file for the pipe.  */
-  fout = CreateFile(name, GENERIC_WRITE, FILE_SHARE_READ, 0,
+  wname = kwsysEncoding_DupToWide(name);
+  fout = CreateFileW(wname, GENERIC_WRITE, FILE_SHARE_READ, 0,
                     CREATE_ALWAYS, 0, 0);
+  free(wname);
   if(fout == INVALID_HANDLE_VALUE)
     {
     return 0;
@@ -1883,10 +1900,13 @@ void kwsysProcessCleanup(kwsysProcess* cp, int error)
       {
       /* Format the error message.  */
       DWORD original = GetLastError();
-      DWORD length = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
+      wchar_t err_msg[KWSYSPE_PIPE_BUFFER_SIZE];
+      DWORD length = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
                                    FORMAT_MESSAGE_IGNORE_INSERTS, 0, original,
                                    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
-                                   cp->ErrorMessage, KWSYSPE_PIPE_BUFFER_SIZE, 0);
+                                   err_msg, KWSYSPE_PIPE_BUFFER_SIZE, 0);
+      WideCharToMultiByte(CP_UTF8, 0, err_msg, -1, cp->ErrorMessage,
+                          KWSYSPE_PIPE_BUFFER_SIZE, NULL, NULL);
       if(length < 1)
         {
         /* FormatMessage failed.  Use a default message.  */
@@ -1924,7 +1944,7 @@ void kwsysProcessCleanup(kwsysProcess* cp, int error)
     /* Restore the working directory.  */
     if(cp->RealWorkingDirectory)
       {
-      SetCurrentDirectory(cp->RealWorkingDirectory);
+      SetCurrentDirectoryW(cp->RealWorkingDirectory);
       }
     }
 
@@ -2222,7 +2242,7 @@ static void kwsysProcessSetExitException(kwsysProcess* cp, int code)
     case STATUS_NO_MEMORY:
     default:
       cp->ExitException = kwsysProcess_Exception_Other;
-      sprintf(cp->ExitExceptionString, "Exit code 0x%x\n", code);
+      _snprintf(cp->ExitExceptionString, KWSYSPE_PIPE_BUFFER_SIZE, "Exit code 0x%x\n", code);
       break;
     }
 }
@@ -2430,7 +2450,7 @@ static int kwsysProcess_List__New_NT4(kwsysProcess_List* self)
      loaded in this program.  This does not actually increment the
      reference count to the module so we do not need to close the
      handle.  */
-  HMODULE hNT = GetModuleHandle("ntdll.dll");
+  HMODULE hNT = GetModuleHandleW(L"ntdll.dll");
   if(hNT)
     {
     /* Get pointers to the needed API functions.  */
@@ -2534,7 +2554,7 @@ static int kwsysProcess_List__New_Snapshot(kwsysProcess_List* self)
      loaded in this program.  This does not actually increment the
      reference count to the module so we do not need to close the
      handle.  */
-  HMODULE hKernel = GetModuleHandle("kernel32.dll");
+  HMODULE hKernel = GetModuleHandleW(L"kernel32.dll");
   if(hKernel)
     {
     self->P_CreateToolhelp32Snapshot =

+ 17 - 17
Source/kwsys/SystemInformation.cxx

@@ -253,7 +253,7 @@ static bool call_cpuid(int select, int result[4])
     _asm {
 #ifdef CPUID_AWARE_COMPILER
       ; we must push/pop the registers <<CPUID>> writes to, as the
-      ; optimiser doesn't know about <<CPUID>>, and so doesn't expect
+      ; optimiser does not know about <<CPUID>>, and so does not expect
       ; these registers to change.
       push eax
       push ebx
@@ -2454,8 +2454,8 @@ bool SystemInformationImplementation::RetrieveCPUClockSpeed()
   if (!retrieved)
     {
     HKEY hKey = NULL;
-    LONG err = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
-      "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0,
+    LONG err = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+      L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0,
       KEY_READ, &hKey);
 
     if (ERROR_SUCCESS == err)
@@ -2464,7 +2464,7 @@ bool SystemInformationImplementation::RetrieveCPUClockSpeed()
       DWORD data = 0;
       DWORD dwSize = sizeof(DWORD);
 
-      err = RegQueryValueEx(hKey, "~MHz", 0,
+      err = RegQueryValueExW(hKey, L"~MHz", 0,
         &dwType, (LPBYTE) &data, &dwSize);
 
       if (ERROR_SUCCESS == err)
@@ -5017,19 +5017,19 @@ bool SystemInformationImplementation::QueryOSInformation()
 
   this->OSName = "Windows";
 
-  OSVERSIONINFOEX osvi;
+  OSVERSIONINFOEXW osvi;
   BOOL bIsWindows64Bit;
   BOOL bOsVersionInfoEx;
   char operatingSystem[256];
 
   // Try calling GetVersionEx using the OSVERSIONINFOEX structure.
-  ZeroMemory (&osvi, sizeof (OSVERSIONINFOEX));
-  osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX);
-  bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi);
+  ZeroMemory (&osvi, sizeof (OSVERSIONINFOEXW));
+  osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEXW);
+  bOsVersionInfoEx = GetVersionExW ((OSVERSIONINFOW*)&osvi);
   if (!bOsVersionInfoEx)
     {
-    osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
-    if (!GetVersionEx ((OSVERSIONINFO *) &osvi))
+    osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFOW);
+    if (!GetVersionExW((OSVERSIONINFOW*)&osvi))
       {
       return false;
       }
@@ -5115,19 +5115,19 @@ bool SystemInformationImplementation::QueryOSInformation()
 #endif        // VER_NT_WORKSTATION
         {
         HKEY hKey;
-        char szProductType[80];
+        wchar_t szProductType[80];
         DWORD dwBufLen;
 
         // Query the registry to retrieve information.
-        RegOpenKeyEx (HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\ProductOptions", 0, KEY_QUERY_VALUE, &hKey);
-        RegQueryValueEx (hKey, "ProductType", NULL, NULL, (LPBYTE) szProductType, &dwBufLen);
+        RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\ProductOptions", 0, KEY_QUERY_VALUE, &hKey);
+        RegQueryValueExW(hKey, L"ProductType", NULL, NULL, (LPBYTE) szProductType, &dwBufLen);
         RegCloseKey (hKey);
 
-        if (lstrcmpi ("WINNT", szProductType) == 0)
+        if (lstrcmpiW(L"WINNT", szProductType) == 0)
           {
           this->OSRelease += " Professional";
           }
-        if (lstrcmpi ("LANMANNT", szProductType) == 0)
+        if (lstrcmpiW(L"LANMANNT", szProductType) == 0)
           {
           // Decide between Windows 2000 Advanced Server and Windows .NET Enterprise Server.
           if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
@@ -5139,7 +5139,7 @@ bool SystemInformationImplementation::QueryOSInformation()
             this->OSRelease += " Server";
             }
           }
-        if (lstrcmpi ("SERVERNT", szProductType) == 0)
+        if (lstrcmpiW(L"SERVERNT", szProductType) == 0)
           {
           // Decide between Windows 2000 Advanced Server and Windows .NET Enterprise Server.
           if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
@@ -5172,7 +5172,7 @@ bool SystemInformationImplementation::QueryOSInformation()
         LPFNPROC DLLProc;
 
         // Load the Kernel32 DLL.
-        hKernelDLL = LoadLibrary ("kernel32");
+        hKernelDLL = LoadLibraryW(L"kernel32");
         if (hKernelDLL != NULL)  {
           // Only XP and .NET Server support IsWOW64Process so... Load dynamically!
           DLLProc = (LPFNPROC) GetProcAddress (hKernelDLL, "IsWow64Process");

+ 194 - 95
Source/kwsys/SystemTools.cxx

@@ -20,6 +20,8 @@
 #include KWSYS_HEADER(RegularExpression.hxx)
 #include KWSYS_HEADER(SystemTools.hxx)
 #include KWSYS_HEADER(Directory.hxx)
+#include KWSYS_HEADER(FStream.hxx)
+#include KWSYS_HEADER(Encoding.hxx)
 
 #include KWSYS_HEADER(ios/iostream)
 #include KWSYS_HEADER(ios/fstream)
@@ -32,6 +34,8 @@
 #if 0
 # include "SystemTools.hxx.in"
 # include "Directory.hxx.in"
+# include "FStream.hxx.in"
+# include "Encoding.hxx.in"
 # include "kwsys_ios_iostream.h.in"
 # include "kwsys_ios_fstream.h.in"
 # include "kwsys_ios_sstream.h.in"
@@ -75,6 +79,9 @@
 // Windows API.
 #if defined(_WIN32)
 # include <windows.h>
+# ifndef INVALID_FILE_ATTRIBUTES
+#  define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
+# endif
 #elif defined (__CYGWIN__)
 # include <windows.h>
 # undef _WIN32
@@ -183,22 +190,25 @@ static inline char *realpath(const char *path, char *resolved_path)
 #if defined(_WIN32) && (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__BORLANDC__) || defined(__MINGW32__))
 inline int Mkdir(const char* dir)
 {
-  return _mkdir(dir);
+  return _wmkdir(KWSYS_NAMESPACE::Encoding::ToWide(dir).c_str());
 }
 inline int Rmdir(const char* dir)
 {
-  return _rmdir(dir);
+  return _wrmdir(KWSYS_NAMESPACE::Encoding::ToWide(dir).c_str());
 }
 inline const char* Getcwd(char* buf, unsigned int len)
 {
-  if(const char* ret = _getcwd(buf, len))
+  std::vector<wchar_t> w_buf(len);
+  if(const wchar_t* ret = _wgetcwd(&w_buf[0], len))
     {
     // make sure the drive letter is capital
-    if(strlen(buf) > 1 && buf[1] == ':')
+    if(wcslen(&w_buf[0]) > 1 && w_buf[1] == L':')
       {
-      buf[0] = toupper(buf[0]);
+      w_buf[0] = towupper(w_buf[0]);
       }
-    return ret;
+    std::string tmp = KWSYS_NAMESPACE::Encoding::ToNarrow(&w_buf[0]);
+    strcpy(buf, tmp.c_str());
+    return buf;
     }
   return 0;
 }
@@ -207,16 +217,18 @@ inline int Chdir(const char* dir)
   #if defined(__BORLANDC__)
   return chdir(dir);
   #else
-  return _chdir(dir);
+  return _wchdir(KWSYS_NAMESPACE::Encoding::ToWide(dir).c_str());
   #endif
 }
 inline void Realpath(const char *path, kwsys_stl::string & resolved_path)
 {
-  char *ptemp;
-  char fullpath[MAX_PATH];
-  if( GetFullPathName(path, sizeof(fullpath), fullpath, &ptemp) )
+  kwsys_stl::wstring tmp = KWSYS_NAMESPACE::Encoding::ToWide(path);
+  wchar_t *ptemp;
+  wchar_t fullpath[MAX_PATH];
+  if( GetFullPathNameW(tmp.c_str(), sizeof(fullpath)/sizeof(fullpath[0]),
+                       fullpath, &ptemp) )
     {
-    resolved_path = fullpath;
+    resolved_path = KWSYS_NAMESPACE::Encoding::ToNarrow(fullpath);
     KWSYS_NAMESPACE::SystemTools::ConvertToUnixSlashes(resolved_path);
     }
   else
@@ -591,6 +603,15 @@ const char* SystemTools::GetExecutableExtension()
 #endif
 }
 
+FILE* SystemTools::Fopen(const char* file, const char* mode)
+{
+#ifdef _WIN32
+  return _wfopen(Encoding::ToWide(file).c_str(),
+                 Encoding::ToWide(mode).c_str());
+#else
+  return fopen(file, mode);
+#endif
+}
 
 bool SystemTools::MakeDirectory(const char* path)
 {
@@ -740,7 +761,7 @@ static DWORD SystemToolsMakeRegistryMode(DWORD mode,
                                          SystemTools::KeyWOW64 view)
 {
   // only add the modes when on a system that supports Wow64.
-  static FARPROC wow64p = GetProcAddress(GetModuleHandle("kernel32"),
+  static FARPROC wow64p = GetProcAddress(GetModuleHandleW(L"kernel32"),
                                          "IsWow64Process");
   if(wow64p == NULL)
     {
@@ -774,8 +795,8 @@ SystemTools::GetRegistrySubKeys(const char *key,
     }
 
   HKEY hKey;
-  if(RegOpenKeyEx(primaryKey,
-                  second.c_str(),
+  if(RegOpenKeyExW(primaryKey,
+                  Encoding::ToWide(second).c_str(),
                   0,
                   SystemToolsMakeRegistryMode(KEY_READ, view),
                   &hKey) != ERROR_SUCCESS)
@@ -784,13 +805,13 @@ SystemTools::GetRegistrySubKeys(const char *key,
     }
   else
     {
-    char name[1024];
+    wchar_t name[1024];
     DWORD dwNameSize = sizeof(name)/sizeof(name[0]);
 
     DWORD i = 0;
-    while (RegEnumKey(hKey, i, name, dwNameSize) == ERROR_SUCCESS)
+    while (RegEnumKeyW(hKey, i, name, dwNameSize) == ERROR_SUCCESS)
       {
-      subkeys.push_back(name);
+      subkeys.push_back(Encoding::ToNarrow(name));
       ++i;
       }
 
@@ -829,8 +850,8 @@ bool SystemTools::ReadRegistryValue(const char *key, kwsys_stl::string &value,
     }
 
   HKEY hKey;
-  if(RegOpenKeyEx(primaryKey,
-                  second.c_str(),
+  if(RegOpenKeyExW(primaryKey,
+                  Encoding::ToWide(second).c_str(),
                   0,
                   SystemToolsMakeRegistryMode(KEY_READ, view),
                   &hKey) != ERROR_SUCCESS)
@@ -841,9 +862,9 @@ bool SystemTools::ReadRegistryValue(const char *key, kwsys_stl::string &value,
     {
     DWORD dwType, dwSize;
     dwSize = 1023;
-    char data[1024];
-    if(RegQueryValueEx(hKey,
-                       (LPTSTR)valuename.c_str(),
+    wchar_t data[1024];
+    if(RegQueryValueExW(hKey,
+                       Encoding::ToWide(valuename).c_str(),
                        NULL,
                        &dwType,
                        (BYTE *)data,
@@ -851,16 +872,17 @@ bool SystemTools::ReadRegistryValue(const char *key, kwsys_stl::string &value,
       {
       if (dwType == REG_SZ)
         {
-        value = data;
+        value = Encoding::ToNarrow(data);
         valueset = true;
         }
       else if (dwType == REG_EXPAND_SZ)
         {
-        char expanded[1024];
+        wchar_t expanded[1024];
         DWORD dwExpandedSize = sizeof(expanded)/sizeof(expanded[0]);
-        if(ExpandEnvironmentStrings(data, expanded, dwExpandedSize))
+        if(ExpandEnvironmentStringsW(data, expanded,
+            dwExpandedSize))
           {
-          value = expanded;
+          value = Encoding::ToNarrow(expanded);
           valueset = true;
           }
         }
@@ -901,9 +923,9 @@ bool SystemTools::WriteRegistryValue(const char *key, const char *value,
 
   HKEY hKey;
   DWORD dwDummy;
-  char lpClass[] = "";
-  if(RegCreateKeyEx(primaryKey,
-                    second.c_str(),
+  wchar_t lpClass[] = L"";
+  if(RegCreateKeyExW(primaryKey,
+                    Encoding::ToWide(second).c_str(),
                     0,
                     lpClass,
                     REG_OPTION_NON_VOLATILE,
@@ -915,12 +937,13 @@ bool SystemTools::WriteRegistryValue(const char *key, const char *value,
     return false;
     }
 
-  if(RegSetValueEx(hKey,
-                   (LPTSTR)valuename.c_str(),
+  std::wstring wvalue = Encoding::ToWide(value);
+  if(RegSetValueExW(hKey,
+                   Encoding::ToWide(valuename).c_str(),
                    0,
                    REG_SZ,
-                   (CONST BYTE *)value,
-                   (DWORD)(strlen(value) + 1)) == ERROR_SUCCESS)
+                   (CONST BYTE *)wvalue.c_str(),
+                   (DWORD)(sizeof(wchar_t) * (wvalue.size() + 1))) == ERROR_SUCCESS)
     {
     return true;
     }
@@ -952,8 +975,8 @@ bool SystemTools::DeleteRegistryValue(const char *key, KeyWOW64 view)
     }
 
   HKEY hKey;
-  if(RegOpenKeyEx(primaryKey,
-                  second.c_str(),
+  if(RegOpenKeyExW(primaryKey,
+                  Encoding::ToWide(second).c_str(),
                   0,
                   SystemToolsMakeRegistryMode(KEY_WRITE, view),
                   &hKey) != ERROR_SUCCESS)
@@ -983,7 +1006,7 @@ bool SystemTools::SameFile(const char* file1, const char* file2)
 #ifdef _WIN32
   HANDLE hFile1, hFile2;
 
-  hFile1 = CreateFile( file1,
+  hFile1 = CreateFileW( Encoding::ToWide(file1).c_str(),
                       GENERIC_READ,
                       FILE_SHARE_READ ,
                       NULL,
@@ -991,7 +1014,7 @@ bool SystemTools::SameFile(const char* file1, const char* file2)
                       FILE_FLAG_BACKUP_SEMANTICS,
                       NULL
     );
-  hFile2 = CreateFile( file2,
+  hFile2 = CreateFileW( Encoding::ToWide(file2).c_str(),
                       GENERIC_READ,
                       FILE_SHARE_READ,
                       NULL,
@@ -1039,15 +1062,6 @@ bool SystemTools::SameFile(const char* file1, const char* file2)
 #endif
 }
 
-//----------------------------------------------------------------------------
-#if defined(_WIN32) || defined(__CYGWIN__)
-static bool WindowsFileExists(const char* filename)
-{
-  WIN32_FILE_ATTRIBUTE_DATA fd;
-  return GetFileAttributesExA(filename, GetFileExInfoStandard, &fd) != 0;
-}
-#endif
-
 //----------------------------------------------------------------------------
 bool SystemTools::FileExists(const char* filename)
 {
@@ -1060,11 +1074,12 @@ bool SystemTools::FileExists(const char* filename)
   char winpath[MAX_PATH];
   if(SystemTools::PathCygwinToWin32(filename, winpath))
     {
-    return WindowsFileExists(winpath);
+    return (GetFileAttributesA(winpath) != INVALID_FILE_ATTRIBUTES);
     }
   return access(filename, R_OK) == 0;
 #elif defined(_WIN32)
-  return WindowsFileExists(filename);
+  return (GetFileAttributesW(Encoding::ToWide(filename).c_str())
+          != INVALID_FILE_ATTRIBUTES);
 #else
   return access(filename, R_OK) == 0;
 #endif
@@ -1107,7 +1122,7 @@ bool SystemTools::Touch(const char* filename, bool create)
 {
   if(create && !SystemTools::FileExists(filename))
     {
-    FILE* file = fopen(filename, "a+b");
+    FILE* file = Fopen(filename, "a+b");
     if(file)
       {
       fclose(file);
@@ -1116,7 +1131,8 @@ bool SystemTools::Touch(const char* filename, bool create)
     return false;
     }
 #if defined(_WIN32) && !defined(__CYGWIN__)
-  HANDLE h = CreateFile(filename, FILE_WRITE_ATTRIBUTES,
+  HANDLE h = CreateFileW(Encoding::ToWide(filename).c_str(),
+                        FILE_WRITE_ATTRIBUTES,
                         FILE_SHARE_WRITE, 0, OPEN_EXISTING,
                         FILE_FLAG_BACKUP_SEMANTICS, 0);
   if(!h)
@@ -1220,11 +1236,13 @@ bool SystemTools::FileTimeCompare(const char* f1, const char* f2,
   // Windows version.  Get the modification time from extended file attributes.
   WIN32_FILE_ATTRIBUTE_DATA f1d;
   WIN32_FILE_ATTRIBUTE_DATA f2d;
-  if(!GetFileAttributesEx(f1, GetFileExInfoStandard, &f1d))
+  if(!GetFileAttributesExW(Encoding::ToWide(f1).c_str(),
+                           GetFileExInfoStandard, &f1d))
     {
     return false;
     }
-  if(!GetFileAttributesEx(f2, GetFileExInfoStandard, &f2d))
+  if(!GetFileAttributesExW(Encoding::ToWide(f2).c_str(),
+                           GetFileExInfoStandard, &f2d))
     {
     return false;
     }
@@ -1932,6 +1950,39 @@ bool SystemTools::CopyFileIfDifferent(const char* source,
 bool SystemTools::FilesDiffer(const char* source,
                               const char* destination)
 {
+
+#if defined(_WIN32)
+  WIN32_FILE_ATTRIBUTE_DATA statSource;
+  if (GetFileAttributesExW(Encoding::ToWide(source).c_str(),
+                           GetFileExInfoStandard,
+                           &statSource) == 0)
+    {
+    return true;
+    }
+
+  WIN32_FILE_ATTRIBUTE_DATA statDestination;
+  if (GetFileAttributesExW(Encoding::ToWide(destination).c_str(),
+                           GetFileExInfoStandard,
+                           &statDestination) == 0)
+    {
+    return true;
+    }
+
+  if(statSource.nFileSizeHigh != statDestination.nFileSizeHigh ||
+     statSource.nFileSizeLow != statDestination.nFileSizeLow)
+    {
+    return true;
+    }
+
+  if(statSource.nFileSizeHigh == 0 && statSource.nFileSizeLow == 0)
+    {
+    return false;
+    }
+  off_t nleft = ((__int64)statSource.nFileSizeHigh << 32) +
+                statSource.nFileSizeLow;
+
+#else
+
   struct stat statSource;
   if (stat(source, &statSource) != 0)
     {
@@ -1953,15 +2004,19 @@ bool SystemTools::FilesDiffer(const char* source,
     {
     return false;
     }
+  off_t nleft = statSource.st_size;
+#endif
 
-#if defined(_WIN32) || defined(__CYGWIN__)
-  kwsys_ios::ifstream finSource(source, (kwsys_ios::ios::binary |
-                                         kwsys_ios::ios::in));
-  kwsys_ios::ifstream finDestination(destination, (kwsys_ios::ios::binary |
-                                                   kwsys_ios::ios::in));
+#if defined(_WIN32)
+  kwsys::ifstream finSource(source,
+                            (kwsys_ios::ios::binary |
+                             kwsys_ios::ios::in));
+  kwsys::ifstream finDestination(destination,
+                                 (kwsys_ios::ios::binary |
+                                  kwsys_ios::ios::in));
 #else
-  kwsys_ios::ifstream finSource(source);
-  kwsys_ios::ifstream finDestination(destination);
+  kwsys::ifstream finSource(source);
+  kwsys::ifstream finDestination(destination);
 #endif
   if(!finSource || !finDestination)
     {
@@ -1971,7 +2026,6 @@ bool SystemTools::FilesDiffer(const char* source,
   // Compare the files a block at a time.
   char source_buf[KWSYS_ST_BUFFER];
   char dest_buf[KWSYS_ST_BUFFER];
-  off_t nleft = statSource.st_size;
   while(nleft > 0)
     {
     // Read a block from each file.
@@ -2044,10 +2098,10 @@ bool SystemTools::CopyFileAlways(const char* source, const char* destination)
   // Open files
 
 #if defined(_WIN32) || defined(__CYGWIN__)
-  kwsys_ios::ifstream fin(source,
-                    kwsys_ios::ios::binary | kwsys_ios::ios::in);
+  kwsys::ifstream fin(source,
+                kwsys_ios::ios::binary | kwsys_ios::ios::in);
 #else
-  kwsys_ios::ifstream fin(source);
+  kwsys::ifstream fin(source);
 #endif
   if(!fin)
     {
@@ -2344,7 +2398,11 @@ bool SystemTools::RemoveFile(const char* source)
   /* Win32 unlink is stupid --- it fails if the file is read-only  */
   SystemTools::SetPermissions(source, S_IWRITE);
 #endif
+#ifdef _WIN32
+  bool res = _wunlink(Encoding::ToWide(source).c_str()) != 0 ? false : true;
+#else
   bool res = unlink(source) != 0 ? false : true;
+#endif
 #ifdef _WIN32
   if ( !res )
     {
@@ -2789,12 +2847,15 @@ bool SystemTools::FileIsDirectory(const char* name)
     }
 
   // Now check the file node type.
+#if defined( _WIN32 )
+  DWORD attr = GetFileAttributesW(Encoding::ToWide(name).c_str());
+  if (attr != INVALID_FILE_ATTRIBUTES)
+    {
+    return (attr & FILE_ATTRIBUTE_DIRECTORY) != 0;
+#else
   struct stat fs;
   if(stat(name, &fs) == 0)
     {
-#if defined( _WIN32 ) && !defined(__CYGWIN__)
-    return ((fs.st_mode & _S_IFDIR) != 0);
-#else
     return S_ISDIR(fs.st_mode);
 #endif
     }
@@ -3279,11 +3340,12 @@ static int GetCasePathName(const kwsys_stl::string & pathIn,
     kwsys_stl::string test_str = casePath;
     test_str += path_components[idx];
 
-    WIN32_FIND_DATA findData;
-    HANDLE hFind = ::FindFirstFile(test_str.c_str(), &findData);
+    WIN32_FIND_DATAW findData;
+    HANDLE hFind = ::FindFirstFileW(Encoding::ToWide(test_str).c_str(),
+      &findData);
     if (INVALID_HANDLE_VALUE != hFind)
       {
-      casePath += findData.cFileName;
+      casePath += Encoding::ToNarrow(findData.cFileName);
       ::FindClose(hFind);
       }
     else
@@ -3733,8 +3795,7 @@ bool SystemTools::FileHasSignature(const char *filename,
     return false;
     }
 
-  FILE *fp;
-  fp = fopen(filename, "rb");
+  FILE *fp = Fopen(filename, "rb");
   if (!fp)
     {
     return false;
@@ -3767,8 +3828,7 @@ SystemTools::DetectFileType(const char *filename,
     return SystemTools::FileTypeUnknown;
     }
 
-  FILE *fp;
-  fp = fopen(filename, "rb");
+  FILE *fp = Fopen(filename, "rb");
   if (!fp)
     {
     return SystemTools::FileTypeUnknown;
@@ -3958,9 +4018,8 @@ bool SystemTools::GetShortPath(const char* path, kwsys_stl::string& shortPath)
 {
 #if defined(WIN32) && !defined(__CYGWIN__)
   const int size = int(strlen(path)) +1; // size of return
-  char *buffer = new char[size];  // create a buffer
   char *tempPath = new char[size];  // create a buffer
-  int ret;
+  DWORD ret;
 
   // if the path passed in has quotes around it, first remove the quotes
   if (path[0] == '"' && path[strlen(path)-1] == '"')
@@ -3973,19 +4032,20 @@ bool SystemTools::GetShortPath(const char* path, kwsys_stl::string& shortPath)
     strcpy(tempPath,path);
     }
 
+  kwsys_stl::wstring wtempPath = Encoding::ToWide(tempPath);
+  kwsys_stl::vector<wchar_t> buffer(wtempPath.size()+1);
   buffer[0] = 0;
-  ret = GetShortPathName(tempPath, buffer, size);
+  ret = GetShortPathNameW(Encoding::ToWide(tempPath).c_str(),
+    &buffer[0], static_cast<DWORD>(wtempPath.size()));
 
-  if(buffer[0] == 0 || ret > size)
+  if(buffer[0] == 0 || ret > wtempPath.size())
     {
-    delete [] buffer;
     delete [] tempPath;
     return false;
     }
   else
     {
-    shortPath = buffer;
-    delete [] buffer;
+    shortPath = Encoding::ToNarrow(&buffer[0]);
     delete [] tempPath;
     return true;
     }
@@ -4212,12 +4272,45 @@ bool SystemTools::GetPermissions(const char* file, mode_t& mode)
     return false;
     }
 
+#if defined(_WIN32)
+  DWORD attr = GetFileAttributesW(Encoding::ToWide(file).c_str());
+  if(attr == INVALID_FILE_ATTRIBUTES)
+    {
+    return false;
+    }
+  if((attr & FILE_ATTRIBUTE_READONLY) != 0)
+    {
+    mode = (_S_IREAD  | (_S_IREAD  >> 3) | (_S_IREAD  >> 6));
+    }
+  else
+    {
+    mode = (_S_IWRITE | (_S_IWRITE >> 3) | (_S_IWRITE >> 6)) |
+           (_S_IREAD  | (_S_IREAD  >> 3) | (_S_IREAD  >> 6));
+    }
+  if((attr & FILE_ATTRIBUTE_DIRECTORY) != 0)
+    {
+    mode |= S_IFDIR | (_S_IEXEC  | (_S_IEXEC  >> 3) | (_S_IEXEC  >> 6));
+    }
+  else
+    {
+    mode |= S_IFREG;
+    }
+  const char* ext = strrchr(file, '.');
+  if(ext && (Strucmp(ext, ".exe") == 0 ||
+    Strucmp(ext, ".com") == 0 ||
+    Strucmp(ext, ".cmd") == 0 ||
+    Strucmp(ext, ".bat") == 0))
+    {
+    mode |= (_S_IEXEC  | (_S_IEXEC  >> 3) | (_S_IEXEC  >> 6));
+    }
+#else
   struct stat st;
   if ( stat(file, &st) < 0 )
     {
     return false;
     }
   mode = st.st_mode;
+#endif
   return true;
 }
 
@@ -4231,7 +4324,11 @@ bool SystemTools::SetPermissions(const char* file, mode_t mode)
     {
     return false;
     }
+#ifdef _WIN32
+  if ( _wchmod(Encoding::ToWide(file).c_str(), mode) < 0 )
+#else
   if ( chmod(file, mode) < 0 )
+#endif
     {
     return false;
     }
@@ -4336,7 +4433,9 @@ void SystemTools::ConvertWindowsCommandLineToUnixArguments(
 
   (*argv)[0] = new char [1024];
 #ifdef _WIN32
-  ::GetModuleFileName(0, (*argv)[0], 1024);
+  wchar_t tmp[1024];
+  ::GetModuleFileNameW(0, tmp, 1024);
+  strcpy((*argv)[0], Encoding::ToNarrow(tmp).c_str());
 #else
   (*argv)[0][0] = '\0';
 #endif
@@ -4396,14 +4495,14 @@ kwsys_stl::string SystemTools::GetOperatingSystemNameAndVersion()
 #ifdef _WIN32
   char buffer[256];
 
-  OSVERSIONINFOEX osvi;
+  OSVERSIONINFOEXA osvi;
   BOOL bOsVersionInfoEx;
 
   // Try calling GetVersionEx using the OSVERSIONINFOEX structure.
   // If that fails, try using the OSVERSIONINFO structure.
 
-  ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
-  osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+  ZeroMemory(&osvi, sizeof(OSVERSIONINFOEXA));
+  osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
 
   bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO *)&osvi);
   if (!bOsVersionInfoEx)
@@ -4546,21 +4645,21 @@ kwsys_stl::string SystemTools::GetOperatingSystemNameAndVersion()
         {
         HKEY hKey;
         #define BUFSIZE 80
-        char szProductType[BUFSIZE];
+        wchar_t szProductType[BUFSIZE];
         DWORD dwBufLen=BUFSIZE;
         LONG lRet;
 
-        lRet = RegOpenKeyEx(
+        lRet = RegOpenKeyExW(
           HKEY_LOCAL_MACHINE,
-          "SYSTEM\\CurrentControlSet\\Control\\ProductOptions",
+          L"SYSTEM\\CurrentControlSet\\Control\\ProductOptions",
           0, KEY_QUERY_VALUE, &hKey);
         if (lRet != ERROR_SUCCESS)
           {
           return 0;
           }
 
-        lRet = RegQueryValueEx(hKey, "ProductType", NULL, NULL,
-                               (LPBYTE) szProductType, &dwBufLen);
+        lRet = RegQueryValueExW(hKey, L"ProductType", NULL, NULL,
+                                (LPBYTE) szProductType, &dwBufLen);
 
         if ((lRet != ERROR_SUCCESS) || (dwBufLen > BUFSIZE))
           {
@@ -4569,15 +4668,15 @@ kwsys_stl::string SystemTools::GetOperatingSystemNameAndVersion()
 
         RegCloseKey(hKey);
 
-        if (lstrcmpi("WINNT", szProductType) == 0)
+        if (lstrcmpiW(L"WINNT", szProductType) == 0)
           {
           res += " Workstation";
           }
-        if (lstrcmpi("LANMANNT", szProductType) == 0)
+        if (lstrcmpiW(L"LANMANNT", szProductType) == 0)
           {
           res += " Server";
           }
-        if (lstrcmpi("SERVERNT", szProductType) == 0)
+        if (lstrcmpiW(L"SERVERNT", szProductType) == 0)
           {
           res += " Advanced Server";
           }
@@ -4593,16 +4692,16 @@ kwsys_stl::string SystemTools::GetOperatingSystemNameAndVersion()
       // Display service pack (if any) and build number.
 
       if (osvi.dwMajorVersion == 4 &&
-          lstrcmpi(osvi.szCSDVersion, "Service Pack 6") == 0)
+          lstrcmpiA(osvi.szCSDVersion, "Service Pack 6") == 0)
         {
         HKEY hKey;
         LONG lRet;
 
         // Test for SP6 versus SP6a.
 
-        lRet = RegOpenKeyEx(
+        lRet = RegOpenKeyExW(
           HKEY_LOCAL_MACHINE,
-          "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix\\Q246009",
+          L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix\\Q246009",
           0, KEY_QUERY_VALUE, &hKey);
 
         if (lRet == ERROR_SUCCESS)

+ 11 - 4
Source/kwsys/SystemTools.hxx.in

@@ -24,6 +24,8 @@
 
 // Required for va_list
 #include <stdarg.h>
+// Required for FILE*
+#include <stdio.h>
 #if @KWSYS_NAMESPACE@_STL_HAVE_STD && !defined(va_list)
 // Some compilers move va_list into the std namespace and there is no way to
 // tell that this has been done. Playing with things being included before or
@@ -42,10 +44,6 @@ namespace @KWSYS_NAMESPACE@
 }
 #endif // va_list
 
-#if defined( _MSC_VER )
-typedef unsigned short mode_t;
-#endif
-
 /* Define these macros temporarily to keep the code readable.  */
 #if !defined (KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
 # define kwsys_stl @KWSYS_NAMESPACE@_stl
@@ -496,6 +494,11 @@ public:
    *  -----------------------------------------------------------------
    */
 
+  /**
+   * Open a file considering unicode.
+   */
+  static FILE* Fopen(const char* file, const char* mode);
+
   /**
    * Make a new directory if it is not there.  This function
    * can make a full path even if none of the directories existed
@@ -684,6 +687,10 @@ public:
    */
   static long int CreationTime(const char* filename);
 
+  #if defined( _MSC_VER )
+  typedef unsigned short mode_t;
+  #endif
+
   /**
    * Get and set permissions of the file.
    */

+ 6 - 0
Source/kwsys/kwsysPlatformTestsCXX.cxx

@@ -674,3 +674,9 @@ int main()
   return a;
 }
 #endif
+
+#ifdef TEST_KWSYS_STL_HAS_WSTRING
+#include <string>
+void f(std ::wstring*) {}
+int main() { return 0; }
+#endif

+ 159 - 0
Source/kwsys/testEncoding.cxx

@@ -0,0 +1,159 @@
+/*============================================================================
+  KWSys - Kitware System Library
+  Copyright 2000-2009 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.
+============================================================================*/
+#include "kwsysPrivate.h"
+
+#if defined(_MSC_VER)
+# pragma warning (disable:4786)
+#endif
+
+#include KWSYS_HEADER(Encoding.hxx)
+#include KWSYS_HEADER(ios/iostream)
+
+#include <locale.h>
+
+// Work-around CMake dependency scanning limitation.  This must
+// duplicate the above list of headers.
+#if 0
+# include "Encoding.hxx.in"
+# include "kwsys_ios_iostream.h.in"
+#endif
+
+//----------------------------------------------------------------------------
+static const unsigned char helloWorldStrings[][32] =
+{
+  // English
+  {'H','e','l','l','o',' ','W','o','r','l','d',0},
+  // Japanese
+  {0xE3, 0x81, 0x93, 0xE3, 0x82, 0x93, 0xE3, 0x81, 0xAB, 0xE3,
+   0x81, 0xA1, 0xE3, 0x81, 0xAF, 0xE4, 0xB8, 0x96, 0xE7, 0x95,
+   0x8C, 0},
+   // Arabic
+  {0xD9, 0x85, 0xD8, 0xB1, 0xD8, 0xAD, 0xD8, 0xA8, 0xD8, 0xA7,
+   0x20, 0xD8, 0xA7, 0xD9, 0x84, 0xD8, 0xB9, 0xD8, 0xA7, 0xD9,
+   0x84, 0xD9, 0x85, 0},
+  // Yiddish
+  {0xD7, 0x94, 0xD7, 0xA2, 0xD7, 0x9C, 0xD7, 0x90, 0x20, 0xD7,
+   0x95, 0xD7, 0x95, 0xD7, 0xA2, 0xD7, 0x9C, 0xD7, 0x98, 0},
+  // Russian
+  {0xD0, 0xBF, 0xD1, 0x80, 0xD0, 0xB8, 0xD0, 0xB2, 0xD0, 0xB5,
+   0xD1, 0x82, 0x20, 0xD0, 0xBC, 0xD0, 0xB8, 0xD1, 0x80, 0},
+  // Latin
+  {0x4D, 0x75, 0x6E, 0x64, 0x75, 0x73, 0x20, 0x73, 0x61, 0x6C,
+   0x76, 0x65, 0},
+  // Swahili
+  {0x68, 0x75, 0x6A, 0x61, 0x6D, 0x62, 0x6F, 0x20, 0x44, 0x75,
+   0x6E, 0x69, 0x61, 0},
+  // Icelandic
+  {0x48, 0x61, 0x6C, 0x6C, 0xC3, 0xB3, 0x20, 0x68, 0x65, 0x69,
+   0x6D, 0x75, 0x72, 0},
+  {0}
+};
+
+//----------------------------------------------------------------------------
+static int testHelloWorldEncoding()
+{
+  int ret = 0;
+  for(int i=0; helloWorldStrings[i][0] != 0; i++)
+    {
+    std::string str = reinterpret_cast<const char*>(helloWorldStrings[i]);
+    std::cout << str << std::endl;
+    std::wstring wstr = kwsys::Encoding::ToWide(str);
+    std::string str2 = kwsys::Encoding::ToNarrow(wstr);
+    if(!wstr.empty() && str != str2)
+      {
+      std::cout << "converted string was different: " << str2 << std::endl;
+      ret++;
+      }
+    }
+  return ret;
+}
+
+static int testRobustEncoding()
+{
+  // test that the conversion functions handle invalid
+  // unicode correctly/gracefully
+
+  int ret = 0;
+  char cstr[] = {(char)-1, 0};
+  // this conversion could fail
+  std::wstring wstr = kwsys::Encoding::ToWide(cstr);
+
+  wstr = kwsys::Encoding::ToWide(NULL);
+  if(wstr != L"")
+    {
+    const wchar_t* wcstr = wstr.c_str();
+    std::cout << "ToWide(NULL) returned";
+    for(size_t i=0; i<wstr.size(); i++)
+      {
+      std::cout << " " << std::hex << (int)wcstr[i];
+      }
+    std::cout << std::endl;
+    ret++;
+    }
+  wstr = kwsys::Encoding::ToWide("");
+  if(wstr != L"")
+    {
+    const wchar_t* wcstr = wstr.c_str();
+    std::cout << "ToWide(\"\") returned";
+    for(size_t i=0; i<wstr.size(); i++)
+      {
+      std::cout << " " << std::hex << (int)wcstr[i];
+      }
+    std::cout << std::endl;
+    ret++;
+    }
+
+#ifdef WIN32
+  // 16 bit wchar_t - we make an invalid surrogate pair
+  wchar_t cwstr[] = {0xD801, 0xDA00, 0};
+  // this conversion could fail
+  std::string win_str = kwsys::Encoding::ToNarrow(cwstr);
+#endif
+
+  std::string str = kwsys::Encoding::ToNarrow(NULL);
+  if(str != "")
+    {
+    std::cout << "ToNarrow(NULL) returned " << str << std::endl;
+    ret++;
+    }
+
+  str = kwsys::Encoding::ToNarrow(L"");
+  if(wstr != L"")
+    {
+    std::cout << "ToNarrow(\"\") returned " << str << std::endl;
+    ret++;
+    }
+
+  return ret;
+}
+
+
+//----------------------------------------------------------------------------
+int testEncoding(int, char*[])
+{
+  const char* loc = setlocale(LC_ALL, "");
+  if(loc)
+    {
+    std::cout << "Locale: " << loc << std::endl;
+    }
+  else
+    {
+    std::cout << "Locale: None" << std::endl;
+    }
+
+  int ret = 0;
+
+  ret |= testHelloWorldEncoding();
+  ret |= testRobustEncoding();
+
+  return ret;
+}