aboutsummaryrefslogtreecommitdiffstats
path: root/exec.cc
blob: 91d996d1607874124fb7ec48fd6aad00eb223842 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include "exec.h"

#include <stdio.h>
#include <stdlib.h>

#include <memory>
#include <unordered_map>

#include "dep.h"
#include "eval.h"
#include "log.h"
#include "string_piece.h"
#include "value.h"

namespace {

struct Runner {
  Runner()
      : echo(true), ignore_error(false) {
  }
  StringPiece output;
  shared_ptr<string> cmd;
  bool echo;
  bool ignore_error;
  //StringPiece shell;
};

}  // namespace

class Executor {
 public:
  explicit Executor(const Vars* vars)
      : vars_(vars) {
  }

  void ExecNode(DepNode* n, DepNode* needed_by) {
    if (done_[n->output])
      return;

    LOG("ExecNode: %s for %s",
        n->output.as_string().c_str(),
        needed_by ? needed_by->output.as_string().c_str() : "(null)");

    for (DepNode* d : n->deps) {
#if 0
      if (d.is_order_only && exists(d->output)) {
      }
#endif
      ExecNode(d, n);
    }

    vector<Runner*> runners;
    CreateRunners(n, &runners);
    for (Runner* runner : runners) {
      if (runner->echo) {
        printf("%s\n", runner->cmd->c_str());
        fflush(stdout);
      }
      system(runner->cmd->c_str());
      delete runner;
    }
  }

  void CreateRunners(DepNode* n, vector<Runner*>* runners) {
    unique_ptr<Evaluator> ev(new Evaluator(vars_));
    for (Value* v : n->cmds) {
      shared_ptr<string> cmd = v->Eval(ev.get());
      while (true) {
        size_t index = cmd->find('\n');
        if (index == string::npos)
          break;

        Runner* runner = new Runner;
        runner->output = n->output;
        runner->cmd = make_shared<string>(cmd->substr(0, index));
        runners->push_back(runner);
        cmd = make_shared<string>(cmd->substr(index + 1));
      }
      Runner* runner = new Runner;
      runner->output = n->output;
      runner->cmd = cmd;
      runners->push_back(runner);
      continue;
    }
  }

 private:
  const Vars* vars_;
  unordered_map<StringPiece, bool> done_;

};

void Exec(const vector<DepNode*>& roots, const Vars* vars) {
  unique_ptr<Executor> executor(new Executor(vars));
  for (DepNode* root : roots) {
    executor->ExecNode(root, NULL);
  }
}