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 #ifndef EVAL_H_
16 #define EVAL_H_
17 
18 #include <memory>
19 #include <unordered_map>
20 #include <unordered_set>
21 #include <vector>
22 
23 #include "loc.h"
24 #include "stmt.h"
25 #include "string_piece.h"
26 #include "symtab.h"
27 
28 using namespace std;
29 
30 class Makefile;
31 class Rule;
32 class Var;
33 class Vars;
34 
35 class Evaluator {
36  public:
37   Evaluator();
38   ~Evaluator();
39 
40   void EvalAssign(const AssignStmt* stmt);
41   void EvalRule(const RuleStmt* stmt);
42   void EvalCommand(const CommandStmt* stmt);
43   void EvalIf(const IfStmt* stmt);
44   void EvalInclude(const IncludeStmt* stmt);
45   void EvalExport(const ExportStmt* stmt);
46 
47   Var* LookupVar(Symbol name);
48   // For target specific variables.
49   Var* LookupVarInCurrentScope(Symbol name);
50 
51   // Equivalent to LookupVar, but doesn't mark as used.
52   Var* PeekVar(Symbol name);
53 
54   string EvalVar(Symbol name);
55 
loc()56   const Loc& loc() const { return loc_; }
set_loc(const Loc & loc)57   void set_loc(const Loc& loc) { loc_ = loc; }
58 
rules()59   const vector<const Rule*>& rules() const { return rules_; }
rule_vars()60   const unordered_map<Symbol, Vars*>& rule_vars() const { return rule_vars_; }
exports()61   const unordered_map<Symbol, bool>& exports() const { return exports_; }
62 
63   void Error(const string& msg);
64 
set_is_bootstrap(bool b)65   void set_is_bootstrap(bool b) { is_bootstrap_ = b; }
set_is_commandline(bool c)66   void set_is_commandline(bool c) { is_commandline_ = c; }
67 
set_current_scope(Vars * v)68   void set_current_scope(Vars* v) { current_scope_ = v; }
69 
avoid_io()70   bool avoid_io() const { return avoid_io_; }
set_avoid_io(bool a)71   void set_avoid_io(bool a) { avoid_io_ = a; }
72 
delayed_output_commands()73   const vector<string>& delayed_output_commands() const {
74     return delayed_output_commands_;
75   }
add_delayed_output_command(const string & c)76   void add_delayed_output_command(const string& c) {
77     delayed_output_commands_.push_back(c);
78   }
clear_delayed_output_commands()79   void clear_delayed_output_commands() { delayed_output_commands_.clear(); }
80 
used_undefined_vars()81   static const unordered_set<Symbol>& used_undefined_vars() {
82     return used_undefined_vars_;
83   }
84 
eval_depth()85   int eval_depth() const { return eval_depth_; }
IncrementEvalDepth()86   void IncrementEvalDepth() { eval_depth_++; }
DecrementEvalDepth()87   void DecrementEvalDepth() { eval_depth_--; }
88 
89   string GetShell();
90   string GetShellFlag();
91   string GetShellAndFlag();
92 
CheckStack()93   void CheckStack() {
94     void* addr = __builtin_frame_address(0);
95     if (__builtin_expect(addr < lowest_stack_ && addr >= stack_addr_, 0)) {
96       lowest_stack_ = addr;
97       lowest_loc_ = loc_;
98     }
99   }
100   void DumpStackStats() const;
101 
ExportDeprecated()102   bool ExportDeprecated() const { return export_message_ && !export_error_; };
ExportObsolete()103   bool ExportObsolete() const { return export_error_; };
SetExportDeprecated(StringPiece msg)104   void SetExportDeprecated(StringPiece msg) {
105     export_message_.reset(new string(msg.as_string()));
106   }
SetExportObsolete(StringPiece msg)107   void SetExportObsolete(StringPiece msg) {
108     export_message_.reset(new string(msg.as_string()));
109     export_error_ = true;
110   }
111 
112  private:
113   Var* EvalRHS(Symbol lhs,
114                Value* rhs,
115                StringPiece orig_rhs,
116                AssignOp op,
117                bool is_override = false);
118   void DoInclude(const string& fname);
119 
120   Var* LookupVarGlobal(Symbol name);
121 
122   // Equivalent to LookupVarInCurrentScope, but doesn't mark as used.
123   Var* PeekVarInCurrentScope(Symbol name);
124 
125   unordered_map<Symbol, Vars*> rule_vars_;
126   vector<const Rule*> rules_;
127   unordered_map<Symbol, bool> exports_;
128 
129   Rule* last_rule_;
130   Vars* current_scope_;
131 
132   Loc loc_;
133   bool is_bootstrap_;
134   bool is_commandline_;
135 
136   bool avoid_io_;
137   // This value tracks the nest level of make expressions. For
138   // example, $(YYY) in $(XXX $(YYY)) is evaluated with depth==2.
139   // This will be used to disallow $(shell) in other make constructs.
140   int eval_depth_;
141   // Commands which should run at ninja-time (i.e., info, warning, and
142   // error).
143   vector<string> delayed_output_commands_;
144 
145   Symbol posix_sym_;
146   bool is_posix_;
147 
148   void* stack_addr_;
149   size_t stack_size_;
150   void* lowest_stack_;
151   Loc lowest_loc_;
152 
153   unique_ptr<string> export_message_;
154   bool export_error_;
155 
156   static unordered_set<Symbol> used_undefined_vars_;
157 
158   Symbol kati_readonly_;
159 };
160 
161 #endif  // EVAL_H_
162