Pārlūkot izejas kodu

Merge branch 'upstream-KWSys' into update-kwsys

* upstream-KWSys:
  KWSys 2016-07-15 (f396bf43)
Brad King 9 gadi atpakaļ
vecāks
revīzija
03407040d4
2 mainītis faili ar 166 papildinājumiem un 71 dzēšanām
  1. 162 71
      Source/kwsys/SystemTools.cxx
  2. 4 0
      Source/kwsys/SystemTools.hxx.in

+ 162 - 71
Source/kwsys/SystemTools.cxx

@@ -388,6 +388,72 @@ class SystemToolsTranslationMap :
 {
 };
 
+/* Type of character storing the environment.  */
+#if defined(_WIN32)
+typedef wchar_t envchar;
+#else
+typedef char envchar;
+#endif
+
+/* Order by environment key only (VAR from VAR=VALUE).  */
+struct kwsysEnvCompare
+{
+  bool operator() (const envchar* l, const envchar* r) const
+    {
+#if defined(_WIN32)
+    const wchar_t* leq = wcschr(l, L'=');
+    const wchar_t* req = wcschr(r, L'=');
+    size_t llen = leq? (leq-l) : wcslen(l);
+    size_t rlen = req? (req-r) : wcslen(r);
+    if(llen == rlen)
+      {
+      return wcsncmp(l,r,llen) < 0;
+      }
+    else
+      {
+      return wcscmp(l,r) < 0;
+      }
+#else
+    const char* leq = strchr(l, '=');
+    const char* req = strchr(r, '=');
+    size_t llen = leq? (leq-l) : strlen(l);
+    size_t rlen = req? (req-r) : strlen(r);
+    if(llen == rlen)
+      {
+      return strncmp(l,r,llen) < 0;
+      }
+    else
+      {
+      return strcmp(l,r) < 0;
+      }
+#endif
+    }
+};
+
+class kwsysEnvSet: public std::set<const envchar*, kwsysEnvCompare>
+{
+public:
+  class Free
+  {
+    const envchar* Env;
+  public:
+    Free(const envchar* env): Env(env) {}
+    ~Free() { free(const_cast<envchar*>(this->Env)); }
+  };
+
+  const envchar* Release(const envchar* env)
+    {
+    const envchar* old = 0;
+    iterator i = this->find(env);
+    if(i != this->end())
+      {
+      old = *i;
+      this->erase(i);
+      }
+    return old;
+    }
+};
+
 #ifdef _WIN32
 struct SystemToolsPathCaseCmp
 {
@@ -406,6 +472,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 +527,19 @@ 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))
+    {
+    std::string& menv = (*SystemTools::EnvMap)[key];
+    menv = env;
+    v = menv.c_str();
+    }
+#else
+  v = getenv(key);
+#endif
+  return v;
 }
 
 const char* SystemTools::GetEnv(const std::string& key)
@@ -468,16 +549,23 @@ 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)
     {
     result = v;
     return true;
     }
-  else
-    {
-    return false;
-    }
+#endif
+  return false;
 }
 
 bool SystemTools::GetEnv(const std::string& key, std::string& result)
@@ -485,13 +573,23 @@ bool SystemTools::GetEnv(const std::string& key, std::string& result)
   return SystemTools::GetEnv(key.c_str(), result);
 }
 
-//----------------------------------------------------------------------------
-
-#if defined(__CYGWIN__) || defined(__GLIBC__)
-# define KWSYS_PUTENV_NAME  /* putenv("A")  removes A.  */
-#elif defined(_WIN32)
-# define KWSYS_PUTENV_EMPTY /* putenv("A=") removes A. */
+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 KWSYS_CXX_HAS_UNSETENV
 /* unsetenv("A") removes A from the environment.
@@ -511,18 +609,15 @@ static int kwsysUnPutEnv(const std::string& env)
   return 0;
 }
 
-#elif defined(KWSYS_PUTENV_EMPTY) || defined(KWSYS_PUTENV_NAME)
-/* putenv("A=") or putenv("A") removes A from the environment.  */
+#elif defined(__CYGWIN__) || defined(__GLIBC__)
+/* putenv("A") removes A from the environment.  It must not put the
+   memory in the environment because it does not have any "=" syntax.  */
 static int kwsysUnPutEnv(const std::string& env)
 {
   int err = 0;
   size_t pos = env.find('=');
   size_t const len = pos == env.npos ? env.size() : pos;
-# ifdef KWSYS_PUTENV_EMPTY
-  size_t const sz = len + 2;
-# else
   size_t const sz = len + 1;
-# endif
   char local_buf[256];
   char* buf = sz > sizeof(local_buf) ? (char*)malloc(sz) : local_buf;
   if(!buf)
@@ -530,20 +625,11 @@ static int kwsysUnPutEnv(const std::string& env)
     return -1;
     }
   strncpy(buf, env.c_str(), len);
-# ifdef KWSYS_PUTENV_EMPTY
-  buf[len] = '=';
-  buf[len+1] = 0;
-  if(putenv(buf) < 0)
-    {
-    err = errno;
-    }
-# else
   buf[len] = 0;
   if(putenv(buf) < 0 && errno != EINVAL)
     {
     err = errno;
     }
-# endif
   if(buf != local_buf)
     {
     free(buf);
@@ -556,6 +642,30 @@ static int kwsysUnPutEnv(const std::string& env)
   return 0;
 }
 
+#elif defined(_WIN32)
+/* putenv("A=") places "A=" in the environment, which is as close to
+   removal as we can get with the putenv API.  We have to leak the
+   most recent value placed in the environment for each variable name
+   on program exit in case exit routines access it.  */
+
+static kwsysEnvSet kwsysUnPutEnvSet;
+
+static int kwsysUnPutEnv(std::string const& env)
+{
+  std::wstring wEnv = Encoding::ToWide(env);
+  size_t const pos = wEnv.find('=');
+  size_t const len = pos == wEnv.npos ? wEnv.size() : pos;
+  wEnv.resize(len+1, L'=');
+  wchar_t* newEnv = _wcsdup(wEnv.c_str());
+  if(!newEnv)
+    {
+    return -1;
+    }
+  kwsysEnvSet::Free oldEnv(kwsysUnPutEnvSet.Release(newEnv));
+  kwsysUnPutEnvSet.insert(newEnv);
+  return _wputenv(newEnv);
+}
+
 #else
 /* Manipulate the "environ" global directly.  */
 static int kwsysUnPutEnv(const std::string& env)
@@ -623,68 +733,46 @@ bool SystemTools::UnPutEnv(const std::string& env)
 #  pragma warning disable 444 /* base has non-virtual destructor */
 # endif
 
-/* Order by environment key only (VAR from VAR=VALUE).  */
-struct kwsysEnvCompare
+class kwsysEnv: public kwsysEnvSet
 {
-  bool operator() (const char* l, const char* r) const
-    {
-    const char* leq = strchr(l, '=');
-    const char* req = strchr(r, '=');
-    size_t llen = leq? (leq-l) : strlen(l);
-    size_t rlen = req? (req-r) : strlen(r);
-    if(llen == rlen)
-      {
-      return strncmp(l,r,llen) < 0;
-      }
-    else
-      {
-      return strcmp(l,r) < 0;
-      }
-    }
-};
-
-class kwsysEnv: public std::set<const char*, kwsysEnvCompare>
-{
-  class Free
-  {
-    const char* Env;
-  public:
-    Free(const char* env): Env(env) {}
-    ~Free() { free(const_cast<char*>(this->Env)); }
-  };
 public:
-  typedef std::set<const char*, kwsysEnvCompare> derived;
   ~kwsysEnv()
     {
-    for(derived::iterator i = this->begin(); i != this->end(); ++i)
+    for(iterator i = this->begin(); i != this->end(); ++i)
       {
+#if defined(_WIN32)
+      const std::string s = Encoding::ToNarrow(*i);
+      kwsysUnPutEnv(s.c_str());
+#else
       kwsysUnPutEnv(*i);
-      free(const_cast<char*>(*i));
-      }
-    }
-  const char* Release(const char* env)
-    {
-    const char* old = 0;
-    derived::iterator i = this->find(env);
-    if(i != this->end())
-      {
-      old = *i;
-      this->erase(i);
+#endif
+      free(const_cast<envchar*>(*i));
       }
-    return old;
     }
   bool Put(const char* env)
     {
-    Free oldEnv(this->Release(env));
-    static_cast<void>(oldEnv);
+#if defined(_WIN32)
+    const std::wstring wEnv = Encoding::ToWide(env);
+    wchar_t* newEnv = _wcsdup(wEnv.c_str());
+#else
     char* newEnv = strdup(env);
+#endif
+    Free oldEnv(this->Release(newEnv));
     this->insert(newEnv);
+#if defined(_WIN32)
+    return _wputenv(newEnv) == 0;
+#else
     return putenv(newEnv) == 0;
+#endif
     }
   bool UnPut(const char* env)
     {
+#if defined(_WIN32)
+    const std::wstring wEnv = Encoding::ToWide(env);
+    Free oldEnv(this->Release(wEnv.c_str()));
+#else
     Free oldEnv(this->Release(env));
-    static_cast<void>(oldEnv);
+#endif
     return kwsysUnPutEnv(env) == 0;
     }
 };
@@ -5371,6 +5459,7 @@ static unsigned int SystemToolsManagerCount;
 SystemToolsTranslationMap *SystemTools::TranslationMap;
 #ifdef _WIN32
 SystemToolsPathCaseMap *SystemTools::PathCaseMap;
+SystemToolsEnvMap *SystemTools::EnvMap;
 #endif
 #ifdef __CYGWIN__
 SystemToolsTranslationMap *SystemTools::Cyg2Win32Map;
@@ -5421,6 +5510,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 +5570,7 @@ void SystemTools::ClassFinalize()
   delete SystemTools::TranslationMap;
 #ifdef _WIN32
   delete SystemTools::PathCaseMap;
+  delete SystemTools::EnvMap;
 #endif
 #ifdef __CYGWIN__
   delete SystemTools::Cyg2Win32Map;

+ 4 - 0
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;