summaryrefslogtreecommitdiffstats
path: root/Source/kwsys/SystemTools.cxx
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2016-07-18 13:28:42 (GMT)
committerBrad King <brad.king@kitware.com>2016-07-18 13:28:42 (GMT)
commit03407040d4d7d89fbb45e941a9dfb4257003a8a8 (patch)
tree9f064958df49861718f38a4216471aa7d314924e /Source/kwsys/SystemTools.cxx
parent4bb3c4102fa40d802ab0b0d0500afe5c9887038f (diff)
parentbbb3216a2cac24ea18731141a3eadc62e11320d2 (diff)
downloadCMake-03407040d4d7d89fbb45e941a9dfb4257003a8a8.zip
CMake-03407040d4d7d89fbb45e941a9dfb4257003a8a8.tar.gz
CMake-03407040d4d7d89fbb45e941a9dfb4257003a8a8.tar.bz2
Merge branch 'upstream-KWSys' into update-kwsys
* upstream-KWSys: KWSys 2016-07-15 (f396bf43)
Diffstat (limited to 'Source/kwsys/SystemTools.cxx')
-rw-r--r--Source/kwsys/SystemTools.cxx233
1 files changed, 162 insertions, 71 deletions
diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx
index c6e668d..f8ea884 100644
--- a/Source/kwsys/SystemTools.cxx
+++ b/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;