make Node::in_edge_ private
[platform/upstream/ninja.git] / src / state.cc
1 // Copyright 2011 Google Inc. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "state.h"
16
17 #include <assert.h>
18 #include <stdio.h>
19
20 #include "edit_distance.h"
21 #include "graph.h"
22 #include "util.h"
23
24 const Rule State::kPhonyRule("phony");
25
26 State::State() : build_log_(NULL) {
27   AddRule(&kPhonyRule);
28 }
29
30 void State::AddRule(const Rule* rule) {
31   assert(LookupRule(rule->name_) == NULL);
32   rules_[rule->name_] = rule;
33 }
34
35 const Rule* State::LookupRule(const string& rule_name) {
36   map<string, const Rule*>::iterator i = rules_.find(rule_name);
37   if (i == rules_.end())
38     return NULL;
39   return i->second;
40 }
41
42 Edge* State::AddEdge(const Rule* rule) {
43   Edge* edge = new Edge();
44   edge->rule_ = rule;
45   edge->env_ = &bindings_;
46   edges_.push_back(edge);
47   return edge;
48 }
49
50 Node* State::GetNode(const string& path) {
51   Node* node = LookupNode(path);
52   if (node)
53     return node;
54   node = new Node(path);
55   paths_[node->path().c_str()] = node;
56   return node;
57 }
58
59 Node* State::LookupNode(const string& path) {
60   Paths::iterator i = paths_.find(path.c_str());
61   if (i != paths_.end())
62     return i->second;
63   return NULL;
64 }
65
66 Node* State::SpellcheckNode(const string& path) {
67   const bool kAllowReplacements = true;
68   const int kMaxValidEditDistance = 3;
69
70   int min_distance = kMaxValidEditDistance + 1;
71   Node* result = NULL;
72   for (Paths::iterator i = paths_.begin(); i != paths_.end(); ++i) {
73     int distance = EditDistance(
74         i->first, path, kAllowReplacements, kMaxValidEditDistance);
75     if (distance < min_distance && i->second) {
76       min_distance = distance;
77       result = i->second;
78     }
79   }
80   return result;
81 }
82
83 void State::AddIn(Edge* edge, const string& path) {
84   Node* node = GetNode(path);
85   edge->inputs_.push_back(node);
86   node->out_edges_.push_back(edge);
87 }
88
89 void State::AddOut(Edge* edge, const string& path) {
90   Node* node = GetNode(path);
91   edge->outputs_.push_back(node);
92   if (node->in_edge()) {
93     Warning("multiple rules generate %s. "
94             "build will not be correct; continuing anyway", path.c_str());
95   }
96   node->set_in_edge(edge);
97 }
98
99 bool State::AddDefault(const string& path, string* err) {
100   Node* node = LookupNode(path);
101   if (!node) {
102     *err = "unknown target '" + path + "'";
103     return false;
104   }
105   defaults_.push_back(node);
106   return true;
107 }
108
109 vector<Node*> State::RootNodes(string* err) {
110   vector<Node*> root_nodes;
111   // Search for nodes with no output.
112   for (vector<Edge*>::iterator e = edges_.begin(); e != edges_.end(); ++e) {
113     for (vector<Node*>::iterator out = (*e)->outputs_.begin();
114          out != (*e)->outputs_.end(); ++out) {
115       if ((*out)->out_edges_.empty())
116         root_nodes.push_back(*out);
117     }
118   }
119
120   if (!edges_.empty() && root_nodes.empty())
121     *err = "could not determine root nodes of build graph";
122
123   assert(edges_.empty() || !root_nodes.empty());
124   return root_nodes;
125 }
126
127 vector<Node*> State::DefaultNodes(string* err) {
128   return defaults_.empty() ? RootNodes(err) : defaults_;
129 }
130
131 void State::Reset() {
132   for (Paths::iterator i = paths_.begin(); i != paths_.end(); ++i)
133     i->second->ResetState();
134   for (vector<Edge*>::iterator e = edges_.begin(); e != edges_.end(); ++e)
135     (*e)->outputs_ready_ = false;
136 }
137
138 void State::Dump() {
139   for (Paths::iterator i = paths_.begin(); i != paths_.end(); ++i) {
140     Node* node = i->second;
141     printf("%s %s\n",
142            node->path().c_str(),
143            node->status_known() ? (node->dirty() ? "dirty" : "clean")
144                                 : "unknown");
145   }
146 }