Merge remote-tracking branch 'aosp/upstream' am: 3c89f197a6 am: 330fd37d4e
am: b5eeb9ed39

Change-Id: Ibad792b9f826f43bb6a316b8c8aa0aaa121c8988
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..b8dc211
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,2 @@
+---
+BasedOnStyle: Chromium
diff --git a/affinity.cc b/affinity.cc
index 5448b29..8be3fad 100644
--- a/affinity.cc
+++ b/affinity.cc
@@ -31,7 +31,7 @@
   cpu_set_t cs;
   CPU_ZERO(&cs);
   std::default_random_engine generator(getpid());
-  std::uniform_int_distribution<int> distribution(0,g_flags.num_cpus-1);
+  std::uniform_int_distribution<int> distribution(0, g_flags.num_cpus - 1);
   int cpu = distribution(generator);
 
   // Try to come up with a CPU and one close to it. This should work on most
@@ -42,7 +42,7 @@
   cpu = cpu - (cpu % 2);
   CPU_SET(cpu, &cs);
   if (g_flags.num_cpus > 1)
-    CPU_SET(cpu+1, &cs);
+    CPU_SET(cpu + 1, &cs);
 
   if (sched_setaffinity(0, sizeof(cs), &cs) < 0)
     WARN("sched_setaffinity: %s", strerror(errno));
diff --git a/command.cc b/command.cc
index 8907630..b072a6a 100644
--- a/command.cc
+++ b/command.cc
@@ -30,12 +30,8 @@
 
 class AutoVar : public Var {
  public:
-  virtual const char* Flavor() const override {
-    return "undefined";
-  }
-  virtual VarOrigin Origin() const override {
-    return VarOrigin::AUTOMATIC;
-  }
+  virtual const char* Flavor() const override { return "undefined"; }
+  virtual VarOrigin Origin() const override { return VarOrigin::AUTOMATIC; }
 
   virtual void AppendVar(Evaluator*, Value*) override { CHECK(false); }
 
@@ -56,13 +52,12 @@
   const char* sym_;
 };
 
-#define DECLARE_AUTO_VAR_CLASS(name)                                    \
-  class name : public AutoVar {                                         \
-   public:                                                              \
-   name(CommandEvaluator* ce, const char* sym)                          \
-       : AutoVar(ce, sym) {}                                            \
-   virtual ~name() = default;                                           \
-   virtual void Eval(Evaluator* ev, string* s) const override;          \
+#define DECLARE_AUTO_VAR_CLASS(name)                                  \
+  class name : public AutoVar {                                       \
+   public:                                                            \
+    name(CommandEvaluator* ce, const char* sym) : AutoVar(ce, sym) {} \
+    virtual ~name() = default;                                        \
+    virtual void Eval(Evaluator* ev, string* s) const override;       \
   }
 
 DECLARE_AUTO_VAR_CLASS(AutoAtVar);
@@ -75,8 +70,7 @@
 class AutoSuffixDVar : public AutoVar {
  public:
   AutoSuffixDVar(CommandEvaluator* ce, const char* sym, Var* wrapped)
-      : AutoVar(ce, sym), wrapped_(wrapped) {
-  }
+      : AutoVar(ce, sym), wrapped_(wrapped) {}
   virtual ~AutoSuffixDVar() = default;
   virtual void Eval(Evaluator* ev, string* s) const override;
 
@@ -130,8 +124,7 @@
 }
 
 void AutoNotImplementedVar::Eval(Evaluator* ev, string*) const {
-  ev->Error(StringPrintf(
-      "Automatic variable `$%s' isn't supported yet", sym_));
+  ev->Error(StringPrintf("Automatic variable `$%s' isn't supported yet", sym_));
 }
 
 void AutoSuffixDVar::Eval(Evaluator* ev, string* s) const {
@@ -171,13 +164,13 @@
 
 }  // namespace
 
-CommandEvaluator::CommandEvaluator(Evaluator* ev)
-    : ev_(ev) {
-#define INSERT_AUTO_VAR(name, sym) do {                                 \
+CommandEvaluator::CommandEvaluator(Evaluator* ev) : ev_(ev) {
+#define INSERT_AUTO_VAR(name, sym)                                      \
+  do {                                                                  \
     Var* v = new name(this, sym);                                       \
     Intern(sym).SetGlobalVar(v);                                        \
-    Intern(sym"D").SetGlobalVar(new AutoSuffixDVar(this, sym"D", v));   \
-    Intern(sym"F").SetGlobalVar(new AutoSuffixFVar(this, sym"F", v));   \
+    Intern(sym "D").SetGlobalVar(new AutoSuffixDVar(this, sym "D", v)); \
+    Intern(sym "F").SetGlobalVar(new AutoSuffixFVar(this, sym "F", v)); \
   } while (0)
   INSERT_AUTO_VAR(AutoAtVar, "@");
   INSERT_AUTO_VAR(AutoLessVar, "<");
diff --git a/command.h b/command.h
index 6e2df6a..5e86333 100644
--- a/command.h
+++ b/command.h
@@ -25,9 +25,7 @@
 class Evaluator;
 
 struct Command {
-  explicit Command(Symbol o)
-      : output(o), echo(true), ignore_error(false) {
-  }
+  explicit Command(Symbol o) : output(o), echo(true), ignore_error(false) {}
   Symbol output;
   string cmd;
   bool echo;
diff --git a/dep.cc b/dep.cc
index 16aeeec..585bcb9 100644
--- a/dep.cc
+++ b/dep.cc
@@ -73,9 +73,7 @@
 
 class RuleTrie {
   struct Entry {
-    Entry(const Rule* r, StringPiece s)
-        : rule(r), suffix(s) {
-    }
+    Entry(const Rule* r, StringPiece s) : rule(r), suffix(s) {}
     const Rule* rule;
     StringPiece suffix;
   };
@@ -127,7 +125,6 @@
   unordered_map<char, RuleTrie*> children_;
 };
 
-
 bool IsSuffixRule(Symbol output) {
   if (output.empty() || output.str()[0] != '.')
     return false;
@@ -136,7 +133,7 @@
   // If there is only a single dot or the third dot, this is not a
   // suffix rule.
   if (dot_index == string::npos ||
-      rest.substr(dot_index+1).find('.') != string::npos) {
+      rest.substr(dot_index + 1).find('.') != string::npos) {
     return false;
   }
   return true;
@@ -154,23 +151,27 @@
       : primary_rule(nullptr),
         parent(nullptr),
         parent_sym(Symbol::IsUninitialized()),
-        is_double_colon(false) {
-  }
+        is_double_colon(false) {}
 
-  void AddImplicitOutput(Symbol output, RuleMerger *merger) {
+  void AddImplicitOutput(Symbol output, RuleMerger* merger) {
     implicit_outputs.push_back(make_pair(output, merger));
   }
 
   void SetImplicitOutput(Symbol output, Symbol p, const RuleMerger* merger) {
     if (!merger->primary_rule) {
-      ERROR("*** implicit output `%s' on phony target `%s'", output.c_str(), p.c_str());
+      ERROR("*** implicit output `%s' on phony target `%s'", output.c_str(),
+            p.c_str());
     }
     if (parent) {
-      ERROR_LOC(merger->primary_rule->cmd_loc(), "*** implicit output `%s' of `%s' was already defined by `%s' at %s:%d",
-                output.c_str(), p.c_str(), parent_sym.c_str(), parent->primary_rule->cmd_loc());
+      ERROR_LOC(merger->primary_rule->cmd_loc(),
+                "*** implicit output `%s' of `%s' was already defined by `%s' "
+                "at %s:%d",
+                output.c_str(), p.c_str(), parent_sym.c_str(),
+                parent->primary_rule->cmd_loc());
     }
     if (primary_rule) {
-      ERROR_LOC(primary_rule->cmd_loc(), "*** implicit output `%s' may not have commands",
+      ERROR_LOC(primary_rule->cmd_loc(),
+                "*** implicit output `%s' may not have commands",
                 output.c_str());
     }
     parent = merger;
@@ -185,15 +186,15 @@
                 output.c_str());
     }
 
-    if (primary_rule && !r->cmds.empty() &&
-        !IsSuffixRule(output) && !r->is_double_colon) {
+    if (primary_rule && !r->cmds.empty() && !IsSuffixRule(output) &&
+        !r->is_double_colon) {
       if (g_flags.werror_overriding_commands) {
         ERROR_LOC(r->cmd_loc(),
-                  "*** overriding commands for target `%s', previously defined at %s:%d",
+                  "*** overriding commands for target `%s', previously defined "
+                  "at %s:%d",
                   output.c_str(), LOCF(primary_rule->cmd_loc()));
       } else {
-        WARN_LOC(r->cmd_loc(),
-                 "warning: overriding commands for target `%s'",
+        WARN_LOC(r->cmd_loc(), "warning: overriding commands for target `%s'",
                  output.c_str());
         WARN_LOC(primary_rule->cmd_loc(),
                  "warning: ignoring old commands for target `%s'",
@@ -208,9 +209,7 @@
     rules.push_back(r);
   }
 
-  void FillDepNodeFromRule(Symbol output,
-                           const Rule* r,
-                           DepNode* n) const {
+  void FillDepNodeFromRule(Symbol output, const Rule* r, DepNode* n) const {
     if (is_double_colon)
       copy(r->cmds.begin(), r->cmds.end(), back_inserter(n->cmds));
 
@@ -230,9 +229,7 @@
       n->loc.lineno = r->cmd_lineno;
   }
 
-  void FillDepNode(Symbol output,
-                   const Rule* pattern_rule,
-                   DepNode* n) const {
+  void FillDepNode(Symbol output, const Rule* pattern_rule, DepNode* n) const {
     if (primary_rule) {
       CHECK(!pattern_rule);
       FillDepNodeFromRule(output, primary_rule, n);
@@ -291,7 +288,7 @@
     ScopedTimeReporter tr("make dep (populate)");
     PopulateRules(rules);
     // TODO?
-    //LOG_STAT("%zu variables", ev->mutable_vars()->size());
+    // LOG_STAT("%zu variables", ev->mutable_vars()->size());
     LOG_STAT("%zu explicit rules", rules_.size());
     LOG_STAT("%zu implicit rules", implicit_rules_->size());
     LOG_STAT("%zu suffix rules", suffix_rules_.size());
@@ -320,20 +317,18 @@
     }
 
     // Note we can safely ignore .DELETE_ON_ERROR for --ninja mode.
-    static const char* kUnsupportedBuiltinTargets[] = {
-      ".DEFAULT",
-      ".PRECIOUS",
-      ".INTERMEDIATE",
-      ".SECONDARY",
-      ".SECONDEXPANSION",
-      ".IGNORE",
-      ".LOW_RESOLUTION_TIME",
-      ".SILENT",
-      ".EXPORT_ALL_VARIABLES",
-      ".NOTPARALLEL",
-      ".ONESHELL",
-      NULL
-    };
+    static const char* kUnsupportedBuiltinTargets[] = {".DEFAULT",
+                                                       ".PRECIOUS",
+                                                       ".INTERMEDIATE",
+                                                       ".SECONDARY",
+                                                       ".SECONDEXPANSION",
+                                                       ".IGNORE",
+                                                       ".LOW_RESOLUTION_TIME",
+                                                       ".SILENT",
+                                                       ".EXPORT_ALL_VARIABLES",
+                                                       ".NOTPARALLEL",
+                                                       ".ONESHELL",
+                                                       NULL};
     for (const char** p = kUnsupportedBuiltinTargets; *p; p++) {
       if (GetRuleInputs(Intern(*p), &targets, &loc)) {
         WARN_LOC(loc, "kati doesn't support %s", *p);
@@ -341,8 +336,7 @@
     }
   }
 
-  ~DepBuilder() {
-  }
+  ~DepBuilder() {}
 
   void Build(vector<Symbol> targets, vector<DepNode*>* nodes) {
     if (!first_rule_.IsValid()) {
@@ -448,7 +442,7 @@
     size_t dot_index = rest.find('.');
 
     StringPiece input_suffix = rest.substr(0, dot_index);
-    StringPiece output_suffix = rest.substr(dot_index+1);
+    StringPiece output_suffix = rest.substr(dot_index + 1);
     shared_ptr<Rule> r = make_shared<Rule>(*rule);
     r->inputs.clear();
     r->inputs.push_back(Intern(input_suffix));
@@ -477,8 +471,8 @@
     if (!rule->cmds.empty())
       return false;
     const string& i = rule->inputs[0].str();
-    return (i == "RCS/%,v" || i == "RCS/%" || i == "%,v" ||
-            i == "s.%" || i == "SCCS/s.%");
+    return (i == "RCS/%,v" || i == "RCS/%" || i == "%,v" || i == "s.%" ||
+            i == "SCCS/s.%");
   }
 
   void PopulateImplicitRule(const Rule* rule) {
@@ -503,7 +497,9 @@
     return nullptr;
   }
 
-  bool CanPickImplicitRule(const Rule* rule, Symbol output, DepNode* n,
+  bool CanPickImplicitRule(const Rule* rule,
+                           Symbol output,
+                           DepNode* n,
                            shared_ptr<Rule>* out_rule) {
     Symbol matched(Symbol::IsUninitialized{});
     for (Symbol output_pattern : rule->output_patterns) {
@@ -600,7 +596,7 @@
     if (found == suffix_rules_.end())
       return rule_merger;
 
-    for (const shared_ptr<Rule> &irule : found->second) {
+    for (const shared_ptr<Rule>& irule : found->second) {
       CHECK(irule->inputs.size() == 1);
       Symbol input = ReplaceSuffix(output, irule->inputs[0]);
       if (!Exists(input))
@@ -621,18 +617,15 @@
   }
 
   DepNode* BuildPlan(Symbol output, Symbol needed_by UNUSED) {
-    LOG("BuildPlan: %s for %s",
-        output.c_str(),
-        needed_by.c_str());
+    LOG("BuildPlan: %s for %s", output.c_str(), needed_by.c_str());
 
     auto found = done_.find(output);
     if (found != done_.end()) {
       return found->second;
     }
 
-    DepNode* n = new DepNode(output,
-                             phony_.count(output),
-                             restat_.count(output));
+    DepNode* n =
+        new DepNode(output, phony_.count(output), restat_.count(output));
     done_[output] = n;
 
     const RuleMerger* rule_merger = nullptr;
diff --git a/eval.cc b/eval.cc
index ecfcd50..2206730 100644
--- a/eval.cc
+++ b/eval.cc
@@ -17,6 +17,7 @@
 #include "eval.h"
 
 #include <errno.h>
+#include <pthread.h>
 #include <string.h>
 
 #include "expr.h"
@@ -38,6 +39,18 @@
       posix_sym_(Intern(".POSIX")),
       is_posix_(false),
       kati_readonly_(Intern(".KATI_READONLY")) {
+#if defined(__APPLE__)
+  stack_size_ = pthread_get_stacksize_np(pthread_self());
+  stack_addr_ = (char*)pthread_get_stackaddr_np(pthread_self()) - stack_size_;
+#else
+  pthread_attr_t attr;
+  CHECK(pthread_getattr_np(pthread_self(), &attr) == 0);
+  CHECK(pthread_attr_getstack(&attr, &stack_addr_, &stack_size_) == 0);
+  CHECK(pthread_attr_destroy(&attr) == 0);
+#endif
+
+  lowest_stack_ = (char*)stack_addr_ + stack_size_;
+  LOG_STAT("Stack size: %zd bytes", stack_size_);
 }
 
 Evaluator::~Evaluator() {
@@ -47,12 +60,16 @@
   // }
 }
 
-Var* Evaluator::EvalRHS(Symbol lhs, Value* rhs_v, StringPiece orig_rhs,
-                        AssignOp op, bool is_override) {
-  VarOrigin origin = (
-      (is_bootstrap_ ? VarOrigin::DEFAULT :
-       is_commandline_ ? VarOrigin::COMMAND_LINE :
-       is_override ? VarOrigin::OVERRIDE : VarOrigin::FILE));
+Var* Evaluator::EvalRHS(Symbol lhs,
+                        Value* rhs_v,
+                        StringPiece orig_rhs,
+                        AssignOp op,
+                        bool is_override) {
+  VarOrigin origin =
+      ((is_bootstrap_ ? VarOrigin::DEFAULT
+                      : is_commandline_ ? VarOrigin::COMMAND_LINE
+                                        : is_override ? VarOrigin::OVERRIDE
+                                                      : VarOrigin::FILE));
 
   Var* rhs = NULL;
   Var* prev = LookupVarInCurrentScope(lhs);
@@ -72,7 +89,8 @@
       if (!prev->IsDefined()) {
         rhs = new RecursiveVar(rhs_v, origin, orig_rhs);
       } else if (prev->ReadOnly()) {
-        Error(StringPrintf("*** cannot assign to readonly variable: %s", lhs.c_str()));
+        Error(StringPrintf("*** cannot assign to readonly variable: %s",
+                           lhs.c_str()));
       } else {
         prev->AppendVar(this, rhs_v);
         rhs = prev;
@@ -118,7 +136,8 @@
     for (auto const& name : WordScanner(rhs)) {
       Var* var = Intern(name).GetGlobalVar();
       if (!var->IsDefined()) {
-        Error(StringPrintf("*** unknown variable: %s", name.as_string().c_str()));
+        Error(
+            StringPrintf("*** unknown variable: %s", name.as_string().c_str()));
       }
       var->SetReadOnly();
     }
@@ -129,11 +148,11 @@
                      stmt->directive == AssignDirective::OVERRIDE);
   if (rhs) {
     bool readonly;
-    lhs.SetGlobalVar(rhs,
-                     stmt->directive == AssignDirective::OVERRIDE,
+    lhs.SetGlobalVar(rhs, stmt->directive == AssignDirective::OVERRIDE,
                      &readonly);
     if (readonly) {
-      Error(StringPrintf("*** cannot assign to readonly variable: %s", lhs.c_str()));
+      Error(StringPrintf("*** cannot assign to readonly variable: %s",
+                         lhs.c_str()));
     }
   }
 }
@@ -152,7 +171,7 @@
 
   Rule* rule;
   RuleVarAssignment rule_var;
-  function<string()> after_term_fn = [this, stmt](){
+  function<string()> after_term_fn = [this, stmt]() {
     return stmt->after_term ? stmt->after_term->Eval(this) : "";
   };
   ParseRule(loc_, expr, stmt->term, after_term_fn, &rule, &rule_var);
@@ -204,7 +223,8 @@
       for (auto const& name : WordScanner(rhs_value)) {
         Var* var = current_scope_->Lookup(Intern(name));
         if (!var->IsDefined()) {
-          Error(StringPrintf("*** unknown variable: %s", name.as_string().c_str()));
+          Error(StringPrintf("*** unknown variable: %s",
+                             name.as_string().c_str()));
         }
         var->SetReadOnly();
       }
@@ -217,7 +237,8 @@
       bool readonly;
       current_scope_->Assign(lhs, new RuleVar(rhs_var, rule_var.op), &readonly);
       if (readonly) {
-        Error(StringPrintf("*** cannot assign to readonly variable: %s", lhs.c_str()));
+        Error(StringPrintf("*** cannot assign to readonly variable: %s",
+                           lhs.c_str()));
       }
     }
     current_scope_ = NULL;
@@ -282,6 +303,8 @@
 }
 
 void Evaluator::DoInclude(const string& fname) {
+  CheckStack();
+
   Makefile* mk = MakefileCacheManager::Get()->ReadMakefile(fname);
   if (!mk->Exists()) {
     Error(StringPrintf("%s does not exist", fname.c_str()));
@@ -393,4 +416,10 @@
   ERROR_LOC(loc_, "%s", msg.c_str());
 }
 
+void Evaluator::DumpStackStats() const {
+  LOG_STAT("Max stack use: %zd bytes at %s:%d",
+           ((char*)stack_addr_ - (char*)lowest_stack_) + stack_size_,
+           LOCF(lowest_loc_));
+}
+
 unordered_set<Symbol> Evaluator::used_undefined_vars_;
diff --git a/eval.h b/eval.h
index c0f27b9..2b62892 100644
--- a/eval.h
+++ b/eval.h
@@ -53,9 +53,7 @@
   void set_loc(const Loc& loc) { loc_ = loc; }
 
   const vector<const Rule*>& rules() const { return rules_; }
-  const unordered_map<Symbol, Vars*>& rule_vars() const {
-    return rule_vars_;
-  }
+  const unordered_map<Symbol, Vars*>& rule_vars() const { return rule_vars_; }
   const unordered_map<Symbol, bool>& exports() const { return exports_; }
 
   void Error(const string& msg);
@@ -74,28 +72,34 @@
   void add_delayed_output_command(const string& c) {
     delayed_output_commands_.push_back(c);
   }
-  void clear_delayed_output_commands() {
-    delayed_output_commands_.clear();
-  }
+  void clear_delayed_output_commands() { delayed_output_commands_.clear(); }
 
   static const unordered_set<Symbol>& used_undefined_vars() {
     return used_undefined_vars_;
   }
 
   int eval_depth() const { return eval_depth_; }
-  void IncrementEvalDepth() {
-    eval_depth_++;
-  }
-  void DecrementEvalDepth() {
-    eval_depth_--;
-  }
+  void IncrementEvalDepth() { eval_depth_++; }
+  void DecrementEvalDepth() { eval_depth_--; }
 
   string GetShell();
   string GetShellFlag();
   string GetShellAndFlag();
 
+  void CheckStack() {
+    void* addr = __builtin_frame_address(0);
+    if (__builtin_expect(addr < lowest_stack_ && addr >= stack_addr_, 0)) {
+      lowest_stack_ = addr;
+      lowest_loc_ = loc_;
+    }
+  }
+  void DumpStackStats() const;
+
  private:
-  Var* EvalRHS(Symbol lhs, Value* rhs, StringPiece orig_rhs, AssignOp op,
+  Var* EvalRHS(Symbol lhs,
+               Value* rhs,
+               StringPiece orig_rhs,
+               AssignOp op,
                bool is_override = false);
   void DoInclude(const string& fname);
 
@@ -124,6 +128,11 @@
   Symbol posix_sym_;
   bool is_posix_;
 
+  void* stack_addr_;
+  size_t stack_size_;
+  void* lowest_stack_;
+  Loc lowest_loc_;
+
   static unordered_set<Symbol> used_undefined_vars_;
 
   Symbol kati_readonly_;
diff --git a/exec.cc b/exec.cc
index fa534d5..aa2bd42 100644
--- a/exec.cc
+++ b/exec.cc
@@ -44,9 +44,7 @@
 
 class Executor {
  public:
-  explicit Executor(Evaluator* ev)
-      : ce_(ev),
-        num_commands_(0) {
+  explicit Executor(Evaluator* ev) : ce_(ev), num_commands_(0) {
     shell_ = ev->GetShell();
     shellflag_ = ev->GetShellFlag();
   }
@@ -64,8 +62,7 @@
     done_[n->output] = kProcessing;
     double output_ts = GetTimestamp(n->output.c_str());
 
-    LOG("ExecNode: %s for %s",
-        n->output.c_str(),
+    LOG("ExecNode: %s for %s", n->output.c_str(),
         needed_by ? needed_by->output.c_str() : "(null)");
 
     if (!n->has_rule && output_ts == kNotExist && !n->is_phony) {
@@ -108,18 +105,16 @@
       }
       if (!g_flags.is_dry_run) {
         string out;
-        int result = RunCommand(shell_, shellflag_,
-                                command->cmd.c_str(),
-                                RedirectStderr::STDOUT,
-                                &out);
+        int result = RunCommand(shell_, shellflag_, command->cmd.c_str(),
+                                RedirectStderr::STDOUT, &out);
         printf("%s", out.c_str());
         if (result != 0) {
           if (command->ignore_error) {
             fprintf(stderr, "[%s] Error %d (ignored)\n",
                     command->output.c_str(), WEXITSTATUS(result));
           } else {
-            fprintf(stderr, "*** [%s] Error %d\n",
-                    command->output.c_str(), WEXITSTATUS(result));
+            fprintf(stderr, "*** [%s] Error %d\n", command->output.c_str(),
+                    WEXITSTATUS(result));
             exit(1);
           }
         }
@@ -131,9 +126,7 @@
     return output_ts;
   }
 
-  uint64_t Count() {
-    return num_commands_;
-  }
+  uint64_t Count() { return num_commands_; }
 
  private:
   CommandEvaluator ce_;
diff --git a/expr.cc b/expr.cc
index 641bf5a..5419900 100644
--- a/expr.cc
+++ b/expr.cc
@@ -25,11 +25,9 @@
 #include "strutil.h"
 #include "var.h"
 
-Evaluable::Evaluable() {
-}
+Evaluable::Evaluable() {}
 
-Evaluable::~Evaluable() {
-}
+Evaluable::~Evaluable() {}
 
 string Evaluable::Eval(Evaluator* ev) const {
   string s;
@@ -37,11 +35,9 @@
   return s;
 }
 
-Value::Value() {
-}
+Value::Value() {}
 
-Value::~Value() {
-}
+Value::~Value() {}
 
 string Value::DebugString() const {
   if (static_cast<const Value*>(this)) {
@@ -52,22 +48,19 @@
 
 class Literal : public Value {
  public:
-  explicit Literal(StringPiece s)
-      : s_(s) {
-  }
+  explicit Literal(StringPiece s) : s_(s) {}
 
   StringPiece val() const { return s_; }
 
-  virtual void Eval(Evaluator*, string* s) const override {
+  virtual void Eval(Evaluator* ev, string* s) const override {
+    ev->CheckStack();
     s->append(s_.begin(), s_.end());
   }
 
   virtual bool IsLiteral() const override { return true; }
   virtual StringPiece GetLiteralValueUnsafe() const override { return s_; }
 
-  virtual string DebugString_() const override {
-    return s_.as_string();
-  }
+  virtual string DebugString_() const override { return s_.as_string(); }
 
  private:
   StringPiece s_;
@@ -75,8 +68,7 @@
 
 class Expr : public Value {
  public:
-  Expr() {
-  }
+  Expr() {}
 
   virtual ~Expr() {
     for (Value* v : vals_) {
@@ -85,11 +77,10 @@
   }
 
   // Takes the ownership of |v|.
-  void AddValue(Value* v) {
-    vals_.push_back(v);
-  }
+  void AddValue(Value* v) { vals_.push_back(v); }
 
   virtual void Eval(Evaluator* ev, string* s) const override {
+    ev->CheckStack();
     for (Value* v : vals_) {
       v->Eval(ev, s);
     }
@@ -126,13 +117,11 @@
 
 class SymRef : public Value {
  public:
-  explicit SymRef(Symbol n)
-      : name_(n) {
-  }
-  virtual ~SymRef() {
-  }
+  explicit SymRef(Symbol n) : name_(n) {}
+  virtual ~SymRef() {}
 
   virtual void Eval(Evaluator* ev, string* s) const override {
+    ev->CheckStack();
     Var* v = ev->LookupVar(name_);
     v->Used(ev, name_);
     v->Eval(ev, s);
@@ -148,14 +137,11 @@
 
 class VarRef : public Value {
  public:
-  explicit VarRef(Value* n)
-      : name_(n) {
-  }
-  virtual ~VarRef() {
-    delete name_;
-  }
+  explicit VarRef(Value* n) : name_(n) {}
+  virtual ~VarRef() { delete name_; }
 
   virtual void Eval(Evaluator* ev, string* s) const override {
+    ev->CheckStack();
     ev->IncrementEvalDepth();
     const string&& name = name_->Eval(ev);
     ev->DecrementEvalDepth();
@@ -176,8 +162,7 @@
 class VarSubst : public Value {
  public:
   explicit VarSubst(Value* n, Value* p, Value* s)
-      : name_(n), pat_(p), subst_(s) {
-  }
+      : name_(n), pat_(p), subst_(s) {}
   virtual ~VarSubst() {
     delete name_;
     delete pat_;
@@ -185,6 +170,7 @@
   }
 
   virtual void Eval(Evaluator* ev, string* s) const override {
+    ev->CheckStack();
     ev->IncrementEvalDepth();
     const string&& name = name_->Eval(ev);
     Symbol sym = Intern(name);
@@ -203,8 +189,7 @@
   }
 
   virtual string DebugString_() const override {
-    return StringPrintf("VarSubst(%s:%s=%s)",
-                        name_->DebugString().c_str(),
+    return StringPrintf("VarSubst(%s:%s=%s)", name_->DebugString().c_str(),
                         pat_->DebugString().c_str(),
                         subst_->DebugString().c_str());
   }
@@ -217,9 +202,7 @@
 
 class Func : public Value {
  public:
-  explicit Func(FuncInfo* fi)
-      : fi_(fi) {
-  }
+  explicit Func(FuncInfo* fi) : fi_(fi) {}
 
   ~Func() {
     for (Value* a : args_)
@@ -227,6 +210,7 @@
   }
 
   virtual void Eval(Evaluator* ev, string* s) const override {
+    ev->CheckStack();
     LOG("Invoke func %s(%s)", name(), JoinValues(args_, ",").c_str());
     ev->IncrementEvalDepth();
     fi_->func(args_, ev, s);
@@ -234,14 +218,11 @@
   }
 
   virtual string DebugString_() const override {
-    return StringPrintf("Func(%s %s)",
-                        fi_->name,
+    return StringPrintf("Func(%s %s)", fi_->name,
                         JoinValues(args_, ",").c_str());
   }
 
-  void AddArg(Value* v) {
-    args_.push_back(v);
-  }
+  void AddArg(Value* v) { args_.push_back(v); }
 
   const char* name() const { return fi_->name; }
   int arity() const { return fi_->arity; }
@@ -285,7 +266,10 @@
 }
 
 void ParseFunc(const Loc& loc,
-               Func* f, StringPiece s, size_t i, char* terms,
+               Func* f,
+               StringPiece s,
+               size_t i,
+               char* terms,
                size_t* index_out) {
   terms[1] = ',';
   terms[2] = '\0';
@@ -306,23 +290,24 @@
         if (isspace(s[i]))
           continue;
         if (s[i] == '\\') {
-          char c = s.get(i+1);
+          char c = s.get(i + 1);
           if (c == '\r' || c == '\n')
             continue;
         }
         break;
       }
     }
-    const bool trim_right_space = (f->trim_space() ||
-                                   (nargs == 1 && f->trim_right_space_1st()));
+    const bool trim_right_space =
+        (f->trim_space() || (nargs == 1 && f->trim_right_space_1st()));
     size_t n;
-    Value* v = ParseExprImpl(loc, s.substr(i), terms, ParseExprOpt::FUNC,
-                             &n, trim_right_space);
+    Value* v = ParseExprImpl(loc, s.substr(i), terms, ParseExprOpt::FUNC, &n,
+                             trim_right_space);
     // TODO: concatLine???
     f->AddArg(v);
     i += n;
     if (i == s.size()) {
-      ERROR_LOC(loc, "*** unterminated call to function '%s': "
+      ERROR_LOC(loc,
+                "*** unterminated call to function '%s': "
                 "missing '%c'.",
                 f->name(), terms[0]);
     }
@@ -337,7 +322,8 @@
   }
 
   if (nargs <= f->min_arity()) {
-    ERROR_LOC(loc, "*** insufficient number of arguments (%d) to function `%s'.",
+    ERROR_LOC(loc,
+              "*** insufficient number of arguments (%d) to function `%s'.",
               nargs - 1, f->name());
   }
 
@@ -359,8 +345,8 @@
   char terms[] = {cp, ':', ' ', 0};
   for (size_t i = 2;;) {
     size_t n;
-    Value* vname = ParseExprImpl(loc, s.substr(i), terms,
-                                 ParseExprOpt::NORMAL, &n);
+    Value* vname =
+        ParseExprImpl(loc, s.substr(i), terms, ParseExprOpt::NORMAL, &n);
     i += n;
     if (s[i] == cp) {
       *index_out = i + 1;
@@ -388,7 +374,7 @@
         if (FuncInfo* fi = GetFuncInfo(lit->val())) {
           delete lit;
           Func* func = new Func(fi);
-          ParseFunc(loc, func, s, i+1, terms, index_out);
+          ParseFunc(loc, func, s, i + 1, terms, index_out);
           return func;
         } else {
           KATI_WARN_LOC(loc, "*warning*: unknown make function '%.*s': %.*s",
@@ -409,8 +395,8 @@
       terms[2] = '\0';
       terms[1] = '=';
       size_t n;
-      Value* pat = ParseExprImpl(loc, s.substr(i+1), terms,
-                                 ParseExprOpt::NORMAL, &n);
+      Value* pat =
+          ParseExprImpl(loc, s.substr(i + 1), terms, ParseExprOpt::NORMAL, &n);
       i += 1 + n;
       if (s[i] == cp) {
         Expr* v = new Expr;
@@ -422,8 +408,8 @@
       }
 
       terms[1] = '\0';
-      Value* subst = ParseExprImpl(loc, s.substr(i+1), terms,
-                                   ParseExprOpt::NORMAL, &n);
+      Value* subst =
+          ParseExprImpl(loc, s.substr(i + 1), terms, ParseExprOpt::NORMAL, &n);
       i += 1 + n;
       *index_out = i + 1;
       return new VarSubst(vname->Compact(), pat, subst);
@@ -433,18 +419,20 @@
     // for detail.
     size_t found = s.find(cp);
     if (found != string::npos) {
-      KATI_WARN_LOC(loc, "*warning*: unmatched parentheses: %.*s",
-                    SPF(s));
+      KATI_WARN_LOC(loc, "*warning*: unmatched parentheses: %.*s", SPF(s));
       *index_out = s.size();
-      return new SymRef(Intern(s.substr(2, found-2)));
+      return new SymRef(Intern(s.substr(2, found - 2)));
     }
     ERROR_LOC(loc, "*** unterminated variable reference.");
   }
 }
 
 Value* ParseExprImpl(const Loc& loc,
-                     StringPiece s, const char* terms, ParseExprOpt opt,
-                     size_t* index_out, bool trim_right_space) {
+                     StringPiece s,
+                     const char* terms,
+                     ParseExprOpt opt,
+                     size_t* index_out,
+                     bool trim_right_space) {
   if (s.get(s.size() - 1) == '\r')
     s.remove_suffix(1);
 
@@ -462,7 +450,7 @@
     // Handle a comment.
     if (!terms && c == '#' && ShouldHandleComments(opt)) {
       if (i > b)
-        r->AddValue(new Literal(s.substr(b, i-b)));
+        r->AddValue(new Literal(s.substr(b, i - b)));
       bool was_backslash = false;
       for (; i < s.size() && !(s[i] == '\n' && !was_backslash); i++) {
         was_backslash = !was_backslash && s[i] == '\\';
@@ -477,16 +465,16 @@
       }
 
       if (i > b)
-        r->AddValue(new Literal(s.substr(b, i-b)));
+        r->AddValue(new Literal(s.substr(b, i - b)));
 
-      if (s[i+1] == '$') {
+      if (s[i + 1] == '$') {
         r->AddValue(new Literal(StringPiece("$")));
         i += 1;
         b = i + 1;
         continue;
       }
 
-      if (terms && strchr(terms, s[i+1])) {
+      if (terms && strchr(terms, s[i + 1])) {
         *index_out = i + 1;
         return r->Compact();
       }
@@ -521,13 +509,13 @@
     }
 
     if (c == '\\' && i + 1 < s.size() && opt != ParseExprOpt::COMMAND) {
-      char n = s[i+1];
+      char n = s[i + 1];
       if (n == '\\') {
         i++;
         continue;
       }
       if (n == '#' && ShouldHandleComments(opt)) {
-        r->AddValue(new Literal(s.substr(b, i-b)));
+        r->AddValue(new Literal(s.substr(b, i - b)));
         i++;
         b = i;
         continue;
@@ -537,7 +525,7 @@
           break;
         }
         if (i > b) {
-          r->AddValue(new Literal(TrimRightSpace(s.substr(b, i-b))));
+          r->AddValue(new Literal(TrimRightSpace(s.substr(b, i - b))));
         }
         r->AddValue(new Literal(StringPiece(" ")));
         // Skip the current escaped newline
@@ -546,7 +534,7 @@
           i++;
         // Then continue skipping escaped newlines, spaces, and tabs
         for (; i < s.size(); i++) {
-          if (s[i] == '\\' && (s.get(i+1) == '\r' || s.get(i+1) == '\n')) {
+          if (s[i] == '\\' && (s.get(i + 1) == '\r' || s.get(i + 1) == '\n')) {
             i++;
             continue;
           }
@@ -561,7 +549,7 @@
   }
 
   if (i > b) {
-    StringPiece rest = s.substr(b, i-b);
+    StringPiece rest = s.substr(b, i - b);
     if (trim_right_space)
       rest = TrimRightSpace(rest);
     if (!rest.empty())
diff --git a/expr.h b/expr.h
index fdd6d36..588c6f7 100644
--- a/expr.h
+++ b/expr.h
@@ -59,10 +59,14 @@
   FUNC,
 };
 
-Value* ParseExprImpl(const Loc& loc, StringPiece s, const char* terms,
+Value* ParseExprImpl(const Loc& loc,
+                     StringPiece s,
+                     const char* terms,
                      ParseExprOpt opt,
-                     size_t* index_out, bool trim_right_space = false);
-Value* ParseExpr(const Loc& loc, StringPiece s,
+                     size_t* index_out,
+                     bool trim_right_space = false);
+Value* ParseExpr(const Loc& loc,
+                 StringPiece s,
                  ParseExprOpt opt = ParseExprOpt::NORMAL);
 
 string JoinValues(const vector<Value*>& vals, const char* sep);
diff --git a/file_cache.cc b/file_cache.cc
index afdb3bd..fe16c3b 100644
--- a/file_cache.cc
+++ b/file_cache.cc
@@ -32,9 +32,7 @@
 
 class MakefileCacheManagerImpl : public MakefileCacheManager {
  public:
-  MakefileCacheManagerImpl() {
-    g_instance = this;
-  }
+  MakefileCacheManagerImpl() { g_instance = this; }
 
   virtual ~MakefileCacheManagerImpl() {
     for (auto p : cache_) {
@@ -58,7 +56,7 @@
       out->insert(p.first);
   }
 
-private:
+ private:
   unordered_map<string, Makefile*> cache_;
 };
 
diff --git a/fileutil.cc b/fileutil.cc
index 4cf653b..7ebb8ec 100644
--- a/fileutil.cc
+++ b/fileutil.cc
@@ -60,10 +60,12 @@
   return GetTimestampFromStat(st);
 }
 
-int RunCommand(const string& shell, const string& shellflag,
-               const string& cmd, RedirectStderr redirect_stderr,
+int RunCommand(const string& shell,
+               const string& shellflag,
+               const string& cmd,
+               RedirectStderr redirect_stderr,
                string* s) {
-  const char* argv[] = { NULL, NULL, NULL, NULL };
+  const char* argv[] = {NULL, NULL, NULL, NULL};
   string cmd_with_shell;
   if (shell[0] != '/' || shell.find_first_of(" $") != string::npos) {
     string cmd_escaped = cmd;
@@ -98,7 +100,7 @@
           PERROR("read failed");
         if (r == 0)
           break;
-        s->append(buf, buf+r);
+        s->append(buf, buf + r);
       }
 
       if (result != 0) {
@@ -156,9 +158,7 @@
 
 class GlobCache {
  public:
-  ~GlobCache() {
-    Clear();
-  }
+  ~GlobCache() { Clear(); }
 
   void Get(const char* pat, vector<string>** files) {
     auto p = cache_.emplace(pat, nullptr);
diff --git a/fileutil.h b/fileutil.h
index 264d9e1..ba5b9b6 100644
--- a/fileutil.h
+++ b/fileutil.h
@@ -36,8 +36,10 @@
   DEV_NULL,
 };
 
-int RunCommand(const string& shell, const string& shellflag,
-               const string& cmd, RedirectStderr redirect_stderr,
+int RunCommand(const string& shell,
+               const string& shellflag,
+               const string& cmd,
+               RedirectStderr redirect_stderr,
                string* out);
 
 void GetExecutablePath(string* path);
@@ -48,12 +50,13 @@
 
 void ClearGlobCache();
 
-#define HANDLE_EINTR(x) ({                                \
-      int r;                                              \
-      do {                                                \
-        r = (x);                                          \
-      } while (r == -1 && errno == EINTR);                \
-      r;                                                  \
-    })
+#define HANDLE_EINTR(x)                  \
+  ({                                     \
+    int r;                               \
+    do {                                 \
+      r = (x);                           \
+    } while (r == -1 && errno == EINTR); \
+    r;                                   \
+  })
 
 #endif  // FILEUTIL_H_
diff --git a/fileutil_bench.cc b/fileutil_bench.cc
index 77a0d35..367c125 100644
--- a/fileutil_bench.cc
+++ b/fileutil_bench.cc
@@ -14,9 +14,9 @@
 
 // +build ignore
 
-#include "fileutil.h"
 #include <benchmark/benchmark.h>
 #include <cstdio>
+#include "fileutil.h"
 
 static void BM_RunCommand(benchmark::State& state) {
   std::string shell = "/bin/bash";
diff --git a/find.cc b/find.cc
index c36c468..a1675d2 100644
--- a/find.cc
+++ b/find.cc
@@ -35,7 +35,8 @@
 #include "strutil.h"
 #include "timeutil.h"
 
-#define FIND_WARN_LOC(...) do {         \
+#define FIND_WARN_LOC(...)              \
+  do {                                  \
     if (g_flags.werror_find_emulator) { \
       ERROR_LOC(__VA_ARGS__);           \
     } else {                            \
@@ -49,6 +50,7 @@
   virtual bool IsTrue(const string& path, unsigned char type) const = 0;
   virtual bool Countable() const = 0;
   virtual unsigned Count() const = 0;
+
  protected:
   FindCond() = default;
 };
@@ -57,19 +59,15 @@
 
 class NameCond : public FindCond {
  public:
-  explicit NameCond(const string& n)
-      : name_(n) {
+  explicit NameCond(const string& n) : name_(n) {
     has_wildcard_ = (n.find_first_of("?*[") != string::npos);
   }
   virtual bool IsTrue(const string& path, unsigned char) const override {
     return fnmatch(name_.c_str(), Basename(path).data(), 0) == 0;
   }
-  virtual bool Countable() const override {
-    return !has_wildcard_;
-  }
-  virtual unsigned Count() const override {
-    return 1;
-  }
+  virtual bool Countable() const override { return !has_wildcard_; }
+  virtual unsigned Count() const override { return 1; }
+
  private:
   string name_;
   bool has_wildcard_;
@@ -77,76 +75,61 @@
 
 class TypeCond : public FindCond {
  public:
-  explicit TypeCond(unsigned char t)
-      : type_(t) {
-  }
+  explicit TypeCond(unsigned char t) : type_(t) {}
   virtual bool IsTrue(const string&, unsigned char type) const override {
     return type == type_;
   }
-  virtual bool Countable() const override {
-    return false;
-  }
-  virtual unsigned Count() const override {
-    return 0;
-  }
+  virtual bool Countable() const override { return false; }
+  virtual unsigned Count() const override { return 0; }
+
  private:
   unsigned char type_;
 };
 
 class NotCond : public FindCond {
  public:
-  NotCond(FindCond* c)
-      : c_(c) {
-  }
+  NotCond(FindCond* c) : c_(c) {}
   virtual bool IsTrue(const string& path, unsigned char type) const override {
     return !c_->IsTrue(path, type);
   }
-  virtual bool Countable() const override {
-    return false;
-  }
-  virtual unsigned Count() const override {
-    return 0;
-  }
+  virtual bool Countable() const override { return false; }
+  virtual unsigned Count() const override { return 0; }
+
  private:
   unique_ptr<FindCond> c_;
 };
 
 class AndCond : public FindCond {
  public:
-  AndCond(FindCond* c1, FindCond* c2)
-      : c1_(c1), c2_(c2) {
-  }
+  AndCond(FindCond* c1, FindCond* c2) : c1_(c1), c2_(c2) {}
   virtual bool IsTrue(const string& path, unsigned char type) const override {
     if (c1_->IsTrue(path, type))
       return c2_->IsTrue(path, type);
     return false;
   }
-  virtual bool Countable() const override {
-    return false;
-  }
-  virtual unsigned Count() const override {
-    return 0;
-  }
+  virtual bool Countable() const override { return false; }
+  virtual unsigned Count() const override { return 0; }
+
  private:
   unique_ptr<FindCond> c1_, c2_;
 };
 
 class OrCond : public FindCond {
  public:
-  OrCond(FindCond* c1, FindCond* c2)
-      : c1_(c1), c2_(c2) {
-  }
+  OrCond(FindCond* c1, FindCond* c2) : c1_(c1), c2_(c2) {}
   virtual bool IsTrue(const string& path, unsigned char type) const override {
     if (!c1_->IsTrue(path, type))
       return c2_->IsTrue(path, type);
     return true;
   }
   virtual bool Countable() const override {
-    return c1_->Countable() && c2_->Countable();;
+    return c1_->Countable() && c2_->Countable();
+    ;
   }
   virtual unsigned Count() const override {
     return c1_->Count() + c2_->Count();
   }
+
  private:
   unique_ptr<FindCond> c1_, c2_;
 };
@@ -155,10 +138,10 @@
  public:
   virtual ~DirentNode() = default;
 
-  virtual const DirentNode* FindDir(StringPiece) const {
-    return NULL;
-  }
-  virtual bool RunFind(const FindCommand& fc, const Loc& loc, int d,
+  virtual const DirentNode* FindDir(StringPiece) const { return NULL; }
+  virtual bool RunFind(const FindCommand& fc,
+                       const Loc& loc,
+                       int d,
                        string* path,
                        unordered_map<const DirentNode*, string>* cur_read_dirs,
                        vector<string>& out) const = 0;
@@ -190,10 +173,11 @@
 class DirentFileNode : public DirentNode {
  public:
   DirentFileNode(const string& name, unsigned char type)
-      : DirentNode(name), type_(type) {
-  }
+      : DirentNode(name), type_(type) {}
 
-  virtual bool RunFind(const FindCommand& fc, const Loc&, int d,
+  virtual bool RunFind(const FindCommand& fc,
+                       const Loc&,
+                       int d,
                        string* path,
                        unordered_map<const DirentNode*, string>*,
                        vector<string>& out) const override {
@@ -237,9 +221,7 @@
 
 class DirentDirNode : public DirentNode {
  public:
-  explicit DirentDirNode(const string& name)
-      : DirentNode(name) {
-  }
+  explicit DirentDirNode(const string& name) : DirentNode(name) {}
 
   ~DirentDirNode() {
     for (auto& p : children_) {
@@ -253,7 +235,8 @@
     size_t index = d.find('/');
     const string& p = d.substr(0, index).as_string();
     if (p.empty() || p == ".")
-      return FindDir(d.substr(index + 1));;
+      return FindDir(d.substr(index + 1));
+    ;
     for (auto& child : children_) {
       if (p == child.first) {
         if (index == string::npos)
@@ -265,13 +248,16 @@
     return NULL;
   }
 
-  virtual bool RunFind(const FindCommand& fc, const Loc& loc, int d,
+  virtual bool RunFind(const FindCommand& fc,
+                       const Loc& loc,
+                       int d,
                        string* path,
                        unordered_map<const DirentNode*, string>* cur_read_dirs,
                        vector<string>& out) const override {
     ScopedReadDirTracker srdt(this, *path, cur_read_dirs);
     if (!srdt.ok()) {
-      FIND_WARN_LOC(loc, "FindEmulator: find: File system loop detected; `%s' "
+      FIND_WARN_LOC(loc,
+                    "FindEmulator: find: File system loop detected; `%s' "
                     "is part of the same file system loop as `%s'.",
                     path->c_str(), srdt.conflicted().c_str());
       return true;
@@ -299,7 +285,7 @@
         // We will handle directories later.
         if (c->IsDirectory())
           continue;
-        if ((*path)[path->size()-1] != '/')
+        if ((*path)[path->size() - 1] != '/')
           *path += '/';
         *path += c->base();
         if (!c->RunFind(fc, loc, d + 1, path, cur_read_dirs, out))
@@ -327,7 +313,7 @@
         DirentNode* c = p.second;
         if (!c->IsDirectory())
           continue;
-        if ((*path)[path->size()-1] != '/')
+        if ((*path)[path->size() - 1] != '/')
           *path += '/';
         *path += c->base();
         if (!c->RunFind(fc, loc, d + 1, path, cur_read_dirs, out))
@@ -337,7 +323,7 @@
     } else {
       for (const auto& p : children_) {
         DirentNode* c = p.second;
-        if ((*path)[path->size()-1] != '/')
+        if ((*path)[path->size() - 1] != '/')
           *path += '/';
         *path += c->base();
         if (!c->RunFind(fc, loc, d + 1, path, cur_read_dirs, out))
@@ -361,8 +347,7 @@
 class DirentSymlinkNode : public DirentNode {
  public:
   explicit DirentSymlinkNode(const string& name)
-      : DirentNode(name), to_(NULL), errno_(0) {
-  }
+      : DirentNode(name), to_(NULL), errno_(0) {}
 
   virtual const DirentNode* FindDir(StringPiece d) const override {
     if (errno_ == 0 && to_)
@@ -370,7 +355,9 @@
     return NULL;
   }
 
-  virtual bool RunFind(const FindCommand& fc, const Loc& loc, int d,
+  virtual bool RunFind(const FindCommand& fc,
+                       const Loc& loc,
+                       int d,
                        string* path,
                        unordered_map<const DirentNode*, string>* cur_read_dirs,
                        vector<string>& out) const override {
@@ -378,8 +365,8 @@
     if (fc.follows_symlinks && errno_ != ENOENT) {
       if (errno_) {
         if (fc.type != FindCommandType::FINDLEAVES) {
-          FIND_WARN_LOC(loc, "FindEmulator: find: `%s': %s",
-                        path->c_str(), strerror(errno_));
+          FIND_WARN_LOC(loc, "FindEmulator: find: `%s': %s", path->c_str(),
+                        strerror(errno_));
         }
         return true;
       }
@@ -399,13 +386,9 @@
     return errno_ == 0 && to_ && to_->IsDirectory();
   }
 
-  void set_to(const DirentNode* to) {
-    to_ = to;
-  }
+  void set_to(const DirentNode* to) { to_ = to; }
 
-  void set_errno(int e) {
-    errno_ = e;
-  }
+  void set_errno(int e) { errno_ = e; }
 
  private:
   const DirentNode* to_;
@@ -415,8 +398,7 @@
 class FindCommandParser {
  public:
   FindCommandParser(StringPiece cmd, FindCommand* fc)
-      : cmd_(cmd), fc_(fc), has_if_(false) {
-  }
+      : cmd_(cmd), fc_(fc), has_if_(false) {}
 
   bool Parse() {
     cur_ = cmd_;
@@ -453,8 +435,8 @@
     }
 
     size_t i = 0;
-    while (i < cur_.size() && !isspace(cur_[i]) &&
-           cur_[i] != ';' && cur_[i] != '&') {
+    while (i < cur_.size() && !isspace(cur_[i]) && cur_[i] != ';' &&
+           cur_[i] != '&') {
       i++;
     }
 
@@ -463,7 +445,7 @@
 
     const char c = tok->get(0);
     if (c == '\'' || c == '"') {
-      if (tok->size() < 2 || (*tok)[tok->size()-1] != c)
+      if (tok->size() < 2 || (*tok)[tok->size() - 1] != c)
         return false;
       *tok = tok->substr(1, tok->size() - 2);
       return true;
@@ -589,9 +571,7 @@
   // <name> ::= '-name' NAME
   // <type> ::= '-type' TYPE
   // <maxdepth> ::= '-maxdepth' MAXDEPTH
-  FindCond* ParseFindCond(StringPiece tok) {
-    return ParseExpr(tok);
-  }
+  FindCond* ParseFindCond(StringPiece tok) { return ParseExpr(tok); }
 
   bool ParseFind() {
     fc_->type = FindCommandType::FIND;
@@ -620,8 +600,8 @@
         const string& depth_str = tok.as_string();
         char* endptr;
         long d = strtol(depth_str.c_str(), &endptr, 10);
-        if (endptr != depth_str.data() + depth_str.size() ||
-            d < 0 || d > INT_MAX) {
+        if (endptr != depth_str.data() + depth_str.size() || d < 0 ||
+            d > INT_MAX) {
           return false;
         }
         fc_->depth = d;
@@ -677,8 +657,8 @@
       }
 
       if (HasPrefix(tok, "--prune=")) {
-        FindCond* cond = new NameCond(
-            tok.substr(strlen("--prune=")).as_string());
+        FindCond* cond =
+            new NameCond(tok.substr(strlen("--prune=")).as_string());
         if (fc_->prune_cond.get()) {
           cond = new OrCond(fc_->prune_cond.release(), cond);
         }
@@ -694,7 +674,7 @@
         }
         fc_->mindepth = d;
       } else if (HasPrefix(tok, "--dir=")) {
-        StringPiece dir= tok.substr(strlen("--dir="));
+        StringPiece dir = tok.substr(strlen("--dir="));
         fc_->finddirs.push_back(dir.as_string());
       } else if (HasPrefix(tok, "--")) {
         if (g_flags.werror_find_emulator) {
@@ -774,18 +754,15 @@
 
 class FindEmulatorImpl : public FindEmulator {
  public:
-  FindEmulatorImpl()
-      : node_cnt_(0), is_initialized_(false) {
+  FindEmulatorImpl() : node_cnt_(0), is_initialized_(false) {
     g_instance = this;
   }
 
   virtual ~FindEmulatorImpl() = default;
 
   bool CanHandle(StringPiece s) const {
-    return (!HasPrefix(s, "../") &&
-            !HasPrefix(s, "/") &&
-            !HasPrefix(s, ".repo") &&
-            !HasPrefix(s, ".git"));
+    return (!HasPrefix(s, "../") && !HasPrefix(s, "/") &&
+            !HasPrefix(s, ".repo") && !HasPrefix(s, ".git"));
   }
 
   const DirentNode* FindDir(StringPiece d, bool* should_fallback) {
@@ -796,11 +773,13 @@
     return r;
   }
 
-  virtual bool HandleFind(const string& cmd UNUSED, const FindCommand& fc,
-                          const Loc& loc, string* out) override {
+  virtual bool HandleFind(const string& cmd UNUSED,
+                          const FindCommand& fc,
+                          const Loc& loc,
+                          string* out) override {
     if (!CanHandle(fc.chdir)) {
-      LOG("FindEmulator: Cannot handle chdir (%.*s): %s",
-          SPF(fc.chdir), cmd.c_str());
+      LOG("FindEmulator: Cannot handle chdir (%.*s): %s", SPF(fc.chdir),
+          cmd.c_str());
       return false;
     }
 
@@ -817,14 +796,14 @@
 
     if (!fc.testdir.empty()) {
       if (!CanHandle(fc.testdir)) {
-        LOG("FindEmulator: Cannot handle test dir (%.*s): %s",
-            SPF(fc.testdir), cmd.c_str());
+        LOG("FindEmulator: Cannot handle test dir (%.*s): %s", SPF(fc.testdir),
+            cmd.c_str());
         return false;
       }
       bool should_fallback = false;
       if (!FindDir(fc.testdir, &should_fallback)) {
-        LOG("FindEmulator: Test dir (%.*s) not found: %s",
-            SPF(fc.testdir), cmd.c_str());
+        LOG("FindEmulator: Test dir (%.*s) not found: %s", SPF(fc.testdir),
+            cmd.c_str());
         return !should_fallback;
       }
     }
@@ -833,8 +812,8 @@
 
     if (!fc.chdir.empty()) {
       if (!CanHandle(fc.chdir)) {
-        LOG("FindEmulator: Cannot handle chdir (%.*s): %s",
-            SPF(fc.chdir), cmd.c_str());
+        LOG("FindEmulator: Cannot handle chdir (%.*s): %s", SPF(fc.chdir),
+            cmd.c_str());
         return false;
       }
       root = root->FindDir(fc.chdir);
@@ -842,7 +821,8 @@
         if (Exists(fc.chdir))
           return false;
         if (!fc.redirect_to_devnull) {
-          FIND_WARN_LOC(loc, "FindEmulator: cd: %.*s: No such file or directory",
+          FIND_WARN_LOC(loc,
+                        "FindEmulator: cd: %.*s: No such file or directory",
                         SPF(fc.chdir));
         }
         return true;
@@ -852,8 +832,8 @@
     vector<string> results;
     for (const string& finddir : fc.finddirs) {
       if (!CanHandle(finddir)) {
-        LOG("FindEmulator: Cannot handle find dir (%s): %s",
-            finddir.c_str(), cmd.c_str());
+        LOG("FindEmulator: Cannot handle find dir (%s): %s", finddir.c_str(),
+            cmd.c_str());
         return false;
       }
 
@@ -864,7 +844,8 @@
           return false;
         }
         if (!fc.redirect_to_devnull) {
-          FIND_WARN_LOC(loc, "FindEmulator: find: `%s': No such file or directory",
+          FIND_WARN_LOC(loc,
+                        "FindEmulator: find: `%s': No such file or directory",
                         ConcatDir(fc.chdir, finddir).c_str());
         }
         continue;
@@ -944,10 +925,8 @@
 
     struct dirent* ent;
     while ((ent = readdir(dir)) != NULL) {
-      if (!strcmp(ent->d_name, ".") ||
-          !strcmp(ent->d_name, "..") ||
-          !strcmp(ent->d_name, ".repo") ||
-          !strcmp(ent->d_name, ".git"))
+      if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..") ||
+          !strcmp(ent->d_name, ".repo") || !strcmp(ent->d_name, ".git"))
         continue;
 
       string npath = path;
@@ -988,7 +967,7 @@
       const string& path = p.first;
       DirentSymlinkNode* s = p.second;
 
-      char buf[PATH_MAX+1];
+      char buf[PATH_MAX + 1];
       buf[PATH_MAX] = 0;
       ssize_t len = readlink(path.c_str(), buf, PATH_MAX);
       if (len < 0) {
@@ -1026,7 +1005,7 @@
           }
         }
       } else if (type != DT_LNK && type != DT_UNKNOWN) {
-          s->set_to(new DirentFileNode(path, type));
+        s->set_to(new DirentFileNode(path, type));
       }
     }
 
@@ -1043,14 +1022,14 @@
 }  // namespace
 
 FindCommand::FindCommand()
-    : follows_symlinks(false), depth(INT_MAX), mindepth(INT_MIN),
+    : follows_symlinks(false),
+      depth(INT_MAX),
+      mindepth(INT_MIN),
       redirect_to_devnull(false),
       found_files(new vector<string>()),
-      read_dirs(new unordered_set<string>()) {
-}
+      read_dirs(new unordered_set<string>()) {}
 
-FindCommand::~FindCommand() {
-}
+FindCommand::~FindCommand() {}
 
 bool FindCommand::Parse(const string& cmd) {
   FindCommandParser fcp(cmd, this);
diff --git a/find.h b/find.h
index 9af261a..8cf3674 100644
--- a/find.h
+++ b/find.h
@@ -62,8 +62,10 @@
  public:
   virtual ~FindEmulator() = default;
 
-  virtual bool HandleFind(const string& cmd, const FindCommand& fc,
-                          const Loc& loc, string* out) = 0;
+  virtual bool HandleFind(const string& cmd,
+                          const FindCommand& fc,
+                          const Loc& loc,
+                          string* out) = 0;
 
   static FindEmulator* Get();
 
diff --git a/find_test.cc b/find_test.cc
index 2ee7e39..10f865c 100644
--- a/find_test.cc
+++ b/find_test.cc
@@ -16,8 +16,8 @@
 
 #include "find.h"
 
-#include <string>
 #include <unistd.h>
+#include <string>
 
 #include "fileutil.h"
 #include "strutil.h"
@@ -92,10 +92,15 @@
     auto nativeIter = nativeWords.begin();
     auto emulatedIter = emulatedWords.begin();
     fprintf(stderr, "%-20s %-20s\n", "Native:", "Emulated:");
-    while (nativeIter != nativeWords.end() || emulatedIter != emulatedWords.end()) {
+    while (nativeIter != nativeWords.end() ||
+           emulatedIter != emulatedWords.end()) {
       fprintf(stderr, " %-20s %-20s\n",
-              (nativeIter == nativeWords.end()) ? "" : (*nativeIter++).as_string().c_str(),
-              (emulatedIter == emulatedWords.end()) ? "" : (*emulatedIter++).as_string().c_str());
+              (nativeIter == nativeWords.end())
+                  ? ""
+                  : (*nativeIter++).as_string().c_str(),
+              (emulatedIter == emulatedWords.end())
+                  ? ""
+                  : (*emulatedIter++).as_string().c_str());
     }
     fprintf(stderr, "------------------------------------------\n");
     unit_test_failed = true;
diff --git a/flags.cc b/flags.cc
index 5f34835..0ac33bb 100644
--- a/flags.cc
+++ b/flags.cc
@@ -103,35 +103,32 @@
       werror_find_emulator = true;
     } else if (!strcmp(arg, "--werror_overriding_commands")) {
       werror_overriding_commands = true;
-    } else if (ParseCommandLineOptionWithArg(
-        "-j", argv, &i, &num_jobs_str)) {
+    } else if (ParseCommandLineOptionWithArg("-j", argv, &i, &num_jobs_str)) {
       num_jobs = strtol(num_jobs_str, NULL, 10);
       if (num_jobs <= 0) {
         ERROR("Invalid -j flag: %s", num_jobs_str);
       }
-    } else if (ParseCommandLineOptionWithArg(
-        "--remote_num_jobs", argv, &i, &num_jobs_str)) {
+    } else if (ParseCommandLineOptionWithArg("--remote_num_jobs", argv, &i,
+                                             &num_jobs_str)) {
       remote_num_jobs = strtol(num_jobs_str, NULL, 10);
       if (remote_num_jobs <= 0) {
         ERROR("Invalid -j flag: %s", num_jobs_str);
       }
-    } else if (ParseCommandLineOptionWithArg(
-        "--ninja_suffix", argv, &i, &ninja_suffix)) {
-    } else if (ParseCommandLineOptionWithArg(
-        "--ninja_dir", argv, &i, &ninja_dir)) {
+    } else if (ParseCommandLineOptionWithArg("--ninja_suffix", argv, &i,
+                                             &ninja_suffix)) {
+    } else if (ParseCommandLineOptionWithArg("--ninja_dir", argv, &i,
+                                             &ninja_dir)) {
     } else if (!strcmp(arg, "--use_find_emulator")) {
       use_find_emulator = true;
+    } else if (ParseCommandLineOptionWithArg("--goma_dir", argv, &i,
+                                             &goma_dir)) {
     } else if (ParseCommandLineOptionWithArg(
-        "--goma_dir", argv, &i, &goma_dir)) {
-    } else if (ParseCommandLineOptionWithArg(
-        "--ignore_optional_include",
-        argv, &i, &ignore_optional_include_pattern)) {
-    } else if (ParseCommandLineOptionWithArg(
-        "--ignore_dirty",
-        argv, &i, &ignore_dirty_pattern)) {
-    } else if (ParseCommandLineOptionWithArg(
-        "--no_ignore_dirty",
-        argv, &i, &no_ignore_dirty_pattern)) {
+                   "--ignore_optional_include", argv, &i,
+                   &ignore_optional_include_pattern)) {
+    } else if (ParseCommandLineOptionWithArg("--ignore_dirty", argv, &i,
+                                             &ignore_dirty_pattern)) {
+    } else if (ParseCommandLineOptionWithArg("--no_ignore_dirty", argv, &i,
+                                             &no_ignore_dirty_pattern)) {
     } else if (arg[0] == '-') {
       ERROR("Unknown flag: %s", arg);
     } else {
diff --git a/func.cc b/func.cc
index cc55f70..220aee0 100644
--- a/func.cc
+++ b/func.cc
@@ -216,9 +216,9 @@
   const string&& n_str = args[0]->Eval(ev);
   int n = GetNumericValueForFunc(n_str);
   if (n < 0) {
-    ev->Error(StringPrintf(
-        "*** non-numeric first argument to `word' function: '%s'.",
-        n_str.c_str()));
+    ev->Error(
+        StringPrintf("*** non-numeric first argument to `word' function: '%s'.",
+                     n_str.c_str()));
   }
   if (n == 0) {
     ev->Error("*** first argument to `word' function must be greater than 0.");
@@ -243,9 +243,9 @@
         s_str.c_str()));
   }
   if (si == 0) {
-    ev->Error(StringPrintf(
-        "*** invalid first argument to `wordlist' function: %s`",
-        s_str.c_str()));
+    ev->Error(
+        StringPrintf("*** invalid first argument to `wordlist' function: %s`",
+                     s_str.c_str()));
   }
 
   const string&& e_str = args[1]->Eval(ev);
@@ -303,8 +303,7 @@
   WordWriter ww(s);
   WordScanner::Iterator iter1, iter2;
   for (iter1 = ws1.begin(), iter2 = ws2.begin();
-       iter1 != ws1.end() && iter2 != ws2.end();
-       ++iter1, ++iter2) {
+       iter1 != ws1.end() && iter2 != ws2.end(); ++iter1, ++iter2) {
     ww.Write(*iter1);
     // Use |AppendString| not to append extra ' '.
     AppendString(*iter2, s);
@@ -462,11 +461,13 @@
 
 void EvalFunc(const vector<Value*>& args, Evaluator* ev, string*) {
   // TODO: eval leaks everything... for now.
-  //const string text = args[0]->Eval(ev);
+  // const string text = args[0]->Eval(ev);
+  ev->CheckStack();
   string* text = new string;
   args[0]->Eval(ev, text);
   if (ev->avoid_io()) {
-    KATI_WARN_LOC(ev->loc(), "*warning*: $(eval) in a recipe is not recommended: %s",
+    KATI_WARN_LOC(ev->loc(),
+                  "*warning*: $(eval) in a recipe is not recommended: %s",
                   text->c_str());
   }
   vector<Stmt*> stmts;
@@ -474,7 +475,7 @@
   for (Stmt* stmt : stmts) {
     LOG("%s", stmt->DebugString().c_str());
     stmt->Eval(ev);
-    //delete stmt;
+    // delete stmt;
   }
 }
 
@@ -488,13 +489,16 @@
 static bool HasNoIoInShellScript(const string& cmd) {
   if (cmd.empty())
     return true;
-  if (HasPrefix(cmd, "echo $((") && cmd[cmd.size()-1] == ')')
+  if (HasPrefix(cmd, "echo $((") && cmd[cmd.size() - 1] == ')')
     return true;
   return false;
 }
 
-static void ShellFuncImpl(const string& shell, const string& shellflag,
-                          const string& cmd, const Loc& loc, string* s,
+static void ShellFuncImpl(const string& shell,
+                          const string& shellflag,
+                          const string& cmd,
+                          const Loc& loc,
+                          string* s,
                           FindCommand** fc) {
   LOG("ShellFunc: %s", cmd.c_str());
 
@@ -526,8 +530,8 @@
 #ifdef TEST_FIND_EMULATOR
   if (need_check) {
     if (*s != out2) {
-      ERROR("FindEmulator is broken: %s\n%s\nvs\n%s",
-            cmd.c_str(), s->c_str(), out2.c_str());
+      ERROR("FindEmulator is broken: %s\n%s\nvs\n%s", cmd.c_str(), s->c_str(),
+            out2.c_str());
     }
   }
 #endif
@@ -556,7 +560,8 @@
   string cmd = args[0]->Eval(ev);
   if (ev->avoid_io() && !HasNoIoInShellScript(cmd)) {
     if (ev->eval_depth() > 1) {
-      ERROR_LOC(ev->loc(), "kati doesn't support passing results of $(shell) "
+      ERROR_LOC(ev->loc(),
+                "kati doesn't support passing results of $(shell) "
                 "to other make constructs: %s",
                 cmd.c_str());
     }
@@ -588,10 +593,10 @@
 
 void CallFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
   static const Symbol tmpvar_names[] = {
-    Intern("0"), Intern("1"),  Intern("2"), Intern("3"), Intern("4"),
-    Intern("5"), Intern("6"),  Intern("7"), Intern("8"), Intern("9")
-  };
+      Intern("0"), Intern("1"), Intern("2"), Intern("3"), Intern("4"),
+      Intern("5"), Intern("6"), Intern("7"), Intern("8"), Intern("9")};
 
+  ev->CheckStack();
   const string&& func_name_buf = args[0]->Eval(ev);
   const StringPiece func_name = TrimSpace(func_name_buf);
   Var* func = ev->LookupVar(Intern(func_name));
@@ -606,25 +611,27 @@
     av.push_back(move(s));
   }
   vector<unique_ptr<ScopedGlobalVar>> sv;
-  for (size_t i = 1; ; i++) {
+  for (size_t i = 1;; i++) {
     string s;
     Symbol tmpvar_name_sym(Symbol::IsUninitialized{});
-    if (i < sizeof(tmpvar_names)/sizeof(tmpvar_names[0])) {
+    if (i < sizeof(tmpvar_names) / sizeof(tmpvar_names[0])) {
       tmpvar_name_sym = tmpvar_names[i];
     } else {
       s = StringPrintf("%d", i);
       tmpvar_name_sym = Intern(s);
     }
     if (i < args.size()) {
-      sv.emplace_back(new ScopedGlobalVar(tmpvar_name_sym, av[i-1].get()));
+      sv.emplace_back(new ScopedGlobalVar(tmpvar_name_sym, av[i - 1].get()));
     } else {
       // We need to blank further automatic vars
-      Var *v = ev->LookupVar(tmpvar_name_sym);
-      if (!v->IsDefined()) break;
-      if (v->Origin() != VarOrigin::AUTOMATIC) break;
+      Var* v = ev->LookupVar(tmpvar_name_sym);
+      if (!v->IsDefined())
+        break;
+      if (v->Origin() != VarOrigin::AUTOMATIC)
+        break;
 
       av.emplace_back(new SimpleVar("", VarOrigin::AUTOMATIC));
-      sv.emplace_back(new ScopedGlobalVar(tmpvar_name_sym, av[i-1].get()));
+      sv.emplace_back(new ScopedGlobalVar(tmpvar_name_sym, av[i - 1].get()));
     }
   }
 
@@ -639,8 +646,8 @@
   ev->DecrementEvalDepth();
   WordWriter ww(s);
   for (StringPiece tok : WordScanner(list)) {
-    unique_ptr<SimpleVar> v(new SimpleVar(
-        tok.as_string(), VarOrigin::AUTOMATIC));
+    unique_ptr<SimpleVar> v(
+        new SimpleVar(tok.as_string(), VarOrigin::AUTOMATIC));
     ScopedGlobalVar sv(Intern(varname), v.get());
     ww.MaybeAddWhitespace();
     args[2]->Eval(ev, s);
@@ -663,7 +670,8 @@
 void InfoFunc(const vector<Value*>& args, Evaluator* ev, string*) {
   const string&& a = args[0]->Eval(ev);
   if (ev->avoid_io()) {
-    ev->add_delayed_output_command(StringPrintf("echo -e \"%s\"", EchoEscape(a).c_str()));
+    ev->add_delayed_output_command(
+        StringPrintf("echo -e \"%s\"", EchoEscape(a).c_str()));
     return;
   }
   printf("%s\n", a.c_str());
@@ -673,8 +681,8 @@
 void WarningFunc(const vector<Value*>& args, Evaluator* ev, string*) {
   const string&& a = args[0]->Eval(ev);
   if (ev->avoid_io()) {
-    ev->add_delayed_output_command(
-        StringPrintf("echo -e \"%s:%d: %s\" 2>&1", LOCF(ev->loc()), EchoEscape(a).c_str()));
+    ev->add_delayed_output_command(StringPrintf(
+        "echo -e \"%s:%d: %s\" 2>&1", LOCF(ev->loc()), EchoEscape(a).c_str()));
     return;
   }
   WARN_LOC(ev->loc(), "%s", a.c_str());
@@ -737,7 +745,10 @@
   *s += out;
 }
 
-static void FileWriteFunc(Evaluator* ev, const string& filename, bool append, string text) {
+static void FileWriteFunc(Evaluator* ev,
+                          const string& filename,
+                          bool append,
+                          string text) {
   FILE* f = fopen(filename.c_str(), append ? "ab" : "wb");
   if (f == NULL) {
     ev->Error("*** fopen failed.");
@@ -805,7 +816,8 @@
 
     FileWriteFunc(ev, filename.as_string(), append, text);
   } else {
-    ev->Error(StringPrintf("*** Invalid file operation: %s.  Stop.", filename.as_string().c_str()));
+    ev->Error(StringPrintf("*** Invalid file operation: %s.  Stop.",
+                           filename.as_string().c_str()));
   }
 }
 
@@ -830,16 +842,22 @@
     }
 
     if (v->Deprecated()) {
-      ev->Error(StringPrintf("*** Cannot call KATI_deprecated_var on already deprecated variable: %s.", sym.c_str()));
+      ev->Error(
+          StringPrintf("*** Cannot call KATI_deprecated_var on already "
+                       "deprecated variable: %s.",
+                       sym.c_str()));
     } else if (v->Obsolete()) {
-      ev->Error(StringPrintf("*** Cannot call KATI_deprecated_var on already obsolete variable: %s.", sym.c_str()));
+      ev->Error(
+          StringPrintf("*** Cannot call KATI_deprecated_var on already "
+                       "obsolete variable: %s.",
+                       sym.c_str()));
     }
 
     v->SetDeprecated(msg);
   }
 }
 
-void ObsoleteVarFunc(const vector<Value*>&args, Evaluator* ev, string*) {
+void ObsoleteVarFunc(const vector<Value*>& args, Evaluator* ev, string*) {
   string vars_str = args[0]->Eval(ev);
   string msg;
 
@@ -860,9 +878,14 @@
     }
 
     if (v->Deprecated()) {
-      ev->Error(StringPrintf("*** Cannot call KATI_obsolete_var on already deprecated variable: %s.", sym.c_str()));
+      ev->Error(
+          StringPrintf("*** Cannot call KATI_obsolete_var on already "
+                       "deprecated variable: %s.",
+                       sym.c_str()));
     } else if (v->Obsolete()) {
-      ev->Error(StringPrintf("*** Cannot call KATI_obsolete_var on already obsolete variable: %s.", sym.c_str()));
+      ev->Error(StringPrintf(
+          "*** Cannot call KATI_obsolete_var on already obsolete variable: %s.",
+          sym.c_str()));
     }
 
     v->SetObsolete(msg);
@@ -870,52 +893,52 @@
 }
 
 FuncInfo g_func_infos[] = {
-  { "patsubst", &PatsubstFunc, 3, 3, false, false },
-  { "strip", &StripFunc, 1, 1, false, false },
-  { "subst", &SubstFunc, 3, 3, false, false },
-  { "findstring", &FindstringFunc, 2, 2, false, false },
-  { "filter", &FilterFunc, 2, 2, false, false },
-  { "filter-out", &FilterOutFunc, 2, 2, false, false },
-  { "sort", &SortFunc, 1, 1, false, false },
-  { "word", &WordFunc, 2, 2, false, false },
-  { "wordlist", &WordlistFunc, 3, 3, false, false },
-  { "words", &WordsFunc, 1, 1, false, false },
-  { "firstword", &FirstwordFunc, 1, 1, false, false },
-  { "lastword", &LastwordFunc, 1, 1, false, false },
+    {"patsubst", &PatsubstFunc, 3, 3, false, false},
+    {"strip", &StripFunc, 1, 1, false, false},
+    {"subst", &SubstFunc, 3, 3, false, false},
+    {"findstring", &FindstringFunc, 2, 2, false, false},
+    {"filter", &FilterFunc, 2, 2, false, false},
+    {"filter-out", &FilterOutFunc, 2, 2, false, false},
+    {"sort", &SortFunc, 1, 1, false, false},
+    {"word", &WordFunc, 2, 2, false, false},
+    {"wordlist", &WordlistFunc, 3, 3, false, false},
+    {"words", &WordsFunc, 1, 1, false, false},
+    {"firstword", &FirstwordFunc, 1, 1, false, false},
+    {"lastword", &LastwordFunc, 1, 1, false, false},
 
-  { "join", &JoinFunc, 2, 2, false, false },
-  { "wildcard", &WildcardFunc, 1, 1, false, false },
-  { "dir", &DirFunc, 1, 1, false, false },
-  { "notdir", &NotdirFunc, 1, 1, false, false },
-  { "suffix", &SuffixFunc, 1, 1, false, false },
-  { "basename", &BasenameFunc, 1, 1, false, false },
-  { "addsuffix", &AddsuffixFunc, 2, 2, false, false },
-  { "addprefix", &AddprefixFunc, 2, 2, false, false },
-  { "realpath", &RealpathFunc, 1, 1, false, false },
-  { "abspath", &AbspathFunc, 1, 1, false, false },
+    {"join", &JoinFunc, 2, 2, false, false},
+    {"wildcard", &WildcardFunc, 1, 1, false, false},
+    {"dir", &DirFunc, 1, 1, false, false},
+    {"notdir", &NotdirFunc, 1, 1, false, false},
+    {"suffix", &SuffixFunc, 1, 1, false, false},
+    {"basename", &BasenameFunc, 1, 1, false, false},
+    {"addsuffix", &AddsuffixFunc, 2, 2, false, false},
+    {"addprefix", &AddprefixFunc, 2, 2, false, false},
+    {"realpath", &RealpathFunc, 1, 1, false, false},
+    {"abspath", &AbspathFunc, 1, 1, false, false},
 
-  { "if", &IfFunc, 3, 2, false, true },
-  { "and", &AndFunc, 0, 0, true, false },
-  { "or", &OrFunc, 0, 0, true, false },
+    {"if", &IfFunc, 3, 2, false, true},
+    {"and", &AndFunc, 0, 0, true, false},
+    {"or", &OrFunc, 0, 0, true, false},
 
-  { "value", &ValueFunc, 1, 1, false, false },
-  { "eval", &EvalFunc, 1, 1, false, false },
-  { "shell", &ShellFunc, 1, 1, false, false },
-  { "call", &CallFunc, 0, 0, false, false },
-  { "foreach", &ForeachFunc, 3, 3, false, false },
+    {"value", &ValueFunc, 1, 1, false, false},
+    {"eval", &EvalFunc, 1, 1, false, false},
+    {"shell", &ShellFunc, 1, 1, false, false},
+    {"call", &CallFunc, 0, 0, false, false},
+    {"foreach", &ForeachFunc, 3, 3, false, false},
 
-  { "origin", &OriginFunc, 1, 1, false, false },
-  { "flavor", &FlavorFunc, 1, 1, false, false },
+    {"origin", &OriginFunc, 1, 1, false, false},
+    {"flavor", &FlavorFunc, 1, 1, false, false},
 
-  { "info", &InfoFunc, 1, 1, false, false },
-  { "warning", &WarningFunc, 1, 1, false, false },
-  { "error", &ErrorFunc, 1, 1, false, false },
+    {"info", &InfoFunc, 1, 1, false, false},
+    {"warning", &WarningFunc, 1, 1, false, false},
+    {"error", &ErrorFunc, 1, 1, false, false},
 
-  { "file", &FileFunc, 2, 1, false, false },
+    {"file", &FileFunc, 2, 1, false, false},
 
-  /* Kati custom extension functions */
-  { "KATI_deprecated_var", &DeprecatedVarFunc, 2, 1, false, false },
-  { "KATI_obsolete_var", &ObsoleteVarFunc, 2, 1, false, false },
+    /* Kati custom extension functions */
+    {"KATI_deprecated_var", &DeprecatedVarFunc, 2, 1, false, false},
+    {"KATI_obsolete_var", &ObsoleteVarFunc, 2, 1, false, false},
 };
 
 unordered_map<StringPiece, FuncInfo*>* g_func_info_map;
diff --git a/io.h b/io.h
index 0193a89..28316f4 100644
--- a/io.h
+++ b/io.h
@@ -31,9 +31,7 @@
 
 struct ScopedFile {
  public:
-  explicit ScopedFile(FILE* fp)
-      : fp_(fp) {
-  }
+  explicit ScopedFile(FILE* fp) : fp_(fp) {}
 
   ~ScopedFile() {
     if (fp_)
diff --git a/loc.h b/loc.h
index 472f331..8c9ed9f 100644
--- a/loc.h
+++ b/loc.h
@@ -20,11 +20,8 @@
 #include "stringprintf.h"
 
 struct Loc {
-  Loc()
-      : filename(0), lineno(-1) {}
-  Loc(const char* f, int l)
-      : filename(f), lineno(l) {
-  }
+  Loc() : filename(0), lineno(-1) {}
+  Loc(const char* f, int l) : filename(f), lineno(l) {}
 
   const char* filename;
   int lineno;
diff --git a/log.cc b/log.cc
index b7141f6..62f2422 100644
--- a/log.cc
+++ b/log.cc
@@ -33,8 +33,8 @@
   if (g_flags.color_warnings) {
     StringPiece filtered = TrimPrefix(msg, "*** ");
 
-    ERROR(BOLD "%s:%d: " RED "error: " RESET BOLD "%s" RESET,
-          file, line, filtered.as_string().c_str());
+    ERROR(BOLD "%s:%d: " RED "error: " RESET BOLD "%s" RESET, file, line,
+          filtered.as_string().c_str());
   } else {
     ERROR("%s:%d: %s", file, line, msg);
   }
@@ -50,8 +50,9 @@
     StringPiece filtered = TrimPrefix(msg, "*warning*: ");
     filtered = TrimPrefix(filtered, "warning: ");
 
-    fprintf(stderr, BOLD "%s:%d: " MAGENTA "warning: " RESET BOLD "%s" RESET "\n",
-            file, line, filtered.as_string().c_str());
+    fprintf(stderr,
+            BOLD "%s:%d: " MAGENTA "warning: " RESET BOLD "%s" RESET "\n", file,
+            line, filtered.as_string().c_str());
   } else {
     fprintf(stderr, "%s:%d: %s\n", file, line, msg);
   }
diff --git a/log.h b/log.h
index 58c733a..ba0bd8b 100644
--- a/log.h
+++ b/log.h
@@ -35,60 +35,72 @@
 #ifdef NOLOG
 #define LOG(args...)
 #else
-#define LOG(args...) do {                                           \
-    fprintf(stderr, "*kati*: %s\n", StringPrintf(args).c_str());    \
-  } while(0)
+#define LOG(args...)                                             \
+  do {                                                           \
+    fprintf(stderr, "*kati*: %s\n", StringPrintf(args).c_str()); \
+  } while (0)
 #endif
 
-#define LOG_STAT(args...) do {                                      \
-    if (g_flags.enable_stat_logs)                                   \
-      fprintf(stderr, "*kati*: %s\n", StringPrintf(args).c_str());  \
-  } while(0)
-
-#define PLOG(...) do {                                              \
-    fprintf(stderr, "%s: %s\n", StringPrintf(__VA_ARGS__).c_str(),  \
-            strerror(errno));                                       \
+#define LOG_STAT(args...)                                          \
+  do {                                                             \
+    if (g_flags.enable_stat_logs)                                  \
+      fprintf(stderr, "*kati*: %s\n", StringPrintf(args).c_str()); \
   } while (0)
 
-#define PERROR(...) do {                                            \
-    PLOG(__VA_ARGS__);                                              \
-    exit(1);                                                        \
+#define PLOG(...)                                                  \
+  do {                                                             \
+    fprintf(stderr, "%s: %s\n", StringPrintf(__VA_ARGS__).c_str(), \
+            strerror(errno));                                      \
   } while (0)
 
-#define WARN(...) do {                                          \
+#define PERROR(...)    \
+  do {                 \
+    PLOG(__VA_ARGS__); \
+    exit(1);           \
+  } while (0)
+
+#define WARN(...)                                               \
+  do {                                                          \
     fprintf(stderr, "%s\n", StringPrintf(__VA_ARGS__).c_str()); \
   } while (0)
 
-#define KATI_WARN(...) do {                                             \
-    if (g_flags.enable_kati_warnings)                                   \
-      fprintf(stderr, "%s\n", StringPrintf(__VA_ARGS__).c_str());       \
+#define KATI_WARN(...)                                            \
+  do {                                                            \
+    if (g_flags.enable_kati_warnings)                             \
+      fprintf(stderr, "%s\n", StringPrintf(__VA_ARGS__).c_str()); \
   } while (0)
 
-#define ERROR(...) do {                                                 \
-    if (!g_log_no_exit) {                                               \
-      fprintf(stderr, "%s\n", StringPrintf(__VA_ARGS__).c_str());       \
-      exit(1);                                                          \
-    }                                                                   \
-    g_last_error = new string(StringPrintf(__VA_ARGS__));               \
+#define ERROR(...)                                                \
+  do {                                                            \
+    if (!g_log_no_exit) {                                         \
+      fprintf(stderr, "%s\n", StringPrintf(__VA_ARGS__).c_str()); \
+      exit(1);                                                    \
+    }                                                             \
+    g_last_error = new string(StringPrintf(__VA_ARGS__));         \
   } while (0)
 
-#define CHECK(c) if (!(c)) ERROR("%s:%d: %s", __FILE__, __LINE__, #c)
+#define CHECK(c) \
+  if (!(c))      \
+  ERROR("%s:%d: %s", __FILE__, __LINE__, #c)
 
 // Set of logging functions that will automatically colorize lines that have
 // location information when --color_warnings is set.
-void ColorWarnLog(const char* file, int line, const char *msg);
-void ColorErrorLog(const char* file, int line, const char *msg);
+void ColorWarnLog(const char* file, int line, const char* msg);
+void ColorErrorLog(const char* file, int line, const char* msg);
 
-#define WARN_LOC(loc, ...) do {                                 \
+#define WARN_LOC(loc, ...)                                      \
+  do {                                                          \
     ColorWarnLog(LOCF(loc), StringPrintf(__VA_ARGS__).c_str()); \
   } while (0)
 
-#define KATI_WARN_LOC(loc, ...) do {                                  \
+#define KATI_WARN_LOC(loc, ...)                                   \
+  do {                                                            \
     if (g_flags.enable_kati_warnings)                             \
       ColorWarnLog(LOCF(loc), StringPrintf(__VA_ARGS__).c_str()); \
-  } while(0)
+  } while (0)
 
-#define ERROR_LOC(loc, ...) do {                                 \
+#define ERROR_LOC(loc, ...)                                      \
+  do {                                                           \
     ColorErrorLog(LOCF(loc), StringPrintf(__VA_ARGS__).c_str()); \
   } while (0)
 
diff --git a/main.cc b/main.cc
index 2e45810..e89e17b 100644
--- a/main.cc
+++ b/main.cc
@@ -15,9 +15,10 @@
 // +build ignore
 
 #include <limits.h>
+#include <signal.h>
 #include <stdio.h>
-#include <string.h>
 #include <stdlib.h>
+#include <string.h>
 #include <time.h>
 #include <unistd.h>
 
@@ -46,7 +47,7 @@
 
 // We know that there are leaks in Kati. Turn off LeakSanitizer by default.
 extern "C" const char* __asan_default_options() {
-  return "detect_leaks=0";
+  return "detect_leaks=0:allow_user_segv_handler=1";
 }
 
 static void Init() {
@@ -67,30 +68,30 @@
 
 static void ReadBootstrapMakefile(const vector<Symbol>& targets,
                                   vector<Stmt*>* stmts) {
-  string bootstrap = (
-      "CC?=cc\n"
+  string bootstrap =
+      ("CC?=cc\n"
 #if defined(__APPLE__)
-      "CXX?=c++\n"
+       "CXX?=c++\n"
 #else
-      "CXX?=g++\n"
+       "CXX?=g++\n"
 #endif
-      "AR?=ar\n"
-      // Pretend to be GNU make 3.81, for compatibility.
-      "MAKE_VERSION?=3.81\n"
-      "KATI?=ckati\n"
-      // Overwrite $SHELL environment variable.
-      "SHELL=/bin/sh\n"
-      // TODO: Add more builtin vars.
+       "AR?=ar\n"
+       // Pretend to be GNU make 3.81, for compatibility.
+       "MAKE_VERSION?=3.81\n"
+       "KATI?=ckati\n"
+       // Overwrite $SHELL environment variable.
+       "SHELL=/bin/sh\n"
+       // TODO: Add more builtin vars.
 
-      // http://www.gnu.org/software/make/manual/make.html#Catalogue-of-Rules
-      // The document above is actually not correct. See default.c:
-      // http://git.savannah.gnu.org/cgit/make.git/tree/default.c?id=4.1
-      ".c.o:\n"
-      "\t$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -o $@ $<\n"
-      ".cc.o:\n"
-      "\t$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -o $@ $<\n"
-      // TODO: Add more builtin rules.
-                      );
+       // http://www.gnu.org/software/make/manual/make.html#Catalogue-of-Rules
+       // The document above is actually not correct. See default.c:
+       // http://git.savannah.gnu.org/cgit/make.git/tree/default.c?id=4.1
+       ".c.o:\n"
+       "\t$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -o $@ $<\n"
+       ".cc.o:\n"
+       "\t$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -o $@ $<\n"
+       // TODO: Add more builtin rules.
+      );
   if (g_flags.generate_ninja) {
     bootstrap += StringPrintf("MAKE?=make -j%d\n",
                               g_flags.num_jobs <= 1 ? 1 : g_flags.num_jobs / 2);
@@ -98,8 +99,8 @@
     bootstrap += StringPrintf("MAKE?=%s\n",
                               JoinStrings(g_flags.subkati_args, " ").c_str());
   }
-  bootstrap += StringPrintf("MAKECMDGOALS?=%s\n",
-                            JoinSymbols(targets, " ").c_str());
+  bootstrap +=
+      StringPrintf("MAKECMDGOALS?=%s\n", JoinSymbols(targets, " ").c_str());
 
   char cwd[PATH_MAX];
   if (!getcwd(cwd, PATH_MAX)) {
@@ -121,6 +122,97 @@
 
 extern "C" char** environ;
 
+class SegfaultHandler {
+ public:
+  explicit SegfaultHandler(Evaluator* ev);
+  ~SegfaultHandler();
+
+  void handle(int, siginfo_t*, void*);
+
+ private:
+  static SegfaultHandler* global_handler;
+
+  void dumpstr(const char* s) const {
+    (void)write(STDERR_FILENO, s, strlen(s));
+  }
+  void dumpint(int i) const {
+    char buf[11];
+    char* ptr = buf + sizeof(buf) - 1;
+
+    if (i < 0) {
+      i = -i;
+      dumpstr("-");
+    } else if (i == 0) {
+      dumpstr("0");
+      return;
+    }
+
+    *ptr = '\0';
+    while (ptr > buf && i > 0) {
+      *--ptr = '0' + (i % 10);
+      i = i / 10;
+    }
+
+    dumpstr(ptr);
+  }
+
+  Evaluator* ev_;
+
+  struct sigaction orig_action_;
+  struct sigaction new_action_;
+};
+
+SegfaultHandler* SegfaultHandler::global_handler = nullptr;
+
+SegfaultHandler::SegfaultHandler(Evaluator* ev) : ev_(ev) {
+  CHECK(global_handler == nullptr);
+  global_handler = this;
+
+  // Construct an alternate stack, so that we can handle stack overflows.
+  stack_t ss;
+  ss.ss_sp = malloc(SIGSTKSZ * 2);
+  CHECK(ss.ss_sp != nullptr);
+  ss.ss_size = SIGSTKSZ * 2;
+  ss.ss_flags = 0;
+  if (sigaltstack(&ss, nullptr) == -1) {
+    PERROR("sigaltstack");
+  }
+
+  // Register our segfault handler using the alternate stack, falling
+  // back to the default handler.
+  sigemptyset(&new_action_.sa_mask);
+  new_action_.sa_flags = SA_ONSTACK | SA_SIGINFO | SA_RESETHAND;
+  new_action_.sa_sigaction = [](int sig, siginfo_t* info, void* context) {
+    if (global_handler != nullptr) {
+      global_handler->handle(sig, info, context);
+    }
+
+    raise(SIGSEGV);
+  };
+  sigaction(SIGSEGV, &new_action_, &orig_action_);
+}
+
+void SegfaultHandler::handle(int sig, siginfo_t* info, void* context) {
+  // Avoid fprintf in case it allocates or tries to do anything else that may
+  // hang.
+  dumpstr("*kati*: Segmentation fault, last evaluated line was ");
+  dumpstr(ev_->loc().filename);
+  dumpstr(":");
+  dumpint(ev_->loc().lineno);
+  dumpstr("\n");
+
+  // Run the original handler, in case we've been preloaded with libSegFault
+  // or similar.
+  if (orig_action_.sa_sigaction != nullptr) {
+    orig_action_.sa_sigaction(sig, info, context);
+  }
+}
+
+SegfaultHandler::~SegfaultHandler() {
+  sigaction(SIGSEGV, &orig_action_, nullptr);
+  global_handler = nullptr;
+}
+
 static int Run(const vector<Symbol>& targets,
                const vector<StringPiece>& cl_vars,
                const string& orig_args) {
@@ -143,19 +235,21 @@
 
   MakefileCacheManager* cache_mgr = NewMakefileCacheManager();
 
-  Intern("MAKEFILE_LIST").SetGlobalVar(
-      new SimpleVar(StringPrintf(" %s", g_flags.makefile), VarOrigin::FILE));
+  Intern("MAKEFILE_LIST")
+      .SetGlobalVar(new SimpleVar(StringPrintf(" %s", g_flags.makefile),
+                                  VarOrigin::FILE));
   for (char** p = environ; *p; p++) {
     SetVar(*p, VarOrigin::ENVIRONMENT);
   }
-  Evaluator* ev = new Evaluator();
+  unique_ptr<Evaluator> ev(new Evaluator());
+  SegfaultHandler segfault(ev.get());
 
   vector<Stmt*> bootstrap_asts;
   ReadBootstrapMakefile(targets, &bootstrap_asts);
   ev->set_is_bootstrap(true);
   for (Stmt* stmt : bootstrap_asts) {
     LOG("%s", stmt->DebugString().c_str());
-    stmt->Eval(ev);
+    stmt->Eval(ev.get());
   }
   ev->set_is_bootstrap(false);
 
@@ -164,7 +258,7 @@
     vector<Stmt*> asts;
     Parse(Intern(l).str(), Loc("*bootstrap*", 0), &asts);
     CHECK(asts.size() == 1);
-    asts[0]->Eval(ev);
+    asts[0]->Eval(ev.get());
   }
   ev->set_is_commandline(false);
 
@@ -173,7 +267,7 @@
     Makefile* mk = cache_mgr->ReadMakefile(g_flags.makefile);
     for (Stmt* stmt : mk->stmts()) {
       LOG("%s", stmt->DebugString().c_str());
-      stmt->Eval(ev);
+      stmt->Eval(ev.get());
     }
   }
 
@@ -185,7 +279,7 @@
   vector<DepNode*> nodes;
   {
     ScopedTimeReporter tr("make dep time");
-    MakeDep(ev, ev->rules(), ev->rule_vars(), targets, &nodes);
+    MakeDep(ev.get(), ev->rules(), ev->rule_vars(), targets, &nodes);
   }
 
   if (g_flags.is_syntax_check_only)
@@ -193,7 +287,8 @@
 
   if (g_flags.generate_ninja) {
     ScopedTimeReporter tr("generate ninja time");
-    GenerateNinja(nodes, ev, orig_args, start_time);
+    GenerateNinja(nodes, ev.get(), orig_args, start_time);
+    ev->DumpStackStats();
     return 0;
   }
 
@@ -201,7 +296,7 @@
     const Symbol name = p.first;
     if (p.second) {
       Var* v = ev->LookupVar(name);
-      const string&& value = v->Eval(ev);
+      const string&& value = v->Eval(ev.get());
       LOG("setenv(%s, %s)", name.c_str(), value.c_str());
       setenv(name.c_str(), value.c_str(), 1);
     } else {
@@ -212,12 +307,13 @@
 
   {
     ScopedTimeReporter tr("exec time");
-    Exec(nodes, ev);
+    Exec(nodes, ev.get());
   }
 
+  ev->DumpStackStats();
+
   for (Stmt* stmt : bootstrap_asts)
     delete stmt;
-  delete ev;
   delete cache_mgr;
 
   return 0;
diff --git a/ninja.cc b/ninja.cc
index 0d7acc9..ac02e0f 100644
--- a/ninja.cc
+++ b/ninja.cc
@@ -200,8 +200,7 @@
       delete nn;
   }
 
-  void Generate(const vector<DepNode*>& nodes,
-                const string& orig_args) {
+  void Generate(const vector<DepNode*>& nodes, const string& orig_args) {
     unlink(GetNinjaStampFilename().c_str());
     PopulateNinjaNodes(nodes);
     GenerateNinja();
@@ -293,7 +292,7 @@
 
         case '\n':
           if (prev_backslash) {
-            cmd_buf->resize(cmd_buf->size()-1);
+            cmd_buf->resize(cmd_buf->size() - 1);
           } else {
             *cmd_buf += ' ';
           }
@@ -317,11 +316,11 @@
     }
 
     if (prev_backslash) {
-      cmd_buf->resize(cmd_buf->size()-1);
+      cmd_buf->resize(cmd_buf->size() - 1);
     }
 
     while (true) {
-      char c = (*cmd_buf)[cmd_buf->size()-1];
+      char c = (*cmd_buf)[cmd_buf->size() - 1];
       if (!isspace(c) && c != ';')
         break;
       cmd_buf->resize(cmd_buf->size() - 1);
@@ -331,7 +330,7 @@
                        cmd_buf->size() - orig_size);
   }
 
-  bool IsOutputMkdir(const char *name, StringPiece cmd) {
+  bool IsOutputMkdir(const char* name, StringPiece cmd) {
     if (!HasPrefix(cmd, "mkdir -p ")) {
       return false;
     }
@@ -347,7 +346,7 @@
     return false;
   }
 
-  bool GetDescriptionFromCommand(StringPiece cmd, string *out) {
+  bool GetDescriptionFromCommand(StringPiece cmd, string* out) {
     if (!HasPrefix(cmd, "echo ")) {
       return false;
     }
@@ -373,21 +372,21 @@
         }
       } else {
         switch (*in) {
-        case '\'':
-        case '"':
-        case '`':
-          quote = *in;
-          break;
+          case '\'':
+          case '"':
+          case '`':
+            quote = *in;
+            break;
 
-        case '<':
-        case '>':
-        case '&':
-        case '|':
-        case ';':
-          return false;
+          case '<':
+          case '>':
+          case '&':
+          case '|':
+          case ';':
+            return false;
 
-        default:
-          out_buf += *in;
+          default:
+            out_buf += *in;
         }
       }
     }
@@ -396,7 +395,7 @@
     return true;
   }
 
-  bool GenShellScript(const char *name,
+  bool GenShellScript(const char* name,
                       const vector<Command*>& commands,
                       string* cmd_buf,
                       string* description) {
@@ -450,8 +449,8 @@
       if (needs_subshell)
         *cmd_buf += " )";
     }
-    return (use_goma_ || g_flags.remote_num_jobs ||
-            g_flags.goma_dir) && !use_gomacc;
+    return (use_goma_ || g_flags.remote_num_jobs || g_flags.goma_dir) &&
+           !use_gomacc;
   }
 
   bool GetDepfile(const DepNode* node, string* cmd_buf, string* depfile) {
@@ -464,7 +463,7 @@
 
     *cmd_buf += ' ';
     bool result = GetDepfileFromCommand(cmd_buf, depfile);
-    cmd_buf->resize(cmd_buf->size()-1);
+    cmd_buf->resize(cmd_buf->size() - 1);
     return result;
   }
 
@@ -487,8 +486,8 @@
       return;
     }
     if (g_flags.enable_debug) {
-      *o << "# " << (node->loc.filename ? node->loc.filename : "(null)")
-         << ':' << node->loc.lineno << "\n";
+      *o << "# " << (node->loc.filename ? node->loc.filename : "(null)") << ':'
+         << node->loc.lineno << "\n";
     }
     if (!commands.empty()) {
       rule_name = StringPrintf("rule%d", nn->rule_id);
@@ -496,8 +495,8 @@
 
       string description = "build $out";
       string cmd_buf;
-      use_local_pool |= GenShellScript(node->output.c_str(), commands,
-                                       &cmd_buf, &description);
+      use_local_pool |= GenShellScript(node->output.c_str(), commands, &cmd_buf,
+                                       &description);
       *o << " description = " << description << "\n";
       EmitDepfile(nn, &cmd_buf, o);
 
@@ -509,8 +508,8 @@
         *o << " command = " << shell_ << " $out.rsp\n";
       } else {
         EscapeShell(&cmd_buf);
-        *o << " command = " << shell_ << ' ' << shell_flags_
-           << " \"" << cmd_buf << "\"\n";
+        *o << " command = " << shell_ << ' ' << shell_flags_ << " \"" << cmd_buf
+           << "\"\n";
       }
       if (node->is_restat) {
         *o << " restat = 1\n";
@@ -530,7 +529,7 @@
         case ':':
         case ' ':
           r += '$';
-          // fall through.
+        // fall through.
         default:
           r += c;
       }
@@ -538,12 +537,12 @@
     return r;
   }
 
-  string EscapeBuildTarget(Symbol s) const {
-    return EscapeNinja(s.str());
-  }
+  string EscapeBuildTarget(Symbol s) const { return EscapeNinja(s.str()); }
 
-  void EmitBuild(NinjaNode* nn, const string& rule_name,
-                 bool use_local_pool, ostringstream* o) {
+  void EmitBuild(NinjaNode* nn,
+                 const string& rule_name,
+                 bool use_local_pool,
+                 ostringstream* o) {
     const DepNode* node = nn->node;
     string target = EscapeBuildTarget(node->output);
     *o << "build " << target;
@@ -581,9 +580,7 @@
     }
   }
 
-  static string GetEnvScriptFilename() {
-    return GetFilename("env%s.sh");
-  }
+  static string GetEnvScriptFilename() { return GetFilename("env%s.sh"); }
 
   void GenerateNinja() {
     ScopedTimeReporter tr("ninja gen (emit)");
@@ -618,12 +615,12 @@
     vector<ostringstream> bufs(num_tasks);
     for (int i = 0; i < num_tasks; i++) {
       tp->Submit([this, i, num_nodes_per_task, &bufs]() {
-          int l = min(num_nodes_per_task * (i + 1),
-                      static_cast<int>(nodes_.size()));
-          for (int j = num_nodes_per_task * i; j < l; j++) {
-            EmitNode(nodes_[j], &bufs[i]);
-          }
-        });
+        int l =
+            min(num_nodes_per_task * (i + 1), static_cast<int>(nodes_.size()));
+        for (int j = num_nodes_per_task * i; j < l; j++) {
+          EmitNode(nodes_[j], &bufs[i]);
+        }
+      });
     }
     tp->Wait();
 
diff --git a/ninja_test.cc b/ninja_test.cc
index 5fc410e..2a7fdc1 100644
--- a/ninja_test.cc
+++ b/ninja_test.cc
@@ -39,6 +39,7 @@
   delete g_last_error;
   g_last_error = NULL;
 
+  // clang-format off
   ASSERT_EQ(GetDepfile("g++ -c fat.cc -o fat.o", &new_cmd), "");
   ASSERT_EQ(GetDepfile("g++ -c fat.cc -MD -o fat.o -o fuga.o", &new_cmd), "fuga.d.tmp");
   ASSERT_EQ(GetDepfile("g++ -c fat.cc -MD -o fat.o", &new_cmd), "fat.d.tmp");
@@ -59,13 +60,19 @@
   // TODO: Fix for automake.
   // ASSERT_EQ(GetDepfile("(/bin/sh ./libtool  --tag=CXX   --mode=compile g++ -DHAVE_CONFIG_H -I. -I./src -I./src     -Wall -Wwrite-strings -Woverloaded-virtual -Wno-sign-compare  -DNO_FRAME_POINTER  -DNDEBUG -g -O2 -MT libglog_la-logging.lo -MD -MP -MF .deps/libglog_la-logging.Tpo -c -o libglog_la-logging.lo `test -f 'src/logging.cc' || echo './'`src/logging.cc) && (mv -f .deps/libglog_la-logging.Tpo .deps/libglog_la-logging.Plo)", &new_cmd), ".deps/libglog_la-logging.Plo");
   // ASSERT_EQ(GetDepfile("(g++ -DHAVE_CONFIG_H -I. -I./src  -I./src  -pthread     -Wall -Wwrite-strings -Woverloaded-virtual -Wno-sign-compare  -DNO_FRAME_POINTER  -g -O2 -MT signalhandler_unittest-signalhandler_unittest.o -MD -MP -MF .deps/signalhandler_unittest-signalhandler_unittest.Tpo -c -o signalhandler_unittest-signalhandler_unittest.o `test -f 'src/signalhandler_unittest.cc' || echo './'`src/signalhandler_unittest.cc) && (mv -f .deps/signalhandler_unittest-signalhandler_unittest.Tpo .deps/signalhandler_unittest-signalhandler_unittest.Po)", &new_cmd), ".deps/signalhandler_unittest-signalhandler_unittest.Po");
+  // clang-format on
 
   assert(!g_last_error);
 }
 
 static void TestGetGomaccPosForAndroidCompileCommand() {
-  ASSERT_EQ(GetGomaccPosForAndroidCompileCommand("prebuilts/clang/linux-x86/host/3.6/bin/clang++ -c foo.c"), 0);
-  ASSERT_EQ(GetGomaccPosForAndroidCompileCommand("prebuilts/misc/linux-x86/ccache/ccache prebuilts/clang/linux-x86/host/3.6/bin/clang++ -c foo.c"), 39);
+  ASSERT_EQ(GetGomaccPosForAndroidCompileCommand(
+                "prebuilts/clang/linux-x86/host/3.6/bin/clang++ -c foo.c"),
+            0);
+  ASSERT_EQ(GetGomaccPosForAndroidCompileCommand(
+                "prebuilts/misc/linux-x86/ccache/ccache "
+                "prebuilts/clang/linux-x86/host/3.6/bin/clang++ -c foo.c"),
+            39);
   ASSERT_EQ(GetGomaccPosForAndroidCompileCommand("echo foo"), string::npos);
 }
 
diff --git a/parser.cc b/parser.cc
index 3822dd8..8041c28 100644
--- a/parser.cc
+++ b/parser.cc
@@ -41,8 +41,8 @@
     int num_nest;
   };
 
-  typedef void (Parser::*DirectiveHandler)(
-      StringPiece line, StringPiece directive);
+  typedef void (Parser::*DirectiveHandler)(StringPiece line,
+                                           StringPiece directive);
   typedef unordered_map<StringPiece, DirectiveHandler> DirectiveMap;
 
  public:
@@ -54,8 +54,7 @@
         num_define_nest_(0),
         num_if_nest_(0),
         loc_(filename, 0),
-        fixed_lineno_(false) {
-  }
+        fixed_lineno_(false) {}
 
   Parser(StringPiece buf, const Loc& loc, vector<Stmt*>* stmts)
       : buf_(buf),
@@ -64,11 +63,9 @@
         out_stmts_(stmts),
         num_if_nest_(0),
         loc_(loc),
-        fixed_lineno_(true) {
-  }
+        fixed_lineno_(true) {}
 
-  ~Parser() {
-  }
+  ~Parser() {}
 
   void Parse() {
     l_ = 0;
@@ -134,9 +131,7 @@
     }
   }
 
-  static void Quit() {
-    delete make_directives_;
-  }
+  static void Quit() { delete make_directives_; }
 
   void set_state(ParserState st) { state_ = st; }
 
@@ -197,8 +192,8 @@
       ParseRule(line, string::npos);
     } else if (line[sep] == '=') {
       ParseAssign(line, sep);
-    } else if (line.get(sep+1) == '=') {
-      ParseAssign(line, sep+1);
+    } else if (line.get(sep + 1) == '=') {
+      ParseAssign(line, sep + 1);
     } else if (line[sep] == ':') {
       ParseRule(line, sep);
     } else {
@@ -301,8 +296,8 @@
       return;
     }
 
-    StringPiece rest = TrimRightSpace(RemoveComment(TrimLeftSpace(
-        line.substr(sizeof("endef")))));
+    StringPiece rest = TrimRightSpace(
+        RemoveComment(TrimLeftSpace(line.substr(sizeof("endef")))));
     if (!rest.empty()) {
       WARN_LOC(loc_, "extraneous text after `endef' directive");
     }
@@ -352,7 +347,7 @@
       stmt->lhs = ParseExprImpl(loc_, s, terms, ParseExprOpt::NORMAL, &n, true);
       if (s[n] != ',')
         return false;
-      s = TrimLeftSpace(s.substr(n+1));
+      s = TrimLeftSpace(s.substr(n + 1));
       stmt->rhs = ParseExprImpl(loc_, s, NULL, ParseExprOpt::NORMAL, &n);
       s = TrimLeftSpace(s.substr(n));
     } else {
@@ -370,7 +365,7 @@
           stmt->lhs = v;
         else
           stmt->rhs = v;
-        s = TrimLeftSpace(s.substr(end+1));
+        s = TrimLeftSpace(s.substr(end + 1));
       }
     }
     if (!s.empty()) {
@@ -453,10 +448,9 @@
   }
 
   void ParseOverride(StringPiece line, StringPiece) {
-    current_directive_ =
-        static_cast<AssignDirective>(
-            (static_cast<int>(current_directive_) |
-             static_cast<int>(AssignDirective::OVERRIDE)));
+    current_directive_ = static_cast<AssignDirective>(
+        (static_cast<int>(current_directive_) |
+         static_cast<int>(AssignDirective::OVERRIDE)));
     if (HandleDirective(line, assign_directives_))
       return;
     if (IsInExport()) {
@@ -466,10 +460,9 @@
   }
 
   void ParseExport(StringPiece line, StringPiece) {
-    current_directive_ =
-        static_cast<AssignDirective>(
-            (static_cast<int>(current_directive_) |
-             static_cast<int>(AssignDirective::EXPORT)));
+    current_directive_ = static_cast<AssignDirective>(
+        (static_cast<int>(current_directive_) |
+         static_cast<int>(AssignDirective::EXPORT)));
     if (HandleDirective(line, assign_directives_))
       return;
     CreateExport(line, true);
@@ -509,8 +502,8 @@
     if (found == directive_map->end())
       return false;
 
-    StringPiece rest = TrimRightSpace(RemoveComment(TrimLeftSpace(
-        line.substr(directive.size()))));
+    StringPiece rest = TrimRightSpace(
+        RemoveComment(TrimLeftSpace(line.substr(directive.size()))));
     (this->*found->second)(rest, directive);
     return true;
   }
@@ -545,8 +538,7 @@
 
 void Parse(Makefile* mk) {
   COLLECT_STATS("parse file time");
-  Parser parser(StringPiece(mk->buf()),
-                mk->filename().c_str(),
+  Parser parser(StringPiece(mk->buf()), mk->filename().c_str(),
                 mk->mutable_stmts());
   parser.Parse();
 }
@@ -557,7 +549,8 @@
   parser.Parse();
 }
 
-void ParseNotAfterRule(StringPiece buf, const Loc& loc,
+void ParseNotAfterRule(StringPiece buf,
+                       const Loc& loc,
                        vector<Stmt*>* out_stmts) {
   Parser parser(buf, loc, out_stmts);
   parser.set_state(ParserState::NOT_AFTER_RULE);
@@ -579,12 +572,15 @@
 size_t Parser::longest_directive_len_;
 vector<ParseErrorStmt*> Parser::parse_errors;
 
-void ParseAssignStatement(StringPiece line, size_t sep,
-                          StringPiece* lhs, StringPiece* rhs, AssignOp* op) {
+void ParseAssignStatement(StringPiece line,
+                          size_t sep,
+                          StringPiece* lhs,
+                          StringPiece* rhs,
+                          AssignOp* op) {
   CHECK(sep != 0);
   *op = AssignOp::EQ;
   size_t lhs_end = sep;
-  switch (line[sep-1]) {
+  switch (line[sep - 1]) {
     case ':':
       lhs_end--;
       *op = AssignOp::COLON_EQ;
diff --git a/parser.h b/parser.h
index 95b7241..e4cf7c2 100644
--- a/parser.h
+++ b/parser.h
@@ -27,11 +27,15 @@
 
 void Parse(Makefile* mk);
 void Parse(StringPiece buf, const Loc& loc, vector<Stmt*>* out_asts);
-void ParseNotAfterRule(StringPiece buf, const Loc& loc,
+void ParseNotAfterRule(StringPiece buf,
+                       const Loc& loc,
                        vector<Stmt*>* out_asts);
 
-void ParseAssignStatement(StringPiece line, size_t sep,
-                          StringPiece* lhs, StringPiece* rhs, AssignOp* op);
+void ParseAssignStatement(StringPiece line,
+                          size_t sep,
+                          StringPiece* lhs,
+                          StringPiece* rhs,
+                          AssignOp* op);
 
 void InitParser();
 void QuitParser();
diff --git a/regen.cc b/regen.cc
index 5b42d8f..b6c2872 100644
--- a/regen.cc
+++ b/regen.cc
@@ -35,12 +35,13 @@
 
 namespace {
 
-#define RETURN_TRUE do {                        \
-      if (g_flags.dump_kati_stamp)              \
-        needs_regen_ = true;                    \
-      else                                      \
-        return true;                            \
-    } while (0)
+#define RETURN_TRUE              \
+  do {                           \
+    if (g_flags.dump_kati_stamp) \
+      needs_regen_ = true;       \
+    else                         \
+      return true;               \
+  } while (0)
 
 bool ShouldIgnoreDirty(StringPiece s) {
   Pattern pat(g_flags.ignore_dirty_pattern);
@@ -66,9 +67,7 @@
   };
 
  public:
-  StampChecker()
-      : needs_regen_(false) {
-  }
+  StampChecker() : needs_regen_(false) {}
 
   ~StampChecker() {
     for (GlobResult* gr : globs_) {
@@ -118,21 +117,23 @@
   }
 
   bool CheckStep1(const string& orig_args) {
-#define LOAD_INT(fp) ({                                                 \
-        int v = LoadInt(fp);                                            \
-        if (v < 0) {                                                    \
-          fprintf(stderr, "incomplete kati_stamp, regenerating...\n");  \
-          RETURN_TRUE;                                                  \
-        }                                                               \
-        v;                                                              \
-      })
+#define LOAD_INT(fp)                                               \
+  ({                                                               \
+    int v = LoadInt(fp);                                           \
+    if (v < 0) {                                                   \
+      fprintf(stderr, "incomplete kati_stamp, regenerating...\n"); \
+      RETURN_TRUE;                                                 \
+    }                                                              \
+    v;                                                             \
+  })
 
-#define LOAD_STRING(fp, s) ({                                           \
-        if (!LoadString(fp, s)) {                                       \
-          fprintf(stderr, "incomplete kati_stamp, regenerating...\n");  \
-          RETURN_TRUE;                                                  \
-        }                                                               \
-      })
+#define LOAD_STRING(fp, s)                                         \
+  ({                                                               \
+    if (!LoadString(fp, s)) {                                      \
+      fprintf(stderr, "incomplete kati_stamp, regenerating...\n"); \
+      RETURN_TRUE;                                                 \
+    }                                                              \
+  })
 
     const string& stamp_filename = GetNinjaStampFilename();
     FILE* fp = fopen(stamp_filename.c_str(), "rb");
@@ -205,10 +206,11 @@
       LOAD_STRING(fp, &s2);
       if (val != s2) {
         if (g_flags.dump_kati_stamp) {
-          printf("env %s: dirty (%s => %.*s)\n",
-                 s.c_str(), s2.c_str(), SPF(val));
+          printf("env %s: dirty (%s => %.*s)\n", s.c_str(), s2.c_str(),
+                 SPF(val));
         } else {
-          fprintf(stderr, "Environment variable %s was modified (%s => %.*s), "
+          fprintf(stderr,
+                  "Environment variable %s was modified (%s => %.*s), "
                   "regenerating...\n",
                   s.c_str(), s2.c_str(), SPF(val));
         }
@@ -369,7 +371,8 @@
     }
 
     if (sr->op == CommandOp::WRITE || sr->op == CommandOp::APPEND) {
-      FILE* f = fopen(sr->cmd.c_str(), (sr->op == CommandOp::WRITE) ? "wb" : "ab");
+      FILE* f =
+          fopen(sr->cmd.c_str(), (sr->op == CommandOp::WRITE) ? "wb" : "ab");
       if (f == NULL) {
         PERROR("fopen");
       }
@@ -394,8 +397,7 @@
     }
 
     FindCommand fc;
-    if (fc.Parse(sr->cmd) &&
-        !fc.chdir.empty() && ShouldIgnoreDirty(fc.chdir)) {
+    if (fc.Parse(sr->cmd) && !fc.chdir.empty() && ShouldIgnoreDirty(fc.chdir)) {
       if (g_flags.dump_kati_stamp)
         printf("shell %s: ignored\n", sr->cmd.c_str());
       return false;
@@ -403,7 +405,8 @@
 
     COLLECT_STATS_WITH_SLOW_REPORT("shell time (regen)", sr->cmd.c_str());
     string result;
-    RunCommand(sr->shell, sr->shellflag, sr->cmd, RedirectStderr::DEV_NULL, &result);
+    RunCommand(sr->shell, sr->shellflag, sr->cmd, RedirectStderr::DEV_NULL,
+               &result);
     FormatForCommandSubstitution(&result);
     if (sr->result != result) {
       if (g_flags.dump_kati_stamp) {
@@ -424,32 +427,32 @@
     unique_ptr<ThreadPool> tp(NewThreadPool(g_flags.num_jobs));
 
     tp->Submit([this]() {
-        string err;
-        // TODO: Make glob cache thread safe and create a task for each glob.
-        for (GlobResult* gr : globs_) {
-          if (CheckGlobResult(gr, &err)) {
-            unique_lock<mutex> lock(mu_);
-            if (!needs_regen_) {
-              needs_regen_ = true;
-              msg_ = err;
-            }
-            break;
+      string err;
+      // TODO: Make glob cache thread safe and create a task for each glob.
+      for (GlobResult* gr : globs_) {
+        if (CheckGlobResult(gr, &err)) {
+          unique_lock<mutex> lock(mu_);
+          if (!needs_regen_) {
+            needs_regen_ = true;
+            msg_ = err;
           }
+          break;
         }
-      });
+      }
+    });
 
     tp->Submit([this]() {
-        for (ShellResult* sr : commands_) {
-          string err;
-          if (CheckShellResult(sr, &err)) {
-            unique_lock<mutex> lock(mu_);
-            if (!needs_regen_) {
-              needs_regen_ = true;
-              msg_ = err;
-            }
+      for (ShellResult* sr : commands_) {
+        string err;
+        if (CheckShellResult(sr, &err)) {
+          unique_lock<mutex> lock(mu_);
+          if (!needs_regen_) {
+            needs_regen_ = true;
+            msg_ = err;
           }
         }
-      });
+      }
+    });
 
     tp->Wait();
     if (needs_regen_) {
diff --git a/regen_dump.cc b/regen_dump.cc
index 7a515f5..f596f90 100644
--- a/regen_dump.cc
+++ b/regen_dump.cc
@@ -33,8 +33,8 @@
     return 1;
   }
 
-  FILE *fp = fopen(argv[1], "rb");
-  if(!fp)
+  FILE* fp = fopen(argv[1], "rb");
+  if (!fp)
     PERROR("fopen");
 
   ScopedFile sfp(fp);
diff --git a/rule.cc b/rule.cc
index 717d0f0..f86df28 100644
--- a/rule.cc
+++ b/rule.cc
@@ -47,15 +47,14 @@
 
 }  // namespace
 
-Rule::Rule()
-    : is_double_colon(false),
-      is_suffix_rule(false),
-      cmd_lineno(0) {
-}
+Rule::Rule() : is_double_colon(false), is_suffix_rule(false), cmd_lineno(0) {}
 
-void ParseRule(Loc& loc, StringPiece line, char term,
-               const function<string()> &after_term_fn,
-               Rule** out_rule, RuleVarAssignment* rule_var) {
+void ParseRule(Loc& loc,
+               StringPiece line,
+               char term,
+               const function<string()>& after_term_fn,
+               Rule** out_rule,
+               RuleVarAssignment* rule_var) {
   size_t index = line.find(':');
   if (index == string::npos) {
     ERROR_LOC(loc, "*** missing separator.");
@@ -67,8 +66,8 @@
     outputs.push_back(Intern(TrimLeadingCurdir(tok)));
   }
 
-  const bool is_first_pattern = (
-      !outputs.empty() && IsPatternRule(outputs[0].str()));
+  const bool is_first_pattern =
+      (!outputs.empty() && IsPatternRule(outputs[0].str()));
   for (size_t i = 1; i < outputs.size(); i++) {
     if (IsPatternRule(outputs[i].str()) != is_first_pattern) {
       ERROR_LOC(loc, "*** mixed implicit and normal rules: deprecated syntax");
@@ -93,7 +92,8 @@
     // target specific variable).
     // See https://github.com/google/kati/issues/83
     if (term_index == 0) {
-      KATI_WARN_LOC(loc, "defining a target which starts with `=', "
+      KATI_WARN_LOC(loc,
+                    "defining a target which starts with `=', "
                     "which is not probably what you meant");
       buf = line.as_string();
       if (term)
@@ -104,8 +104,8 @@
       term_index = string::npos;
     } else {
       rule_var->outputs.swap(outputs);
-      ParseAssignStatement(rest, term_index,
-                           &rule_var->lhs, &rule_var->rhs, &rule_var->op);
+      ParseAssignStatement(rest, term_index, &rule_var->lhs, &rule_var->rhs,
+                           &rule_var->op);
       *out_rule = NULL;
       return;
     }
@@ -139,7 +139,7 @@
   }
 
   StringPiece second = rest.substr(0, index);
-  StringPiece third = rest.substr(index+1);
+  StringPiece third = rest.substr(index + 1);
 
   for (StringPiece tok : WordScanner(second)) {
     tok = TrimLeadingCurdir(tok);
diff --git a/rule.h b/rule.h
index 48394bb..4cbca8e 100644
--- a/rule.h
+++ b/rule.h
@@ -48,9 +48,7 @@
   int cmd_lineno;
 
  private:
-  void Error(const string& msg) {
-    ERROR_LOC(loc, "%s", msg.c_str());
-  }
+  void Error(const string& msg) { ERROR_LOC(loc, "%s", msg.c_str()); }
 };
 
 struct RuleVarAssignment {
@@ -64,8 +62,11 @@
 // after the terminator |term| is needed (this happens only when
 // |term| is '='), |after_term_fn| will be called to obtain the right
 // hand side.
-void ParseRule(Loc& loc, StringPiece line, char term,
-               const function<string()> &after_term_fn,
-               Rule** rule, RuleVarAssignment* rule_var);
+void ParseRule(Loc& loc,
+               StringPiece line,
+               char term,
+               const function<string()>& after_term_fn,
+               Rule** rule,
+               RuleVarAssignment* rule_var);
 
 #endif  // RULE_H_
diff --git a/stats.cc b/stats.cc
index fc170f0..8bd3e73 100644
--- a/stats.cc
+++ b/stats.cc
@@ -33,8 +33,7 @@
 
 }  // namespace
 
-Stats::Stats(const char* name)
-    : name_(name), elapsed_(0), cnt_(0) {
+Stats::Stats(const char* name) : name_(name), elapsed_(0), cnt_(0) {
   unique_lock<mutex> lock(g_mu);
   if (g_stats == NULL)
     g_stats = new vector<Stats*>;
diff --git a/stats.h b/stats.h
index 63acc55..e77503a 100644
--- a/stats.h
+++ b/stats.h
@@ -50,12 +50,12 @@
 
 void ReportAllStats();
 
-#define COLLECT_STATS(name)                     \
-  static Stats stats(name);                     \
+#define COLLECT_STATS(name) \
+  static Stats stats(name); \
   ScopedStatsRecorder ssr(&stats)
 
-#define COLLECT_STATS_WITH_SLOW_REPORT(name, msg)       \
-  static Stats stats(name);                             \
+#define COLLECT_STATS_WITH_SLOW_REPORT(name, msg) \
+  static Stats stats(name);                       \
   ScopedStatsRecorder ssr(&stats, msg)
 
 #endif  // STATS_H_
diff --git a/stmt.cc b/stmt.cc
index 155e0cd..44875d0 100644
--- a/stmt.cc
+++ b/stmt.cc
@@ -27,32 +27,43 @@
 
 string RuleStmt::DebugString() const {
   return StringPrintf("RuleStmt(expr=%s term=%d after_term=%s loc=%s:%d)",
-                      expr->DebugString().c_str(),
-                      term,
-                      after_term->DebugString().c_str(),
-                      LOCF(loc()));
+                      expr->DebugString().c_str(), term,
+                      after_term->DebugString().c_str(), LOCF(loc()));
 }
 
 string AssignStmt::DebugString() const {
   const char* opstr = "???";
   switch (op) {
-    case AssignOp::EQ: opstr = "EQ"; break;
-    case AssignOp::COLON_EQ: opstr = "COLON_EQ"; break;
-    case AssignOp::PLUS_EQ: opstr = "PLUS_EQ"; break;
-    case AssignOp::QUESTION_EQ: opstr = "QUESTION_EQ"; break;
+    case AssignOp::EQ:
+      opstr = "EQ";
+      break;
+    case AssignOp::COLON_EQ:
+      opstr = "COLON_EQ";
+      break;
+    case AssignOp::PLUS_EQ:
+      opstr = "PLUS_EQ";
+      break;
+    case AssignOp::QUESTION_EQ:
+      opstr = "QUESTION_EQ";
+      break;
   }
   const char* dirstr = "???";
   switch (directive) {
-    case AssignDirective::NONE: dirstr = ""; break;
-    case AssignDirective::OVERRIDE: dirstr = "override"; break;
-    case AssignDirective::EXPORT: dirstr = "export"; break;
+    case AssignDirective::NONE:
+      dirstr = "";
+      break;
+    case AssignDirective::OVERRIDE:
+      dirstr = "override";
+      break;
+    case AssignDirective::EXPORT:
+      dirstr = "export";
+      break;
   }
-  return StringPrintf("AssignStmt(lhs=%s rhs=%s (%s) "
-                      "opstr=%s dir=%s loc=%s:%d)",
-                      lhs->DebugString().c_str(),
-                      rhs->DebugString().c_str(),
-                      NoLineBreak(orig_rhs.as_string()).c_str(),
-                      opstr, dirstr, LOCF(loc()));
+  return StringPrintf(
+      "AssignStmt(lhs=%s rhs=%s (%s) "
+      "opstr=%s dir=%s loc=%s:%d)",
+      lhs->DebugString().c_str(), rhs->DebugString().c_str(),
+      NoLineBreak(orig_rhs.as_string()).c_str(), opstr, dirstr, LOCF(loc()));
 }
 
 Symbol AssignStmt::GetLhsSymbol(Evaluator* ev) const {
@@ -69,42 +80,44 @@
 }
 
 string CommandStmt::DebugString() const {
-  return StringPrintf("CommandStmt(%s, loc=%s:%d)",
-                      expr->DebugString().c_str(), LOCF(loc()));
+  return StringPrintf("CommandStmt(%s, loc=%s:%d)", expr->DebugString().c_str(),
+                      LOCF(loc()));
 }
 
 string IfStmt::DebugString() const {
   const char* opstr = "???";
   switch (op) {
-    case CondOp::IFEQ: opstr = "ifeq"; break;
-    case CondOp::IFNEQ: opstr = "ifneq"; break;
-    case CondOp::IFDEF: opstr = "ifdef"; break;
-    case CondOp::IFNDEF: opstr = "ifndef"; break;
+    case CondOp::IFEQ:
+      opstr = "ifeq";
+      break;
+    case CondOp::IFNEQ:
+      opstr = "ifneq";
+      break;
+    case CondOp::IFDEF:
+      opstr = "ifdef";
+      break;
+    case CondOp::IFNDEF:
+      opstr = "ifndef";
+      break;
   }
   return StringPrintf("IfStmt(op=%s, lhs=%s, rhs=%s t=%zu f=%zu loc=%s:%d)",
-                      opstr,
-                      lhs->DebugString().c_str(),
-                      rhs->DebugString().c_str(),
-                      true_stmts.size(),
-                      false_stmts.size(),
-                      LOCF(loc()));
+                      opstr, lhs->DebugString().c_str(),
+                      rhs->DebugString().c_str(), true_stmts.size(),
+                      false_stmts.size(), LOCF(loc()));
 }
 
 string IncludeStmt::DebugString() const {
-  return StringPrintf("IncludeStmt(%s, loc=%s:%d)",
-                      expr->DebugString().c_str(), LOCF(loc()));
+  return StringPrintf("IncludeStmt(%s, loc=%s:%d)", expr->DebugString().c_str(),
+                      LOCF(loc()));
 }
 
 string ExportStmt::DebugString() const {
   return StringPrintf("ExportStmt(%s, %d, loc=%s:%d)",
-                      expr->DebugString().c_str(),
-                      is_export,
-                      LOCF(loc()));
+                      expr->DebugString().c_str(), is_export, LOCF(loc()));
 }
 
 string ParseErrorStmt::DebugString() const {
-  return StringPrintf("ParseErrorStmt(%s, loc=%s:%d)",
-                      msg.c_str(),
+  return StringPrintf("ParseErrorStmt(%s, loc=%s:%d)", msg.c_str(),
                       LOCF(loc()));
 }
 
@@ -159,8 +172,7 @@
   ev->EvalExport(this);
 }
 
-ParseErrorStmt::~ParseErrorStmt() {
-}
+ParseErrorStmt::~ParseErrorStmt() {}
 
 void ParseErrorStmt::Eval(Evaluator* ev) const {
   ev->set_loc(loc());
diff --git a/stmt.h b/stmt.h
index 3b6feeb..a08cc87 100644
--- a/stmt.h
+++ b/stmt.h
@@ -34,7 +34,7 @@
   QUESTION_EQ,
 };
 
-enum struct AssignDirective  {
+enum struct AssignDirective {
   NONE = 0,
   OVERRIDE = 1,
   EXPORT = 2,
@@ -86,9 +86,7 @@
   AssignOp op;
   AssignDirective directive;
 
-  AssignStmt()
-      : lhs_sym_cache_(Symbol::IsUninitialized{}) {
-  }
+  AssignStmt() : lhs_sym_cache_(Symbol::IsUninitialized{}) {}
   virtual ~AssignStmt();
 
   virtual void Eval(Evaluator* ev) const;
diff --git a/string_piece.cc b/string_piece.cc
index d287616..e739219 100644
--- a/string_piece.cc
+++ b/string_piece.cc
@@ -63,8 +63,8 @@
   if (pos > length_)
     return npos;
 
-  const char* result = std::search(ptr_ + pos, ptr_ + length_,
-                                   s.ptr_, s.ptr_ + s.length_);
+  const char* result =
+      std::search(ptr_ + pos, ptr_ + length_, s.ptr_, s.ptr_ + s.length_);
   const size_type xpos = result - ptr_;
   return xpos + s.length_ <= length_ ? xpos : npos;
 }
@@ -93,7 +93,7 @@
   if (length_ == 0)
     return npos;
 
-  for (size_type i = std::min(pos, length_ - 1); ; --i) {
+  for (size_type i = std::min(pos, length_ - 1);; --i) {
     if (ptr_[i] == c)
       return i;
     if (i == 0)
@@ -128,7 +128,7 @@
   if (s.length_ == 1)
     return find_first_of(s.ptr_[0], pos);
 
-  bool lookup[UCHAR_MAX + 1] = { false };
+  bool lookup[UCHAR_MAX + 1] = {false};
   BuildLookupTable(s, lookup);
   for (size_type i = pos; i < length_; ++i) {
     if (lookup[static_cast<unsigned char>(ptr_[i])]) {
@@ -150,7 +150,7 @@
   if (s.length_ == 1)
     return find_first_not_of(s.ptr_[0], pos);
 
-  bool lookup[UCHAR_MAX + 1] = { false };
+  bool lookup[UCHAR_MAX + 1] = {false};
   BuildLookupTable(s, lookup);
   for (size_type i = pos; i < length_; ++i) {
     if (!lookup[static_cast<unsigned char>(ptr_[i])]) {
@@ -180,9 +180,9 @@
   if (s.length_ == 1)
     return find_last_of(s.ptr_[0], pos);
 
-  bool lookup[UCHAR_MAX + 1] = { false };
+  bool lookup[UCHAR_MAX + 1] = {false};
   BuildLookupTable(s, lookup);
-  for (size_type i = std::min(pos, length_ - 1); ; --i) {
+  for (size_type i = std::min(pos, length_ - 1);; --i) {
     if (lookup[static_cast<unsigned char>(ptr_[i])])
       return i;
     if (i == 0)
@@ -204,9 +204,9 @@
   if (s.length_ == 1)
     return find_last_not_of(s.ptr_[0], pos);
 
-  bool lookup[UCHAR_MAX + 1] = { false };
+  bool lookup[UCHAR_MAX + 1] = {false};
   BuildLookupTable(s, lookup);
-  for (; ; --i) {
+  for (;; --i) {
     if (!lookup[static_cast<unsigned char>(ptr_[i])])
       return i;
     if (i == 0)
@@ -219,7 +219,7 @@
   if (length_ == 0)
     return npos;
 
-  for (size_type i = std::min(pos, length_ - 1); ; --i) {
+  for (size_type i = std::min(pos, length_ - 1);; --i) {
     if (ptr_[i] != c)
       return i;
     if (i == 0)
@@ -229,8 +229,10 @@
 }
 
 StringPiece StringPiece::substr(size_type pos, size_type n) const {
-  if (pos > length_) pos = length_;
-  if (n > length_ - pos) n = length_ - pos;
+  if (pos > length_)
+    pos = length_;
+  if (n > length_ - pos)
+    n = length_ - pos;
   return StringPiece(ptr_ + pos, n);
 }
 
diff --git a/string_piece.h b/string_piece.h
index 219af9f..df3562f 100644
--- a/string_piece.h
+++ b/string_piece.h
@@ -61,15 +61,13 @@
   // We provide non-explicit singleton constructors so users can pass
   // in a "const char*" or a "string" wherever a "StringPiece" is
   // expected.
-  StringPiece() : ptr_(NULL), length_(0) { }
+  StringPiece() : ptr_(NULL), length_(0) {}
   StringPiece(const char* str)
-    : ptr_(str), length_((str == NULL) ? 0 : strlen(str)) { }
-  StringPiece(const std::string& str)
-    : ptr_(str.data()), length_(str.size()) { }
+      : ptr_(str), length_((str == NULL) ? 0 : strlen(str)) {}
+  StringPiece(const std::string& str) : ptr_(str.data()), length_(str.size()) {}
   StringPiece(const std::string&& str)
-    : ptr_(str.data()), length_(str.size()) { }
-  StringPiece(const char* offset, size_type len)
-    : ptr_(offset), length_(len) { }
+      : ptr_(str.data()), length_(str.size()) {}
+  StringPiece(const char* offset, size_type len) : ptr_(offset), length_(len) {}
 
   // data() may return a pointer to a buffer with embedded NULs, and the
   // returned buffer may or may not be null terminated.  Therefore it is
@@ -104,16 +102,16 @@
     length_ -= n;
   }
 
-  void remove_suffix(size_type n) {
-    length_ -= n;
-  }
+  void remove_suffix(size_type n) { length_ -= n; }
 
   int compare(const StringPiece& x) const {
-    int r = wordmemcmp(
-        ptr_, x.ptr_, (length_ < x.length_ ? length_ : x.length_));
+    int r =
+        wordmemcmp(ptr_, x.ptr_, (length_ < x.length_ ? length_ : x.length_));
     if (r == 0) {
-      if (length_ < x.length_) r = -1;
-      else if (length_ > x.length_) r = +1;
+      if (length_ < x.length_)
+        r = -1;
+      else if (length_ > x.length_)
+        r = +1;
     }
     return r;
   }
@@ -135,7 +133,7 @@
   // Does "this" end with "x"
   bool ends_with(const StringPiece& x) const {
     return ((length_ >= x.length_) &&
-            (wordmemcmp(ptr_ + (length_-x.length_), x.ptr_, x.length_) == 0));
+            (wordmemcmp(ptr_ + (length_ - x.length_), x.ptr_, x.length_) == 0));
   }
 
   iterator begin() const { return ptr_; }
@@ -143,9 +141,7 @@
   const_reverse_iterator rbegin() const {
     return const_reverse_iterator(ptr_ + length_);
   }
-  const_reverse_iterator rend() const {
-    return const_reverse_iterator(ptr_);
-  }
+  const_reverse_iterator rend() const { return const_reverse_iterator(ptr_); }
 
   size_type max_size() const { return length_; }
   size_type capacity() const { return length_; }
@@ -181,8 +177,8 @@
   char get(size_type i) const { return i < length_ ? ptr_[i] : 0; }
 
  private:
-  const char*   ptr_;
-  size_type     length_;
+  const char* ptr_;
+  size_type length_;
 };
 
 bool operator==(const StringPiece& x, const StringPiece& y);
@@ -210,7 +206,8 @@
 }
 
 namespace std {
-template<> struct hash<StringPiece> {
+template <>
+struct hash<StringPiece> {
   size_t operator()(const StringPiece& s) const {
     size_t result = 0;
     for (char c : s) {
@@ -220,7 +217,7 @@
   }
 };
 
-}
+}  // namespace std
 
 #define SPF(s) static_cast<int>((s).size()), (s).data()
 
diff --git a/strutil.cc b/strutil.cc
index 632d151..a585963 100644
--- a/strutil.cc
+++ b/strutil.cc
@@ -36,8 +36,10 @@
 }
 
 #ifdef __SSE4_2__
-static int SkipUntilSSE42(const char* s, int len,
-                          const char* ranges, int ranges_size) {
+static int SkipUntilSSE42(const char* s,
+                          int len,
+                          const char* ranges,
+                          int ranges_size) {
   __m128i ranges16 = _mm_loadu_si128((const __m128i*)ranges);
   len &= ~15;
   int i = 0;
@@ -56,8 +58,10 @@
 #endif
 
 template <typename Cond>
-static int SkipUntil(const char* s, int len,
-                     const char* ranges UNUSED, int ranges_size UNUSED,
+static int SkipUntil(const char* s,
+                     int len,
+                     const char* ranges UNUSED,
+                     int ranges_size UNUSED,
                      Cond cond) {
   int i = 0;
 #ifdef __SSE4_2__
@@ -95,9 +99,7 @@
   return in->substr(s, i - s);
 }
 
-WordScanner::WordScanner(StringPiece in)
-    : in_(in) {
-}
+WordScanner::WordScanner(StringPiece in) : in_(in) {}
 
 WordScanner::Iterator WordScanner::begin() const {
   Iterator iter;
@@ -121,10 +123,7 @@
     o->push_back(t);
 }
 
-WordWriter::WordWriter(string* o)
-    : out_(o),
-      needs_space_(false) {
-}
+WordWriter::WordWriter(string* o) : out_(o), needs_space_(false) {}
 
 void WordWriter::MaybeAddWhitespace() {
   if (needs_space_) {
@@ -139,8 +138,7 @@
   AppendString(s, out_);
 }
 
-ScopedTerminator::ScopedTerminator(StringPiece s)
-    : s_(s), c_(s[s.size()]) {
+ScopedTerminator::ScopedTerminator(StringPiece s) : s_(s), c_(s[s.size()]) {
   const_cast<char*>(s_.data())[s_.size()] = '\0';
 }
 
@@ -166,7 +164,7 @@
   size_t found = str.find(w);
   if (found == string::npos)
     return false;
-  if (found != 0 && !isSpace(str[found-1]))
+  if (found != 0 && !isSpace(str[found - 1]))
     return false;
   size_t end = found + w.size();
   if (end != str.size() && !isSpace(str[end]))
@@ -188,9 +186,7 @@
   return str.substr(0, size_diff);
 }
 
-Pattern::Pattern(StringPiece pat)
-    : pat_(pat), percent_index_(pat.find('%')) {
-}
+Pattern::Pattern(StringPiece pat) : pat_(pat), percent_index_(pat.find('%')) {}
 
 bool Pattern::Match(StringPiece str) const {
   if (percent_index_ == string::npos)
@@ -210,7 +206,8 @@
                     str.size() - (pat_.size() - percent_index_ - 1));
 }
 
-void Pattern::AppendSubst(StringPiece str, StringPiece subst,
+void Pattern::AppendSubst(StringPiece str,
+                          StringPiece subst,
                           string* out) const {
   if (percent_index_ == string::npos) {
     if (str == pat_) {
@@ -229,8 +226,8 @@
       return;
     } else {
       AppendString(subst.substr(0, subst_percent_index), out);
-      AppendString(str.substr(percent_index_,
-                              str.size() - pat_.size() + 1), out);
+      AppendString(str.substr(percent_index_, str.size() - pat_.size() + 1),
+                   out);
       AppendString(subst.substr(subst_percent_index + 1), out);
       return;
     }
@@ -238,7 +235,8 @@
   AppendString(str, out);
 }
 
-void Pattern::AppendSubstRef(StringPiece str, StringPiece subst,
+void Pattern::AppendSubstRef(StringPiece str,
+                             StringPiece subst,
                              string* out) const {
   if (percent_index_ != string::npos && subst.find('%') != string::npos) {
     AppendSubst(str, subst, out);
@@ -266,7 +264,7 @@
   for (; i < s.size(); i++) {
     if (isSpace(s[i]))
       continue;
-    char n = s.get(i+1);
+    char n = s.get(i + 1);
     if (s[i] == '\\' && (n == '\r' || n == '\n')) {
       i++;
       continue;
@@ -372,7 +370,7 @@
     }
     prev_start = j;
   }
-  if (j > 1 && (*o)[j-1] == '/')
+  if (j > 1 && (*o)[j - 1] == '/')
     j--;
   o->resize(j);
 }
@@ -395,7 +393,7 @@
   NormalizePath(o);
 }
 
-template<typename Cond>
+template <typename Cond>
 size_t FindOutsideParenImpl(StringPiece s, Cond cond) {
   bool prev_backslash = false;
   stack<char> paren_stack;
@@ -425,19 +423,17 @@
 }
 
 size_t FindOutsideParen(StringPiece s, char c) {
-  return FindOutsideParenImpl(s, [&c](char d){return c == d;});
+  return FindOutsideParenImpl(s, [&c](char d) { return c == d; });
 }
 
 size_t FindTwoOutsideParen(StringPiece s, char c1, char c2) {
-  return FindOutsideParenImpl(s, [&c1, &c2](char d){
-      return d == c1 || d == c2;
-    });
+  return FindOutsideParenImpl(
+      s, [&c1, &c2](char d) { return d == c1 || d == c2; });
 }
 
 size_t FindThreeOutsideParen(StringPiece s, char c1, char c2, char c3) {
-  return FindOutsideParenImpl(s, [&c1, &c2, &c3](char d){
-      return d == c1 || d == c2 || d == c3;
-    });
+  return FindOutsideParenImpl(
+      s, [&c1, &c2, &c3](char d) { return d == c1 || d == c2 || d == c3; });
 }
 
 size_t FindEndOfLine(StringPiece s, size_t e, size_t* lf_cnt) {
@@ -453,13 +449,13 @@
     if (c == '\0')
       break;
     if (c == '\\') {
-      if (s[e+1] == '\n') {
+      if (s[e + 1] == '\n') {
         e += 2;
         ++*lf_cnt;
-      } else if (s[e+1] == '\r' && s[e+2] == '\n') {
+      } else if (s[e + 1] == '\r' && s[e + 2] == '\n') {
         e += 3;
         ++*lf_cnt;
-      } else if (s[e+1] == '\\') {
+      } else if (s[e + 1] == '\\') {
         e += 2;
       } else {
         e++;
@@ -479,7 +475,7 @@
 }
 
 void FormatForCommandSubstitution(string* s) {
-  while ((*s)[s->size()-1] == '\n')
+  while ((*s)[s->size() - 1] == '\n')
     s->pop_back();
   for (size_t i = 0; i < s->size(); i++) {
     if ((*s)[i] == '\n')
@@ -507,11 +503,11 @@
   return r;
 }
 
-string EchoEscape(const string &str) {
-  const char *in = str.c_str();
+string EchoEscape(const string& str) {
+  const char* in = str.c_str();
   string buf;
   for (; *in; in++) {
-    switch(*in) {
+    switch (*in) {
       case '\\':
         buf += "\\\\\\\\";
         break;
@@ -545,7 +541,7 @@
     char c = (*s)[i];
     r += '\\';
     if (c == '$') {
-      if ((*s)[i+1] == '$') {
+      if ((*s)[i + 1] == '$') {
         r += '$';
         i++;
       }
diff --git a/strutil.h b/strutil.h
index ff3d6a1..cc4d519 100644
--- a/strutil.h
+++ b/strutil.h
@@ -142,7 +142,7 @@
 
 string ConcatDir(StringPiece b, StringPiece n);
 
-string EchoEscape(const string &str);
+string EchoEscape(const string& str);
 
 void EscapeShell(string* s);
 
diff --git a/strutil_test.cc b/strutil_test.cc
index a26cf4d..e83b4c3 100644
--- a/strutil_test.cc
+++ b/strutil_test.cc
@@ -160,8 +160,8 @@
 // freeing the allocated pages.
 const char* CreateProtectedString(const char* str) {
   int pagesize = sysconf(_SC_PAGE_SIZE);
-  void *buffer;
-  char *buffer_str;
+  void* buffer;
+  char* buffer_str;
 
   // Allocate two pages of memory
   if (posix_memalign(&buffer, pagesize, pagesize * 2) != 0) {
diff --git a/symtab.cc b/symtab.cc
index 0e51c21..0640ea3 100644
--- a/symtab.cc
+++ b/symtab.cc
@@ -30,9 +30,7 @@
 #include "var.h"
 
 struct SymbolData {
-  SymbolData()
-      : gv(kUndefined) {
-  }
+  SymbolData() : gv(kUndefined) {}
 
   Var* gv;
 };
@@ -43,9 +41,7 @@
 Symbol kEmptySym = Symbol(Symbol::IsUninitialized());
 Symbol kShellSym = Symbol(Symbol::IsUninitialized());
 
-Symbol::Symbol(int v)
-    : v_(v) {
-}
+Symbol::Symbol(int v) : v_(v) {}
 
 Var* Symbol::GetGlobalVar() const {
   if (static_cast<size_t>(v_) >= g_symbol_data.size()) {
@@ -73,13 +69,12 @@
   } else if (readonly != nullptr) {
     *readonly = false;
   }
-  if (!is_override &&
-      (orig->Origin() == VarOrigin::OVERRIDE ||
-       orig->Origin() == VarOrigin::ENVIRONMENT_OVERRIDE)) {
+  if (!is_override && (orig->Origin() == VarOrigin::OVERRIDE ||
+                       orig->Origin() == VarOrigin::ENVIRONMENT_OVERRIDE)) {
     return;
   }
   if (orig->Origin() == VarOrigin::COMMAND_LINE &&
-         v->Origin() == VarOrigin::FILE) {
+      v->Origin() == VarOrigin::FILE) {
     return;
   }
   if (orig->Origin() == VarOrigin::AUTOMATIC) {
diff --git a/symtab.h b/symtab.h
index 7e39be9..0469b65 100644
--- a/symtab.h
+++ b/symtab.h
@@ -30,17 +30,11 @@
 class Symbol {
  public:
   struct IsUninitialized {};
-  explicit Symbol(IsUninitialized)
-    : v_(-1) {
-  }
+  explicit Symbol(IsUninitialized) : v_(-1) {}
 
-  const string& str() const {
-    return *((*g_symbols)[v_]);
-  }
+  const string& str() const { return *((*g_symbols)[v_]); }
 
-  const char* c_str() const {
-    return str().c_str();
-  }
+  const char* c_str() const { return str().c_str(); }
 
   bool empty() const { return !v_; }
 
@@ -56,7 +50,9 @@
   bool IsValid() const { return v_ >= 0; }
 
   Var* GetGlobalVar() const;
-  void SetGlobalVar(Var* v, bool is_override = false, bool* readonly = nullptr) const;
+  void SetGlobalVar(Var* v,
+                    bool is_override = false,
+                    bool* readonly = nullptr) const;
 
  private:
   explicit Symbol(int v);
@@ -85,12 +81,11 @@
 }
 
 namespace std {
-template<> struct hash<Symbol> {
-  size_t operator()(const Symbol& s) const {
-    return s.val();
-  }
+template <>
+struct hash<Symbol> {
+  size_t operator()(const Symbol& s) const { return s.val(); }
 };
-}
+}  // namespace std
 
 extern Symbol kEmptySym;
 extern Symbol kShellSym;
diff --git a/testcase/segfault_stack_overflow.sh b/testcase/segfault_stack_overflow.sh
new file mode 100644
index 0000000..2ba425b
--- /dev/null
+++ b/testcase/segfault_stack_overflow.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+#
+# Copyright 2017 Google Inc. All rights reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http:#www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+set -u
+
+mk="$@"
+
+cat <<EOF > Makefile
+a = \$(a) \$(a) \$(a) \$(a)
+\$(a)
+EOF
+
+if echo "${mk}" | grep -qv "kati"; then
+  # Make detects this differently
+  echo 'Segmentation fault, last evaluated line was Makefile:2'
+else
+  # runtest.rb strips *kati*: lines, so strip that prefix to test
+  # Grab only *kati* lines, since asan may print a backtrace
+  ${mk} 2>&1 | grep "*kati*" | sed "s/^\*kati\*: //"
+fi
diff --git a/testutil.h b/testutil.h
index 7036409..be6125c 100644
--- a/testutil.h
+++ b/testutil.h
@@ -18,17 +18,19 @@
 
 bool g_failed;
 
-#define ASSERT_EQ(a, b)                                                 \
-  do {                                                                  \
-    if ((a) != (b)) {                                                   \
-      fprintf(stderr,                                                   \
+#define ASSERT_EQ(a, b)                                                     \
+  do {                                                                      \
+    if ((a) != (b)) {                                                       \
+      fprintf(stderr,                                                       \
               "Assertion failure at %s:%d: %s (which is \"%.*s\") vs %s\n", \
-              __FILE__, __LINE__, #a, SPF(GetStringPiece(a)), #b);      \
-      g_failed = true;                                                  \
-    }                                                                   \
-  } while(0)
+              __FILE__, __LINE__, #a, SPF(GetStringPiece(a)), #b);          \
+      g_failed = true;                                                      \
+    }                                                                       \
+  } while (0)
 
-StringPiece GetStringPiece(StringPiece s) { return s; }
+StringPiece GetStringPiece(StringPiece s) {
+  return s;
+}
 StringPiece GetStringPiece(size_t v) {
   static char buf[64];
   sprintf(buf, "%zd", v);
diff --git a/thread_local.h b/thread_local.h
index 28b146a..d9d5191 100644
--- a/thread_local.h
+++ b/thread_local.h
@@ -55,28 +55,23 @@
   delete reinterpret_cast<Type>(ptr);
 }
 
-template<typename Type, pthread_key_t* key>
+template <typename Type, pthread_key_t* key>
 void ThreadLocalInit() {
   if (pthread_key_create(key, ThreadLocalDestructor<Type>))
     ERROR("Failed to create a pthread key for TLS errno=%d", errno);
 }
 
-template<typename Type, pthread_key_t* key, pthread_once_t* once>
+template <typename Type, pthread_key_t* key, pthread_once_t* once>
 class ThreadLocal {
  public:
-  Type& Ref() {
-    return *GetPointer();
-  }
-  Type Get() {
-    return Ref();
-  }
-  void Set(const Type& value) {
-    Ref() = value;
-  }
+  Type& Ref() { return *GetPointer(); }
+  Type Get() { return Ref(); }
+  void Set(const Type& value) { Ref() = value; }
   Type* GetPointer() {
     pthread_once(once, ThreadLocalInit<Type*, key>);
     Type* value = reinterpret_cast<Type*>(pthread_getspecific(*key));
-    if (value) return value;
+    if (value)
+      return value;
     // new Type() for PODs means zero initialization.
     value = new Type();
     int error = pthread_setspecific(*key, value);
@@ -88,11 +83,11 @@
 
 // We need a namespace for name##_key and name##_once since template parameters
 // do not accept unnamed values such as static global variables.
-#define DEFINE_THREAD_LOCAL(Type, name)                 \
-  namespace {                                           \
-  pthread_once_t name##_once = PTHREAD_ONCE_INIT;       \
-  pthread_key_t name##_key;                             \
-  }                                                     \
+#define DEFINE_THREAD_LOCAL(Type, name)           \
+  namespace {                                     \
+  pthread_once_t name##_once = PTHREAD_ONCE_INIT; \
+  pthread_key_t name##_key;                       \
+  }                                               \
   ThreadLocal<Type, &name##_key, &name##_once> name;
 
 #define TLS_REF(x) x.Ref()
diff --git a/thread_pool.cc b/thread_pool.cc
index b2429cb..4acf7b9 100644
--- a/thread_pool.cc
+++ b/thread_pool.cc
@@ -26,8 +26,7 @@
 
 class ThreadPoolImpl : public ThreadPool {
  public:
-  explicit ThreadPoolImpl(int num_threads)
-      : is_waiting_(false) {
+  explicit ThreadPoolImpl(int num_threads) : is_waiting_(false) {
     SetAffinityForMultiThread();
     threads_.reserve(num_threads);
     for (int i = 0; i < num_threads; i++) {
@@ -35,8 +34,7 @@
     }
   }
 
-  virtual ~ThreadPoolImpl() override {
-  }
+  virtual ~ThreadPoolImpl() override {}
 
   virtual void Submit(function<void(void)> task) override {
     unique_lock<mutex> lock(mu_);
diff --git a/timeutil.cc b/timeutil.cc
index 93f6435..0b43bf4 100644
--- a/timeutil.cc
+++ b/timeutil.cc
@@ -35,8 +35,7 @@
 }
 
 ScopedTimeReporter::ScopedTimeReporter(const char* name)
-    : name_(name), start_(GetTime()) {
-}
+    : name_(name), start_(GetTime()) {}
 
 ScopedTimeReporter::~ScopedTimeReporter() {
   double elapsed = GetTime() - start_;
diff --git a/var.cc b/var.cc
index 1e6f5bb..14ccee6 100644
--- a/var.cc
+++ b/var.cc
@@ -25,38 +25,42 @@
 
 const char* GetOriginStr(VarOrigin origin) {
   switch (origin) {
-    case VarOrigin::UNDEFINED: return "undefined";
-    case VarOrigin::DEFAULT: return "default";
-    case VarOrigin::ENVIRONMENT: return "environment";
-    case VarOrigin::ENVIRONMENT_OVERRIDE: return "environment override";
-    case VarOrigin::FILE: return "file";
-    case VarOrigin::COMMAND_LINE: return "command line";
-    case VarOrigin::OVERRIDE: return "override";
-    case VarOrigin::AUTOMATIC: return "automatic";
+    case VarOrigin::UNDEFINED:
+      return "undefined";
+    case VarOrigin::DEFAULT:
+      return "default";
+    case VarOrigin::ENVIRONMENT:
+      return "environment";
+    case VarOrigin::ENVIRONMENT_OVERRIDE:
+      return "environment override";
+    case VarOrigin::FILE:
+      return "file";
+    case VarOrigin::COMMAND_LINE:
+      return "command line";
+    case VarOrigin::OVERRIDE:
+      return "override";
+    case VarOrigin::AUTOMATIC:
+      return "automatic";
   }
   CHECK(false);
   return "*** broken origin ***";
 }
 
-Var::Var() : readonly_(false), message_(), error_(false) {
-}
+Var::Var() : readonly_(false), message_(), error_(false) {}
 
-Var::~Var() {
-}
+Var::~Var() {}
 
 void Var::AppendVar(Evaluator*, Value*) {
   CHECK(false);
 }
 
-SimpleVar::SimpleVar(VarOrigin origin)
-    : origin_(origin) {
-}
+SimpleVar::SimpleVar(VarOrigin origin) : origin_(origin) {}
 
 SimpleVar::SimpleVar(const string& v, VarOrigin origin)
-    : v_(v), origin_(origin) {
-}
+    : v_(v), origin_(origin) {}
 
-void SimpleVar::Eval(Evaluator*, string* s) const {
+void SimpleVar::Eval(Evaluator* ev, string* s) const {
+  ev->CheckStack();
   *s += v_;
 }
 
@@ -76,14 +80,15 @@
 }
 
 RecursiveVar::RecursiveVar(Value* v, VarOrigin origin, StringPiece orig)
-    : v_(v), origin_(origin), orig_(orig) {
-}
+    : v_(v), origin_(origin), orig_(orig) {}
 
 void RecursiveVar::Eval(Evaluator* ev, string* s) const {
+  ev->CheckStack();
   v_->Eval(ev, s);
 }
 
-void RecursiveVar::AppendVar(Evaluator*, Value* v) {
+void RecursiveVar::AppendVar(Evaluator* ev, Value* v) {
+  ev->CheckStack();
   v_ = NewExpr3(v_, NewLiteral(" "), v);
 }
 
diff --git a/var.h b/var.h
index 15f461e..47d80c1 100644
--- a/var.h
+++ b/var.h
@@ -82,9 +82,11 @@
     }
 
     if (error_) {
-      ev->Error(StringPrintf("*** %s is obsolete%s.", sym.c_str(), message_->c_str()));
+      ev->Error(StringPrintf("*** %s is obsolete%s.", sym.c_str(),
+                             message_->c_str()));
     } else {
-      WARN_LOC(ev->loc(), "%s has been deprecated%s.", sym.c_str(), message_->c_str());
+      WARN_LOC(ev->loc(), "%s has been deprecated%s.", sym.c_str(),
+               message_->c_str());
     }
   }
 
@@ -102,12 +104,8 @@
   explicit SimpleVar(VarOrigin origin);
   SimpleVar(const string& v, VarOrigin origin);
 
-  virtual const char* Flavor() const override {
-    return "simple";
-  }
-  virtual VarOrigin Origin() const override {
-    return origin_;
-  }
+  virtual const char* Flavor() const override { return "simple"; }
+  virtual VarOrigin Origin() const override { return origin_; }
 
   virtual void Eval(Evaluator* ev, string* s) const override;
 
@@ -128,12 +126,8 @@
  public:
   RecursiveVar(Value* v, VarOrigin origin, StringPiece orig);
 
-  virtual const char* Flavor() const override {
-    return "recursive";
-  }
-  virtual VarOrigin Origin() const override {
-    return origin_;
-  }
+  virtual const char* Flavor() const override { return "recursive"; }
+  virtual VarOrigin Origin() const override { return origin_; }
 
   virtual void Eval(Evaluator* ev, string* s) const override;
 
@@ -153,12 +147,8 @@
  public:
   UndefinedVar();
 
-  virtual const char* Flavor() const override {
-    return "undefined";
-  }
-  virtual VarOrigin Origin() const override {
-    return VarOrigin::UNDEFINED;
-  }
+  virtual const char* Flavor() const override { return "undefined"; }
+  virtual VarOrigin Origin() const override { return VarOrigin::UNDEFINED; }
   virtual bool IsDefined() const override { return false; }
 
   virtual void Eval(Evaluator* ev, string* s) const override;
@@ -172,33 +162,20 @@
 
 class RuleVar : public Var {
  public:
-  RuleVar(Var* v, AssignOp op)
-      : v_(v), op_(op) {}
-  virtual ~RuleVar() {
-    delete v_;
-  }
+  RuleVar(Var* v, AssignOp op) : v_(v), op_(op) {}
+  virtual ~RuleVar() { delete v_; }
 
-  virtual const char* Flavor() const override {
-    return v_->Flavor();
-  }
-  virtual VarOrigin Origin() const override {
-    return v_->Origin();
-  }
-  virtual bool IsDefined() const override {
-    return v_->IsDefined();
-  }
+  virtual const char* Flavor() const override { return v_->Flavor(); }
+  virtual VarOrigin Origin() const override { return v_->Origin(); }
+  virtual bool IsDefined() const override { return v_->IsDefined(); }
   virtual void Eval(Evaluator* ev, string* s) const override {
     v_->Eval(ev, s);
   }
   virtual void AppendVar(Evaluator* ev, Value* v) override {
     v_->AppendVar(ev, v);
   }
-  virtual StringPiece String() const override {
-    return v_->String();
-  }
-  virtual string DebugString() const override {
-    return v_->DebugString();
-  }
+  virtual StringPiece String() const override { return v_->String(); }
+  virtual string DebugString() const override { return v_->DebugString(); }
 
   Var* v() const { return v_; }
   AssignOp op() const { return op_; }
@@ -218,9 +195,7 @@
 
   static void add_used_env_vars(Symbol v);
 
-  static const unordered_set<Symbol>& used_env_vars() {
-    return used_env_vars_;
-  }
+  static const unordered_set<Symbol>& used_env_vars() { return used_env_vars_; }
 
  private:
   static unordered_set<Symbol> used_env_vars_;