/src/ninja/src/eval_env.cc
Line | Count | Source |
1 | | // Copyright 2011 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 | | #include <assert.h> |
16 | | |
17 | | #include "eval_env.h" |
18 | | |
19 | | using namespace std; |
20 | | |
21 | 638k | string BindingEnv::LookupVariable(const string& var) { |
22 | 638k | map<string, string>::iterator i = bindings_.find(var); |
23 | 638k | if (i != bindings_.end()) |
24 | 530k | return i->second; |
25 | 107k | if (parent_) |
26 | 34.7k | return parent_->LookupVariable(var); |
27 | 73.1k | return ""; |
28 | 107k | } |
29 | | |
30 | 242k | void BindingEnv::AddBinding(const string& key, const string& val) { |
31 | 242k | bindings_[key] = val; |
32 | 242k | } |
33 | | |
34 | 2.83k | void BindingEnv::AddRule(std::unique_ptr<const Rule> rule) { |
35 | 2.83k | assert(LookupRuleCurrentScope(rule->name()) == NULL); |
36 | 2.83k | rules_[rule->name()] = std::move(rule); |
37 | 2.83k | } |
38 | | |
39 | 5.03k | const Rule* BindingEnv::LookupRuleCurrentScope(const string& rule_name) { |
40 | 5.03k | auto i = rules_.find(rule_name); |
41 | 5.03k | if (i == rules_.end()) |
42 | 5.02k | return NULL; |
43 | 8 | return i->second.get(); |
44 | 5.03k | } |
45 | | |
46 | 161k | const Rule* BindingEnv::LookupRule(const string& rule_name) { |
47 | 161k | auto i = rules_.find(rule_name); |
48 | 161k | if (i != rules_.end()) |
49 | 161k | return i->second.get(); |
50 | 24 | if (parent_) |
51 | 0 | return parent_->LookupRule(rule_name); |
52 | 24 | return NULL; |
53 | 24 | } |
54 | | |
55 | 8.52k | void Rule::AddBinding(const string& key, const EvalString& val) { |
56 | 8.52k | bindings_[key] = val; |
57 | 8.52k | } |
58 | | |
59 | 493k | const EvalString* Rule::GetBinding(const string& key) const { |
60 | 493k | Bindings::const_iterator i = bindings_.find(key); |
61 | 493k | if (i == bindings_.end()) |
62 | 493k | return NULL; |
63 | 729 | return &i->second; |
64 | 493k | } |
65 | | |
66 | 720 | std::unique_ptr<Rule> Rule::Phony() { |
67 | 720 | auto rule = std::unique_ptr<Rule>(new Rule("phony")); |
68 | 720 | rule->phony_ = true; |
69 | 720 | return rule; |
70 | 720 | } |
71 | | |
72 | 161k | bool Rule::IsPhony() const { |
73 | 161k | return phony_; |
74 | 161k | } |
75 | | |
76 | | // static |
77 | 8.53k | bool Rule::IsReservedBinding(const string& var) { |
78 | 8.53k | return var == "command" || |
79 | 4.73k | var == "depfile" || |
80 | 4.28k | var == "dyndep" || |
81 | 3.88k | var == "description" || |
82 | 3.61k | var == "deps" || |
83 | 3.09k | var == "generator" || |
84 | 2.58k | var == "pool" || |
85 | 1.69k | var == "restat" || |
86 | 1.33k | var == "rspfile" || |
87 | 1.03k | var == "rspfile_content" || |
88 | 555 | var == "msvc_deps_prefix"; |
89 | 8.53k | } |
90 | | |
91 | 0 | const map<string, std::unique_ptr<const Rule>>& BindingEnv::GetRules() const { |
92 | 0 | return rules_; |
93 | 0 | } |
94 | | |
95 | | string BindingEnv::LookupWithFallback(const string& var, |
96 | | const EvalString* eval, |
97 | 493k | Env* env) { |
98 | 493k | map<string, string>::iterator i = bindings_.find(var); |
99 | 493k | if (i != bindings_.end()) |
100 | 1.46k | return i->second; |
101 | | |
102 | 492k | if (eval) |
103 | 729 | return eval->Evaluate(env); |
104 | | |
105 | 491k | if (parent_) |
106 | 317 | return parent_->LookupVariable(var); |
107 | | |
108 | 491k | return ""; |
109 | 491k | } |
110 | | |
111 | 1.78M | string EvalString::Evaluate(Env* env) const { |
112 | 1.78M | if (parsed_.empty()) { |
113 | 1.22M | return single_token_; |
114 | 1.22M | } |
115 | | |
116 | 560k | string result; |
117 | 1.75M | for (TokenList::const_iterator i = parsed_.begin(); i != parsed_.end(); ++i) { |
118 | 1.19M | if (i->second == RAW) |
119 | 420k | result.append(i->first); |
120 | 776k | else |
121 | 776k | result.append(env->LookupVariable(i->first)); |
122 | 1.19M | } |
123 | 560k | return result; |
124 | 1.78M | } |
125 | | |
126 | 2.19M | void EvalString::AddText(StringPiece text) { |
127 | 2.19M | if (parsed_.empty()) { |
128 | 1.72M | single_token_.append(text.begin(), text.end()); |
129 | 1.72M | } else if (!parsed_.empty() && parsed_.back().second == RAW) { |
130 | 235k | parsed_.back().first.append(text.begin(), text.end()); |
131 | 237k | } else { |
132 | 237k | parsed_.push_back(std::make_pair(text.AsString(), RAW)); |
133 | 237k | } |
134 | 2.19M | } |
135 | | |
136 | 852k | void EvalString::AddSpecial(StringPiece text) { |
137 | 852k | if (parsed_.empty() && !single_token_.empty()) { |
138 | | // Going from one to two tokens, so we can no longer apply |
139 | | // our single_token_ optimization and need to push everything |
140 | | // onto the vector. |
141 | 237k | parsed_.push_back(std::make_pair(std::move(single_token_), RAW)); |
142 | 237k | } |
143 | 852k | parsed_.push_back(std::make_pair(text.AsString(), SPECIAL)); |
144 | 852k | } |
145 | | |
146 | 0 | string EvalString::Serialize() const { |
147 | 0 | string result; |
148 | 0 | if (parsed_.empty() && !single_token_.empty()) { |
149 | 0 | result.append("["); |
150 | 0 | result.append(single_token_); |
151 | 0 | result.append("]"); |
152 | 0 | } else { |
153 | 0 | for (const auto& pair : parsed_) { |
154 | 0 | result.append("["); |
155 | 0 | if (pair.second == SPECIAL) |
156 | 0 | result.append("$"); |
157 | 0 | result.append(pair.first.begin(), pair.first.end()); |
158 | 0 | result.append("]"); |
159 | 0 | } |
160 | 0 | } |
161 | 0 | return result; |
162 | 0 | } |
163 | | |
164 | 0 | string EvalString::Unparse() const { |
165 | 0 | string result; |
166 | 0 | if (parsed_.empty() && !single_token_.empty()) { |
167 | 0 | result.append(single_token_.begin(), single_token_.end()); |
168 | 0 | } else { |
169 | 0 | for (TokenList::const_iterator i = parsed_.begin(); |
170 | 0 | i != parsed_.end(); ++i) { |
171 | 0 | bool special = (i->second == SPECIAL); |
172 | 0 | if (special) |
173 | 0 | result.append("${"); |
174 | 0 | result.append(i->first.begin(), i->first.end()); |
175 | 0 | if (special) |
176 | 0 | result.append("}"); |
177 | 0 | } |
178 | 0 | } |
179 | 0 | return result; |
180 | 0 | } |