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.
20 #elif defined( _WIN32)
34 #include <sys/types.h>
43 #if defined(__APPLE__) || defined(__FreeBSD__)
44 #include <sys/sysctl.h>
45 #elif defined(__SVR4) && defined(__sun)
47 #include <sys/loadavg.h>
49 #include <libperfstat.h>
50 #elif defined(linux) || defined(__GLIBC__)
51 #include <sys/sysinfo.h>
54 #include "edit_distance.h"
57 void Fatal(const char* msg, ...) {
59 fprintf(stderr, "ninja: fatal: ");
61 vfprintf(stderr, msg, ap);
63 fprintf(stderr, "\n");
65 // On Windows, some tools may inject extra threads.
66 // exit() may block on locks held by those threads, so forcibly exit.
75 void Warning(const char* msg, ...) {
77 fprintf(stderr, "ninja: warning: ");
79 vfprintf(stderr, msg, ap);
81 fprintf(stderr, "\n");
84 void Error(const char* msg, ...) {
86 fprintf(stderr, "ninja: error: ");
88 vfprintf(stderr, msg, ap);
90 fprintf(stderr, "\n");
93 bool CanonicalizePath(string* path, unsigned int* slash_bits, string* err) {
94 METRIC_RECORD("canonicalize str");
95 size_t len = path->size();
99 if (!CanonicalizePath(str, &len, slash_bits, err))
106 static unsigned int ShiftOverBit(int offset, unsigned int bits) {
107 // e.g. for |offset| == 2:
108 // | ... 9 8 7 6 5 4 3 2 1 0 |
109 // \_________________/ \_/
111 // So we drop the bit at offset and move above "down" into its place.
112 unsigned int above = bits & ~((1 << (offset + 1)) - 1);
113 unsigned int below = bits & ((1 << offset) - 1);
114 return (above >> 1) | below;
118 bool CanonicalizePath(char* path, size_t* len, unsigned int* slash_bits,
120 // WARNING: this function is performance-critical; please benchmark
121 // any changes you make to it.
122 METRIC_RECORD("canonicalize path");
128 const int kMaxPathComponents = 30;
129 char* components[kMaxPathComponents];
130 int component_count = 0;
134 const char* src = start;
135 const char* end = start + *len;
138 unsigned int bits = 0;
139 unsigned int bits_mask = 1;
141 // Convert \ to /, setting a bit in |bits| for each \ encountered.
142 for (char* c = path; c < end; ++c) {
147 // Intentional fallthrough.
153 if (bits_offset > 32) {
154 *err = "too many path components";
163 // network path starts with //
164 if (*len > 1 && *(src + 1) == '/') {
180 if (src + 1 == end || src[1] == '/') {
181 // '.' component; eliminate.
184 bits = ShiftOverBit(bits_offset, bits);
187 } else if (src[1] == '.' && (src + 2 == end || src[2] == '/')) {
188 // '..' component. Back up if possible.
189 if (component_count > 0) {
190 dst = components[component_count - 1];
194 bits = ShiftOverBit(bits_offset, bits);
196 bits = ShiftOverBit(bits_offset, bits);
210 bits = ShiftOverBit(bits_offset, bits);
215 if (component_count == kMaxPathComponents)
216 Fatal("path has too many components : %s", path);
217 components[component_count] = dst;
220 while (*src != '/' && src != end)
225 *dst++ = *src++; // Copy '/' or final \0 character as well.
233 *len = dst - start - 1;
242 static inline bool IsKnownShellSafeCharacter(char ch) {
243 if ('A' <= ch && ch <= 'Z') return true;
244 if ('a' <= ch && ch <= 'z') return true;
245 if ('0' <= ch && ch <= '9') return true;
259 static inline bool IsKnownWin32SafeCharacter(char ch) {
269 static inline bool StringNeedsShellEscaping(const string& input) {
270 for (size_t i = 0; i < input.size(); ++i) {
271 if (!IsKnownShellSafeCharacter(input[i])) return true;
276 static inline bool StringNeedsWin32Escaping(const string& input) {
277 for (size_t i = 0; i < input.size(); ++i) {
278 if (!IsKnownWin32SafeCharacter(input[i])) return true;
283 void GetShellEscapedString(const string& input, string* result) {
286 if (!StringNeedsShellEscaping(input)) {
287 result->append(input);
291 const char kQuote = '\'';
292 const char kEscapeSequence[] = "'\\'";
294 result->push_back(kQuote);
296 string::const_iterator span_begin = input.begin();
297 for (string::const_iterator it = input.begin(), end = input.end(); it != end;
300 result->append(span_begin, it);
301 result->append(kEscapeSequence);
305 result->append(span_begin, input.end());
306 result->push_back(kQuote);
310 void GetWin32EscapedString(const string& input, string* result) {
312 if (!StringNeedsWin32Escaping(input)) {
313 result->append(input);
317 const char kQuote = '"';
318 const char kBackslash = '\\';
320 result->push_back(kQuote);
321 size_t consecutive_backslash_count = 0;
322 string::const_iterator span_begin = input.begin();
323 for (string::const_iterator it = input.begin(), end = input.end(); it != end;
327 ++consecutive_backslash_count;
330 result->append(span_begin, it);
331 result->append(consecutive_backslash_count + 1, kBackslash);
333 consecutive_backslash_count = 0;
336 consecutive_backslash_count = 0;
340 result->append(span_begin, input.end());
341 result->append(consecutive_backslash_count, kBackslash);
342 result->push_back(kQuote);
345 int ReadFile(const string& path, string* contents, string* err) {
347 // This makes a ninja run on a set of 1500 manifest files about 4% faster
348 // than using the generic fopen code below.
350 HANDLE f = ::CreateFile(path.c_str(),
355 FILE_FLAG_SEQUENTIAL_SCAN,
357 if (f == INVALID_HANDLE_VALUE) {
358 err->assign(GetLastErrorString());
365 if (!::ReadFile(f, buf, sizeof(buf), &len, NULL)) {
366 err->assign(GetLastErrorString());
372 contents->append(buf, len);
377 FILE* f = fopen(path.c_str(), "rb");
379 err->assign(strerror(errno));
385 while ((len = fread(buf, 1, sizeof(buf), f)) > 0) {
386 contents->append(buf, len);
389 err->assign(strerror(errno)); // XXX errno?
399 void SetCloseOnExec(int fd) {
401 int flags = fcntl(fd, F_GETFD);
403 perror("fcntl(F_GETFD)");
405 if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0)
406 perror("fcntl(F_SETFD)");
409 HANDLE hd = (HANDLE) _get_osfhandle(fd);
410 if (! SetHandleInformation(hd, HANDLE_FLAG_INHERIT, 0)) {
411 fprintf(stderr, "SetHandleInformation(): %s", GetLastErrorString().c_str());
417 const char* SpellcheckStringV(const string& text,
418 const vector<const char*>& words) {
419 const bool kAllowReplacements = true;
420 const int kMaxValidEditDistance = 3;
422 int min_distance = kMaxValidEditDistance + 1;
423 const char* result = NULL;
424 for (vector<const char*>::const_iterator i = words.begin();
425 i != words.end(); ++i) {
426 int distance = EditDistance(*i, text, kAllowReplacements,
427 kMaxValidEditDistance);
428 if (distance < min_distance) {
429 min_distance = distance;
436 const char* SpellcheckString(const char* text, ...) {
437 // Note: This takes a const char* instead of a string& because using
438 // va_start() with a reference parameter is undefined behavior.
441 vector<const char*> words;
443 while ((word = va_arg(ap, const char*)))
444 words.push_back(word);
446 return SpellcheckStringV(text, words);
450 string GetLastErrorString() {
451 DWORD err = GetLastError();
455 FORMAT_MESSAGE_ALLOCATE_BUFFER |
456 FORMAT_MESSAGE_FROM_SYSTEM |
457 FORMAT_MESSAGE_IGNORE_INSERTS,
460 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
464 string msg = msg_buf;
469 void Win32Fatal(const char* function) {
470 Fatal("%s: %s", function, GetLastErrorString().c_str());
474 static bool islatinalpha(int c) {
475 // isalpha() is locale-dependent.
476 return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
479 string StripAnsiEscapeCodes(const string& in) {
481 stripped.reserve(in.size());
483 for (size_t i = 0; i < in.size(); ++i) {
484 if (in[i] != '\33') {
485 // Not an escape code.
486 stripped.push_back(in[i]);
490 // Only strip CSIs for now.
491 if (i + 1 >= in.size()) break;
492 if (in[i + 1] != '[') continue; // Not a CSI.
495 // Skip everything up to and including the next [a-zA-Z].
496 while (i < in.size() && !islatinalpha(in[i]))
502 int GetProcessorCount() {
505 GetNativeSystemInfo(&info);
506 return info.dwNumberOfProcessors;
508 return sysconf(_SC_NPROCESSORS_ONLN);
512 #if defined(_WIN32) || defined(__CYGWIN__)
513 static double CalculateProcessorLoad(uint64_t idle_ticks, uint64_t total_ticks)
515 static uint64_t previous_idle_ticks = 0;
516 static uint64_t previous_total_ticks = 0;
517 static double previous_load = -0.0;
519 uint64_t idle_ticks_since_last_time = idle_ticks - previous_idle_ticks;
520 uint64_t total_ticks_since_last_time = total_ticks - previous_total_ticks;
522 bool first_call = (previous_total_ticks == 0);
523 bool ticks_not_updated_since_last_call = (total_ticks_since_last_time == 0);
526 if (first_call || ticks_not_updated_since_last_call) {
527 load = previous_load;
530 double idle_to_total_ratio =
531 ((double)idle_ticks_since_last_time) / total_ticks_since_last_time;
532 double load_since_last_call = 1.0 - idle_to_total_ratio;
534 // Filter/smooth result when possible.
535 if(previous_load > 0) {
536 load = 0.9 * previous_load + 0.1 * load_since_last_call;
538 load = load_since_last_call;
542 previous_load = load;
543 previous_total_ticks = total_ticks;
544 previous_idle_ticks = idle_ticks;
549 static uint64_t FileTimeToTickCount(const FILETIME & ft)
551 uint64_t high = (((uint64_t)(ft.dwHighDateTime)) << 32);
552 uint64_t low = ft.dwLowDateTime;
556 double GetLoadAverage() {
557 FILETIME idle_time, kernel_time, user_time;
558 BOOL get_system_time_succeeded =
559 GetSystemTimes(&idle_time, &kernel_time, &user_time);
561 double posix_compatible_load;
562 if (get_system_time_succeeded) {
563 uint64_t idle_ticks = FileTimeToTickCount(idle_time);
565 // kernel_time from GetSystemTimes already includes idle_time.
566 uint64_t total_ticks =
567 FileTimeToTickCount(kernel_time) + FileTimeToTickCount(user_time);
569 double processor_load = CalculateProcessorLoad(idle_ticks, total_ticks);
570 posix_compatible_load = processor_load * GetProcessorCount();
573 posix_compatible_load = -0.0;
576 return posix_compatible_load;
579 double GetLoadAverage() {
580 perfstat_cpu_total_t cpu_stats;
581 if (perfstat_cpu_total(NULL, &cpu_stats, sizeof(cpu_stats), 1) < 0) {
585 // Calculation taken from comment in libperfstats.h
586 return double(cpu_stats.loadavg[0]) / double(1 << SBITS);
589 double GetLoadAverage() {
590 double loadavg[3] = { 0.0f, 0.0f, 0.0f };
591 if (getloadavg(loadavg, 3) < 0) {
592 // Maybe we should return an error here or the availability of
593 // getloadavg(3) should be checked when ninja is configured.
600 string ElideMiddle(const string& str, size_t width) {
601 const int kMargin = 3; // Space for "...".
603 if (result.size() + kMargin > width) {
604 size_t elide_size = (width - kMargin) / 2;
605 result = result.substr(0, elide_size)
607 + result.substr(result.size() - elide_size, elide_size);
612 bool Truncate(const string& path, size_t size, string* err) {
614 int fh = _sopen(path.c_str(), _O_RDWR | _O_CREAT, _SH_DENYNO,
615 _S_IREAD | _S_IWRITE);
616 int success = _chsize(fh, size);
619 int success = truncate(path.c_str(), size);
621 // Both truncate() and _chsize() return 0 on success and set errno and return
624 *err = strerror(errno);