import
authorEvan Martin <martine@danga.com>
Fri, 15 Oct 2010 05:14:06 +0000 (22:14 -0700)
committerEvan Martin <martine@danga.com>
Fri, 15 Oct 2010 05:14:06 +0000 (22:14 -0700)
.gitignore [new file with mode: 0644]
Makefile [new file with mode: 0644]
ninja.cc [new file with mode: 0644]
ninja.h [new file with mode: 0644]
ninja_test.cc [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..6484956
--- /dev/null
@@ -0,0 +1,2 @@
+ninja
+ninja_test
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..18f8918
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,7 @@
+CXXFLAGS := -Wall -g
+
+all: ninja ninja_test
+ninja: ninja.cc | Makefile
+
+ninja_test: LDFLAGS = -lgtest -lgtest_main
+ninja_test: ninja_test.cc | Makefile
diff --git a/ninja.cc b/ninja.cc
new file mode 100644 (file)
index 0000000..3e305c8
--- /dev/null
+++ b/ninja.cc
@@ -0,0 +1,5 @@
+#include "ninja.h"
+
+int main(int argc, char** argv) {
+  return 0;
+}
diff --git a/ninja.h b/ninja.h
new file mode 100644 (file)
index 0000000..e6eb3e1
--- /dev/null
+++ b/ninja.h
@@ -0,0 +1,80 @@
+#include <map>
+#include <string>
+#include <vector>
+
+using namespace std;
+
+struct Node;
+struct FileStat {
+  FileStat(const string& path) : path_(path), node_(NULL) {}
+  string path_;
+  Node* node_;
+};
+
+struct Edge;
+struct Node {
+  Node(FileStat* file) : file_(file), dirty_(false) {}
+  FileStat* file_;
+  bool dirty_;
+  vector<Edge*> edges_;
+};
+
+struct Rule {
+  Rule(const string& name, const string& command) :
+    name_(name), command_(command) {}
+  string name_;
+  string command_;
+};
+
+struct Edge {
+  Rule* rule_;
+  enum InOut { IN, OUT };
+  vector<Node*> inputs_;
+  vector<Node*> outputs_;
+};
+
+struct StatCache {
+  map<string, FileStat*> paths_;
+};
+struct State {
+  StatCache stat_cache_;
+  map<string, Rule*> rules_;
+  vector<Edge*> edges_;
+
+  Rule* AddRule(const string& name, const string& command);
+  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);
+};
+
+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;
+  edges_.push_back(edge);
+  return edge;
+}
+
+Node* State::GetNode(const string& path) {
+  FileStat* file = new FileStat(path);
+  stat_cache_.paths_[path] = file;
+  return new Node(file);
+}
+
+void State::AddInOut(Edge* edge, Edge::InOut inout, const string& path) {
+  Node* node = GetNode(path);
+  if (inout == Edge::IN)
+    edge->inputs_.push_back(node);
+  else
+    edge->outputs_.push_back(node);
+}
diff --git a/ninja_test.cc b/ninja_test.cc
new file mode 100644 (file)
index 0000000..145c53c
--- /dev/null
@@ -0,0 +1,20 @@
+#include "ninja.h"
+
+#include <gtest/gtest.h>
+
+struct NinjaTest : public testing::Test {
+  NinjaTest() {
+    rule_cat_ = state_.AddRule("cat", "cat @in > $out");
+  }
+
+  Rule* rule_cat_;
+  State state_;
+};
+
+TEST_F(NinjaTest, Basic) {
+  Edge* edge = state_.AddEdge(rule_cat_);
+  state_.AddInOut(edge, Edge::IN, "in1");
+  state_.AddInOut(edge, Edge::IN, "in2");
+  state_.AddInOut(edge, Edge::OUT, "out");
+}
+