blob: 6322fc1b6d6fa18b11675d6168c9e6b31586c933 [file] [log] [blame]
Shinichiro Hamaji1d545aa2015-06-23 15:29:13 +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
Fumitoshi Ukai744bb2b2015-06-25 00:10:52 +090015// +build ignore
16
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090017#include "eval.h"
18
Shinichiro Hamaji861bd642015-06-19 16:59:13 +090019#include <errno.h>
Shinichiro Hamaji861bd642015-06-19 16:59:13 +090020#include <string.h>
Shinichiro Hamaji6e6de8d2015-06-18 11:12:58 +090021
Shinichiro Hamaji645cca72015-09-24 17:04:21 +090022#include "expr.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090023#include "file.h"
Shinichiro Hamaji6e6de8d2015-06-18 11:12:58 +090024#include "file_cache.h"
Shinichiro Hamaji0e3873a2015-07-05 15:48:28 +090025#include "fileutil.h"
Shinichiro Hamaji45a0c762015-06-26 06:47:10 +090026#include "parser.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090027#include "rule.h"
Shinichiro Hamaji645cca72015-09-24 17:04:21 +090028#include "stmt.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090029#include "strutil.h"
Shinichiro Hamajie7992752015-06-29 18:38:35 +090030#include "symtab.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090031#include "var.h"
32
Shinichiro Hamajic9b9e5e2016-02-18 18:18:54 +090033Evaluator::Evaluator()
34 : last_rule_(NULL),
Shinichiro Hamajife002942015-07-02 03:42:27 +090035 current_scope_(NULL),
Shinichiro Hamaji28da2372015-11-30 19:03:53 +090036 avoid_io_(false),
37 eval_depth_(0) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090038}
39
40Evaluator::~Evaluator() {
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +090041 // delete vars_;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090042 // for (auto p : rule_vars) {
43 // delete p.second;
44 // }
45}
46
Shinichiro Hamajie7992752015-06-29 18:38:35 +090047Var* Evaluator::EvalRHS(Symbol lhs, Value* rhs_v, StringPiece orig_rhs,
Shinichiro Hamaji420f7752015-06-26 04:02:02 +090048 AssignOp op, bool is_override) {
Shinichiro Hamajif62e9a72015-06-26 04:18:21 +090049 VarOrigin origin = (
50 (is_bootstrap_ ? VarOrigin::DEFAULT :
51 is_override ? VarOrigin::OVERRIDE : VarOrigin::FILE));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090052
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090053 Var* rhs = NULL;
Shinichiro Hamaji4c469b32015-06-15 19:53:36 +090054 bool needs_assign = true;
Shinichiro Hamaji784b9952015-06-23 14:29:32 +090055 switch (op) {
Shinichiro Hamaji90e52ce2016-02-10 13:53:41 +090056 case AssignOp::COLON_EQ: {
57 SimpleVar* sv = new SimpleVar(origin);
58 rhs_v->Eval(this, sv->mutable_value());
59 rhs = sv;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090060 break;
Shinichiro Hamaji90e52ce2016-02-10 13:53:41 +090061 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090062 case AssignOp::EQ:
Shinichiro Hamaji784b9952015-06-23 14:29:32 +090063 rhs = new RecursiveVar(rhs_v, origin, orig_rhs);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090064 break;
65 case AssignOp::PLUS_EQ: {
66 Var* prev = LookupVarInCurrentScope(lhs);
67 if (!prev->IsDefined()) {
Shinichiro Hamaji784b9952015-06-23 14:29:32 +090068 rhs = new RecursiveVar(rhs_v, origin, orig_rhs);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090069 } else {
Shinichiro Hamaji784b9952015-06-23 14:29:32 +090070 prev->AppendVar(this, rhs_v);
Shinichiro Hamaji4c469b32015-06-15 19:53:36 +090071 rhs = prev;
72 needs_assign = false;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090073 }
74 break;
75 }
76 case AssignOp::QUESTION_EQ: {
77 Var* prev = LookupVarInCurrentScope(lhs);
78 if (!prev->IsDefined()) {
Shinichiro Hamaji784b9952015-06-23 14:29:32 +090079 rhs = new RecursiveVar(rhs_v, origin, orig_rhs);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090080 } else {
Shinichiro Hamajibef30602015-06-18 17:14:01 +090081 rhs = prev;
82 needs_assign = false;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090083 }
84 break;
85 }
86 }
87
Shinichiro Hamajie7992752015-06-29 18:38:35 +090088 LOG("Assign: %s=%s", lhs.c_str(), rhs->DebugString().c_str());
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +090089 if (needs_assign) {
90 return rhs;
91 }
92 return NULL;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090093}
94
Shinichiro Hamaji645cca72015-09-24 17:04:21 +090095void Evaluator::EvalAssign(const AssignStmt* stmt) {
96 loc_ = stmt->loc();
Shinichiro Hamaji784b9952015-06-23 14:29:32 +090097 last_rule_ = NULL;
Shinichiro Hamaji92a47382016-02-17 17:19:21 +090098 Symbol lhs = stmt->GetLhsSymbol(this);
Shinichiro Hamaji0d4deb62015-06-26 07:47:17 +090099 if (lhs.empty())
100 Error("*** empty variable name.");
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900101 Var* rhs = EvalRHS(lhs, stmt->rhs, stmt->orig_rhs, stmt->op,
102 stmt->directive == AssignDirective::OVERRIDE);
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900103 if (rhs)
Shinichiro Hamajic9b9e5e2016-02-18 18:18:54 +0900104 lhs.SetGlobalVar(rhs);
Shinichiro Hamaji784b9952015-06-23 14:29:32 +0900105}
106
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900107void Evaluator::EvalRule(const RuleStmt* stmt) {
108 loc_ = stmt->loc();
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900109 last_rule_ = NULL;
110
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900111 const string&& expr = stmt->expr->Eval(this);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900112 // See semicolon.mk.
Shinichiro Hamajiea549762015-12-07 14:24:23 +0900113 if (expr.find_first_not_of(" \t;") == string::npos) {
114 if (stmt->term == ';')
115 Error("*** missing rule before commands.");
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900116 return;
Shinichiro Hamajiea549762015-12-07 14:24:23 +0900117 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900118
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +0900119 Rule* rule;
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900120 RuleVarAssignment rule_var;
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900121 ParseRule(loc_, expr, stmt->term, &rule, &rule_var);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900122
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +0900123 if (rule) {
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900124 if (stmt->term == ';') {
125 rule->cmds.push_back(stmt->after_term);
Shinichiro Hamaji2928f462015-06-23 20:24:53 +0900126 }
127
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +0900128 LOG("Rule: %s", rule->DebugString().c_str());
Shinichiro Hamaji7a2659e2016-02-08 14:32:56 +0900129 rules_.push_back(rule);
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +0900130 last_rule_ = rule;
131 return;
132 }
133
Shinichiro Hamaji772ff7f2016-02-08 18:33:54 +0900134 Symbol lhs = Intern(rule_var.lhs);
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900135 for (Symbol output : rule_var.outputs) {
Shinichiro Hamaji2a047892015-06-29 13:56:41 +0900136 auto p = rule_vars_.emplace(output, nullptr);
Shinichiro Hamaji784b9952015-06-23 14:29:32 +0900137 if (p.second) {
138 p.first->second = new Vars;
139 }
140
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900141 Value* rhs = stmt->after_term;
Shinichiro Hamaji784b9952015-06-23 14:29:32 +0900142 if (!rule_var.rhs.empty()) {
143 Value* lit = NewLiteral(rule_var.rhs);
144 if (rhs) {
Shinichiro Hamaji5e3e3d22015-06-24 16:53:44 +0900145 // TODO: We always insert two whitespaces around the
146 // terminator. Preserve whitespaces properly.
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900147 if (stmt->term == ';') {
Shinichiro Hamaji388e8582015-07-03 16:51:46 +0900148 rhs = NewExpr3(lit, NewLiteral(StringPiece(" ; ")), rhs);
Shinichiro Hamaji5e3e3d22015-06-24 16:53:44 +0900149 } else {
Shinichiro Hamaji388e8582015-07-03 16:51:46 +0900150 rhs = NewExpr3(lit, NewLiteral(StringPiece(" = ")), rhs);
Shinichiro Hamaji5e3e3d22015-06-24 16:53:44 +0900151 }
Shinichiro Hamaji784b9952015-06-23 14:29:32 +0900152 } else {
153 rhs = lit;
154 }
155 }
156
157 current_scope_ = p.first->second;
Shinichiro Hamaji388e8582015-07-03 16:51:46 +0900158 Var* rhs_var = EvalRHS(lhs, rhs, StringPiece("*TODO*"), rule_var.op);
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900159 if (rhs_var)
160 current_scope_->Assign(lhs, new RuleVar(rhs_var, rule_var.op));
Shinichiro Hamaji784b9952015-06-23 14:29:32 +0900161 current_scope_ = NULL;
162 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900163}
164
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900165void Evaluator::EvalCommand(const CommandStmt* stmt) {
166 loc_ = stmt->loc();
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900167
168 if (!last_rule_) {
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900169 vector<Stmt*> stmts;
170 ParseNotAfterRule(stmt->orig, stmt->loc(), &stmts);
171 for (Stmt* a : stmts)
Shinichiro Hamaji631a9f82015-07-05 14:18:15 +0900172 a->Eval(this);
173 return;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900174 }
175
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900176 last_rule_->cmds.push_back(stmt->expr);
Shinichiro Hamajiff4584d2015-06-24 17:45:14 +0900177 if (last_rule_->cmd_lineno == 0)
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900178 last_rule_->cmd_lineno = stmt->loc().lineno;
179 LOG("Command: %s", stmt->expr->DebugString().c_str());
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900180}
181
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900182void Evaluator::EvalIf(const IfStmt* stmt) {
183 loc_ = stmt->loc();
Shinichiro Hamaji6e6de8d2015-06-18 11:12:58 +0900184
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900185 bool is_true;
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900186 switch (stmt->op) {
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900187 case CondOp::IFDEF:
188 case CondOp::IFNDEF: {
Shinichiro Hamaji4421dda2015-10-21 13:36:50 +0900189 string var_name;
190 stmt->lhs->Eval(this, &var_name);
Shinichiro Hamajid236eb02015-10-27 10:02:15 +0900191 Symbol lhs = Intern(TrimRightSpace(var_name));
192 if (lhs.str().find_first_of(" \t") != string::npos)
Shinichiro Hamaji4421dda2015-10-21 13:36:50 +0900193 Error("*** invalid syntax in conditional.");
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900194 Var* v = LookupVarInCurrentScope(lhs);
Shinichiro Hamajifb415ad2015-08-14 17:19:34 +0900195 const string&& s = v->Eval(this);
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900196 is_true = (s.empty() == (stmt->op == CondOp::IFNDEF));
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900197 break;
198 }
199 case CondOp::IFEQ:
200 case CondOp::IFNEQ: {
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900201 const string&& lhs = stmt->lhs->Eval(this);
202 const string&& rhs = stmt->rhs->Eval(this);
203 is_true = ((lhs == rhs) == (stmt->op == CondOp::IFEQ));
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900204 break;
205 }
206 default:
207 CHECK(false);
Shinichiro Hamaji8d503012015-07-03 16:26:15 +0900208 abort();
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900209 }
210
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900211 const vector<Stmt*>* stmts;
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900212 if (is_true) {
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900213 stmts = &stmt->true_stmts;
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900214 } else {
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900215 stmts = &stmt->false_stmts;
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900216 }
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900217 for (Stmt* a : *stmts) {
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +0900218 LOG("%s", a->DebugString().c_str());
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900219 a->Eval(this);
220 }
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900221}
222
Shinichiro Hamaji0e3873a2015-07-05 15:48:28 +0900223void Evaluator::DoInclude(const string& fname) {
Shinichiro Hamaji6e6de8d2015-06-18 11:12:58 +0900224 Makefile* mk = MakefileCacheManager::Get()->ReadMakefile(fname);
Shinichiro Hamaji0e3873a2015-07-05 15:48:28 +0900225 CHECK(mk->Exists());
Shinichiro Hamaji6e6de8d2015-06-18 11:12:58 +0900226
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900227 Var* var_list = LookupVar(Intern("MAKEFILE_LIST"));
228 var_list->AppendVar(this, NewLiteral(Intern(TrimLeadingCurdir(fname)).str()));
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900229 for (Stmt* stmt : mk->stmts()) {
230 LOG("%s", stmt->DebugString().c_str());
231 stmt->Eval(this);
Shinichiro Hamaji6e6de8d2015-06-18 11:12:58 +0900232 }
233}
234
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900235void Evaluator::EvalInclude(const IncludeStmt* stmt) {
236 loc_ = stmt->loc();
Shinichiro Hamaji6e6de8d2015-06-18 11:12:58 +0900237 last_rule_ = NULL;
238
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900239 const string&& pats = stmt->expr->Eval(this);
Shinichiro Hamajifb415ad2015-08-14 17:19:34 +0900240 for (StringPiece pat : WordScanner(pats)) {
Shinichiro Hamaji6e6de8d2015-06-18 11:12:58 +0900241 ScopedTerminator st(pat);
Shinichiro Hamaji0e3873a2015-07-05 15:48:28 +0900242 vector<string>* files;
243 Glob(pat.data(), &files);
244
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900245 if (stmt->should_exist) {
Shinichiro Hamaji0e3873a2015-07-05 15:48:28 +0900246 if (files->empty()) {
Shinichiro Hamaji85c74a22015-09-28 13:54:11 +0900247 // TOOD: Kati does not support building a missing include file.
248 Error(StringPrintf("%s: %s", pat.data(), strerror(errno)));
Shinichiro Hamaji6e6de8d2015-06-18 11:12:58 +0900249 }
Shinichiro Hamaji0e3873a2015-07-05 15:48:28 +0900250 }
251
252 for (const string& fname : *files) {
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900253 if (!stmt->should_exist && g_flags.ignore_optional_include_pattern &&
Shinichiro Hamaji003d06e2015-09-09 18:22:04 +0900254 Pattern(g_flags.ignore_optional_include_pattern).Match(fname)) {
Shinichiro Hamaji0e3873a2015-07-05 15:48:28 +0900255 return;
256 }
257 DoInclude(fname);
Shinichiro Hamaji6e6de8d2015-06-18 11:12:58 +0900258 }
259 }
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900260}
261
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900262void Evaluator::EvalExport(const ExportStmt* stmt) {
263 loc_ = stmt->loc();
Shinichiro Hamaji6e6de8d2015-06-18 11:12:58 +0900264 last_rule_ = NULL;
265
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900266 const string&& exports = stmt->expr->Eval(this);
Shinichiro Hamajifb415ad2015-08-14 17:19:34 +0900267 for (StringPiece tok : WordScanner(exports)) {
Shinichiro Hamaji45a0c762015-06-26 06:47:10 +0900268 size_t equal_index = tok.find('=');
269 if (equal_index == string::npos) {
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900270 exports_[Intern(tok)] = stmt->is_export;
Shinichiro Hamaji45a0c762015-06-26 06:47:10 +0900271 } else if (equal_index == 0 ||
272 (equal_index == 1 &&
273 (tok[0] == ':' || tok[0] == '?' || tok[0] == '+'))) {
274 // Do not export tokens after an assignment.
275 break;
276 } else {
277 StringPiece lhs, rhs;
278 AssignOp op;
279 ParseAssignStatement(tok, equal_index, &lhs, &rhs, &op);
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900280 exports_[Intern(lhs)] = stmt->is_export;
Shinichiro Hamaji45a0c762015-06-26 06:47:10 +0900281 }
282 }
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900283}
284
Shinichiro Hamaji7e708012015-07-31 13:07:34 +0900285Var* Evaluator::LookupVarGlobal(Symbol name) {
Shinichiro Hamajic9b9e5e2016-02-18 18:18:54 +0900286 Var* v = name.GetGlobalVar();
Shinichiro Hamaji7e708012015-07-31 13:07:34 +0900287 if (v->IsDefined())
288 return v;
Shinichiro Hamaji7e708012015-07-31 13:07:34 +0900289 used_undefined_vars_.insert(name);
290 return v;
291}
292
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900293Var* Evaluator::LookupVar(Symbol name) {
Shinichiro Hamaji784b9952015-06-23 14:29:32 +0900294 if (current_scope_) {
295 Var* v = current_scope_->Lookup(name);
296 if (v->IsDefined())
297 return v;
298 }
Shinichiro Hamaji7e708012015-07-31 13:07:34 +0900299 return LookupVarGlobal(name);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900300}
301
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900302Var* Evaluator::LookupVarInCurrentScope(Symbol name) {
Shinichiro Hamaji784b9952015-06-23 14:29:32 +0900303 if (current_scope_) {
304 return current_scope_->Lookup(name);
305 }
Shinichiro Hamaji7e708012015-07-31 13:07:34 +0900306 return LookupVarGlobal(name);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900307}
308
Shinichiro Hamajifb415ad2015-08-14 17:19:34 +0900309string Evaluator::EvalVar(Symbol name) {
Shinichiro Hamaji94d6f2a2015-07-05 05:32:25 +0900310 return LookupVar(name)->Eval(this);
311}
312
Shinichiro Hamaji9619b362015-06-16 16:13:25 +0900313void Evaluator::Error(const string& msg) {
Shinichiro Hamaji8ee8c372015-06-16 16:19:40 +0900314 ERROR("%s:%d: %s", LOCF(loc_), msg.c_str());
Shinichiro Hamaji9619b362015-06-16 16:13:25 +0900315}
Shinichiro Hamaji7e708012015-07-31 13:07:34 +0900316
317unordered_set<Symbol> Evaluator::used_undefined_vars_;