blob: f5d314333be64971d79de78c49785a1a60a6b73c [file] [log] [blame]
Virgile Bellob2f1fb22013-08-23 12:44:05 +00001//===-- Windows.cpp ---------------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10// This file provides Windows support functions
11
12#include "lldb/Host/windows/windows.h"
13#include "lldb/Host/windows/win32.h"
14
15#include <stdio.h>
16#include <stdarg.h>
17#include <string.h>
18#include <stdlib.h>
19#include <io.h>
20#include <cerrno>
Hafiz Abid Qadeerbdb51592014-03-12 10:39:46 +000021#include <ctype.h>
Virgile Bellob2f1fb22013-08-23 12:44:05 +000022
Ted Woodward4744ec62015-05-12 18:47:33 +000023// These prototypes are defined in <direct.h>, but it also defines chdir() and getcwd(), giving multiply defined errors
24extern "C"
25{
26 char *_getcwd(char *buffer, int maxlen);
27 int _chdir(const char *path);
28}
29
Virgile Bellob2f1fb22013-08-23 12:44:05 +000030int vasprintf(char **ret, const char *fmt, va_list ap)
31{
32 char *buf;
33 int len;
34 size_t buflen;
35 va_list ap2;
36
37#if defined(_MSC_VER) || defined(__MINGW64)
38 ap2 = ap;
39 len = _vscprintf(fmt, ap2);
40#else
41 va_copy(ap2, ap);
42 len = vsnprintf(NULL, 0, fmt, ap2);
43#endif
44
45 if (len >= 0 && (buf = (char*) malloc ((buflen = (size_t) (len + 1)))) != NULL) {
46 len = vsnprintf(buf, buflen, fmt, ap);
47 *ret = buf;
48 } else {
49 *ret = NULL;
50 len = -1;
51 }
52
53 va_end(ap2);
54 return len;
55}
56
Virgile Bellod87fc152013-09-07 05:05:49 +000057char* strcasestr(const char *s, const char* find)
Virgile Bellob2f1fb22013-08-23 12:44:05 +000058{
59 char c, sc;
60 size_t len;
61
62 if ((c = *find++) != 0) {
63 c = tolower((unsigned char) c);
64 len = strlen(find);
65 do {
66 do {
67 if ((sc = *s++) == 0)
68 return 0;
69 } while ((char) tolower((unsigned char) sc) != c);
70 } while (strncasecmp(s, find, len) != 0);
71 s--;
72 }
73 return ((char *) s);
74}
75
Virgile Belloae12a362013-08-27 16:21:49 +000076char* realpath(const char * name, char * resolved)
Virgile Bellob2f1fb22013-08-23 12:44:05 +000077{
78 char *retname = NULL; /* we will return this, if we fail */
79
80 /* SUSv3 says we must set `errno = EINVAL', and return NULL,
81 * if `name' is passed as a NULL pointer.
82 */
83
84 if (name == NULL)
85 errno = EINVAL;
86
87 /* Otherwise, `name' must refer to a readable filesystem object,
88 * if we are going to resolve its absolute path name.
89 */
90
91 else if (access(name, 4) == 0)
92 {
93 /* If `name' didn't point to an existing entity,
94 * then we don't get to here; we simply fall past this block,
95 * returning NULL, with `errno' appropriately set by `access'.
96 *
97 * When we _do_ get to here, then we can use `_fullpath' to
98 * resolve the full path for `name' into `resolved', but first,
99 * check that we have a suitable buffer, in which to return it.
100 */
101
102 if ((retname = resolved) == NULL)
103 {
104 /* Caller didn't give us a buffer, so we'll exercise the
105 * option granted by SUSv3, and allocate one.
106 *
107 * `_fullpath' would do this for us, but it uses `malloc', and
108 * Microsoft's implementation doesn't set `errno' on failure.
109 * If we don't do this explicitly ourselves, then we will not
110 * know if `_fullpath' fails on `malloc' failure, or for some
111 * other reason, and we want to set `errno = ENOMEM' for the
112 * `malloc' failure case.
113 */
114
115 retname = (char*) malloc(_MAX_PATH);
116 }
117
118 /* By now, we should have a valid buffer.
119 * If we don't, then we know that `malloc' failed,
120 * so we can set `errno = ENOMEM' appropriately.
121 */
122
123 if (retname == NULL)
124 errno = ENOMEM;
125
126 /* Otherwise, when we do have a valid buffer,
127 * `_fullpath' should only fail if the path name is too long.
128 */
129
130 else if ((retname = _fullpath(retname, name, _MAX_PATH)) == NULL)
131 errno = ENAMETOOLONG;
132 }
133
134 /* By the time we get to here,
135 * `retname' either points to the required resolved path name,
136 * or it is NULL, with `errno' set appropriately, either of which
137 * is our required return condition.
138 */
139
140 if (retname != NULL)
141 {
142 // Do a LongPath<->ShortPath roundtrip so that case is resolved by OS
143 int initialLength = strlen(retname);
144 TCHAR buffer[MAX_PATH];
145 GetShortPathName(retname, buffer, MAX_PATH);
146 GetLongPathName(buffer, retname, initialLength + 1);
147
148 // Force drive to be upper case
149 if (retname[1] == ':')
150 retname[0] = toupper(retname[0]);
151 }
152
153 return retname;
154}
Virgile Bellod87fc152013-09-07 05:05:49 +0000155
156#ifdef _MSC_VER
157
158char* basename(char *path)
159{
160 char* l1 = strrchr(path, '\\');
161 char* l2 = strrchr(path, '/');
162 if (l2 > l1) l1 = l2;
163 if (!l1) return path; // no base name
164 return &l1[1];
165}
166
Ted Woodward4744ec62015-05-12 18:47:33 +0000167// use _getcwd() instead of GetCurrentDirectory() because it updates errno
Virgile Bellod87fc152013-09-07 05:05:49 +0000168char* getcwd(char* path, int max)
169{
Ted Woodward4744ec62015-05-12 18:47:33 +0000170 return _getcwd(path, max);
171}
172
173// use _chdir() instead of SetCurrentDirectory() because it updates errno
174int chdir(const char* path)
175{
176 return _chdir(path);
Virgile Bellod87fc152013-09-07 05:05:49 +0000177}
178
179char *dirname(char *path)
180{
181 char* l1 = strrchr(path, '\\');
182 char* l2 = strrchr(path, '/');
183 if (l2 > l1) l1 = l2;
184 if (!l1) return NULL; // no dir name
185 *l1 = 0;
186 return path;
187}
188
189int strcasecmp(const char* s1, const char* s2)
190{
Zachary Turner12f6f532014-07-29 19:08:55 +0000191 return stricmp(s1, s2);
Virgile Bellod87fc152013-09-07 05:05:49 +0000192}
193
194int strncasecmp(const char* s1, const char* s2, size_t n)
195{
Zachary Turner12f6f532014-07-29 19:08:55 +0000196 return strnicmp(s1, s2, n);
Virgile Bellod87fc152013-09-07 05:05:49 +0000197}
198
199int usleep(uint32_t useconds)
200{
Chaoren Lin0ef00272015-05-29 19:34:57 +0000201 Sleep(useconds / 1000);
202 return 0;
203}
204
205int snprintf(char *buffer, size_t count, const char *format, ...)
206{
207 int old_errno = errno;
208 va_list argptr;
209 va_start(argptr, format);
210 int r = vsnprintf(buffer, count, format, argptr);
211 int new_errno = errno;
212 buffer[count-1] = '\0';
213 if (r == -1 || r == count)
214 {
215 FILE *nul = fopen("nul", "w");
216 int bytes_written = vfprintf(nul, format, argptr);
217 fclose(nul);
218 if (bytes_written < count)
219 errno = new_errno;
220 else
221 {
222 errno = old_errno;
223 r = bytes_written;
224 }
225 }
226 va_end(argptr);
227 return r;
Virgile Bellod87fc152013-09-07 05:05:49 +0000228}
229
230#endif // _MSC_VER