blob: 6b48f68f57d3b7d05253057673e5b916b48a7745 [file] [log] [blame]
Shinichiro Hamaji5f86e1a2015-06-29 14:25:39 +09001// Copyright 2015 Google Inc. All rights reserved
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15// +build ignore
16
17#include "command.h"
18
19#include <unordered_map>
20#include <unordered_set>
21
22#include "dep.h"
23#include "eval.h"
24#include "log.h"
25#include "strutil.h"
26#include "var.h"
27
28namespace {
29
30class AutoVar : public Var {
31 public:
32 virtual const char* Flavor() const override {
33 return "undefined";
34 }
35 virtual VarOrigin Origin() const override {
36 return VarOrigin::AUTOMATIC;
37 }
38
39 virtual void AppendVar(Evaluator*, Value*) override { CHECK(false); }
40
41 virtual StringPiece String() const override {
42 ERROR("$(value %s) is not implemented yet", sym_);
43 return "";
44 }
45
46 virtual string DebugString() const override {
47 return string("AutoVar(") + sym_ + ")";
48 }
49
50 protected:
51 AutoVar(CommandEvaluator* ce, const char* sym) : ce_(ce), sym_(sym) {}
52 virtual ~AutoVar() = default;
53
54 CommandEvaluator* ce_;
55 const char* sym_;
56};
57
58#define DECLARE_AUTO_VAR_CLASS(name) \
59 class name : public AutoVar { \
60 public: \
61 name(CommandEvaluator* ce, const char* sym) \
62 : AutoVar(ce, sym) {} \
63 virtual ~name() = default; \
64 virtual void Eval(Evaluator* ev, string* s) const override; \
65 }
66
67DECLARE_AUTO_VAR_CLASS(AutoAtVar);
68DECLARE_AUTO_VAR_CLASS(AutoLessVar);
69DECLARE_AUTO_VAR_CLASS(AutoHatVar);
70DECLARE_AUTO_VAR_CLASS(AutoPlusVar);
71DECLARE_AUTO_VAR_CLASS(AutoStarVar);
72
73class AutoSuffixDVar : public AutoVar {
74 public:
75 AutoSuffixDVar(CommandEvaluator* ce, const char* sym, Var* wrapped)
76 : AutoVar(ce, sym), wrapped_(wrapped) {
77 }
78 virtual ~AutoSuffixDVar() = default;
79 virtual void Eval(Evaluator* ev, string* s) const override;
80
81 private:
82 Var* wrapped_;
83};
84
85class AutoSuffixFVar : public AutoVar {
86 public:
87 AutoSuffixFVar(CommandEvaluator* ce, const char* sym, Var* wrapped)
88 : AutoVar(ce, sym), wrapped_(wrapped) {}
89 virtual ~AutoSuffixFVar() = default;
90 virtual void Eval(Evaluator* ev, string* s) const override;
91
92 private:
93 Var* wrapped_;
94};
95
96void AutoAtVar::Eval(Evaluator*, string* s) const {
Shinichiro Hamajie7992752015-06-29 18:38:35 +090097 *s += ce_->current_dep_node()->output.str();
Shinichiro Hamaji5f86e1a2015-06-29 14:25:39 +090098}
99
100void AutoLessVar::Eval(Evaluator*, string* s) const {
101 auto& ai = ce_->current_dep_node()->actual_inputs;
102 if (!ai.empty())
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900103 *s += ai[0].str();
Shinichiro Hamaji5f86e1a2015-06-29 14:25:39 +0900104}
105
106void AutoHatVar::Eval(Evaluator*, string* s) const {
107 unordered_set<StringPiece> seen;
108 WordWriter ww(s);
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900109 for (Symbol ai : ce_->current_dep_node()->actual_inputs) {
110 if (seen.insert(ai.str()).second)
111 ww.Write(ai.str());
Shinichiro Hamaji5f86e1a2015-06-29 14:25:39 +0900112 }
113}
114
115void AutoPlusVar::Eval(Evaluator*, string* s) const {
116 WordWriter ww(s);
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900117 for (Symbol ai : ce_->current_dep_node()->actual_inputs) {
118 ww.Write(ai.str());
Shinichiro Hamaji5f86e1a2015-06-29 14:25:39 +0900119 }
120}
121
122void AutoStarVar::Eval(Evaluator*, string* s) const {
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900123 AppendString(StripExt(ce_->current_dep_node()->output.str()), s);
Shinichiro Hamaji5f86e1a2015-06-29 14:25:39 +0900124}
125
126void AutoSuffixDVar::Eval(Evaluator* ev, string* s) const {
127 string buf;
128 wrapped_->Eval(ev, &buf);
129 WordWriter ww(s);
130 for (StringPiece tok : WordScanner(buf)) {
131 ww.Write(Dirname(tok));
132 }
133}
134
135void AutoSuffixFVar::Eval(Evaluator* ev, string* s) const {
136 string buf;
137 wrapped_->Eval(ev, &buf);
138 WordWriter ww(s);
139 for (StringPiece tok : WordScanner(buf)) {
140 ww.Write(Basename(tok));
141 }
142}
143
144void ParseCommandPrefixes(StringPiece* s, bool* echo, bool* ignore_error) {
145 *s = TrimLeftSpace(*s);
146 while (true) {
147 char c = s->get(0);
148 if (c == '@') {
149 *echo = false;
150 } else if (c == '-') {
151 *ignore_error = true;
152 } else {
153 break;
154 }
155 *s = TrimLeftSpace(s->substr(1));
156 }
157}
158
159} // namespace
160
161CommandEvaluator::CommandEvaluator(Evaluator* ev)
162 : ev_(ev) {
163 Vars* vars = ev_->mutable_vars();
164#define INSERT_AUTO_VAR(name, sym) do { \
165 Var* v = new name(this, sym); \
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900166 (*vars)[Intern(sym)] = v; \
167 (*vars)[Intern(sym"D")] = new AutoSuffixDVar(this, sym"D", v); \
168 (*vars)[Intern(sym"F")] = new AutoSuffixFVar(this, sym"F", v); \
Shinichiro Hamaji5f86e1a2015-06-29 14:25:39 +0900169 } while (0)
170 INSERT_AUTO_VAR(AutoAtVar, "@");
171 INSERT_AUTO_VAR(AutoLessVar, "<");
172 INSERT_AUTO_VAR(AutoHatVar, "^");
173 INSERT_AUTO_VAR(AutoPlusVar, "+");
174 INSERT_AUTO_VAR(AutoStarVar, "*");
175}
176
177void CommandEvaluator::Eval(DepNode* n, vector<Command*>* commands) {
Shinichiro Hamaji86e11332015-07-28 15:24:17 +0900178 ev_->set_loc(n->loc);
Shinichiro Hamaji5f86e1a2015-06-29 14:25:39 +0900179 ev_->set_current_scope(n->rule_vars);
180 current_dep_node_ = n;
181 for (Value* v : n->cmds) {
182 shared_ptr<string> cmds_buf = v->Eval(ev_);
183 StringPiece cmds = *cmds_buf;
184 bool global_echo = true;
185 bool global_ignore_error = false;
186 ParseCommandPrefixes(&cmds, &global_echo, &global_ignore_error);
187 if (cmds == "")
188 continue;
189 while (true) {
190 size_t lf_cnt;
191 size_t index = FindEndOfLine(cmds, 0, &lf_cnt);
192 if (index == cmds.size())
193 index = string::npos;
194 StringPiece cmd = TrimLeftSpace(cmds.substr(0, index));
195 cmds = cmds.substr(index + 1);
196
197 bool echo = global_echo;
198 bool ignore_error = global_ignore_error;
199 ParseCommandPrefixes(&cmd, &echo, &ignore_error);
200
201 if (!cmd.empty()) {
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900202 Command* command = new Command(n->output);
Shinichiro Hamaji5f86e1a2015-06-29 14:25:39 +0900203 command->cmd = make_shared<string>(cmd.as_string());
204 command->echo = echo;
205 command->ignore_error = ignore_error;
206 commands->push_back(command);
207 }
208 if (index == string::npos)
209 break;
210 }
211 continue;
212 }
Shinichiro Hamaji86e11332015-07-28 15:24:17 +0900213
214 if (!ev_->delayed_output_commands().empty()) {
215 vector<Command*> output_commands;
216 for (const string& cmd : ev_->delayed_output_commands()) {
217 Command* c = new Command(n->output);
218 c->cmd = make_shared<string>(cmd);
219 c->echo = false;
220 c->ignore_error = false;
221 output_commands.push_back(c);
222 }
223 // Prepend |output_commands|.
224 commands->swap(output_commands);
225 copy(output_commands.begin(), output_commands.end(),
226 back_inserter(*commands));
227 ev_->clear_delayed_output_commands();
228 }
229
Shinichiro Hamaji5f86e1a2015-06-29 14:25:39 +0900230 ev_->set_current_scope(NULL);
231}