aboutsummaryrefslogtreecommitdiffstats
path: root/eval.h
blob: 4fb5f0519210d67d02a47a13e0f81619462ccb36 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
// Copyright 2015 Google Inc. All rights reserved
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef EVAL_H_
#define EVAL_H_

#include <memory>
#include <unordered_map>
#include <unordered_set>
#include <vector>

#include "loc.h"
#include "stmt.h"
#include "string_piece.h"
#include "symtab.h"

using namespace std;

class Makefile;
class Rule;
class Var;
class Vars;

class Evaluator {
 public:
  Evaluator();
  ~Evaluator();

  void EvalAssign(const AssignStmt* stmt);
  void EvalRule(const RuleStmt* stmt);
  void EvalCommand(const CommandStmt* stmt);
  void EvalIf(const IfStmt* stmt);
  void EvalInclude(const IncludeStmt* stmt);
  void EvalExport(const ExportStmt* stmt);

  Var* LookupVar(Symbol name);
  // For target specific variables.
  Var* LookupVarInCurrentScope(Symbol name);

  // Equivalent to LookupVar, but doesn't mark as used.
  Var* PeekVar(Symbol name);

  string EvalVar(Symbol name);

  const Loc& loc() const { return loc_; }
  void set_loc(const Loc& loc) { loc_ = loc; }

  const vector<const Rule*>& rules() const { return rules_; }
  const unordered_map<Symbol, Vars*>& rule_vars() const { return rule_vars_; }
  const unordered_map<Symbol, bool>& exports() const { return exports_; }

  void Error(const string& msg);

  void set_is_bootstrap(bool b) { is_bootstrap_ = b; }
  void set_is_commandline(bool c) { is_commandline_ = c; }

  void set_current_scope(Vars* v) { current_scope_ = v; }

  bool avoid_io() const { return avoid_io_; }
  void set_avoid_io(bool a) { avoid_io_ = a; }

  const vector<string>& delayed_output_commands() const {
    return delayed_output_commands_;
  }
  void add_delayed_output_command(const string& c) {
    delayed_output_commands_.push_back(c);
  }
  void clear_delayed_output_commands() { delayed_output_commands_.clear(); }

  static const unordered_set<Symbol>& used_undefined_vars() {
    return used_undefined_vars_;
  }

  int eval_depth() const { return eval_depth_; }
  void IncrementEvalDepth() { eval_depth_++; }
  void DecrementEvalDepth() { eval_depth_--; }

  string GetShell();
  string GetShellFlag();
  string GetShellAndFlag();

  void CheckStack() {
    void* addr = __builtin_frame_address(0);
    if (__builtin_expect(addr < lowest_stack_ && addr >= stack_addr_, 0)) {
      lowest_stack_ = addr;
      lowest_loc_ = loc_;
    }
  }
  void DumpStackStats() const;

  bool ExportDeprecated() const { return export_message_ && !export_error_; };
  bool ExportObsolete() const { return export_error_; };
  void SetExportDeprecated(StringPiece msg) {
    export_message_.reset(new string(msg.as_string()));
  }
  void SetExportObsolete(StringPiece msg) {
    export_message_.reset(new string(msg.as_string()));
    export_error_ = true;
  }

 private:
  Var* EvalRHS(Symbol lhs,
               Value* rhs,
               StringPiece orig_rhs,
               AssignOp op,
               bool is_override = false);
  void DoInclude(const string& fname);

  Var* LookupVarGlobal(Symbol name);

  // Equivalent to LookupVarInCurrentScope, but doesn't mark as used.
  Var* PeekVarInCurrentScope(Symbol name);

  unordered_map<Symbol, Vars*> rule_vars_;
  vector<const Rule*> rules_;
  unordered_map<Symbol, bool> exports_;

  Rule* last_rule_;
  Vars* current_scope_;

  Loc loc_;
  bool is_bootstrap_;
  bool is_commandline_;

  bool avoid_io_;
  // This value tracks the nest level of make expressions. For
  // example, $(YYY) in $(XXX $(YYY)) is evaluated with depth==2.
  // This will be used to disallow $(shell) in other make constructs.
  int eval_depth_;
  // Commands which should run at ninja-time (i.e., info, warning, and
  // error).
  vector<string> delayed_output_commands_;

  Symbol posix_sym_;
  bool is_posix_;

  void* stack_addr_;
  size_t stack_size_;
  void* lowest_stack_;
  Loc lowest_loc_;

  unique_ptr<string> export_message_;
  bool export_error_;

  static unordered_set<Symbol> used_undefined_vars_;

  Symbol kati_readonly_;
};

#endif  // EVAL_H_