blob: 8459d80cec19a4124395ae2d095e60334fa61e51 [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>
21
22int vasprintf(char **ret, const char *fmt, va_list ap)
23{
24 char *buf;
25 int len;
26 size_t buflen;
27 va_list ap2;
28
29#if defined(_MSC_VER) || defined(__MINGW64)
30 ap2 = ap;
31 len = _vscprintf(fmt, ap2);
32#else
33 va_copy(ap2, ap);
34 len = vsnprintf(NULL, 0, fmt, ap2);
35#endif
36
37 if (len >= 0 && (buf = (char*) malloc ((buflen = (size_t) (len + 1)))) != NULL) {
38 len = vsnprintf(buf, buflen, fmt, ap);
39 *ret = buf;
40 } else {
41 *ret = NULL;
42 len = -1;
43 }
44
45 va_end(ap2);
46 return len;
47}
48
Virgile Bellod87fc152013-09-07 05:05:49 +000049char* strcasestr(const char *s, const char* find)
Virgile Bellob2f1fb22013-08-23 12:44:05 +000050{
51 char c, sc;
52 size_t len;
53
54 if ((c = *find++) != 0) {
55 c = tolower((unsigned char) c);
56 len = strlen(find);
57 do {
58 do {
59 if ((sc = *s++) == 0)
60 return 0;
61 } while ((char) tolower((unsigned char) sc) != c);
62 } while (strncasecmp(s, find, len) != 0);
63 s--;
64 }
65 return ((char *) s);
66}
67
Virgile Belloae12a362013-08-27 16:21:49 +000068char* realpath(const char * name, char * resolved)
Virgile Bellob2f1fb22013-08-23 12:44:05 +000069{
70 char *retname = NULL; /* we will return this, if we fail */
71
72 /* SUSv3 says we must set `errno = EINVAL', and return NULL,
73 * if `name' is passed as a NULL pointer.
74 */
75
76 if (name == NULL)
77 errno = EINVAL;
78
79 /* Otherwise, `name' must refer to a readable filesystem object,
80 * if we are going to resolve its absolute path name.
81 */
82
83 else if (access(name, 4) == 0)
84 {
85 /* If `name' didn't point to an existing entity,
86 * then we don't get to here; we simply fall past this block,
87 * returning NULL, with `errno' appropriately set by `access'.
88 *
89 * When we _do_ get to here, then we can use `_fullpath' to
90 * resolve the full path for `name' into `resolved', but first,
91 * check that we have a suitable buffer, in which to return it.
92 */
93
94 if ((retname = resolved) == NULL)
95 {
96 /* Caller didn't give us a buffer, so we'll exercise the
97 * option granted by SUSv3, and allocate one.
98 *
99 * `_fullpath' would do this for us, but it uses `malloc', and
100 * Microsoft's implementation doesn't set `errno' on failure.
101 * If we don't do this explicitly ourselves, then we will not
102 * know if `_fullpath' fails on `malloc' failure, or for some
103 * other reason, and we want to set `errno = ENOMEM' for the
104 * `malloc' failure case.
105 */
106
107 retname = (char*) malloc(_MAX_PATH);
108 }
109
110 /* By now, we should have a valid buffer.
111 * If we don't, then we know that `malloc' failed,
112 * so we can set `errno = ENOMEM' appropriately.
113 */
114
115 if (retname == NULL)
116 errno = ENOMEM;
117
118 /* Otherwise, when we do have a valid buffer,
119 * `_fullpath' should only fail if the path name is too long.
120 */
121
122 else if ((retname = _fullpath(retname, name, _MAX_PATH)) == NULL)
123 errno = ENAMETOOLONG;
124 }
125
126 /* By the time we get to here,
127 * `retname' either points to the required resolved path name,
128 * or it is NULL, with `errno' set appropriately, either of which
129 * is our required return condition.
130 */
131
132 if (retname != NULL)
133 {
134 // Do a LongPath<->ShortPath roundtrip so that case is resolved by OS
135 int initialLength = strlen(retname);
136 TCHAR buffer[MAX_PATH];
137 GetShortPathName(retname, buffer, MAX_PATH);
138 GetLongPathName(buffer, retname, initialLength + 1);
139
140 // Force drive to be upper case
141 if (retname[1] == ':')
142 retname[0] = toupper(retname[0]);
143 }
144
145 return retname;
146}
Virgile Bellod87fc152013-09-07 05:05:49 +0000147
148#ifdef _MSC_VER
149
150char* basename(char *path)
151{
152 char* l1 = strrchr(path, '\\');
153 char* l2 = strrchr(path, '/');
154 if (l2 > l1) l1 = l2;
155 if (!l1) return path; // no base name
156 return &l1[1];
157}
158
159char* getcwd(char* path, int max)
160{
161 if (GetCurrentDirectory(max, path) == 0)
162 return path;
163 return NULL;
164}
165
166char *dirname(char *path)
167{
168 char* l1 = strrchr(path, '\\');
169 char* l2 = strrchr(path, '/');
170 if (l2 > l1) l1 = l2;
171 if (!l1) return NULL; // no dir name
172 *l1 = 0;
173 return path;
174}
175
176int strcasecmp(const char* s1, const char* s2)
177{
178 while (*s1 != '\0' && tolower(*s1) == tolower(*s2))
179 {
180 s1++;
181 s2++;
182 }
183
184 return tolower(*(unsigned char *) s1) - tolower(*(unsigned char *) s2);
185}
186
187int strncasecmp(const char* s1, const char* s2, size_t n)
188{
189 if (n == 0)
190 return 0;
191
192 while (n-- != 0 && tolower(*s1) == tolower(*s2))
193 {
194 if (n == 0 || *s1 == '\0' || *s2 == '\0')
195 break;
196 s1++;
197 s2++;
198 }
199
200 return tolower(*(unsigned char *) s1) - tolower(*(unsigned char *) s2);
201}
202
203int usleep(uint32_t useconds)
204{
205 Sleep(useconds / 1000);
206 return 0;
207}
208
209#endif // _MSC_VER