[llvm] r190423 - Add getenv() wrapper that works on multibyte environment variable.
罗勇刚(Yonggang Luo)
luoyonggang at gmail.com
Tue Sep 10 18:10:00 PDT 2013
在 2013年9月11日 上午3:51,"Rui Ueyama" <ruiu at google.com>写道:
>
> Author: ruiu
> Date: Tue Sep 10 14:45:51 2013
> New Revision: 190423
>
> URL: http://llvm.org/viewvc/llvm-project?rev=190423&view=rev
> Log:
> Add getenv() wrapper that works on multibyte environment variable.
>
> On Windows, character encoding of multibyte environment variable varies
> depending on settings. The only reliable way to handle it I think is to
use
> GetEnvironmentVariableW().
>
> GetEnvironmentVariableW() works on wchar_t string, which is on Windows
UTF16
> string. That's not ideal because we use UTF-8 as the internal encoding in
LLVM.
> This patch defines a wrapper function which takes and returns UTF-8
string for
> GetEnvironmentVariableW().
>
> The wrapper function does not do any conversion and just forwards the
argument
> to getenv() on Unix.
>
> Differential Revision: http://llvm-reviews.chandlerc.com/D1612
>
> Modified:
> llvm/trunk/include/llvm/Support/Process.h
> llvm/trunk/lib/Support/Unix/Process.inc
> llvm/trunk/lib/Support/Windows/Path.inc
> llvm/trunk/lib/Support/Windows/Process.inc
> llvm/trunk/lib/Support/Windows/Windows.h
> llvm/trunk/unittests/Support/ProcessTest.cpp
>
> Modified: llvm/trunk/include/llvm/Support/Process.h
> URL:
http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/Process.h?rev=190423&r1=190422&r2=190423&view=diff
>
==============================================================================
> --- llvm/trunk/include/llvm/Support/Process.h (original)
> +++ llvm/trunk/include/llvm/Support/Process.h Tue Sep 10 14:45:51 2013
> @@ -25,11 +25,14 @@
> #ifndef LLVM_SUPPORT_PROCESS_H
> #define LLVM_SUPPORT_PROCESS_H
>
> +#include "llvm/ADT/Optional.h"
> #include "llvm/Config/llvm-config.h"
> #include "llvm/Support/DataTypes.h"
> #include "llvm/Support/TimeValue.h"
>
> namespace llvm {
> +class StringRef;
> +
> namespace sys {
>
> class self_process;
> @@ -161,6 +164,10 @@ public:
> /// @brief Prevent core file generation.
> static void PreventCoreFiles();
>
> + // This function returns the environment variable \arg name's value as
a UTF-8
> + // string. \arg Name is assumed to be in UTF-8 encoding too.
> + static Optional<std::string> GetEnv(StringRef name);
> +
> /// This function determines if the standard input is connected
directly
> /// to a user's input (keyboard probably), rather than coming from a
file
> /// or pipe.
>
> Modified: llvm/trunk/lib/Support/Unix/Process.inc
> URL:
http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Unix/Process.inc?rev=190423&r1=190422&r2=190423&view=diff
>
==============================================================================
> --- llvm/trunk/lib/Support/Unix/Process.inc (original)
> +++ llvm/trunk/lib/Support/Unix/Process.inc Tue Sep 10 14:45:51 2013
> @@ -13,6 +13,7 @@
>
> #include "Unix.h"
> #include "llvm/ADT/Hashing.h"
> +#include "llvm/ADT/StringRef.h"
> #include "llvm/Support/Mutex.h"
> #include "llvm/Support/MutexGuard.h"
> #include "llvm/Support/TimeValue.h"
> @@ -181,6 +182,14 @@ void Process::PreventCoreFiles() {
> #endif
> }
>
> +Optional<std::string> Process::GetEnv(StringRef Name) {
> + std::string NameStr = Name.str();
> + const char *Val = ::getenv(NameStr.c_str());
> + if (!Val)
> + return None;
> + return std::string(Val);
> +}
> +
> bool Process::StandardInIsUserInput() {
> return FileDescriptorIsDisplayed(STDIN_FILENO);
> }
>
> Modified: llvm/trunk/lib/Support/Windows/Path.inc
> URL:
http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Windows/Path.inc?rev=190423&r1=190422&r2=190423&view=diff
>
==============================================================================
> --- llvm/trunk/lib/Support/Windows/Path.inc (original)
> +++ llvm/trunk/lib/Support/Windows/Path.inc Tue Sep 10 14:45:51 2013
> @@ -37,6 +37,9 @@ typedef int errno_t;
>
> using namespace llvm;
>
> +using llvm::sys::windows::UTF8ToUTF16;
> +using llvm::sys::windows::UTF16ToUTF8;
> +
> namespace {
> typedef BOOLEAN (WINAPI *PtrCreateSymbolicLinkW)(
> /*__in*/ LPCWSTR lpSymlinkFileName,
> @@ -47,61 +50,6 @@ namespace {
> ::GetProcAddress(::GetModuleHandleA("kernel32.dll"),
> "CreateSymbolicLinkW"));
>
> - error_code UTF8ToUTF16(StringRef utf8, SmallVectorImpl<wchar_t>
&utf16) {
> - int len = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
> - utf8.begin(), utf8.size(),
> - utf16.begin(), 0);
> -
> - if (len == 0)
> - return windows_error(::GetLastError());
> -
> - utf16.reserve(len + 1);
> - utf16.set_size(len);
> -
> - len = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
> - utf8.begin(), utf8.size(),
> - utf16.begin(), utf16.size());
> -
> - if (len == 0)
> - return windows_error(::GetLastError());
> -
> - // Make utf16 null terminated.
> - utf16.push_back(0);
> - utf16.pop_back();
> -
> - return error_code::success();
> - }
> -
> - error_code UTF16ToUTF8(const wchar_t *utf16, size_t utf16_len,
> - SmallVectorImpl<char> &utf8) {
> - // Get length.
> - int len = ::WideCharToMultiByte(CP_UTF8, 0,
> - utf16, utf16_len,
> - utf8.begin(), 0,
> - NULL, NULL);
> -
> - if (len == 0)
> - return windows_error(::GetLastError());
> -
> - utf8.reserve(len);
> - utf8.set_size(len);
> -
> - // Now do the actual conversion.
> - len = ::WideCharToMultiByte(CP_UTF8, 0,
> - utf16, utf16_len,
> - utf8.data(), utf8.size(),
> - NULL, NULL);
> -
> - if (len == 0)
> - return windows_error(::GetLastError());
> -
> - // Make utf8 null terminated.
> - utf8.push_back(0);
> - utf8.pop_back();
> -
> - return error_code::success();
> - }
> -
> error_code TempDir(SmallVectorImpl<wchar_t> &result) {
> retry_temp_dir:
> DWORD len = ::GetTempPathW(result.capacity(), result.begin());
> @@ -1092,7 +1040,64 @@ error_code openFileForWrite(const Twine
> ResultFD = FD;
> return error_code::success();
> }
> -
> } // end namespace fs
> +
> +namespace windows {
> +llvm::error_code UTF8ToUTF16(llvm::StringRef utf8,
> + llvm::SmallVectorImpl<wchar_t> &utf16) {
> + int len = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
> + utf8.begin(), utf8.size(),
> + utf16.begin(), 0);
> +
> + if (len == 0)
> + return llvm::windows_error(::GetLastError());
> +
> + utf16.reserve(len + 1);
> + utf16.set_size(len);
> +
> + len = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
> + utf8.begin(), utf8.size(),
> + utf16.begin(), utf16.size());
> +
> + if (len == 0)
> + return llvm::windows_error(::GetLastError());
> +
> + // Make utf16 null terminated.
> + utf16.push_back(0);
> + utf16.pop_back();
> +
> + return llvm::error_code::success();
> +}
> +
> +llvm::error_code UTF16ToUTF8(const wchar_t *utf16, size_t utf16_len,
> + llvm::SmallVectorImpl<char> &utf8) {
> + // Get length.
> + int len = ::WideCharToMultiByte(CP_UTF8, 0,
> + utf16, utf16_len,
> + utf8.begin(), 0,
> + NULL, NULL);
> +
> + if (len == 0)
> + return llvm::windows_error(::GetLastError());
> +
> + utf8.reserve(len);
> + utf8.set_size(len);
> +
> + // Now do the actual conversion.
> + len = ::WideCharToMultiByte(CP_UTF8, 0,
> + utf16, utf16_len,
> + utf8.data(), utf8.size(),
> + NULL, NULL);
> +
> + if (len == 0)
> + return llvm::windows_error(::GetLastError());
> +
> + // Make utf8 null terminated.
> + utf8.push_back(0);
> + utf8.pop_back();
> +
> + return llvm::error_code::success();
> +}
> +} // end namespace windows
> } // end namespace sys
> } // end namespace llvm
>
> Modified: llvm/trunk/lib/Support/Windows/Process.inc
> URL:
http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Windows/Process.inc?rev=190423&r1=190422&r2=190423&view=diff
>
==============================================================================
> --- llvm/trunk/lib/Support/Windows/Process.inc (original)
> +++ llvm/trunk/lib/Support/Windows/Process.inc Tue Sep 10 14:45:51 2013
> @@ -140,6 +140,36 @@ void Process::PreventCoreFiles() {
> SEM_NOOPENFILEERRORBOX);
> }
>
> +/// Returns the environment variable \arg Name's value as a string
encoded in
> +/// UTF-8. \arg Name is assumed to be in UTF-8 encoding.
> +Optional<std::string> Process::GetEnv(StringRef Name) {
> + // Convert the argument to UTF-16 to pass it to _wgetenv().
comment shiukd be GetEnvironmentVariableW
> + SmallVector<wchar_t, 128> NameUTF16;
> + if (error_code ec = windows::UTF8ToUTF16(Name, NameUTF16))
> + return None;
> +
> + // Environment variable can be encoded in non-UTF8 encoding, and
there's no
> + // way to know what the encoding is. The only reliable way to look up
> + // multibyte environment variable is to use GetEnvironmentVariableW().
> + std::vector<wchar_t> Buf(16);
> + size_t Size = 0;
> + for (;;) {
> + Size = GetEnvironmentVariableW(&NameUTF16[0], &Buf[0], Buf.size());
> + if (Size < Buf.size())
> + break;
> + // Try again with larger buffer.
> + Buf.resize(Size + 1);
> + }
> + if (Size == 0)
> + return None;
> +
> + // Convert the result from UTF-16 to UTF-8.
> + SmallVector<char, 128> Res;
> + if (error_code ec = windows::UTF16ToUTF8(&Buf[0], Size, Res))
> + return None;
> + return std::string(&Res[0]);
> +}
> +
> bool Process::StandardInIsUserInput() {
> return FileDescriptorIsDisplayed(0);
> }
>
> Modified: llvm/trunk/lib/Support/Windows/Windows.h
> URL:
http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Windows/Windows.h?rev=190423&r1=190422&r2=190423&view=diff
>
==============================================================================
> --- llvm/trunk/lib/Support/Windows/Windows.h (original)
> +++ llvm/trunk/lib/Support/Windows/Windows.h Tue Sep 10 14:45:51 2013
> @@ -24,13 +24,17 @@
> #define _WIN32_IE 0x0600 // MinGW at it again.
> #define WIN32_LEAN_AND_MEAN
>
> +#include "llvm/ADT/SmallVector.h"
> +#include "llvm/ADT/StringRef.h"
> #include "llvm/Config/config.h" // Get build system configuration
settings
> #include "llvm/Support/Compiler.h"
> +#include "llvm/Support/system_error.h"
> #include <windows.h>
> #include <wincrypt.h>
> #include <shlobj.h>
> #include <cassert>
> #include <string>
> +#include <vector>
>
> inline bool MakeErrMsg(std::string* ErrMsg, const std::string& prefix) {
> if (!ErrMsg)
> @@ -148,4 +152,13 @@ c_str(SmallVectorImpl<T> &str) {
> str.pop_back();
> return str.data();
> }
> +
> +namespace sys {
> +namespace windows {
> +error_code UTF8ToUTF16(StringRef utf8,
> + SmallVectorImpl<wchar_t> &utf16);
> +error_code UTF16ToUTF8(const wchar_t *utf16, size_t utf16_len,
> + SmallVectorImpl<char> &utf8);
> +} // end namespace windows
> +} // end namespace sys
> } // end namespace llvm.
>
> Modified: llvm/trunk/unittests/Support/ProcessTest.cpp
> URL:
http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/ProcessTest.cpp?rev=190423&r1=190422&r2=190423&view=diff
>
==============================================================================
> --- llvm/trunk/unittests/Support/ProcessTest.cpp (original)
> +++ llvm/trunk/unittests/Support/ProcessTest.cpp Tue Sep 10 14:45:51 2013
> @@ -39,4 +39,32 @@ TEST(ProcessTest, SelfProcess) {
> EXPECT_GT(TimeValue::MaxTime, process::get_self()->get_wall_time());
> }
>
> +#ifdef LLVM_ON_WIN32
> +#define setenv(name, var, ignore) _putenv_s(name, var)
> +#endif
> +
> +#if HAVE_SETENV || defined(LLVM_ON_WIN32)
> +TEST(ProcessTest, Basic) {
> + setenv("__LLVM_TEST_ENVIRON_VAR__", "abc", true);
> + Optional<std::string>
val(Process::GetEnv("__LLVM_TEST_ENVIRON_VAR__"));
> + EXPECT_TRUE(val.hasValue());
> + EXPECT_STREQ("abc", val->c_str());
> +}
> +
> +TEST(ProcessTest, None) {
> + Optional<std::string> val(
> + Process::GetEnv("__LLVM_TEST_ENVIRON_NO_SUCH_VAR__"));
> + EXPECT_FALSE(val.hasValue());
> +}
> +#endif
> +
> +#ifdef LLVM_ON_WIN32
> +TEST(ProcessTest, Wchar) {
> + SetEnvironmentVariableW(L"__LLVM_TEST_ENVIRON_VAR__",
L"abcdefghijklmnopqrs");
> + Optional<std::string>
val(Process::GetEnv("__LLVM_TEST_ENVIRON_VAR__"));
> + EXPECT_TRUE(val.hasValue());
> + EXPECT_STREQ("abcdefghijklmnopqrs", val->c_str());
> +}
> +#endif
> +
> } // end anonymous namespace
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20130911/d14c6add/attachment.html>
More information about the llvm-commits
mailing list