don't crash on missing rules
authorEvan Martin <martine@danga.com>
Fri, 22 Oct 2010 16:53:49 +0000 (09:53 -0700)
committerEvan Martin <martine@danga.com>
Fri, 22 Oct 2010 16:53:49 +0000 (09:53 -0700)
manifest_parser.h
ninja.h
ninja_test.cc

index 6ecbe7e..6b65437 100644 (file)
@@ -265,10 +265,14 @@ bool ManifestParser::ParseEdge(string* err) {
     outs.push_back(out);
   }
 
-  string rule;
-  if (!parser_.ReadToken(&rule))
+  string rule_name;
+  if (!parser_.ReadToken(&rule_name))
     return parser_.Error("expected build command name", err);
 
+  Rule* rule = state_->LookupRule(rule_name);
+  if (!rule)
+    return parser_.Error("unknown build rule '" + rule_name + "'", err);
+
   for (;;) {
     string in;
     if (!parser_.ReadToken(&in))
@@ -280,8 +284,6 @@ bool ManifestParser::ParseEdge(string* err) {
     return false;
 
   Edge* edge = state_->AddEdge(rule);
-  if (!edge)
-    return parser_.Error("unknown build rule name name", err);
   for (vector<string>::iterator i = ins.begin(); i != ins.end(); ++i)
     state_->AddInOut(edge, Edge::IN, *i);
   for (vector<string>::iterator i = outs.begin(); i != outs.end(); ++i)
diff --git a/ninja.h b/ninja.h
index edc5b58..a3e432d 100644 (file)
--- a/ninja.h
+++ b/ninja.h
@@ -225,8 +225,8 @@ struct State : public EvalString::Env {
   virtual string Evaluate(const string& var);
 
   Rule* AddRule(const string& name, const string& command);
+  Rule* LookupRule(const string& rule_name);
   Edge* AddEdge(Rule* rule);
-  Edge* AddEdge(const string& rule_name);
   Node* GetNode(const string& path);
   void AddInOut(Edge* edge, Edge::InOut inout, const string& path);
   void AddBinding(const string& key, const string& val);
@@ -241,16 +241,20 @@ string State::Evaluate(const string& var) {
   return "";
 }
 
+
+Rule* State::LookupRule(const string& rule_name) {
+  map<string, Rule*>::iterator i = rules_.find(rule_name);
+  if (i == rules_.end())
+    return NULL;
+  return i->second;
+}
+
 Rule* State::AddRule(const string& name, const string& command) {
   Rule* rule = new Rule(name, command);
   rules_[name] = rule;
   return rule;
 }
 
-Edge* State::AddEdge(const string& rule_name) {
-  return AddEdge(rules_[rule_name]);
-}
-
 Edge* State::AddEdge(Rule* rule) {
   Edge* edge = new Edge();
   edge->rule_ = rule;
index 0794915..bdba975 100644 (file)
@@ -95,6 +95,13 @@ TEST(Parser, Errors) {
     EXPECT_FALSE(parser.Parse("x = 3\ny 2", &err));
     EXPECT_EQ("line 2, col 3: expected '=', got '2'", err);
   }
+
+  {
+    ManifestParser parser(&state);
+    string err;
+    EXPECT_FALSE(parser.Parse("build x: y z\n", &err));
+    EXPECT_EQ("line 1, col 10: unknown build rule 'y'", err);
+  }
 }
 
 TEST(State, Basic) {