31 #include <sys/types.h>
40 #if defined(__APPLE__) || defined(__FreeBSD__)
41 #include <sys/sysctl.h>
42 #elif defined(__SVR4) && defined(__sun)
44 #include <sys/loadavg.h>
45 #elif defined(linux) || defined(__GLIBC__)
46 #include <sys/sysinfo.h>
52 void Fatal(
const char* msg, ...) {
54 fprintf(stderr,
"ninja: fatal: ");
56 vfprintf(stderr, msg, ap);
58 fprintf(stderr,
"\n");
72 fprintf(stderr,
"ninja: warning: ");
74 vfprintf(stderr, msg, ap);
76 fprintf(stderr,
"\n");
79 void Error(
const char* msg, ...) {
81 fprintf(stderr,
"ninja: error: ");
83 vfprintf(stderr, msg, ap);
85 fprintf(stderr,
"\n");
90 size_t len = path->size();
109 const int kMaxPathComponents = 30;
110 char* components[kMaxPathComponents];
111 int component_count = 0;
115 const char* src = start;
116 const char* end = start + *len;
121 if (*len > 1 && *(src + 1) ==
'/') {
136 if (src + 1 == end || src[1] ==
'/') {
140 }
else if (src[1] ==
'.' && (src + 2 == end || src[2] ==
'/')) {
142 if (component_count > 0) {
143 dst = components[component_count - 1];
160 if (component_count == kMaxPathComponents)
161 Fatal(
"path has too many components : %s", path);
162 components[component_count] = dst;
165 while (*src !=
'/' && src != end)
171 *err =
"path canonicalizes to the empty path";
175 *len = dst - start - 1;
180 if (
'A' <= ch && ch <=
'Z')
return true;
181 if (
'a' <= ch && ch <=
'z')
return true;
182 if (
'0' <= ch && ch <=
'9')
return true;
207 for (
size_t i = 0; i < input.size(); ++i) {
214 for (
size_t i = 0; i < input.size(); ++i) {
224 result->append(input);
228 const char kQuote =
'\'';
229 const char kEscapeSequence[] =
"'\\'";
231 result->push_back(kQuote);
233 string::const_iterator span_begin = input.begin();
234 for (string::const_iterator it = input.begin(), end = input.end(); it != end;
237 result->append(span_begin, it);
238 result->append(kEscapeSequence);
242 result->append(span_begin, input.end());
243 result->push_back(kQuote);
250 result->append(input);
254 const char kQuote =
'"';
255 const char kBackslash =
'\\';
257 result->push_back(kQuote);
258 size_t consecutive_backslash_count = 0;
259 string::const_iterator span_begin = input.begin();
260 for (string::const_iterator it = input.begin(), end = input.end(); it != end;
264 ++consecutive_backslash_count;
267 result->append(span_begin, it);
268 result->append(consecutive_backslash_count + 1, kBackslash);
270 consecutive_backslash_count = 0;
273 consecutive_backslash_count = 0;
277 result->append(span_begin, input.end());
278 result->append(consecutive_backslash_count, kBackslash);
279 result->push_back(kQuote);
282 int ReadFile(
const string& path,
string* contents,
string* err) {
283 FILE* f = fopen(path.c_str(),
"r");
285 err->assign(strerror(errno));
291 while ((len = fread(buf, 1,
sizeof(buf), f)) > 0) {
292 contents->append(buf, len);
295 err->assign(strerror(errno));
306 int flags = fcntl(fd, F_GETFD);
308 perror(
"fcntl(F_GETFD)");
310 if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0)
311 perror(
"fcntl(F_SETFD)");
315 if (! SetHandleInformation(hd, HANDLE_FLAG_INHERIT, 0)) {
316 fprintf(stderr,
"SetHandleInformation(): %s", GetLastErrorString().c_str());
323 const vector<const char*>& words) {
324 const bool kAllowReplacements =
true;
325 const int kMaxValidEditDistance = 3;
327 int min_distance = kMaxValidEditDistance + 1;
328 const char* result = NULL;
329 for (vector<const char*>::const_iterator i = words.begin();
330 i != words.end(); ++i) {
331 int distance =
EditDistance(*i, text, kAllowReplacements,
332 kMaxValidEditDistance);
333 if (distance < min_distance) {
334 min_distance = distance;
346 vector<const char*> words;
348 while ((word = va_arg(ap,
const char*)))
349 words.push_back(word);
355 string GetLastErrorString() {
356 DWORD err = GetLastError();
360 FORMAT_MESSAGE_ALLOCATE_BUFFER |
361 FORMAT_MESSAGE_FROM_SYSTEM |
362 FORMAT_MESSAGE_IGNORE_INSERTS,
365 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
369 string msg = msg_buf;
374 void Win32Fatal(
const char*
function) {
375 Fatal(
"%s: %s",
function, GetLastErrorString().c_str());
381 return (c >=
'a' && c <=
'z') || (c >=
'A' && c <=
'Z');
386 stripped.reserve(in.size());
388 for (
size_t i = 0; i < in.size(); ++i) {
389 if (in[i] !=
'\33') {
391 stripped.push_back(in[i]);
396 if (i + 1 >= in.size())
break;
397 if (in[i + 1] !=
'[')
continue;
410 GetSystemInfo(&info);
411 return info.dwNumberOfProcessors;
413 return sysconf(_SC_NPROCESSORS_ONLN);
417 #if defined(_WIN32) || defined(__CYGWIN__)
425 double loadavg[3] = { 0.0f, 0.0f, 0.0f };
426 if (getloadavg(loadavg, 3) < 0) {
436 const int kMargin = 3;
438 if (result.size() + kMargin > width) {
439 size_t elide_size = (width - kMargin) / 2;
440 result = result.substr(0, elide_size)
442 + result.substr(result.size() - elide_size, elide_size);
447 bool Truncate(
const string& path,
size_t size,
string* err) {
449 int fh = _sopen(path.c_str(), _O_RDWR | _O_CREAT, _SH_DENYNO,
450 _S_IREAD | _S_IWRITE);
451 int success = _chsize(fh, size);
454 int success = truncate(path.c_str(), size);
459 *err = strerror(errno);
static bool StringNeedsShellEscaping(const string &input)
const char * SpellcheckString(const char *text,...)
Like SpellcheckStringV, but takes a NULL-terminated list.
void GetWin32EscapedString(const string &input, string *result)
void GetShellEscapedString(const string &input, string *result)
Appends |input| to |*result|, escaping according to the whims of either Bash, or Win32's CommandLineT...
bool CanonicalizePath(string *path, string *err)
Canonicalize a path like "foo/../bar.h" into just "bar.h".
void SetCloseOnExec(int fd)
Mark a file descriptor to not be inherited on exec()s.
static bool IsKnownWin32SafeCharacter(char ch)
static bool StringNeedsWin32Escaping(const string &input)
static bool islatinalpha(int c)
int ReadFile(const string &path, string *contents, string *err)
Read a file to a string (in text mode: with CRLF conversion on Windows).
#define METRIC_RECORD(name)
The primary interface to metrics.
static bool IsKnownShellSafeCharacter(char ch)
bool Truncate(const string &path, size_t size, string *err)
Truncates a file to the given size.
string StripAnsiEscapeCodes(const string &in)
Removes all Ansi escape codes (http://www.termsys.demon.co.uk/vtansi.htm).
void Fatal(const char *msg,...)
Log a fatal message and exit.
const char * SpellcheckStringV(const string &text, const vector< const char * > &words)
Given a misspelled string and a list of correct spellings, returns the closest match or NULL if there...
void Warning(const char *msg,...)
Log a warning message.
int EditDistance(const StringPiece &s1, const StringPiece &s2, bool allow_replacements, int max_edit_distance)
void Error(const char *msg,...)
Log an error message.
string ElideMiddle(const string &str, size_t width)
Elide the given string str with '...' in the middle if the length exceeds width.