1 // 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 "flags.h"
25 #include "log.h"
26 #include "strutil.h"
27 #include "var.h"
28
29 namespace {
30
31 class AutoVar : public Var {
32 public:
AutoVar()33 AutoVar() : Var(VarOrigin::AUTOMATIC) {}
Flavor() const34 virtual const char* Flavor() const override { return "undefined"; }
35
AppendVar(Evaluator *,Value *)36 virtual void AppendVar(Evaluator*, Value*) override { CHECK(false); }
37
String() const38 virtual StringPiece String() const override {
39 ERROR("$(value %s) is not implemented yet", sym_);
40 return "";
41 }
42
DebugString() const43 virtual string DebugString() const override {
44 return string("AutoVar(") + sym_ + ")";
45 }
46
47 protected:
AutoVar(CommandEvaluator * ce,const char * sym)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
55 #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; \
61 }
62
63 DECLARE_AUTO_VAR_CLASS(AutoAtVar);
64 DECLARE_AUTO_VAR_CLASS(AutoLessVar);
65 DECLARE_AUTO_VAR_CLASS(AutoHatVar);
66 DECLARE_AUTO_VAR_CLASS(AutoPlusVar);
67 DECLARE_AUTO_VAR_CLASS(AutoStarVar);
68 DECLARE_AUTO_VAR_CLASS(AutoNotImplementedVar);
69
70 class AutoSuffixDVar : public AutoVar {
71 public:
AutoSuffixDVar(CommandEvaluator * ce,const char * sym,Var * wrapped)72 AutoSuffixDVar(CommandEvaluator* ce, const char* sym, Var* wrapped)
73 : AutoVar(ce, sym), wrapped_(wrapped) {}
74 virtual ~AutoSuffixDVar() = default;
75 virtual void Eval(Evaluator* ev, string* s) const override;
76
77 private:
78 Var* wrapped_;
79 };
80
81 class AutoSuffixFVar : public AutoVar {
82 public:
AutoSuffixFVar(CommandEvaluator * ce,const char * sym,Var * wrapped)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
Eval(Evaluator *,string * s) const92 void AutoAtVar::Eval(Evaluator*, string* s) const {
93 *s += ce_->current_dep_node()->output.str();
94 }
95
Eval(Evaluator *,string * s) const96 void AutoLessVar::Eval(Evaluator*, string* s) const {
97 auto& ai = ce_->current_dep_node()->actual_inputs;
98 if (!ai.empty())
99 *s += ai[0].str();
100 }
101
Eval(Evaluator *,string * s) const102 void AutoHatVar::Eval(Evaluator*, string* s) const {
103 unordered_set<StringPiece> seen;
104 WordWriter ww(s);
105 for (Symbol ai : ce_->current_dep_node()->actual_inputs) {
106 if (seen.insert(ai.str()).second)
107 ww.Write(ai.str());
108 }
109 }
110
Eval(Evaluator *,string * s) const111 void AutoPlusVar::Eval(Evaluator*, string* s) const {
112 WordWriter ww(s);
113 for (Symbol ai : ce_->current_dep_node()->actual_inputs) {
114 ww.Write(ai.str());
115 }
116 }
117
Eval(Evaluator *,string * s) const118 void AutoStarVar::Eval(Evaluator*, string* s) const {
119 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);
124 }
125
Eval(Evaluator * ev,string *) const126 void AutoNotImplementedVar::Eval(Evaluator* ev, string*) const {
127 ev->Error(StringPrintf("Automatic variable `$%s' isn't supported yet", sym_));
128 }
129
Eval(Evaluator * ev,string * s) const130 void 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
Eval(Evaluator * ev,string * s) const139 void 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
ParseCommandPrefixes(StringPiece * s,bool * echo,bool * ignore_error)148 void 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;
156 } else if (c == '+') {
157 // ignore recursion marker
158 } else {
159 break;
160 }
161 *s = TrimLeftSpace(s->substr(1));
162 }
163 }
164
165 } // namespace
166
CommandEvaluator(Evaluator * ev)167 CommandEvaluator::CommandEvaluator(Evaluator* ev) : ev_(ev) {
168 #define INSERT_AUTO_VAR(name, sym) \
169 do { \
170 Var* v = new name(this, sym); \
171 Intern(sym).SetGlobalVar(v); \
172 Intern(sym "D").SetGlobalVar(new AutoSuffixDVar(this, sym "D", v)); \
173 Intern(sym "F").SetGlobalVar(new AutoSuffixFVar(this, sym "F", v)); \
174 } 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, "*");
180 // TODO: Implement them.
181 INSERT_AUTO_VAR(AutoNotImplementedVar, "%");
182 INSERT_AUTO_VAR(AutoNotImplementedVar, "?");
183 INSERT_AUTO_VAR(AutoNotImplementedVar, "|");
184 }
185
Eval(DepNode * n,vector<Command * > * commands)186 void CommandEvaluator::Eval(DepNode* n, vector<Command*>* commands) {
187 ev_->set_loc(n->loc);
188 ev_->set_current_scope(n->rule_vars);
189 current_dep_node_ = n;
190 for (Value* v : n->cmds) {
191 const string&& cmds_buf = v->Eval(ev_);
192 StringPiece cmds = cmds_buf;
193 bool global_echo = !g_flags.is_silent_mode;
194 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()) {
211 Command* command = new Command(n->output);
212 command->cmd = cmd.as_string();
213 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 }
222
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);
227 c->cmd = cmd;
228 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
239 ev_->set_current_scope(NULL);
240 }
241