diff options
Diffstat (limited to 'lib/Support/Windows')
-rw-r--r-- | lib/Support/Windows/Path.inc | 117 | ||||
-rw-r--r-- | lib/Support/Windows/Process.inc | 30 | ||||
-rw-r--r-- | lib/Support/Windows/Windows.h | 13 |
3 files changed, 104 insertions, 56 deletions
diff --git a/lib/Support/Windows/Path.inc b/lib/Support/Windows/Path.inc index 645d5238db..94a501b39a 100644 --- a/lib/Support/Windows/Path.inc +++ b/lib/Support/Windows/Path.inc @@ -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 &Name, int &ResultFD, 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 diff --git a/lib/Support/Windows/Process.inc b/lib/Support/Windows/Process.inc index f840d064d8..0191751a82 100644 --- a/lib/Support/Windows/Process.inc +++ b/lib/Support/Windows/Process.inc @@ -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(). + 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); } diff --git a/lib/Support/Windows/Windows.h b/lib/Support/Windows/Windows.h index 4cdac788a0..1236fe5652 100644 --- a/lib/Support/Windows/Windows.h +++ b/lib/Support/Windows/Windows.h @@ -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. |