diff --git a/SystemTools.cxx b/SystemTools.cxx index c6471c60823dac7843ea0486e066f9598de22a48..5c91a308adacf2b16a249304cd41296bf2fdb2d5 100644 --- a/SystemTools.cxx +++ b/SystemTools.cxx @@ -389,13 +389,31 @@ 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); @@ -408,6 +426,7 @@ struct kwsysEnvCompare { return strcmp(l,r) < 0; } +#endif } }; @@ -453,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 @@ -506,7 +528,17 @@ void SystemTools::GetPath(std::vector<std::string>& path, const char* env) const char* SystemTools::GetEnv(const char* 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; } @@ -517,12 +549,22 @@ 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; } +#endif return false; } @@ -592,19 +634,20 @@ static int kwsysUnPutEnv(const std::string& env) static kwsysEnvSet kwsysUnPutEnvSet; -static int kwsysUnPutEnv(std::string env) +static int kwsysUnPutEnv(std::string const& env) { - size_t const pos = env.find('='); - size_t const len = pos == env.npos ? env.size() : pos; - env.resize(len+1, '='); - char* newEnv = strdup(env.c_str()); + 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 putenv(newEnv); + return _wputenv(newEnv); } #else @@ -681,20 +724,39 @@ public: { 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); +#endif free(const_cast<envchar*>(*i)); } } bool Put(const char* env) { +#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)); +#endif return kwsysUnPutEnv(env) == 0; } }; @@ -5381,6 +5443,7 @@ static unsigned int SystemToolsManagerCount; SystemToolsTranslationMap *SystemTools::TranslationMap; #ifdef _WIN32 SystemToolsPathCaseMap *SystemTools::PathCaseMap; +SystemToolsEnvMap *SystemTools::EnvMap; #endif #ifdef __CYGWIN__ SystemToolsTranslationMap *SystemTools::Cyg2Win32Map; @@ -5431,6 +5494,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; @@ -5490,6 +5554,7 @@ void SystemTools::ClassFinalize() delete SystemTools::TranslationMap; #ifdef _WIN32 delete SystemTools::PathCaseMap; + delete SystemTools::EnvMap; #endif #ifdef __CYGWIN__ delete SystemTools::Cyg2Win32Map; diff --git a/SystemTools.hxx.in b/SystemTools.hxx.in index bba5a5cd3b651d97a079d6242126ad25c630c9d6..d7c71df9ad38a386dee34f31404b4cb8dcca1962 100644 --- a/SystemTools.hxx.in +++ b/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 @@ -989,6 +990,7 @@ private: static SystemToolsTranslationMap *TranslationMap; #ifdef _WIN32 static SystemToolsPathCaseMap *PathCaseMap; + static SystemToolsEnvMap *EnvMap; #endif #ifdef __CYGWIN__ static SystemToolsTranslationMap *Cyg2Win32Map;