[C++] The first commit for C++ version
16 tests out of 169 are passing.
diff --git a/dep.cc b/dep.cc
new file mode 100644
index 0000000..426b1a2
--- /dev/null
+++ b/dep.cc
@@ -0,0 +1,193 @@
+#include "dep.h"
+
+#include <memory>
+
+#include "log.h"
+#include "rule.h"
+#include "var.h"
+
+static vector<DepNode*>* g_dep_node_pool;
+
+DepNode::DepNode(StringPiece o, bool p)
+ : output(o),
+ has_rule(false),
+ is_order_only(false),
+ is_phony(p),
+ target_specific_vars(NULL) {
+ g_dep_node_pool->push_back(this);
+}
+
+class DepBuilder {
+ public:
+ DepBuilder(const vector<Rule*>& rules,
+ const Vars& vars,
+ const unordered_map<StringPiece, Vars*>& rule_vars)
+ : vars_(vars),
+ rule_vars_(rule_vars),
+ first_rule_(NULL) {
+ PopulateRules(rules);
+ }
+
+ void Build(vector<StringPiece> targets,
+ vector<DepNode*>* nodes) {
+ if (targets.empty()) {
+ if (!first_rule_) {
+ ERROR("*** No targets.");
+ }
+ CHECK(!first_rule_->outputs.empty());
+ targets.push_back(first_rule_->outputs[0]);
+ }
+
+ // TODO: LogStats?
+
+ for (StringPiece target : targets) {
+ unique_ptr<Vars> tsvs(new Vars);
+ DepNode* n = BuildPlan(target, "", tsvs.get());
+ nodes->push_back(n);
+ }
+ }
+
+ private:
+ void PopulateRules(const vector<Rule*>& rules) {
+ for (Rule* rule : rules) {
+ if (rule->outputs.empty()) {
+ PopulateImplicitRule(rule);
+ } else {
+ PopulateExplicitRule(rule);
+ }
+ }
+ }
+
+ void PopulateExplicitRule(Rule* rule) {
+ for (StringPiece output : rule->outputs) {
+ // isSuffixRule := db.populateSuffixRule(rule, output)
+
+
+ /*
+ if oldRule, present := db.rules[output]; present {
+ r := mergeRules(oldRule, rule, output, isSuffixRule)
+ db.rules[output] = r
+ } else {
+ db.rules[output] = rule
+ if db.firstRule == nil && !strings.HasPrefix(output, ".") {
+ db.firstRule = rule
+ }
+ }
+ */
+
+ auto p = rules_.insert(make_pair(output, rule));
+ if (p.second) {
+ if (!first_rule_ && output.get(0) != '.') {
+ first_rule_ = rule;
+ }
+ } else {
+ // TODO: merge
+ CHECK(false);
+ }
+ }
+ }
+
+ void PopulateImplicitRule(Rule*) {
+ CHECK(false);
+ }
+
+ Rule* LookupRule(StringPiece o) {
+ auto found = rules_.find(o);
+ if (found != rules_.end())
+ return found->second;
+ return NULL;
+ }
+
+ Vars* LookupRuleVars(StringPiece o) {
+ auto found = rule_vars_.find(o);
+ if (found != rule_vars_.end())
+ return found->second;
+ return NULL;
+ }
+
+ bool PickRule(StringPiece output, Rule** r, Vars** v) {
+ Rule* rule = LookupRule(output);
+ Vars* vars = LookupRuleVars(output);
+ *r = rule;
+ *v = vars;
+ if (rule) {
+ if (!rule->cmds.empty()) {
+ return true;
+ }
+ }
+ return rule;
+ }
+
+ DepNode* BuildPlan(StringPiece output, StringPiece needed_by, Vars* tsvs) {
+ LOG("BuildPlan: %s for %s",
+ output.as_string().c_str(),
+ needed_by.as_string().c_str());
+
+ auto found = done_.find(output);
+ if (found != done_.end()) {
+ return found->second;
+ }
+
+ DepNode* n = new DepNode(output, phony_[output]);
+ done_[output] = n;
+
+ Rule* rule;
+ Vars* vars;
+ if (!PickRule(output, &rule, &vars)) {
+ return n;
+ }
+
+ // TODO: Handle TSVs
+
+ for (StringPiece input : rule->inputs) {
+ if (rule->output_patterns.size() > 0) {
+ if (rule->output_patterns.size() > 1) {
+ ERROR("TODO: multiple output pattern is not supported yet");
+ }
+ ERROR("TODO");
+ }
+
+ n->actual_inputs.push_back(input);
+ DepNode* c = BuildPlan(input, output, tsvs);
+ n->deps.push_back(c);
+ }
+
+ // TODO: order only
+ n->has_rule = true;
+ n->cmds = rule->cmds;
+
+ return n;
+ }
+
+ unordered_map<StringPiece, Rule*> rules_;
+ const Vars& vars_;
+ const unordered_map<StringPiece, Vars*>& rule_vars_;
+
+ vector<Rule*> implicit_rules_; // pattern=%. no prefix,suffix.
+ //vector<Rule*> iprefix_rules_; // pattern=prefix%.. may have suffix
+ //vector<Rule*> isuffix_rules_; // pattern=%suffix no prefix
+
+ unordered_map<StringPiece, vector<Rule*>> suffix_rules_;
+ Rule* first_rule_;
+ unordered_map<StringPiece, DepNode*> done_;
+ unordered_map<StringPiece, bool> phony_;
+};
+
+void MakeDep(const vector<Rule*>& rules,
+ const Vars& vars,
+ const unordered_map<StringPiece, Vars*>& rule_vars,
+ const vector<StringPiece>& targets,
+ vector<DepNode*>* nodes) {
+ DepBuilder db(rules, vars, rule_vars);
+ db.Build(targets, nodes);
+}
+
+void InitDepNodePool() {
+ g_dep_node_pool = new vector<DepNode*>;
+}
+
+void QuitDepNodePool() {
+ for (DepNode* n : *g_dep_node_pool)
+ delete n;
+ delete g_dep_node_pool;
+}