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 | string BindingEnv::LookupVariable(const string& var) { |
22 | map<string, string>::iterator i = bindings_.find(var); |
23 | if (i != bindings_.end()) |
24 | return i->second; |
25 | if (parent_) |
26 | return parent_->LookupVariable(var); |
27 | return "" ; |
28 | } |
29 | |
30 | void BindingEnv::AddBinding(const string& key, const string& val) { |
31 | bindings_[key] = val; |
32 | } |
33 | |
34 | void BindingEnv::AddRule(const Rule* rule) { |
35 | assert(LookupRuleCurrentScope(rule->name()) == NULL); |
36 | rules_[rule->name()] = rule; |
37 | } |
38 | |
39 | const Rule* BindingEnv::LookupRuleCurrentScope(const string& rule_name) { |
40 | map<string, const Rule*>::iterator i = rules_.find(rule_name); |
41 | if (i == rules_.end()) |
42 | return NULL; |
43 | return i->second; |
44 | } |
45 | |
46 | const Rule* BindingEnv::LookupRule(const string& rule_name) { |
47 | map<string, const Rule*>::iterator i = rules_.find(rule_name); |
48 | if (i != rules_.end()) |
49 | return i->second; |
50 | if (parent_) |
51 | return parent_->LookupRule(rule_name); |
52 | return NULL; |
53 | } |
54 | |
55 | void Rule::AddBinding(const string& key, const EvalString& val) { |
56 | bindings_[key] = val; |
57 | } |
58 | |
59 | const EvalString* Rule::GetBinding(const string& key) const { |
60 | Bindings::const_iterator i = bindings_.find(key); |
61 | if (i == bindings_.end()) |
62 | return NULL; |
63 | return &i->second; |
64 | } |
65 | |
66 | // static |
67 | bool Rule::IsReservedBinding(const string& var) { |
68 | return var == "command" || |
69 | var == "depfile" || |
70 | var == "dyndep" || |
71 | var == "description" || |
72 | var == "deps" || |
73 | var == "generator" || |
74 | var == "pool" || |
75 | var == "restat" || |
76 | var == "rspfile" || |
77 | var == "rspfile_content" || |
78 | var == "msvc_deps_prefix" ; |
79 | } |
80 | |
81 | const map<string, const Rule*>& BindingEnv::GetRules() const { |
82 | return rules_; |
83 | } |
84 | |
85 | string BindingEnv::LookupWithFallback(const string& var, |
86 | const EvalString* eval, |
87 | Env* env) { |
88 | map<string, string>::iterator i = bindings_.find(var); |
89 | if (i != bindings_.end()) |
90 | return i->second; |
91 | |
92 | if (eval) |
93 | return eval->Evaluate(env); |
94 | |
95 | if (parent_) |
96 | return parent_->LookupVariable(var); |
97 | |
98 | return "" ; |
99 | } |
100 | |
101 | string EvalString::Evaluate(Env* env) const { |
102 | string result; |
103 | for (TokenList::const_iterator i = parsed_.begin(); i != parsed_.end(); ++i) { |
104 | if (i->second == RAW) |
105 | result.append(i->first); |
106 | else |
107 | result.append(env->LookupVariable(i->first)); |
108 | } |
109 | return result; |
110 | } |
111 | |
112 | void EvalString::AddText(StringPiece text) { |
113 | // Add it to the end of an existing RAW token if possible. |
114 | if (!parsed_.empty() && parsed_.back().second == RAW) { |
115 | parsed_.back().first.append(text.str_, text.len_); |
116 | } else { |
117 | parsed_.push_back(make_pair(text.AsString(), RAW)); |
118 | } |
119 | } |
120 | void EvalString::AddSpecial(StringPiece text) { |
121 | parsed_.push_back(make_pair(text.AsString(), SPECIAL)); |
122 | } |
123 | |
124 | string EvalString::Serialize() const { |
125 | string result; |
126 | for (TokenList::const_iterator i = parsed_.begin(); |
127 | i != parsed_.end(); ++i) { |
128 | result.append("[" ); |
129 | if (i->second == SPECIAL) |
130 | result.append("$" ); |
131 | result.append(i->first); |
132 | result.append("]" ); |
133 | } |
134 | return result; |
135 | } |
136 | |
137 | string EvalString::Unparse() const { |
138 | string result; |
139 | for (TokenList::const_iterator i = parsed_.begin(); |
140 | i != parsed_.end(); ++i) { |
141 | bool special = (i->second == SPECIAL); |
142 | if (special) |
143 | result.append("${" ); |
144 | result.append(i->first); |
145 | if (special) |
146 | result.append("}" ); |
147 | } |
148 | return result; |
149 | } |
150 | |