From 1b50bd3f5c1f608a84df89c2f5e187a53f0be31d Mon Sep 17 00:00:00 2001 From: KWSys Upstream Date: Fri, 2 Dec 2016 09:36:32 -0500 Subject: KWSys 2016-12-02 (4967ccc0) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Code extracted from: http://public.kitware.com/KWSys.git at commit 4967ccc054d268c430e73445f3a103e737c5f5f7 (master). Upstream Shortlog ----------------- Chuck Atkins (2): f1afce25 DynamicLoader: Re-organize preprocessor checks to use if, elif, else d94f92f7 DynamicLoader: Expand noop implementation to more platforms Dāvis Mosāns (2): f069db91 Encoding: Fix conversion of strings that contain null bytes 4967ccc0 ConsoleBuf: Fix output for strings that contain null byte --- CMakeLists.txt | 13 +++- ConsoleBuf.hxx.in | 5 +- DynamicLoader.cxx | 154 +++++++++++++++++++++--------------------------- EncodingCXX.cxx | 60 ++++++++++++++++++- testConsoleBuf.cxx | 33 ++++++++--- testConsoleBuf.hxx | 2 +- testConsoleBufChild.cxx | 3 +- testEncoding.cxx | 31 ++++++++++ 8 files changed, 198 insertions(+), 103 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b8a9a6b..9eb3b2d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -429,6 +429,17 @@ SET_SOURCE_FILES_PROPERTIES(ProcessUNIX.c System.c PROPERTIES COMPILE_FLAGS "-DKWSYS_C_HAS_PTRDIFF_T=${KWSYS_C_HAS_PTRDIFF_T} -DKWSYS_C_HAS_SSIZE_T=${KWSYS_C_HAS_SSIZE_T}" ) +IF(KWSYS_USE_DynamicLoader) + GET_PROPERTY(KWSYS_SUPPORTS_SHARED_LIBS GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS) + IF(KWSYS_SUPPORTS_SHARED_LIBS) + SET(KWSYS_SUPPORTS_SHARED_LIBS 1) + ELSE() + SET(KWSYS_SUPPORTS_SHARED_LIBS 0) + ENDIF() + SET_PROPERTY(SOURCE DynamicLoader.cxx APPEND PROPERTY COMPILE_DEFINITIONS + KWSYS_SUPPORTS_SHARED_LIBS=${KWSYS_SUPPORTS_SHARED_LIBS}) +ENDIF() + IF(KWSYS_USE_SystemTools) KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_SETENV "Checking whether CXX compiler has setenv" DIRECT) @@ -868,7 +879,7 @@ ENDIF() IF(KWSYS_USE_Encoding) # Set default 8 bit encoding in "EndcodingC.c". - SET_PROPERTY(SOURCE EncodingC.c APPEND PROPERTY COMPILE_DEFINITIONS + SET_PROPERTY(SOURCE EncodingC.c EncodingCXX.cxx APPEND PROPERTY COMPILE_DEFINITIONS KWSYS_ENCODING_DEFAULT_CODEPAGE=${KWSYS_ENCODING_DEFAULT_CODEPAGE}) ENDIF() diff --git a/ConsoleBuf.hxx.in b/ConsoleBuf.hxx.in index c45a351..cb58865 100644 --- a/ConsoleBuf.hxx.in +++ b/ConsoleBuf.hxx.in @@ -327,14 +327,13 @@ private: const int length = WideCharToMultiByte(m_activeOutputCodepage, 0, wbuffer.c_str(), (int)wbuffer.size(), NULL, 0, NULL, NULL); - char* buf = new char[length + 1]; + char* buf = new char[length]; const bool success = WideCharToMultiByte(m_activeOutputCodepage, 0, wbuffer.c_str(), (int)wbuffer.size(), buf, length, NULL, NULL) > 0 ? true : false; - buf[length] = '\0'; - buffer = buf; + buffer = std::string(buf, length); delete[] buf; return success; } diff --git a/DynamicLoader.cxx b/DynamicLoader.cxx index e0268c0..e494db6 100644 --- a/DynamicLoader.cxx +++ b/DynamicLoader.cxx @@ -12,20 +12,63 @@ #include "DynamicLoader.hxx.in" #endif -// This file is actually 3 different implementations. -// 1. HP machines which uses shl_load -// 2. Mac OS X 10.2.x and earlier which uses NSLinkModule -// 3. Windows which uses LoadLibrary -// 4. Most unix systems (including Mac OS X 10.3 and later) which use dlopen -// (default) Each part of the ifdef contains a complete implementation for +// This file actually contains several different implementations: +// * NOOP for environments without dynamic libs +// * HP machines which uses shl_load +// * Mac OS X 10.2.x and earlier which uses NSLinkModule +// * Windows which uses LoadLibrary +// * BeOS / Haiku +// * FreeMiNT for Atari +// * Default implementation for *NIX systems (including Mac OS X 10.3 and +// later) which use dlopen +// +// Each part of the ifdef contains a complete implementation for // the static methods of DynamicLoader. -// --------------------------------------------------------------- -// 1. Implementation for HPUX machines -#ifdef __hpux +#if !KWSYS_SUPPORTS_SHARED_LIBS +//---------------------------------------------------------------------------- +// Implementation for environments without dynamic libs +#include // for strerror() + +namespace KWSYS_NAMESPACE { + +//---------------------------------------------------------------------------- +DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary( + const std::string& libname) +{ + return 0; +} + +//---------------------------------------------------------------------------- +int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib) +{ + if (!lib) { + return 0; + } + + return 1; +} + +//---------------------------------------------------------------------------- +DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress( + DynamicLoader::LibraryHandle lib, const std::string& sym) +{ + return 0; +} + +//---------------------------------------------------------------------------- +const char* DynamicLoader::LastError() +{ + return "General error"; +} + +} // namespace KWSYS_NAMESPACE + +#elif defined(__hpux) +//---------------------------------------------------------------------------- +// Implementation for HPUX machines #include #include -#define DYNAMICLOADER_DEFINED 1 namespace KWSYS_NAMESPACE { @@ -88,15 +131,11 @@ const char* DynamicLoader::LastError() } // namespace KWSYS_NAMESPACE -#endif //__hpux - -// --------------------------------------------------------------- -// 2. Implementation for Mac OS X 10.2.x and earlier -#ifdef __APPLE__ -#if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 +#elif defined(__APPLE__) && (MAC_OS_X_VERSION_MAX_ALLOWED < 1030) +//---------------------------------------------------------------------------- +// Implementation for Mac OS X 10.2.x and earlier #include #include // for strlen -#define DYNAMICLOADER_DEFINED 1 namespace KWSYS_NAMESPACE { @@ -160,14 +199,10 @@ const char* DynamicLoader::LastError() } // namespace KWSYS_NAMESPACE -#endif // MAC_OS_X_VERSION_MAX_ALLOWED < 1030 -#endif // __APPLE__ - -// --------------------------------------------------------------- -// 3. Implementation for Windows win32 code but not cygwin -#if defined(_WIN32) && !defined(__CYGWIN__) +#elif defined(_WIN32) && !defined(__CYGWIN__) +//---------------------------------------------------------------------------- +// Implementation for Windows win32 code but not cygwin #include -#define DYNAMICLOADER_DEFINED 1 namespace KWSYS_NAMESPACE { @@ -263,19 +298,14 @@ const char* DynamicLoader::LastError() } // namespace KWSYS_NAMESPACE -#endif //_WIN32 - -// --------------------------------------------------------------- -// 4. Implementation for BeOS -#if defined __BEOS__ - +#elif defined(__BEOS__) +//---------------------------------------------------------------------------- +// Implementation for BeOS / Haiku #include // for strerror() #include #include -#define DYNAMICLOADER_DEFINED 1 - namespace KWSYS_NAMESPACE { static image_id last_dynamic_err = B_OK; @@ -351,54 +381,10 @@ const char* DynamicLoader::LastError() } } // namespace KWSYS_NAMESPACE -#endif - -// --------------------------------------------------------------- -// 5. Implementation for systems without dynamic libs -// __gnu_blrts__ is IBM BlueGene/L -// __LIBCATAMOUNT__ is defined on Catamount on Cray compute nodes -#if defined(__gnu_blrts__) || defined(__LIBCATAMOUNT__) || \ - defined(__CRAYXT_COMPUTE_LINUX_TARGET) -#include // for strerror() -#define DYNAMICLOADER_DEFINED 1 - -namespace KWSYS_NAMESPACE { - -//---------------------------------------------------------------------------- -DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary( - const std::string& libname) -{ - return 0; -} +#elif defined(__MINT__) //---------------------------------------------------------------------------- -int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib) -{ - if (!lib) { - return 0; - } - - return 1; -} - -//---------------------------------------------------------------------------- -DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress( - DynamicLoader::LibraryHandle lib, const std::string& sym) -{ - return 0; -} - -//---------------------------------------------------------------------------- -const char* DynamicLoader::LastError() -{ - return "General error"; -} - -} // namespace KWSYS_NAMESPACE -#endif - -#ifdef __MINT__ -#define DYNAMICLOADER_DEFINED 1 +// Implementation for FreeMiNT on Atari #define _GNU_SOURCE /* for program_invocation_name */ #include #include @@ -447,14 +433,11 @@ const char* DynamicLoader::LastError() } } // namespace KWSYS_NAMESPACE -#endif -// --------------------------------------------------------------- -// 6. Implementation for default UNIX machines. -// if nothing has been defined then use this -#ifndef DYNAMICLOADER_DEFINED -#define DYNAMICLOADER_DEFINED 1 -// Setup for most unix machines +#else +//---------------------------------------------------------------------------- +// Default implementation for *NIX systems (including Mac OS X 10.3 and +// later) which use dlopen #include namespace KWSYS_NAMESPACE { @@ -498,5 +481,4 @@ const char* DynamicLoader::LastError() } } // namespace KWSYS_NAMESPACE - #endif diff --git a/EncodingCXX.cxx b/EncodingCXX.cxx index 5c58bcb..e904c1a 100644 --- a/EncodingCXX.cxx +++ b/EncodingCXX.cxx @@ -125,12 +125,68 @@ char const* const* Encoding::CommandLineArguments::argv() const std::wstring Encoding::ToWide(const std::string& str) { - return ToWide(str.c_str()); + std::wstring wstr; +#if defined(_WIN32) + const int wlength = MultiByteToWideChar( + KWSYS_ENCODING_DEFAULT_CODEPAGE, 0, str.data(), int(str.size()), NULL, 0); + if (wlength > 0) { + wchar_t* wdata = new wchar_t[wlength]; + int r = MultiByteToWideChar(KWSYS_ENCODING_DEFAULT_CODEPAGE, 0, str.data(), + int(str.size()), wdata, wlength); + if (r > 0) { + wstr = std::wstring(wdata, wlength); + } + delete[] wdata; + } +#else + size_t pos = 0; + size_t nullPos = 0; + do { + if (pos < str.size() && str.at(pos) != '\0') { + wstr += ToWide(str.c_str() + pos); + } + nullPos = str.find('\0', pos); + if (nullPos != str.npos) { + pos = nullPos + 1; + wstr += wchar_t('\0'); + } + } while (nullPos != str.npos); +#endif + return wstr; } std::string Encoding::ToNarrow(const std::wstring& str) { - return ToNarrow(str.c_str()); + std::string nstr; +#if defined(_WIN32) + int length = + WideCharToMultiByte(KWSYS_ENCODING_DEFAULT_CODEPAGE, 0, str.c_str(), + int(str.size()), NULL, 0, NULL, NULL); + if (length > 0) { + char* data = new char[length]; + int r = + WideCharToMultiByte(KWSYS_ENCODING_DEFAULT_CODEPAGE, 0, str.c_str(), + int(str.size()), data, length, NULL, NULL); + if (r > 0) { + nstr = std::string(data, length); + } + delete[] data; + } +#else + size_t pos = 0; + size_t nullPos = 0; + do { + if (pos < str.size() && str.at(pos) != '\0') { + nstr += ToNarrow(str.c_str() + pos); + } + nullPos = str.find(wchar_t('\0'), pos); + if (nullPos != str.npos) { + pos = nullPos + 1; + nstr += '\0'; + } + } while (nullPos != str.npos); +#endif + return nstr; } std::wstring Encoding::ToWide(const char* cstr) diff --git a/testConsoleBuf.cxx b/testConsoleBuf.cxx index bd58fb6..3b8cdab 100644 --- a/testConsoleBuf.cxx +++ b/testConsoleBuf.cxx @@ -18,6 +18,7 @@ #if defined(_WIN32) +#include #include #include #include @@ -318,6 +319,7 @@ static int testPipe() bytesRead == 0) { throw std::runtime_error("ReadFile#1 failed!"); } + buffer[bytesRead] = 0; if ((bytesRead < encodedTestString.size() + 1 + encodedInputTestString.size() && !ReadFile(outPipeRead, buffer + bytesRead, @@ -336,8 +338,12 @@ static int testPipe() bytesRead == 0) { throw std::runtime_error("ReadFile#3 failed!"); } - buffer2[bytesRead - 1] = 0; - didFail = encodedTestString.compare(buffer2) == 0 ? 0 : 1; + buffer2[bytesRead] = 0; + didFail = + encodedTestString.compare(0, encodedTestString.npos, buffer2, + encodedTestString.size()) == 0 + ? 0 + : 1; } if (didFail != 0) { std::cerr << "Pipe's output didn't match expected output!" @@ -423,23 +429,28 @@ static int testFile() bytesRead == 0) { throw std::runtime_error("ReadFile#1 failed!"); } - buffer[bytesRead - 1] = 0; + buffer[bytesRead] = 0; if (memcmp(buffer, encodedTestString.c_str(), encodedTestString.size()) == 0 && memcmp(buffer + encodedTestString.size() + 1, encodedInputTestString.c_str(), - encodedInputTestString.size() - 1) == 0) { + encodedInputTestString.size()) == 0) { bytesRead = 0; if (SetFilePointer(errFile, 0, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER) { throw std::runtime_error("SetFilePointer#2 failed!"); } + if (!ReadFile(errFile, buffer2, sizeof(buffer2), &bytesRead, NULL) || bytesRead == 0) { throw std::runtime_error("ReadFile#2 failed!"); } - buffer2[bytesRead - 1] = 0; - didFail = encodedTestString.compare(buffer2) == 0 ? 0 : 1; + buffer2[bytesRead] = 0; + didFail = + encodedTestString.compare(0, encodedTestString.npos, buffer2, + encodedTestString.size()) == 0 + ? 0 + : 1; } if (didFail != 0) { std::cerr << "File's output didn't match expected output!" @@ -448,7 +459,7 @@ static int testFile() encodedTestString.size()); dumpBuffers(encodedInputTestString.c_str(), buffer + encodedTestString.size() + 1, - encodedInputTestString.size() - 1); + encodedInputTestString.size()); dumpBuffers(encodedTestString.c_str(), buffer2, encodedTestString.size()); } @@ -685,6 +696,7 @@ static int testConsole() throw std::runtime_error("ReadConsoleOutputCharacter failed!"); } std::wstring wideTestString = kwsys::Encoding::ToWide(encodedTestString); + std::replace(wideTestString.begin(), wideTestString.end(), '\0', ' '); std::wstring wideInputTestString = kwsys::Encoding::ToWide(encodedInputTestString); if (memcmp(outputBuffer, wideTestString.c_str(), @@ -757,8 +769,11 @@ int testConsoleBuf(int, char* []) return 1; } - encodedTestString = kwsys::Encoding::ToNarrow(UnicodeTestString); - encodedInputTestString = kwsys::Encoding::ToNarrow(UnicodeInputTestString); + encodedTestString = kwsys::Encoding::ToNarrow(std::wstring( + UnicodeTestString, sizeof(UnicodeTestString) / sizeof(wchar_t) - 1)); + encodedInputTestString = kwsys::Encoding::ToNarrow( + std::wstring(UnicodeInputTestString, + sizeof(UnicodeInputTestString) / sizeof(wchar_t) - 1)); encodedInputTestString += "\n"; ret |= testPipe(); diff --git a/testConsoleBuf.hxx b/testConsoleBuf.hxx index 8891960..e93cb4f 100644 --- a/testConsoleBuf.hxx +++ b/testConsoleBuf.hxx @@ -11,7 +11,7 @@ static const wchar_t AfterOutputEventName[] = L"AfterOutputEvent"; // यूनिकोड είναι здорово! static const wchar_t UnicodeTestString[] = L"\u092F\u0942\u0928\u093F\u0915\u094B\u0921 " - L"\u03B5\u03AF\u03BD\u03B1\u03B9 " + L"\u03B5\u03AF\u03BD\0\u03B1\u03B9 " L"\u0437\u0434\u043E\u0440\u043E\u0432\u043E!"; #endif diff --git a/testConsoleBufChild.cxx b/testConsoleBufChild.cxx index 313323e..83bf545 100644 --- a/testConsoleBufChild.cxx +++ b/testConsoleBufChild.cxx @@ -28,7 +28,8 @@ int main(int argc, const char* argv[]) std::cout << argv[1] << std::endl; std::cerr << argv[1] << std::endl; } else { - std::string str = kwsys::Encoding::ToNarrow(UnicodeTestString); + std::string str = kwsys::Encoding::ToNarrow(std::wstring( + UnicodeTestString, sizeof(UnicodeTestString) / sizeof(wchar_t) - 1)); std::cout << str << std::endl; std::cerr << str << std::endl; } diff --git a/testEncoding.cxx b/testEncoding.cxx index 996976f..03f2ec9 100644 --- a/testEncoding.cxx +++ b/testEncoding.cxx @@ -9,6 +9,7 @@ #include KWSYS_HEADER(Encoding.hxx) #include KWSYS_HEADER(Encoding.h) +#include #include #include #include @@ -124,6 +125,35 @@ static int testRobustEncoding() return ret; } +static int testWithNulls() +{ + int ret = 0; + std::vector strings; + strings.push_back(std::string("ab") + '\0' + 'c'); + strings.push_back(std::string("d") + '\0' + '\0' + 'e'); + strings.push_back(std::string() + '\0' + 'f'); + strings.push_back(std::string() + '\0' + '\0' + "gh"); + strings.push_back(std::string("ij") + '\0'); + strings.push_back(std::string("k") + '\0' + '\0'); + strings.push_back(std::string("\0\0\0\0", 4) + "lmn" + + std::string("\0\0\0\0", 4)); + for (std::vector::iterator it = strings.begin(); + it != strings.end(); ++it) { + std::wstring wstr = kwsys::Encoding::ToWide(*it); + std::string str = kwsys::Encoding::ToNarrow(wstr); + std::string s(*it); + std::replace(s.begin(), s.end(), '\0', ' '); + std::cout << "'" << s << "' (" << it->size() << ")" << std::endl; + if (str != *it) { + std::replace(str.begin(), str.end(), '\0', ' '); + std::cout << "string with null was different: '" << str << "' (" + << str.size() << ")" << std::endl; + ret++; + } + } + return ret; +} + static int testCommandLineArguments() { int status = 0; @@ -165,6 +195,7 @@ int testEncoding(int, char* []) ret |= testHelloWorldEncoding(); ret |= testRobustEncoding(); ret |= testCommandLineArguments(); + ret |= testWithNulls(); return ret; } -- cgit v0.12