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 SymbolSet& used_undefined_vars() { return used_undefined_vars_; } 82 eval_depth()83 int eval_depth() const { return eval_depth_; } IncrementEvalDepth()84 void IncrementEvalDepth() { eval_depth_++; } DecrementEvalDepth()85 void DecrementEvalDepth() { eval_depth_--; } 86 87 string GetShell(); 88 string GetShellFlag(); 89 string GetShellAndFlag(); 90 CheckStack()91 void CheckStack() { 92 void* addr = __builtin_frame_address(0); 93 if (__builtin_expect(addr < lowest_stack_ && addr >= stack_addr_, 0)) { 94 lowest_stack_ = addr; 95 lowest_loc_ = loc_; 96 } 97 } 98 void DumpStackStats() const; 99 ExportDeprecated()100 bool ExportDeprecated() const { return export_message_ && !export_error_; }; ExportObsolete()101 bool ExportObsolete() const { return export_error_; }; SetExportDeprecated(StringPiece msg)102 void SetExportDeprecated(StringPiece msg) { 103 export_message_.reset(new string(msg.as_string())); 104 } SetExportObsolete(StringPiece msg)105 void SetExportObsolete(StringPiece msg) { 106 export_message_.reset(new string(msg.as_string())); 107 export_error_ = true; 108 } 109 110 private: 111 Var* EvalRHS(Symbol lhs, 112 Value* rhs, 113 StringPiece orig_rhs, 114 AssignOp op, 115 bool is_override, 116 bool* needs_assign); 117 void DoInclude(const string& fname); 118 119 Var* LookupVarGlobal(Symbol name); 120 121 // Equivalent to LookupVarInCurrentScope, but doesn't mark as used. 122 Var* PeekVarInCurrentScope(Symbol name); 123 124 void MarkVarsReadonly(Value* var_list); 125 126 void EvalRuleSpecificAssign(const vector<Symbol>& targets, 127 const RuleStmt* stmt, 128 const StringPiece& lhs_string, 129 size_t separator_pos); 130 131 unordered_map<Symbol, Vars*> rule_vars_; 132 vector<const Rule*> rules_; 133 unordered_map<Symbol, bool> exports_; 134 135 Rule* last_rule_; 136 Vars* current_scope_; 137 138 Loc loc_; 139 bool is_bootstrap_; 140 bool is_commandline_; 141 142 bool avoid_io_; 143 // This value tracks the nest level of make expressions. For 144 // example, $(YYY) in $(XXX $(YYY)) is evaluated with depth==2. 145 // This will be used to disallow $(shell) in other make constructs. 146 int eval_depth_; 147 // Commands which should run at ninja-time (i.e., info, warning, and 148 // error). 149 vector<string> delayed_output_commands_; 150 151 Symbol posix_sym_; 152 bool is_posix_; 153 154 void* stack_addr_; 155 size_t stack_size_; 156 void* lowest_stack_; 157 Loc lowest_loc_; 158 159 unique_ptr<string> export_message_; 160 bool export_error_; 161 162 static SymbolSet used_undefined_vars_; 163 }; 164 165 #endif // EVAL_H_ 166