/// An Env for an Edge, providing $in and $out.
struct EdgeEnv : public Env {
EdgeEnv(Edge* edge) : edge_(edge) {}
- virtual string LookupVariable(const string& var) {
- string result;
- if (var == "in") {
- int explicit_deps = edge_->inputs_.size() - edge_->implicit_deps_ -
- edge_->order_only_deps_;
- for (vector<Node*>::iterator i = edge_->inputs_.begin();
- i != edge_->inputs_.end() && explicit_deps; ++i, --explicit_deps) {
- if (!result.empty())
- result.push_back(' ');
- result.append((*i)->path());
- }
- } else if (var == "out") {
- for (vector<Node*>::iterator i = edge_->outputs_.begin();
- i != edge_->outputs_.end(); ++i) {
- if (!result.empty())
- result.push_back(' ');
- result.append((*i)->path());
- }
- } else if (edge_->env_) {
- return edge_->env_->LookupVariable(var);
- }
- return result;
- }
+ virtual string LookupVariable(const string& var);
+
+ /// Given a span of Nodes, construct a list of paths suitable for a command
+ /// line. XXX here is where shell-escaping of e.g spaces should happen.
+ string MakePathList(vector<Node*>::iterator begin,
+ vector<Node*>::iterator end);
+
Edge* edge_;
};
+string EdgeEnv::LookupVariable(const string& var) {
+ if (var == "in") {
+ int explicit_deps_count = edge_->inputs_.size() - edge_->implicit_deps_ -
+ edge_->order_only_deps_;
+ return MakePathList(edge_->inputs_.begin(),
+ edge_->inputs_.begin() + explicit_deps_count);
+ } else if (var == "out") {
+ return MakePathList(edge_->outputs_.begin(),
+ edge_->outputs_.end());
+ } else if (edge_->env_) {
+ return edge_->env_->LookupVariable(var);
+ } else {
+ // XXX shoudl we warn here?
+ return string();
+ }
+}
+
+string EdgeEnv::MakePathList(vector<Node*>::iterator begin,
+ vector<Node*>::iterator end) {
+ string result;
+ for (vector<Node*>::iterator i = begin; i != end; ++i) {
+ if (!result.empty())
+ result.push_back(' ');
+ result.append((*i)->path());
+ }
+ return result;
+}
+
string Edge::EvaluateCommand() {
EdgeEnv env(this);
return rule_->command_.Evaluate(&env);