1 // Copyright 2011 Google Inc. All Rights Reserved.
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
28 #include <sys/types.h>
37 #include <direct.h> // _mkdir
40 #include "edit_distance.h"
43 void Fatal(const char* msg, ...) {
45 fprintf(stderr, "ninja: FATAL: ");
47 vfprintf(stderr, msg, ap);
49 fprintf(stderr, "\n");
51 // On Windows, some tools may inject extra threads.
52 // exit() may block on locks held by those threads, so forcibly exit.
61 void Warning(const char* msg, ...) {
63 fprintf(stderr, "ninja: WARNING: ");
65 vfprintf(stderr, msg, ap);
67 fprintf(stderr, "\n");
70 void Error(const char* msg, ...) {
72 fprintf(stderr, "ninja: ERROR: ");
74 vfprintf(stderr, msg, ap);
76 fprintf(stderr, "\n");
79 bool CanonicalizePath(string* path, string* err) {
80 METRIC_RECORD("canonicalize str");
81 int len = path->size();
82 if (!CanonicalizePath(&(*path)[0], &len, err))
88 bool CanonicalizePath(char* path, int* len, string* err) {
89 // WARNING: this function is performance-critical; please benchmark
90 // any changes you make to it.
91 METRIC_RECORD("canonicalize path");
97 const int kMaxPathComponents = 30;
98 char* components[kMaxPathComponents];
99 int component_count = 0;
103 const char* src = start;
104 const char* end = start + *len;
112 const char* sep = (const char*)memchr(src, '/', end - src);
117 if (sep - src == 1) {
118 // '.' component; eliminate.
121 } else if (sep - src == 2 && src[1] == '.') {
122 // '..' component. Back up if possible.
123 if (component_count > 0) {
124 dst = components[component_count - 1];
136 if (component_count == kMaxPathComponents)
137 Fatal("path has too many components");
138 components[component_count] = dst;
148 *len = dst - start - 1;
152 int MakeDir(const string& path) {
154 return _mkdir(path.c_str());
156 return mkdir(path.c_str(), 0777);
160 int ReadFile(const string& path, string* contents, string* err) {
161 FILE* f = fopen(path.c_str(), "r");
163 err->assign(strerror(errno));
169 while ((len = fread(buf, 1, sizeof(buf), f)) > 0) {
170 contents->append(buf, len);
173 err->assign(strerror(errno)); // XXX errno?
182 void SetCloseOnExec(int fd) {
184 int flags = fcntl(fd, F_GETFD);
186 perror("fcntl(F_GETFD)");
188 if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0)
189 perror("fcntl(F_SETFD)");
192 // On Windows, handles must be explicitly marked to be passed to a
193 // spawned process, so there's nothing to do here.
194 NINJA_UNUSED_ARG(fd);
198 int64_t GetTimeMillis() {
200 // GetTickCount64 is only available on Vista or later.
201 return GetTickCount();
204 gettimeofday(&now, NULL);
205 return ((int64_t)now.tv_sec * 1000) + (now.tv_usec / 1000);
209 const char* SpellcheckStringV(const string& text,
210 const vector<const char*>& words) {
211 const bool kAllowReplacements = true;
212 const int kMaxValidEditDistance = 3;
214 int min_distance = kMaxValidEditDistance + 1;
215 const char* result = NULL;
216 for (vector<const char*>::const_iterator i = words.begin();
217 i != words.end(); ++i) {
218 int distance = EditDistance(*i, text, kAllowReplacements,
219 kMaxValidEditDistance);
220 if (distance < min_distance) {
221 min_distance = distance;
228 const char* SpellcheckString(const string& text, ...) {
231 vector<const char*> words;
233 while ((word = va_arg(ap, const char*)))
234 words.push_back(word);
235 return SpellcheckStringV(text, words);
239 string GetLastErrorString() {
240 DWORD err = GetLastError();
244 FORMAT_MESSAGE_ALLOCATE_BUFFER |
245 FORMAT_MESSAGE_FROM_SYSTEM |
246 FORMAT_MESSAGE_IGNORE_INSERTS,
249 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
253 string msg = msg_buf;
259 static bool islatinalpha(int c) {
260 // isalpha() is locale-dependent.
261 return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
264 string StripAnsiEscapeCodes(const string& in) {
266 stripped.reserve(in.size());
268 for (size_t i = 0; i < in.size(); ++i) {
269 if (in[i] != '\33') {
270 // Not an escape code.
271 stripped.push_back(in[i]);
275 // Only strip CSIs for now.
276 if (i + 1 >= in.size()) break;
277 if (in[i + 1] != '[') continue; // Not a CSI.
280 // Skip everything up to and including the next [a-zA-Z].
281 while (i < in.size() && !islatinalpha(in[i]))