blob: fa7bebbb5e0cd9cd0430967d8eb97f77f913f895 [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>
Dan Willemsen36e57292017-10-09 11:23:32 -070020#include <pthread.h>
Shinichiro Hamaji861bd642015-06-19 16:59:13 +090021#include <string.h>
Shinichiro Hamaji6e6de8d2015-06-18 11:12:58 +090022
Shinichiro Hamaji645cca72015-09-24 17:04:21 +090023#include "expr.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090024#include "file.h"
Shinichiro Hamaji6e6de8d2015-06-18 11:12:58 +090025#include "file_cache.h"
Shinichiro Hamaji0e3873a2015-07-05 15:48:28 +090026#include "fileutil.h"
Shinichiro Hamaji45a0c762015-06-26 06:47:10 +090027#include "parser.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090028#include "rule.h"
Shinichiro Hamaji645cca72015-09-24 17:04:21 +090029#include "stmt.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090030#include "strutil.h"
Shinichiro Hamajie7992752015-06-29 18:38:35 +090031#include "symtab.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090032#include "var.h"
33
Shinichiro Hamajic9b9e5e2016-02-18 18:18:54 +090034Evaluator::Evaluator()
35 : last_rule_(NULL),
Shinichiro Hamajife002942015-07-02 03:42:27 +090036 current_scope_(NULL),
Shinichiro Hamaji28da2372015-11-30 19:03:53 +090037 avoid_io_(false),
Shinichiro Hamaji2941ea02016-04-27 17:26:21 +090038 eval_depth_(0),
39 posix_sym_(Intern(".POSIX")),
Dan Willemsenf87d49e2016-09-29 20:09:47 -070040 is_posix_(false),
Dan Willemsenc3f6a972018-02-27 00:25:01 -080041 export_error_(false),
Dan Willemsen36e57292017-10-09 11:23:32 -070042 kati_readonly_(Intern(".KATI_READONLY")) {
43#if defined(__APPLE__)
44 stack_size_ = pthread_get_stacksize_np(pthread_self());
45 stack_addr_ = (char*)pthread_get_stackaddr_np(pthread_self()) - stack_size_;
46#else
47 pthread_attr_t attr;
48 CHECK(pthread_getattr_np(pthread_self(), &attr) == 0);
49 CHECK(pthread_attr_getstack(&attr, &stack_addr_, &stack_size_) == 0);
50 CHECK(pthread_attr_destroy(&attr) == 0);
51#endif
52
53 lowest_stack_ = (char*)stack_addr_ + stack_size_;
54 LOG_STAT("Stack size: %zd bytes", stack_size_);
55}
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090056
57Evaluator::~Evaluator() {
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +090058 // delete vars_;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090059 // for (auto p : rule_vars) {
60 // delete p.second;
61 // }
62}
63
Dan Willemsen3ce083f2017-10-11 22:17:48 -070064Var* Evaluator::EvalRHS(Symbol lhs,
65 Value* rhs_v,
66 StringPiece orig_rhs,
67 AssignOp op,
68 bool is_override) {
69 VarOrigin origin =
70 ((is_bootstrap_ ? VarOrigin::DEFAULT
71 : is_commandline_ ? VarOrigin::COMMAND_LINE
72 : is_override ? VarOrigin::OVERRIDE
73 : VarOrigin::FILE));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090074
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090075 Var* rhs = NULL;
Dan Willemsenff90ea32017-11-21 13:22:26 -080076 Var* prev = NULL;
Shinichiro Hamaji4c469b32015-06-15 19:53:36 +090077 bool needs_assign = true;
Dan Willemsen276e96a2017-10-03 14:24:48 -070078
Shinichiro Hamaji784b9952015-06-23 14:29:32 +090079 switch (op) {
Shinichiro Hamaji90e52ce2016-02-10 13:53:41 +090080 case AssignOp::COLON_EQ: {
Dan Willemsenff90ea32017-11-21 13:22:26 -080081 prev = PeekVarInCurrentScope(lhs);
Shinichiro Hamaji90e52ce2016-02-10 13:53:41 +090082 SimpleVar* sv = new SimpleVar(origin);
83 rhs_v->Eval(this, sv->mutable_value());
84 rhs = sv;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090085 break;
Shinichiro Hamaji90e52ce2016-02-10 13:53:41 +090086 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090087 case AssignOp::EQ:
Dan Willemsenff90ea32017-11-21 13:22:26 -080088 prev = PeekVarInCurrentScope(lhs);
Shinichiro Hamaji784b9952015-06-23 14:29:32 +090089 rhs = new RecursiveVar(rhs_v, origin, orig_rhs);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090090 break;
91 case AssignOp::PLUS_EQ: {
Dan Willemsenff90ea32017-11-21 13:22:26 -080092 prev = LookupVarInCurrentScope(lhs);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090093 if (!prev->IsDefined()) {
Shinichiro Hamaji784b9952015-06-23 14:29:32 +090094 rhs = new RecursiveVar(rhs_v, origin, orig_rhs);
Dan Willemsenf87d49e2016-09-29 20:09:47 -070095 } else if (prev->ReadOnly()) {
Dan Willemsen3ce083f2017-10-11 22:17:48 -070096 Error(StringPrintf("*** cannot assign to readonly variable: %s",
97 lhs.c_str()));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090098 } else {
Shinichiro Hamaji784b9952015-06-23 14:29:32 +090099 prev->AppendVar(this, rhs_v);
Shinichiro Hamaji4c469b32015-06-15 19:53:36 +0900100 rhs = prev;
101 needs_assign = false;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900102 }
103 break;
104 }
105 case AssignOp::QUESTION_EQ: {
Dan Willemsenff90ea32017-11-21 13:22:26 -0800106 prev = LookupVarInCurrentScope(lhs);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900107 if (!prev->IsDefined()) {
Shinichiro Hamaji784b9952015-06-23 14:29:32 +0900108 rhs = new RecursiveVar(rhs_v, origin, orig_rhs);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900109 } else {
Shinichiro Hamajibef30602015-06-18 17:14:01 +0900110 rhs = prev;
111 needs_assign = false;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900112 }
113 break;
114 }
115 }
116
Dan Willemsenff90ea32017-11-21 13:22:26 -0800117 if (prev != NULL) {
118 prev->Used(this, lhs);
119 if (prev->Deprecated()) {
120 if (needs_assign) {
121 rhs->SetDeprecated(prev->DeprecatedMessage());
122 }
Dan Willemsen276e96a2017-10-03 14:24:48 -0700123 }
124 }
125
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900126 LOG("Assign: %s=%s", lhs.c_str(), rhs->DebugString().c_str());
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900127 if (needs_assign) {
128 return rhs;
129 }
130 return NULL;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900131}
132
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900133void Evaluator::EvalAssign(const AssignStmt* stmt) {
134 loc_ = stmt->loc();
Shinichiro Hamaji784b9952015-06-23 14:29:32 +0900135 last_rule_ = NULL;
Shinichiro Hamaji92a47382016-02-17 17:19:21 +0900136 Symbol lhs = stmt->GetLhsSymbol(this);
Shinichiro Hamaji0d4deb62015-06-26 07:47:17 +0900137 if (lhs.empty())
138 Error("*** empty variable name.");
Dan Willemsenf87d49e2016-09-29 20:09:47 -0700139
140 if (lhs == kati_readonly_) {
141 string rhs;
142 stmt->rhs->Eval(this, &rhs);
143 for (auto const& name : WordScanner(rhs)) {
144 Var* var = Intern(name).GetGlobalVar();
145 if (!var->IsDefined()) {
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700146 Error(
147 StringPrintf("*** unknown variable: %s", name.as_string().c_str()));
Dan Willemsenf87d49e2016-09-29 20:09:47 -0700148 }
149 var->SetReadOnly();
150 }
151 return;
152 }
153
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900154 Var* rhs = EvalRHS(lhs, stmt->rhs, stmt->orig_rhs, stmt->op,
155 stmt->directive == AssignDirective::OVERRIDE);
Dan Willemsenf87d49e2016-09-29 20:09:47 -0700156 if (rhs) {
157 bool readonly;
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700158 lhs.SetGlobalVar(rhs, stmt->directive == AssignDirective::OVERRIDE,
Dan Willemsenf87d49e2016-09-29 20:09:47 -0700159 &readonly);
160 if (readonly) {
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700161 Error(StringPrintf("*** cannot assign to readonly variable: %s",
162 lhs.c_str()));
Dan Willemsenf87d49e2016-09-29 20:09:47 -0700163 }
164 }
Shinichiro Hamaji784b9952015-06-23 14:29:32 +0900165}
166
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900167void Evaluator::EvalRule(const RuleStmt* stmt) {
168 loc_ = stmt->loc();
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900169 last_rule_ = NULL;
170
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900171 const string&& expr = stmt->expr->Eval(this);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900172 // See semicolon.mk.
Shinichiro Hamajiea549762015-12-07 14:24:23 +0900173 if (expr.find_first_not_of(" \t;") == string::npos) {
174 if (stmt->term == ';')
175 Error("*** missing rule before commands.");
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900176 return;
Shinichiro Hamajiea549762015-12-07 14:24:23 +0900177 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900178
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +0900179 Rule* rule;
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900180 RuleVarAssignment rule_var;
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700181 function<string()> after_term_fn = [this, stmt]() {
Shinichiro Hamajic4f76622016-06-30 13:05:10 +0900182 return stmt->after_term ? stmt->after_term->Eval(this) : "";
183 };
184 ParseRule(loc_, expr, stmt->term, after_term_fn, &rule, &rule_var);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900185
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +0900186 if (rule) {
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900187 if (stmt->term == ';') {
188 rule->cmds.push_back(stmt->after_term);
Shinichiro Hamaji2928f462015-06-23 20:24:53 +0900189 }
190
Shinichiro Hamaji2941ea02016-04-27 17:26:21 +0900191 for (Symbol o : rule->outputs) {
192 if (o == posix_sym_)
193 is_posix_ = true;
194 }
195
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +0900196 LOG("Rule: %s", rule->DebugString().c_str());
Shinichiro Hamaji7a2659e2016-02-08 14:32:56 +0900197 rules_.push_back(rule);
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +0900198 last_rule_ = rule;
199 return;
200 }
201
Shinichiro Hamaji772ff7f2016-02-08 18:33:54 +0900202 Symbol lhs = Intern(rule_var.lhs);
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900203 for (Symbol output : rule_var.outputs) {
Shinichiro Hamaji2a047892015-06-29 13:56:41 +0900204 auto p = rule_vars_.emplace(output, nullptr);
Shinichiro Hamaji784b9952015-06-23 14:29:32 +0900205 if (p.second) {
206 p.first->second = new Vars;
207 }
208
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900209 Value* rhs = stmt->after_term;
Shinichiro Hamaji784b9952015-06-23 14:29:32 +0900210 if (!rule_var.rhs.empty()) {
211 Value* lit = NewLiteral(rule_var.rhs);
212 if (rhs) {
Shinichiro Hamaji5e3e3d22015-06-24 16:53:44 +0900213 // TODO: We always insert two whitespaces around the
214 // terminator. Preserve whitespaces properly.
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900215 if (stmt->term == ';') {
Shinichiro Hamaji388e8582015-07-03 16:51:46 +0900216 rhs = NewExpr3(lit, NewLiteral(StringPiece(" ; ")), rhs);
Shinichiro Hamaji5e3e3d22015-06-24 16:53:44 +0900217 } else {
Shinichiro Hamaji388e8582015-07-03 16:51:46 +0900218 rhs = NewExpr3(lit, NewLiteral(StringPiece(" = ")), rhs);
Shinichiro Hamaji5e3e3d22015-06-24 16:53:44 +0900219 }
Shinichiro Hamaji784b9952015-06-23 14:29:32 +0900220 } else {
221 rhs = lit;
222 }
223 }
224
225 current_scope_ = p.first->second;
Dan Willemsenf87d49e2016-09-29 20:09:47 -0700226
227 if (lhs == kati_readonly_) {
228 string rhs_value;
229 rhs->Eval(this, &rhs_value);
230 for (auto const& name : WordScanner(rhs_value)) {
231 Var* var = current_scope_->Lookup(Intern(name));
232 if (!var->IsDefined()) {
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700233 Error(StringPrintf("*** unknown variable: %s",
234 name.as_string().c_str()));
Dan Willemsenf87d49e2016-09-29 20:09:47 -0700235 }
236 var->SetReadOnly();
237 }
238 current_scope_ = NULL;
239 continue;
240 }
241
Shinichiro Hamaji388e8582015-07-03 16:51:46 +0900242 Var* rhs_var = EvalRHS(lhs, rhs, StringPiece("*TODO*"), rule_var.op);
Dan Willemsenf87d49e2016-09-29 20:09:47 -0700243 if (rhs_var) {
244 bool readonly;
245 current_scope_->Assign(lhs, new RuleVar(rhs_var, rule_var.op), &readonly);
246 if (readonly) {
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700247 Error(StringPrintf("*** cannot assign to readonly variable: %s",
248 lhs.c_str()));
Dan Willemsenf87d49e2016-09-29 20:09:47 -0700249 }
250 }
Shinichiro Hamaji784b9952015-06-23 14:29:32 +0900251 current_scope_ = NULL;
252 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900253}
254
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900255void Evaluator::EvalCommand(const CommandStmt* stmt) {
256 loc_ = stmt->loc();
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900257
258 if (!last_rule_) {
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900259 vector<Stmt*> stmts;
260 ParseNotAfterRule(stmt->orig, stmt->loc(), &stmts);
261 for (Stmt* a : stmts)
Shinichiro Hamaji631a9f82015-07-05 14:18:15 +0900262 a->Eval(this);
263 return;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900264 }
265
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900266 last_rule_->cmds.push_back(stmt->expr);
Shinichiro Hamajiff4584d2015-06-24 17:45:14 +0900267 if (last_rule_->cmd_lineno == 0)
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900268 last_rule_->cmd_lineno = stmt->loc().lineno;
269 LOG("Command: %s", stmt->expr->DebugString().c_str());
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900270}
271
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900272void Evaluator::EvalIf(const IfStmt* stmt) {
273 loc_ = stmt->loc();
Shinichiro Hamaji6e6de8d2015-06-18 11:12:58 +0900274
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900275 bool is_true;
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900276 switch (stmt->op) {
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900277 case CondOp::IFDEF:
278 case CondOp::IFNDEF: {
Shinichiro Hamaji4421dda2015-10-21 13:36:50 +0900279 string var_name;
280 stmt->lhs->Eval(this, &var_name);
Shinichiro Hamajid236eb02015-10-27 10:02:15 +0900281 Symbol lhs = Intern(TrimRightSpace(var_name));
282 if (lhs.str().find_first_of(" \t") != string::npos)
Shinichiro Hamaji4421dda2015-10-21 13:36:50 +0900283 Error("*** invalid syntax in conditional.");
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900284 Var* v = LookupVarInCurrentScope(lhs);
Shinichiro Hamaji52fe6fc2016-06-09 16:14:51 +0900285 is_true = (v->String().empty() == (stmt->op == CondOp::IFNDEF));
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900286 break;
287 }
288 case CondOp::IFEQ:
289 case CondOp::IFNEQ: {
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900290 const string&& lhs = stmt->lhs->Eval(this);
291 const string&& rhs = stmt->rhs->Eval(this);
292 is_true = ((lhs == rhs) == (stmt->op == CondOp::IFEQ));
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900293 break;
294 }
295 default:
296 CHECK(false);
Shinichiro Hamaji8d503012015-07-03 16:26:15 +0900297 abort();
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900298 }
299
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900300 const vector<Stmt*>* stmts;
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900301 if (is_true) {
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900302 stmts = &stmt->true_stmts;
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900303 } else {
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900304 stmts = &stmt->false_stmts;
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900305 }
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900306 for (Stmt* a : *stmts) {
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +0900307 LOG("%s", a->DebugString().c_str());
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900308 a->Eval(this);
309 }
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900310}
311
Shinichiro Hamaji0e3873a2015-07-05 15:48:28 +0900312void Evaluator::DoInclude(const string& fname) {
Dan Willemsen36e57292017-10-09 11:23:32 -0700313 CheckStack();
314
Shinichiro Hamaji6e6de8d2015-06-18 11:12:58 +0900315 Makefile* mk = MakefileCacheManager::Get()->ReadMakefile(fname);
Nick Lewycky067e9f12016-06-22 13:57:25 -0700316 if (!mk->Exists()) {
317 Error(StringPrintf("%s does not exist", fname.c_str()));
318 }
Shinichiro Hamaji6e6de8d2015-06-18 11:12:58 +0900319
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900320 Var* var_list = LookupVar(Intern("MAKEFILE_LIST"));
321 var_list->AppendVar(this, NewLiteral(Intern(TrimLeadingCurdir(fname)).str()));
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900322 for (Stmt* stmt : mk->stmts()) {
323 LOG("%s", stmt->DebugString().c_str());
324 stmt->Eval(this);
Shinichiro Hamaji6e6de8d2015-06-18 11:12:58 +0900325 }
326}
327
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900328void Evaluator::EvalInclude(const IncludeStmt* stmt) {
329 loc_ = stmt->loc();
Shinichiro Hamaji6e6de8d2015-06-18 11:12:58 +0900330 last_rule_ = NULL;
331
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900332 const string&& pats = stmt->expr->Eval(this);
Shinichiro Hamajifb415ad2015-08-14 17:19:34 +0900333 for (StringPiece pat : WordScanner(pats)) {
Shinichiro Hamaji6e6de8d2015-06-18 11:12:58 +0900334 ScopedTerminator st(pat);
Shinichiro Hamaji0e3873a2015-07-05 15:48:28 +0900335 vector<string>* files;
336 Glob(pat.data(), &files);
337
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900338 if (stmt->should_exist) {
Shinichiro Hamaji0e3873a2015-07-05 15:48:28 +0900339 if (files->empty()) {
Nick Lewyckyf8dad362016-06-22 14:22:33 -0700340 // TODO: Kati does not support building a missing include file.
Shinichiro Hamaji85c74a22015-09-28 13:54:11 +0900341 Error(StringPrintf("%s: %s", pat.data(), strerror(errno)));
Shinichiro Hamaji6e6de8d2015-06-18 11:12:58 +0900342 }
Shinichiro Hamaji0e3873a2015-07-05 15:48:28 +0900343 }
344
345 for (const string& fname : *files) {
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900346 if (!stmt->should_exist && g_flags.ignore_optional_include_pattern &&
Shinichiro Hamaji003d06e2015-09-09 18:22:04 +0900347 Pattern(g_flags.ignore_optional_include_pattern).Match(fname)) {
Stefan Becker786881c2016-04-08 15:45:16 +0300348 continue;
Shinichiro Hamaji0e3873a2015-07-05 15:48:28 +0900349 }
350 DoInclude(fname);
Shinichiro Hamaji6e6de8d2015-06-18 11:12:58 +0900351 }
352 }
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900353}
354
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900355void Evaluator::EvalExport(const ExportStmt* stmt) {
356 loc_ = stmt->loc();
Shinichiro Hamaji6e6de8d2015-06-18 11:12:58 +0900357 last_rule_ = NULL;
358
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900359 const string&& exports = stmt->expr->Eval(this);
Shinichiro Hamajifb415ad2015-08-14 17:19:34 +0900360 for (StringPiece tok : WordScanner(exports)) {
Shinichiro Hamaji45a0c762015-06-26 06:47:10 +0900361 size_t equal_index = tok.find('=');
Dan Willemsenc3f6a972018-02-27 00:25:01 -0800362 StringPiece lhs;
Shinichiro Hamaji45a0c762015-06-26 06:47:10 +0900363 if (equal_index == string::npos) {
Dan Willemsenc3f6a972018-02-27 00:25:01 -0800364 lhs = tok;
Shinichiro Hamaji45a0c762015-06-26 06:47:10 +0900365 } else if (equal_index == 0 ||
366 (equal_index == 1 &&
367 (tok[0] == ':' || tok[0] == '?' || tok[0] == '+'))) {
368 // Do not export tokens after an assignment.
369 break;
370 } else {
Dan Willemsenc3f6a972018-02-27 00:25:01 -0800371 StringPiece rhs;
Shinichiro Hamaji45a0c762015-06-26 06:47:10 +0900372 AssignOp op;
373 ParseAssignStatement(tok, equal_index, &lhs, &rhs, &op);
Dan Willemsenc3f6a972018-02-27 00:25:01 -0800374 }
375 Symbol sym = Intern(lhs);
376 exports_[sym] = stmt->is_export;
377
378 if (export_message_) {
379 const char* prefix = "";
380 if (!stmt->is_export) {
381 prefix = "un";
382 }
383
384 if (export_error_) {
385 Error(StringPrintf("*** %s: %sexport is obsolete%s.", sym.c_str(),
386 prefix, export_message_->c_str()));
387 } else {
388 WARN_LOC(loc(), "%s: %sexport has been deprecated%s.", sym.c_str(),
389 prefix, export_message_->c_str());
390 }
Shinichiro Hamaji45a0c762015-06-26 06:47:10 +0900391 }
392 }
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900393}
394
Shinichiro Hamaji7e708012015-07-31 13:07:34 +0900395Var* Evaluator::LookupVarGlobal(Symbol name) {
Shinichiro Hamajic9b9e5e2016-02-18 18:18:54 +0900396 Var* v = name.GetGlobalVar();
Shinichiro Hamaji7e708012015-07-31 13:07:34 +0900397 if (v->IsDefined())
398 return v;
Shinichiro Hamaji7e708012015-07-31 13:07:34 +0900399 used_undefined_vars_.insert(name);
400 return v;
401}
402
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900403Var* Evaluator::LookupVar(Symbol name) {
Shinichiro Hamaji784b9952015-06-23 14:29:32 +0900404 if (current_scope_) {
405 Var* v = current_scope_->Lookup(name);
406 if (v->IsDefined())
407 return v;
408 }
Shinichiro Hamaji7e708012015-07-31 13:07:34 +0900409 return LookupVarGlobal(name);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900410}
411
Dan Willemsen74197412017-12-27 16:50:09 -0800412Var* Evaluator::PeekVar(Symbol name) {
413 if (current_scope_) {
414 Var* v = current_scope_->Peek(name);
415 if (v->IsDefined())
416 return v;
417 }
418 return name.PeekGlobalVar();
419}
420
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900421Var* Evaluator::LookupVarInCurrentScope(Symbol name) {
Shinichiro Hamaji784b9952015-06-23 14:29:32 +0900422 if (current_scope_) {
423 return current_scope_->Lookup(name);
424 }
Shinichiro Hamaji7e708012015-07-31 13:07:34 +0900425 return LookupVarGlobal(name);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900426}
427
Dan Willemsenff90ea32017-11-21 13:22:26 -0800428Var* Evaluator::PeekVarInCurrentScope(Symbol name) {
429 if (current_scope_) {
430 return current_scope_->Peek(name);
431 }
432 return name.PeekGlobalVar();
433}
434
Shinichiro Hamajifb415ad2015-08-14 17:19:34 +0900435string Evaluator::EvalVar(Symbol name) {
Shinichiro Hamaji94d6f2a2015-07-05 05:32:25 +0900436 return LookupVar(name)->Eval(this);
437}
438
Shinichiro Hamaji2941ea02016-04-27 17:26:21 +0900439string Evaluator::GetShell() {
440 return EvalVar(kShellSym);
441}
442
443string Evaluator::GetShellFlag() {
444 // TODO: Handle $(.SHELLFLAGS)
445 return is_posix_ ? "-ec" : "-c";
446}
447
448string Evaluator::GetShellAndFlag() {
449 string shell = GetShell();
450 shell += ' ';
451 shell += GetShellFlag();
452 return shell;
453}
454
Shinichiro Hamaji9619b362015-06-16 16:13:25 +0900455void Evaluator::Error(const string& msg) {
Dan Willemsene41c7552017-02-22 14:31:16 -0800456 ERROR_LOC(loc_, "%s", msg.c_str());
Shinichiro Hamaji9619b362015-06-16 16:13:25 +0900457}
Shinichiro Hamaji7e708012015-07-31 13:07:34 +0900458
Dan Willemsen36e57292017-10-09 11:23:32 -0700459void Evaluator::DumpStackStats() const {
460 LOG_STAT("Max stack use: %zd bytes at %s:%d",
461 ((char*)stack_addr_ - (char*)lowest_stack_) + stack_size_,
462 LOCF(lowest_loc_));
463}
464
Shinichiro Hamaji7e708012015-07-31 13:07:34 +0900465unordered_set<Symbol> Evaluator::used_undefined_vars_;