1 // Copyright 2011 Google Inc. All Rights Reserved.
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
20 #include "edit_distance.h"
24 const Rule State::kPhonyRule("phony");
26 State::State() : build_log_(NULL) {
30 void State::AddRule(const Rule* rule) {
31 assert(LookupRule(rule->name_) == NULL);
32 rules_[rule->name_] = rule;
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())
42 Edge* State::AddEdge(const Rule* rule) {
43 Edge* edge = new Edge();
45 edge->env_ = &bindings_;
46 edges_.push_back(edge);
50 Node* State::GetNode(const string& path) {
51 Node* node = LookupNode(path);
54 node = new Node(path);
55 paths_[node->path().c_str()] = node;
59 Node* State::LookupNode(const string& path) {
60 Paths::iterator i = paths_.find(path.c_str());
61 if (i != paths_.end())
66 Node* State::SpellcheckNode(const string& path) {
67 const bool kAllowReplacements = true;
68 const int kMaxValidEditDistance = 3;
70 int min_distance = kMaxValidEditDistance + 1;
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;
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);
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());
96 node->set_in_edge(edge);
99 bool State::AddDefault(const string& path, string* err) {
100 Node* node = LookupNode(path);
102 *err = "unknown target '" + path + "'";
105 defaults_.push_back(node);
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);
120 if (!edges_.empty() && root_nodes.empty())
121 *err = "could not determine root nodes of build graph";
123 assert(edges_.empty() || !root_nodes.empty());
127 vector<Node*> State::DefaultNodes(string* err) {
128 return defaults_.empty() ? RootNodes(err) : defaults_;
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;
139 for (Paths::iterator i = paths_.begin(); i != paths_.end(); ++i) {
140 Node* node = i->second;
142 node->path().c_str(),
143 node->status_known() ? (node->dirty() ? "dirty" : "clean")