blob: 04bb16872498beac16c8fbed0150878e6730c38a [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"
Shinichiro Hamajib6a04542015-09-09 17:37:41 +090024#include "flags.h"
Shinichiro Hamaji5f86e1a2015-06-29 14:25:39 +090025#include "log.h"
26#include "strutil.h"
27#include "var.h"
28
29namespace {
30
31class AutoVar : public Var {
32 public:
Sasha Smundakae1d58c2018-08-22 09:39:42 -070033 AutoVar() : Var(VarOrigin::AUTOMATIC) {}
Dan Willemsen3ce083f2017-10-11 22:17:48 -070034 virtual const char* Flavor() const override { return "undefined"; }
Shinichiro Hamaji5f86e1a2015-06-29 14:25:39 +090035
36 virtual void AppendVar(Evaluator*, Value*) override { CHECK(false); }
37
38 virtual StringPiece String() const override {
39 ERROR("$(value %s) is not implemented yet", sym_);
40 return "";
41 }
42
43 virtual string DebugString() const override {
44 return string("AutoVar(") + sym_ + ")";
45 }
46
47 protected:
48 AutoVar(CommandEvaluator* ce, const char* sym) : ce_(ce), sym_(sym) {}
49 virtual ~AutoVar() = default;
50
51 CommandEvaluator* ce_;
52 const char* sym_;
53};
54
Dan Willemsen3ce083f2017-10-11 22:17:48 -070055#define DECLARE_AUTO_VAR_CLASS(name) \
56 class name : public AutoVar { \
57 public: \
58 name(CommandEvaluator* ce, const char* sym) : AutoVar(ce, sym) {} \
59 virtual ~name() = default; \
60 virtual void Eval(Evaluator* ev, string* s) const override; \
Shinichiro Hamaji5f86e1a2015-06-29 14:25:39 +090061 }
62
63DECLARE_AUTO_VAR_CLASS(AutoAtVar);
64DECLARE_AUTO_VAR_CLASS(AutoLessVar);
65DECLARE_AUTO_VAR_CLASS(AutoHatVar);
66DECLARE_AUTO_VAR_CLASS(AutoPlusVar);
67DECLARE_AUTO_VAR_CLASS(AutoStarVar);
Shinichiro Hamajib552df32015-12-12 12:37:51 +090068DECLARE_AUTO_VAR_CLASS(AutoNotImplementedVar);
Shinichiro Hamaji5f86e1a2015-06-29 14:25:39 +090069
70class AutoSuffixDVar : public AutoVar {
71 public:
72 AutoSuffixDVar(CommandEvaluator* ce, const char* sym, Var* wrapped)
Dan Willemsen3ce083f2017-10-11 22:17:48 -070073 : AutoVar(ce, sym), wrapped_(wrapped) {}
Shinichiro Hamaji5f86e1a2015-06-29 14:25:39 +090074 virtual ~AutoSuffixDVar() = default;
75 virtual void Eval(Evaluator* ev, string* s) const override;
76
77 private:
78 Var* wrapped_;
79};
80
81class AutoSuffixFVar : public AutoVar {
82 public:
83 AutoSuffixFVar(CommandEvaluator* ce, const char* sym, Var* wrapped)
84 : AutoVar(ce, sym), wrapped_(wrapped) {}
85 virtual ~AutoSuffixFVar() = default;
86 virtual void Eval(Evaluator* ev, string* s) const override;
87
88 private:
89 Var* wrapped_;
90};
91
92void AutoAtVar::Eval(Evaluator*, string* s) const {
Shinichiro Hamajie7992752015-06-29 18:38:35 +090093 *s += ce_->current_dep_node()->output.str();
Shinichiro Hamaji5f86e1a2015-06-29 14:25:39 +090094}
95
96void AutoLessVar::Eval(Evaluator*, string* s) const {
97 auto& ai = ce_->current_dep_node()->actual_inputs;
98 if (!ai.empty())
Shinichiro Hamajie7992752015-06-29 18:38:35 +090099 *s += ai[0].str();
Shinichiro Hamaji5f86e1a2015-06-29 14:25:39 +0900100}
101
102void AutoHatVar::Eval(Evaluator*, string* s) const {
103 unordered_set<StringPiece> seen;
104 WordWriter ww(s);
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900105 for (Symbol ai : ce_->current_dep_node()->actual_inputs) {
106 if (seen.insert(ai.str()).second)
107 ww.Write(ai.str());
Shinichiro Hamaji5f86e1a2015-06-29 14:25:39 +0900108 }
109}
110
111void AutoPlusVar::Eval(Evaluator*, string* s) const {
112 WordWriter ww(s);
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900113 for (Symbol ai : ce_->current_dep_node()->actual_inputs) {
114 ww.Write(ai.str());
Shinichiro Hamaji5f86e1a2015-06-29 14:25:39 +0900115 }
116}
117
118void AutoStarVar::Eval(Evaluator*, string* s) const {
Shinichiro Hamajia7984ad2015-09-11 16:33:16 +0900119 const DepNode* n = ce_->current_dep_node();
120 if (!n->output_pattern.IsValid())
121 return;
122 Pattern pat(n->output_pattern.str());
123 pat.Stem(n->output.str()).AppendToString(s);
Shinichiro Hamaji5f86e1a2015-06-29 14:25:39 +0900124}
125
Shinichiro Hamajib91fb6f2015-12-18 15:59:13 +0900126void AutoNotImplementedVar::Eval(Evaluator* ev, string*) const {
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700127 ev->Error(StringPrintf("Automatic variable `$%s' isn't supported yet", sym_));
Shinichiro Hamajib552df32015-12-12 12:37:51 +0900128}
129
Shinichiro Hamaji5f86e1a2015-06-29 14:25:39 +0900130void AutoSuffixDVar::Eval(Evaluator* ev, string* s) const {
131 string buf;
132 wrapped_->Eval(ev, &buf);
133 WordWriter ww(s);
134 for (StringPiece tok : WordScanner(buf)) {
135 ww.Write(Dirname(tok));
136 }
137}
138
139void AutoSuffixFVar::Eval(Evaluator* ev, string* s) const {
140 string buf;
141 wrapped_->Eval(ev, &buf);
142 WordWriter ww(s);
143 for (StringPiece tok : WordScanner(buf)) {
144 ww.Write(Basename(tok));
145 }
146}
147
148void ParseCommandPrefixes(StringPiece* s, bool* echo, bool* ignore_error) {
149 *s = TrimLeftSpace(*s);
150 while (true) {
151 char c = s->get(0);
152 if (c == '@') {
153 *echo = false;
154 } else if (c == '-') {
155 *ignore_error = true;
Stefan Becker952d4452016-04-13 13:55:34 +0300156 } else if (c == '+') {
157 // ignore recursion marker
Shinichiro Hamaji5f86e1a2015-06-29 14:25:39 +0900158 } else {
159 break;
160 }
161 *s = TrimLeftSpace(s->substr(1));
162 }
163}
164
165} // namespace
166
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700167CommandEvaluator::CommandEvaluator(Evaluator* ev) : ev_(ev) {
168#define INSERT_AUTO_VAR(name, sym) \
169 do { \
Shinichiro Hamaji5f86e1a2015-06-29 14:25:39 +0900170 Var* v = new name(this, sym); \
Shinichiro Hamajic9b9e5e2016-02-18 18:18:54 +0900171 Intern(sym).SetGlobalVar(v); \
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700172 Intern(sym "D").SetGlobalVar(new AutoSuffixDVar(this, sym "D", v)); \
173 Intern(sym "F").SetGlobalVar(new AutoSuffixFVar(this, sym "F", v)); \
Shinichiro Hamaji5f86e1a2015-06-29 14:25:39 +0900174 } while (0)
175 INSERT_AUTO_VAR(AutoAtVar, "@");
176 INSERT_AUTO_VAR(AutoLessVar, "<");
177 INSERT_AUTO_VAR(AutoHatVar, "^");
178 INSERT_AUTO_VAR(AutoPlusVar, "+");
179 INSERT_AUTO_VAR(AutoStarVar, "*");
Shinichiro Hamajib552df32015-12-12 12:37:51 +0900180 // TODO: Implement them.
181 INSERT_AUTO_VAR(AutoNotImplementedVar, "%");
182 INSERT_AUTO_VAR(AutoNotImplementedVar, "?");
183 INSERT_AUTO_VAR(AutoNotImplementedVar, "|");
Shinichiro Hamaji5f86e1a2015-06-29 14:25:39 +0900184}
185
186void CommandEvaluator::Eval(DepNode* n, vector<Command*>* commands) {
Shinichiro Hamaji86e11332015-07-28 15:24:17 +0900187 ev_->set_loc(n->loc);
Shinichiro Hamaji5f86e1a2015-06-29 14:25:39 +0900188 ev_->set_current_scope(n->rule_vars);
189 current_dep_node_ = n;
190 for (Value* v : n->cmds) {
Shinichiro Hamajifb415ad2015-08-14 17:19:34 +0900191 const string&& cmds_buf = v->Eval(ev_);
192 StringPiece cmds = cmds_buf;
Shinichiro Hamaji003d06e2015-09-09 18:22:04 +0900193 bool global_echo = !g_flags.is_silent_mode;
Shinichiro Hamaji5f86e1a2015-06-29 14:25:39 +0900194 bool global_ignore_error = false;
195 ParseCommandPrefixes(&cmds, &global_echo, &global_ignore_error);
196 if (cmds == "")
197 continue;
198 while (true) {
199 size_t lf_cnt;
200 size_t index = FindEndOfLine(cmds, 0, &lf_cnt);
201 if (index == cmds.size())
202 index = string::npos;
203 StringPiece cmd = TrimLeftSpace(cmds.substr(0, index));
204 cmds = cmds.substr(index + 1);
205
206 bool echo = global_echo;
207 bool ignore_error = global_ignore_error;
208 ParseCommandPrefixes(&cmd, &echo, &ignore_error);
209
210 if (!cmd.empty()) {
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900211 Command* command = new Command(n->output);
Shinichiro Hamajifb415ad2015-08-14 17:19:34 +0900212 command->cmd = cmd.as_string();
Shinichiro Hamaji5f86e1a2015-06-29 14:25:39 +0900213 command->echo = echo;
214 command->ignore_error = ignore_error;
215 commands->push_back(command);
216 }
217 if (index == string::npos)
218 break;
219 }
220 continue;
221 }
Shinichiro Hamaji86e11332015-07-28 15:24:17 +0900222
223 if (!ev_->delayed_output_commands().empty()) {
224 vector<Command*> output_commands;
225 for (const string& cmd : ev_->delayed_output_commands()) {
226 Command* c = new Command(n->output);
Shinichiro Hamajifb415ad2015-08-14 17:19:34 +0900227 c->cmd = cmd;
Shinichiro Hamaji86e11332015-07-28 15:24:17 +0900228 c->echo = false;
229 c->ignore_error = false;
230 output_commands.push_back(c);
231 }
232 // Prepend |output_commands|.
233 commands->swap(output_commands);
234 copy(output_commands.begin(), output_commands.end(),
235 back_inserter(*commands));
236 ev_->clear_delayed_output_commands();
237 }
238
Shinichiro Hamaji5f86e1a2015-06-29 14:25:39 +0900239 ev_->set_current_scope(NULL);
240}