[cmake-developers] [PATCH v3 1/7] On Windows use correct encoding for SystemTools::GetEnv

Dāvis Mosāns davispuh at gmail.com
Wed Jul 6 15:12:07 EDT 2016


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    | 56 ++++++++++++++++++++++++++++++++++-------
 Source/kwsys/SystemTools.hxx.in |  2 ++
 2 files changed, 49 insertions(+), 9 deletions(-)

diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx
index c6e668d..2b1db4d 100644
--- a/Source/kwsys/SystemTools.cxx
+++ b/Source/kwsys/SystemTools.cxx
@@ -468,16 +468,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 +490,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 +554,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 +712,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)
     {
diff --git a/Source/kwsys/SystemTools.hxx.in b/Source/kwsys/SystemTools.hxx.in
index bba5a5c..c9b18b7 100644
--- a/Source/kwsys/SystemTools.hxx.in
+++ b/Source/kwsys/SystemTools.hxx.in
@@ -843,6 +843,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 */
-- 
2.9.0



More information about the cmake-developers mailing list