aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--exec.cc107
-rw-r--r--exec.h2
2 files changed, 99 insertions, 10 deletions
diff --git a/exec.cc b/exec.cc
index 91d996d..337e7f8 100644
--- a/exec.cc
+++ b/exec.cc
@@ -5,15 +5,61 @@
#include <memory>
#include <unordered_map>
+#include <unordered_set>
+#include <utility>
+#include <vector>
#include "dep.h"
#include "eval.h"
#include "log.h"
#include "string_piece.h"
+#include "strutil.h"
#include "value.h"
+#include "var.h"
namespace {
+class Executor;
+
+class AutoVar : public Var {
+ public:
+ virtual const char* Flavor() const override {
+ return "undefined";
+ }
+ virtual const char* Origin() const override {
+ return "automatic";
+ }
+
+ virtual bool IsDefined() const override { CHECK(false); }
+ virtual void AppendVar(Evaluator*, Value*) override { CHECK(false); }
+
+ virtual string DebugString() const override {
+ return string("AutoVar(") + sym_ + ")";
+ }
+
+ protected:
+ AutoVar(Executor* ex, const char* sym) : ex_(ex), sym_(sym) {}
+ virtual ~AutoVar() = default;
+
+ Executor* ex_;
+ const char* sym_;
+};
+
+#define DECLARE_AUTO_VAR_CLASS(name) \
+ class name : public AutoVar { \
+ public: \
+ name(Executor* ex, const char* sym) \
+ : AutoVar(ex, sym) {} \
+ virtual ~name() = default; \
+ virtual void Eval(Evaluator* ev, string* s) const override; \
+ }
+
+DECLARE_AUTO_VAR_CLASS(AutoAtVar);
+DECLARE_AUTO_VAR_CLASS(AutoLessVar);
+DECLARE_AUTO_VAR_CLASS(AutoHatVar);
+DECLARE_AUTO_VAR_CLASS(AutoPlusVar);
+DECLARE_AUTO_VAR_CLASS(AutoStarVar);
+
struct Runner {
Runner()
: echo(true), ignore_error(false) {
@@ -25,12 +71,20 @@ struct Runner {
//StringPiece shell;
};
-} // namespace
-
class Executor {
public:
- explicit Executor(const Vars* vars)
- : vars_(vars) {
+ explicit Executor(Vars* vars)
+ : vars_(vars),
+ ev_(new Evaluator(vars_)) {
+#define INSERT_AUTO_VAR(name, sym) do { \
+ Var* v = new AutoAtVar(this, sym); \
+ (*vars)[STRING_PIECE(sym)] = v; \
+ } while (0)
+ INSERT_AUTO_VAR(AutoAtVar, "@");
+ INSERT_AUTO_VAR(AutoLessVar, "<");
+ INSERT_AUTO_VAR(AutoHatVar, "^");
+ INSERT_AUTO_VAR(AutoPlusVar, "+");
+ INSERT_AUTO_VAR(AutoStarVar, "*");
}
void ExecNode(DepNode* n, DepNode* needed_by) {
@@ -62,9 +116,9 @@ class Executor {
}
void CreateRunners(DepNode* n, vector<Runner*>* runners) {
- unique_ptr<Evaluator> ev(new Evaluator(vars_));
+ current_dep_node_ = n;
for (Value* v : n->cmds) {
- shared_ptr<string> cmd = v->Eval(ev.get());
+ shared_ptr<string> cmd = v->Eval(ev_.get());
while (true) {
size_t index = cmd->find('\n');
if (index == string::npos)
@@ -84,13 +138,48 @@ class Executor {
}
}
+ const DepNode* current_dep_node() const { return current_dep_node_; }
+
private:
- const Vars* vars_;
+ Vars* vars_;
+ unique_ptr<Evaluator> ev_;
unordered_map<StringPiece, bool> done_;
-
+ DepNode* current_dep_node_;
};
-void Exec(const vector<DepNode*>& roots, const Vars* vars) {
+void AutoAtVar::Eval(Evaluator*, string* s) const {
+ AppendString(ex_->current_dep_node()->output, s);
+}
+
+void AutoLessVar::Eval(Evaluator*, string* s) const {
+ auto& ai = ex_->current_dep_node()->actual_inputs;
+ if (!ai.empty())
+ AppendString(ai[0], s);
+}
+
+void AutoHatVar::Eval(Evaluator*, string* s) const {
+ unordered_set<StringPiece> seen;
+ WordWriter ww(s);
+ for (StringPiece ai : ex_->current_dep_node()->actual_inputs) {
+ if (seen.insert(ai).second)
+ ww.Write(ai);
+ }
+}
+
+void AutoPlusVar::Eval(Evaluator*, string* s) const {
+ WordWriter ww(s);
+ for (StringPiece ai : ex_->current_dep_node()->actual_inputs) {
+ ww.Write(ai);
+ }
+}
+
+void AutoStarVar::Eval(Evaluator*, string* s) const {
+ AppendString(StripExt(ex_->current_dep_node()->output), s);
+}
+
+} // namespace
+
+void Exec(const vector<DepNode*>& roots, Vars* vars) {
unique_ptr<Executor> executor(new Executor(vars));
for (DepNode* root : roots) {
executor->ExecNode(root, NULL);
diff --git a/exec.h b/exec.h
index 0f5944a..31b7b0a 100644
--- a/exec.h
+++ b/exec.h
@@ -8,6 +8,6 @@ using namespace std;
class DepNode;
class Vars;
-void Exec(const vector<DepNode*>& roots, const Vars* vars);
+void Exec(const vector<DepNode*>& roots, Vars* vars);
#endif // EXEC_H_