1 //===-- Windows.cpp ---------------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file provides Windows support functions
12 #include "lldb/Host/PosixApi.h"
13 #include "lldb/Host/windows/windows.h"
15 #include "llvm/Support/ConvertUTF.h"
26 // These prototypes are defined in <direct.h>, but it also defines chdir() and
27 // getcwd(), giving multiply defined errors
29 char *_getcwd(char *buffer, int maxlen);
30 int _chdir(const char *path);
34 bool utf8ToWide(const char *utf8, wchar_t *buf, size_t bufSize) {
35 const llvm::UTF8 *sourceStart = reinterpret_cast<const llvm::UTF8 *>(utf8);
36 size_t sourceLen = strlen(utf8) + 1 /* convert null too */;
37 llvm::UTF16 *target = reinterpret_cast<llvm::UTF16 *>(buf);
38 llvm::ConversionFlags flags = llvm::strictConversion;
39 return llvm::ConvertUTF8toUTF16(&sourceStart, sourceStart + sourceLen, &target,
40 target + bufSize, flags) == llvm::conversionOK;
43 bool wideToUtf8(const wchar_t *wide, char *buf, size_t bufSize) {
44 const llvm::UTF16 *sourceStart = reinterpret_cast<const llvm::UTF16 *>(wide);
45 size_t sourceLen = wcslen(wide) + 1 /* convert null too */;
46 llvm::UTF8 *target = reinterpret_cast<llvm::UTF8 *>(buf);
47 llvm::ConversionFlags flags = llvm::strictConversion;
48 return llvm::ConvertUTF16toUTF8(&sourceStart, sourceStart + sourceLen, &target,
49 target + bufSize, flags) == llvm::conversionOK;
53 int vasprintf(char **ret, const char *fmt, va_list ap) {
59 #if defined(_MSC_VER) || defined(__MINGW64)
61 len = _vscprintf(fmt, ap2);
64 len = vsnprintf(NULL, 0, fmt, ap2);
68 (buf = (char *)malloc((buflen = (size_t)(len + 1)))) != NULL) {
69 len = vsnprintf(buf, buflen, fmt, ap);
80 char *strcasestr(const char *s, const char *find) {
84 if ((c = *find++) != 0) {
85 c = tolower((unsigned char)c);
91 } while ((char)tolower((unsigned char)sc) != c);
92 } while (strncasecmp(s, find, len) != 0);
98 char *realpath(const char *name, char *resolved) {
101 /* SUSv3 says we must set `errno = EINVAL', and return NULL,
102 * if `name' is passed as a NULL pointer.
109 /* Otherwise, `name' must refer to a readable filesystem object,
110 * if we are going to resolve its absolute path name.
112 wchar_t wideNameBuffer[PATH_MAX];
113 wchar_t *wideName = wideNameBuffer;
114 if (!utf8ToWide(name, wideName, PATH_MAX)) {
119 if (_waccess(wideName, 4) != 0)
122 /* If `name' didn't point to an existing entity,
123 * then we don't get to here; we simply fall past this block,
124 * returning NULL, with `errno' appropriately set by `access'.
126 * When we _do_ get to here, then we can use `_fullpath' to
127 * resolve the full path for `name' into `resolved', but first,
128 * check that we have a suitable buffer, in which to return it.
131 if ((retname = resolved) == NULL) {
132 /* Caller didn't give us a buffer, so we'll exercise the
133 * option granted by SUSv3, and allocate one.
135 * `_fullpath' would do this for us, but it uses `malloc', and
136 * Microsoft's implementation doesn't set `errno' on failure.
137 * If we don't do this explicitly ourselves, then we will not
138 * know if `_fullpath' fails on `malloc' failure, or for some
139 * other reason, and we want to set `errno = ENOMEM' for the
140 * `malloc' failure case.
143 retname = (char *)malloc(PATH_MAX);
144 if (retname == NULL) {
150 /* Otherwise, when we do have a valid buffer,
151 * `_fullpath' should only fail if the path name is too long.
154 wchar_t wideFullPathBuffer[PATH_MAX];
155 wchar_t *wideFullPath;
156 if ((wideFullPath = _wfullpath(wideFullPathBuffer, wideName, PATH_MAX)) ==
158 errno = ENAMETOOLONG;
162 // Do a LongPath<->ShortPath roundtrip so that case is resolved by OS
163 // FIXME: Check for failure
164 size_t initialLength = wcslen(wideFullPath);
165 GetShortPathNameW(wideFullPath, wideNameBuffer, PATH_MAX);
166 GetLongPathNameW(wideNameBuffer, wideFullPathBuffer, initialLength + 1);
168 // Convert back to UTF-8
169 if (!wideToUtf8(wideFullPathBuffer, retname, PATH_MAX)) {
174 // Force drive to be upper case
175 if (retname[1] == ':')
176 retname[0] = toupper(retname[0]);
183 char *basename(char *path) {
184 char *l1 = strrchr(path, '\\');
185 char *l2 = strrchr(path, '/');
189 return path; // no base name
193 // use _getcwd() instead of GetCurrentDirectory() because it updates errno
194 char *getcwd(char *path, int max) {
195 assert(path == NULL || max <= PATH_MAX);
196 wchar_t wpath[PATH_MAX];
197 if (wchar_t *wresult = _wgetcwd(wpath, PATH_MAX)) {
198 // Caller is allowed to pass in NULL for `path`.
199 // In that case, we're supposed to allocate a
200 // buffer on the caller's behalf.
202 max = UNI_MAX_UTF8_BYTES_PER_CODE_POINT * wcslen(wresult) + 1;
203 path = (char *)malloc(max);
209 if (wideToUtf8(wresult, path, max))
215 // use _chdir() instead of SetCurrentDirectory() because it updates errno
216 int chdir(const char *path) { return _chdir(path); }
218 char *dirname(char *path) {
219 char *l1 = strrchr(path, '\\');
220 char *l2 = strrchr(path, '/');
224 return NULL; // no dir name
229 int strcasecmp(const char *s1, const char *s2) { return stricmp(s1, s2); }
231 int strncasecmp(const char *s1, const char *s2, size_t n) {
232 return strnicmp(s1, s2, n);
235 int usleep(uint32_t useconds) {
236 Sleep(useconds / 1000);
241 namespace lldb_private {
242 int vsnprintf(char *buffer, size_t count, const char *format, va_list argptr) {
243 int old_errno = errno;
244 int r = ::vsnprintf(buffer, count, format, argptr);
245 int new_errno = errno;
246 buffer[count - 1] = '\0';
247 if (r == -1 || r == count) {
248 FILE *nul = fopen("nul", "w");
249 int bytes_written = ::vfprintf(nul, format, argptr);
251 if (bytes_written < count)
260 } // namespace lldb_private