From 5b2d5709f381c3207391dff14de33add3a25d8a6 Mon Sep 17 00:00:00 2001 From: Marian Klymov <nekto1989@gmail.com> Date: Sat, 21 Dec 2019 12:06:38 +0200 Subject: [PATCH] String: Add wrapper around strdup. strdup isn't part of the ISO C standard and may be not available without compiler extensions --- CMakeLists.txt | 10 +++++++++- EncodingCXX.cxx | 10 +++++++--- ProcessUNIX.c | 10 ++++++---- ProcessWin32.c | 6 ++++-- String.c | 20 +++++++++++++++++++- String.h.in | 9 +++++++++ SystemTools.cxx | 7 ++++--- testProcess.c | 4 +++- testSystemTools.cxx | 4 +++- 9 files changed, 64 insertions(+), 16 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 09bcdb9..61a7d9f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -158,6 +158,7 @@ IF(KWSYS_USE_SystemTools) SET(KWSYS_USE_Directory 1) SET(KWSYS_USE_FStream 1) SET(KWSYS_USE_Encoding 1) + SET(KWSYS_USE_String 1) ENDIF() IF(KWSYS_USE_Glob) SET(KWSYS_USE_Directory 1) @@ -167,6 +168,7 @@ IF(KWSYS_USE_Glob) SET(KWSYS_USE_Encoding 1) ENDIF() IF(KWSYS_USE_Process) + SET(KWSYS_USE_String 1) SET(KWSYS_USE_System 1) SET(KWSYS_USE_Encoding 1) ENDIF() @@ -188,6 +190,9 @@ ENDIF() IF(KWSYS_USE_ConsoleBuf) SET(KWSYS_USE_Encoding 1) ENDIF() +IF(KWSYS_USE_Encoding) + SET(KWSYS_USE_String 1) +ENDIF() # Specify default 8 bit encoding for Windows IF(NOT KWSYS_ENCODING_DEFAULT_CODEPAGE) @@ -210,6 +215,7 @@ ENDIF() # Include helper macros. INCLUDE(${CMAKE_CURRENT_SOURCE_DIR}/kwsysPlatformTests.cmake) +INCLUDE(CheckSymbolExists) INCLUDE(CheckTypeSize) # Do full dependency headers. @@ -1028,9 +1034,11 @@ IF(WIN32) ENDIF() IF(KWSYS_USE_String) + CHECK_SYMBOL_EXISTS(strdup "string.h" KWSYS_C_HAS_STRDUP) + CHECK_SYMBOL_EXISTS(_strdup "string.h" KWSYS_C_HAS__STRDUP) # Activate code in "String.c". See the comment in the source. SET_SOURCE_FILES_PROPERTIES(String.c PROPERTIES - COMPILE_FLAGS "-DKWSYS_STRING_C") + COMPILE_FLAGS "-DKWSYS_STRING_C -DKWSYS_C_HAS_STRDUP=${KWSYS_C_HAS_STRDUP} -DKWSYS_C_HAS__STRDUP=${KWSYS_C_HAS__STRDUP}") ENDIF() IF(KWSYS_USE_Encoding) diff --git a/EncodingCXX.cxx b/EncodingCXX.cxx index 5cad934..0229a75 100644 --- a/EncodingCXX.cxx +++ b/EncodingCXX.cxx @@ -9,12 +9,14 @@ #include "kwsysPrivate.h" #include KWSYS_HEADER(Encoding.hxx) #include KWSYS_HEADER(Encoding.h) +#include KWSYS_HEADER(String.h) // Work-around CMake dependency scanning limitation. This must // duplicate the above list of headers. #if 0 # include "Encoding.h.in" # include "Encoding.hxx.in" +# include "String.h.in" #endif #include <stdlib.h> @@ -63,7 +65,7 @@ Encoding::CommandLineArguments::CommandLineArguments(int ac, { this->argv_.resize(ac + 1); for (int i = 0; i < ac; i++) { - this->argv_[i] = strdup(av[i]); + this->argv_[i] = kwsysString_strdup(av[i]); } this->argv_[ac] = nullptr; } @@ -90,7 +92,8 @@ Encoding::CommandLineArguments::CommandLineArguments( { this->argv_.resize(other.argv_.size()); for (size_t i = 0; i < this->argv_.size(); i++) { - this->argv_[i] = other.argv_[i] ? strdup(other.argv_[i]) : nullptr; + this->argv_[i] = + other.argv_[i] ? kwsysString_strdup(other.argv_[i]) : KWSYS_NULLPTR; } } @@ -105,7 +108,8 @@ Encoding::CommandLineArguments& Encoding::CommandLineArguments::operator=( this->argv_.resize(other.argv_.size()); for (i = 0; i < this->argv_.size(); i++) { - this->argv_[i] = other.argv_[i] ? strdup(other.argv_[i]) : nullptr; + this->argv_[i] = + other.argv_[i] ? kwsysString_strdup(other.argv_[i]) : KWSYS_NULLPTR; } } diff --git a/ProcessUNIX.c b/ProcessUNIX.c index f65690b..ebe5561 100644 --- a/ProcessUNIX.c +++ b/ProcessUNIX.c @@ -2,12 +2,14 @@ file Copyright.txt or https://cmake.org/licensing#kwsys for details. */ #include "kwsysPrivate.h" #include KWSYS_HEADER(Process.h) +#include KWSYS_HEADER(String.h) #include KWSYS_HEADER(System.h) /* Work-around CMake dependency scanning limitation. This must duplicate the above list of headers. */ #if 0 # include "Process.h.in" +# include "String.h.in" # include "System.h.in" #endif @@ -52,7 +54,7 @@ do. #include <stddef.h> /* ptrdiff_t */ #include <stdio.h> /* snprintf */ #include <stdlib.h> /* malloc, free */ -#include <string.h> /* strdup, strerror, memset */ +#include <string.h> /* strerror, memset */ #include <sys/stat.h> /* open mode */ #include <sys/time.h> /* struct timeval */ #include <sys/types.h> /* pid_t, fd_set */ @@ -443,7 +445,7 @@ int kwsysProcess_AddCommand(kwsysProcess* cp, char const* const* command) } for (i = 0; i < n; ++i) { assert(command[i]); /* Quiet Clang scan-build. */ - newCommands[cp->NumberOfCommands][i] = strdup(command[i]); + newCommands[cp->NumberOfCommands][i] = kwsysString_strdup(command[i]); if (!newCommands[cp->NumberOfCommands][i]) { break; } @@ -496,7 +498,7 @@ int kwsysProcess_SetWorkingDirectory(kwsysProcess* cp, const char* dir) cp->WorkingDirectory = 0; } if (dir) { - cp->WorkingDirectory = strdup(dir); + cp->WorkingDirectory = kwsysString_strdup(dir); if (!cp->WorkingDirectory) { return 0; } @@ -528,7 +530,7 @@ int kwsysProcess_SetPipeFile(kwsysProcess* cp, int prPipe, const char* file) *pfile = 0; } if (file) { - *pfile = strdup(file); + *pfile = kwsysString_strdup(file); if (!*pfile) { return 0; } diff --git a/ProcessWin32.c b/ProcessWin32.c index 68c5218..20cc3e2 100644 --- a/ProcessWin32.c +++ b/ProcessWin32.c @@ -3,12 +3,14 @@ #include "kwsysPrivate.h" #include KWSYS_HEADER(Process.h) #include KWSYS_HEADER(Encoding.h) +#include KWSYS_HEADER(String.h) /* Work-around CMake dependency scanning limitation. This must duplicate the above list of headers. */ #if 0 # include "Encoding.h.in" # include "Process.h.in" +# include "String.h.in" #endif /* @@ -30,7 +32,7 @@ a UNIX-style select system call. #endif #include <io.h> /* _unlink */ #include <stdio.h> /* sprintf */ -#include <string.h> /* strlen, strdup */ +#include <string.h> /* strlen */ #ifdef __WATCOMC__ # define _unlink unlink #endif @@ -717,7 +719,7 @@ int kwsysProcess_SetPipeFile(kwsysProcess* cp, int pipe, const char* file) *pfile = 0; } if (file) { - *pfile = strdup(file); + *pfile = kwsysString_strdup(file); if (!*pfile) { return 0; } diff --git a/String.c b/String.c index daf7ad1..9165390 100644 --- a/String.c +++ b/String.c @@ -17,10 +17,11 @@ condition blocks the compiler from seeing the symbols defined here. # include "String.h.in" # endif +# include <string.h> /* memcpy, _strdup, strdup, strlen */ + /* Select an implementation for strcasecmp. */ # if defined(_MSC_VER) # define KWSYS_STRING_USE_STRICMP -# include <string.h> # elif defined(__GNUC__) # define KWSYS_STRING_USE_STRCASECMP # include <strings.h> @@ -97,4 +98,21 @@ int kwsysString_strncasecmp(const char* lhs, const char* rhs, size_t n) # endif } +/*--------------------------------------------------------------------------*/ +char* kwsysString_strdup(const char* str1) +{ +# if defined(KWSYS_C_HAS__STRDUP) + return _strdup(str1); +# elif defined(KWSYS_C_HAS_STRDUP) + return strdup(str1); +# else + size_t size = strlen(s) + 1; + char* p = malloc(size); + if (p) { + memcpy(p, s, size); + } + return p; +# endif +} + #endif /* KWSYS_STRING_C */ diff --git a/String.h.in b/String.h.in index 7c9348a..dd6ab30 100644 --- a/String.h.in +++ b/String.h.in @@ -18,6 +18,7 @@ #if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS # define kwsysString_strcasecmp kwsys_ns(String_strcasecmp) # define kwsysString_strncasecmp kwsys_ns(String_strncasecmp) +# define kwsysString_strdup kwsys_ns(String_strdup) #endif #if defined(__cplusplus) @@ -39,6 +40,13 @@ kwsysEXPORT int kwsysString_strcasecmp(const char* lhs, const char* rhs); kwsysEXPORT int kwsysString_strncasecmp(const char* lhs, const char* rhs, size_t n); +/** + * Returns a pointer to a null-terminated byte string, which is a duplicate + * of the string pointed to by str1. The returned pointer must be passed to + * free to avoid a memory leak. + */ +kwsysEXPORT char* kwsysString_strdup(const char* str1); + #if defined(__cplusplus) } /* extern "C" */ #endif @@ -51,6 +59,7 @@ kwsysEXPORT int kwsysString_strncasecmp(const char* lhs, const char* rhs, # if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS # undef kwsysString_strcasecmp # undef kwsysString_strncasecmp +# undef kwsysString_strdup # endif #endif diff --git a/SystemTools.cxx b/SystemTools.cxx index 39873e6..1bdc055 100644 --- a/SystemTools.cxx +++ b/SystemTools.cxx @@ -23,6 +23,7 @@ #include KWSYS_HEADER(FStream.hxx) #include KWSYS_HEADER(Encoding.h) #include KWSYS_HEADER(Encoding.hxx) +#include KWSYS_HEADER(String.h) #include <fstream> #include <iostream> @@ -38,6 +39,7 @@ # include "Encoding.hxx.in" # include "FStream.hxx.in" # include "RegularExpression.hxx.in" +# include "String.h.in" # include "SystemTools.hxx.in" #endif @@ -343,7 +345,6 @@ extern FILE* popen(__const char* __command, __const char* __modes) __THROW; extern int pclose(FILE* __stream) __THROW; extern char* realpath(__const char* __restrict __name, char* __restrict __resolved) __THROW; -extern char* strdup(__const char* __s) __THROW; extern int putenv(char* __string) __THROW; } #endif @@ -836,7 +837,7 @@ public: const std::wstring wEnv = Encoding::ToWide(env); wchar_t* newEnv = _wcsdup(wEnv.c_str()); # else - char* newEnv = strdup(env); + char* newEnv = kwsysString_strdup(env); # endif Free oldEnv(this->Release(newEnv)); this->insert(newEnv); @@ -981,7 +982,7 @@ void SystemToolsStatic::ReplaceString(std::string& source, const char* replace, } // perform replacements until done - char* orig = strdup(src); + char* orig = kwsysString_strdup(src); char* currentPos = orig; searchPos = searchPos - src + orig; diff --git a/testProcess.c b/testProcess.c index 39aaa23..ce1c744 100644 --- a/testProcess.c +++ b/testProcess.c @@ -3,12 +3,14 @@ #include "kwsysPrivate.h" #include KWSYS_HEADER(Process.h) #include KWSYS_HEADER(Encoding.h) +#include KWSYS_HEADER(String.h) /* Work-around CMake dependency scanning limitation. This must duplicate the above list of headers. */ #if 0 # include "Encoding.h.in" # include "Process.h.in" +# include "String.h.in" #endif #include <assert.h> @@ -675,7 +677,7 @@ int main(int argc, const char* argv[]) } } #ifdef _WIN32 - if (n == 0 && (argv0 = strdup(argv[0]))) { + if (n == 0 && (argv0 = kwsysString_strdup(argv[0]))) { /* Try converting to forward slashes to see if it works. */ char* c; for (c = argv0; *c; ++c) { diff --git a/testSystemTools.cxx b/testSystemTools.cxx index 1f3a15b..b8b3665 100644 --- a/testSystemTools.cxx +++ b/testSystemTools.cxx @@ -7,12 +7,14 @@ #endif #include KWSYS_HEADER(FStream.hxx) +#include KWSYS_HEADER(String.h) #include KWSYS_HEADER(SystemTools.hxx) // Work-around CMake dependency scanning limitation. This must // duplicate the above list of headers. #if 0 # include "FStream.hxx.in" +# include "String.h.in" # include "SystemTools.hxx.in" #endif @@ -537,7 +539,7 @@ static bool CheckStringOperations() } delete[] cres; - char* cres2 = strdup("Mary Had A Little Lamb."); + char* cres2 = kwsysString_strdup("Mary Had A Little Lamb."); kwsys::SystemTools::ReplaceChars(cres2, "aeiou", 'X'); if (strcmp(cres2, "MXry HXd A LXttlX LXmb.")) { std::cerr << "Problem with ReplaceChars " -- GitLab