On Windows getenv (and putenv) uses ANSI codepage so it needs to be encoded to internally used encoding (eg. UTF-8). Here we use _wgetenv (and _wputenv) instead and encode that.
Also add SystemTools::HasEnv function. --- Source/kwsys/SystemTools.cxx | 80 +++++++++++++++++++++++++++++++++++------ Source/kwsys/SystemTools.hxx.in | 4 +++ 2 files changed, 74 insertions(+), 10 deletions(-) diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx index c6e668d..5bcf0d0 100644 --- a/Source/kwsys/SystemTools.cxx +++ b/Source/kwsys/SystemTools.cxx @@ -406,6 +406,9 @@ struct SystemToolsPathCaseCmp class SystemToolsPathCaseMap: public std::map<std::string, std::string, SystemToolsPathCaseCmp> {}; + +class SystemToolsEnvMap : + public std::map<std::string,std::string> {}; #endif // adds the elements of the env variable path to the arg passed in @@ -458,7 +461,23 @@ void SystemTools::GetPath(std::vector<std::string>& path, const char* env) const char* SystemTools::GetEnv(const char* key) { - return getenv(key); + const char *v = 0; +#if defined(_WIN32) + std::string env; + if (SystemTools::GetEnv(key, env)) { + const std::string skey = key; + SystemToolsEnvMap::iterator i = EnvMap->find(skey); + if (i != EnvMap->end()) { + i->second = env; + } else { + i = EnvMap->insert(SystemToolsEnvMap::value_type(skey, env)).first; + } + v = i->second.c_str(); + } +#else + v = getenv(key); +#endif + return v; } const char* SystemTools::GetEnv(const std::string& key) @@ -468,16 +487,21 @@ const char* SystemTools::GetEnv(const std::string& key) bool SystemTools::GetEnv(const char* key, std::string& result) { +#if defined(_WIN32) + const std::wstring wkey = Encoding::ToWide(key); + const wchar_t* wv = _wgetenv(wkey.c_str()); + if (wv) { + result = Encoding::ToNarrow(wv); + return true; + } +#else const char* v = getenv(key); - if(v) - { + if (v) { result = v; return true; - } - else - { - return false; - } + } +#endif + return false; } bool SystemTools::GetEnv(const std::string& key, std::string& result) @@ -485,6 +509,22 @@ bool SystemTools::GetEnv(const std::string& key, std::string& result) return SystemTools::GetEnv(key.c_str(), result); } +bool SystemTools::HasEnv(const char* key) +{ +#if defined(_WIN32) + const std::wstring wkey = Encoding::ToWide(key); + const wchar_t* v = _wgetenv(wkey.c_str()); +#else + const char* v = getenv(key); +#endif + return v != 0; +} + +bool SystemTools::HasEnv(const std::string& key) +{ + return SystemTools::HasEnv(key.c_str()); +} + //---------------------------------------------------------------------------- #if defined(__CYGWIN__) || defined(__GLIBC__) @@ -533,13 +573,25 @@ static int kwsysUnPutEnv(const std::string& env) # ifdef KWSYS_PUTENV_EMPTY buf[len] = '='; buf[len+1] = 0; - if(putenv(buf) < 0) +#if defined(_WIN32) + const std::wstring wbuf = Encoding::ToWide(buf); + const int r = _wputenv(wbuf.c_str()); +#else + const int r = putenv(buf); +#endif + if(r < 0) { err = errno; } # else buf[len] = 0; - if(putenv(buf) < 0 && errno != EINVAL) +#if defined(_WIN32) + const std::wstring wbuf = Encoding::ToWide(buf); + const int r = _wputenv(wbuf.c_str()); +#else + const int r = putenv(buf); +#endif + if(r < 0 && errno != EINVAL) { err = errno; } @@ -679,7 +731,12 @@ public: static_cast<void>(oldEnv); char* newEnv = strdup(env); this->insert(newEnv); +#if defined(_WIN32) + const std::wstring wEnv = Encoding::ToWide(newEnv); + return _wputenv(wEnv.c_str()) == 0; +#else return putenv(newEnv) == 0; +#endif } bool UnPut(const char* env) { @@ -5371,6 +5428,7 @@ static unsigned int SystemToolsManagerCount; SystemToolsTranslationMap *SystemTools::TranslationMap; #ifdef _WIN32 SystemToolsPathCaseMap *SystemTools::PathCaseMap; +SystemToolsEnvMap *SystemTools::EnvMap; #endif #ifdef __CYGWIN__ SystemToolsTranslationMap *SystemTools::Cyg2Win32Map; @@ -5421,6 +5479,7 @@ void SystemTools::ClassInitialize() SystemTools::TranslationMap = new SystemToolsTranslationMap; #ifdef _WIN32 SystemTools::PathCaseMap = new SystemToolsPathCaseMap; + SystemTools::EnvMap = new SystemToolsEnvMap; #endif #ifdef __CYGWIN__ SystemTools::Cyg2Win32Map = new SystemToolsTranslationMap; @@ -5480,6 +5539,7 @@ void SystemTools::ClassFinalize() delete SystemTools::TranslationMap; #ifdef _WIN32 delete SystemTools::PathCaseMap; + delete SystemTools::EnvMap; #endif #ifdef __CYGWIN__ delete SystemTools::Cyg2Win32Map; diff --git a/Source/kwsys/SystemTools.hxx.in b/Source/kwsys/SystemTools.hxx.in index bba5a5c..8f01e75 100644 --- a/Source/kwsys/SystemTools.hxx.in +++ b/Source/kwsys/SystemTools.hxx.in @@ -53,6 +53,7 @@ namespace @KWSYS_NAMESPACE@ class SystemToolsTranslationMap; class SystemToolsPathCaseMap; +class SystemToolsEnvMap; /** \class SystemToolsManager * \brief Use to make sure SystemTools is initialized before it is used @@ -843,6 +844,8 @@ public: static const char* GetEnv(const std::string& key); static bool GetEnv(const char* key, std::string& result); static bool GetEnv(const std::string& key, std::string& result); + static bool HasEnv(const char* key); + static bool HasEnv(const std::string& key); /** Put a string into the environment of the form var=value */ @@ -989,6 +992,7 @@ private: static SystemToolsTranslationMap *TranslationMap; #ifdef _WIN32 static SystemToolsPathCaseMap *PathCaseMap; + static SystemToolsEnvMap *EnvMap; #endif #ifdef __CYGWIN__ static SystemToolsTranslationMap *Cyg2Win32Map; -- 2.9.0 -- Powered by www.kitware.com Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Kitware offers various services to support the CMake community. For more information on each offering, please visit: CMake Support: http://cmake.org/cmake/help/support.html CMake Consulting: http://cmake.org/cmake/help/consulting.html CMake Training Courses: http://cmake.org/cmake/help/training.html Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Follow this link to subscribe/unsubscribe: http://public.kitware.com/mailman/listinfo/cmake-developers