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 // +build ignore
16
17 #include "var.h"
18
19 #include "eval.h"
20 #include "expr.h"
21 #include "log.h"
22
23 unordered_map<const Var*, string> Var::diagnostic_messages_;
24
GetOriginStr(VarOrigin origin)25 const char* GetOriginStr(VarOrigin origin) {
26 switch (origin) {
27 case VarOrigin::UNDEFINED:
28 return "undefined";
29 case VarOrigin::DEFAULT:
30 return "default";
31 case VarOrigin::ENVIRONMENT:
32 return "environment";
33 case VarOrigin::ENVIRONMENT_OVERRIDE:
34 return "environment override";
35 case VarOrigin::FILE:
36 return "file";
37 case VarOrigin::COMMAND_LINE:
38 return "command line";
39 case VarOrigin::OVERRIDE:
40 return "override";
41 case VarOrigin::AUTOMATIC:
42 return "automatic";
43 }
44 CHECK(false);
45 return "*** broken origin ***";
46 }
47
Var()48 Var::Var() : Var(VarOrigin::UNDEFINED) {}
49
Var(VarOrigin origin)50 Var::Var(VarOrigin origin)
51 : origin_(origin), readonly_(false), deprecated_(false), obsolete_(false) {}
52
~Var()53 Var::~Var() {
54 diagnostic_messages_.erase(this);
55 }
56
AppendVar(Evaluator *,Value *)57 void Var::AppendVar(Evaluator*, Value*) {
58 CHECK(false);
59 }
60
SetDeprecated(const StringPiece & msg)61 void Var::SetDeprecated(const StringPiece& msg) {
62 deprecated_ = true;
63 diagnostic_messages_[this] = msg.as_string();
64 }
65
SetObsolete(const StringPiece & msg)66 void Var::SetObsolete(const StringPiece& msg) {
67 obsolete_ = true;
68 diagnostic_messages_[this] = msg.as_string();
69 }
70
Used(Evaluator * ev,const Symbol & sym) const71 void Var::Used(Evaluator* ev, const Symbol& sym) const {
72 if (obsolete_) {
73 ev->Error(StringPrintf("*** %s is obsolete%s.", sym.c_str(),
74 diagnostic_message_text()));
75 } else if (deprecated_) {
76 WARN_LOC(ev->loc(), "%s has been deprecated%s.", sym.c_str(),
77 diagnostic_message_text());
78 }
79 }
80
diagnostic_message_text() const81 const char* Var::diagnostic_message_text() const {
82 auto it = diagnostic_messages_.find(this);
83 return it == diagnostic_messages_.end() ? "" : it->second.c_str();
84 }
85
DeprecatedMessage() const86 const string& Var::DeprecatedMessage() const {
87 static const string empty_string;
88 auto it = diagnostic_messages_.find(this);
89 return it == diagnostic_messages_.end() ? empty_string : it->second;
90 }
91
Undefined()92 Var* Var::Undefined() {
93 static Var* undefined_var;
94 if (!undefined_var) {
95 undefined_var = new UndefinedVar();
96 }
97 return undefined_var;
98 }
99
SimpleVar(VarOrigin origin)100 SimpleVar::SimpleVar(VarOrigin origin) : Var(origin) {}
101
SimpleVar(const string & v,VarOrigin origin)102 SimpleVar::SimpleVar(const string& v, VarOrigin origin) : Var(origin), v_(v) {}
103
SimpleVar(VarOrigin origin,Evaluator * ev,Value * v)104 SimpleVar::SimpleVar(VarOrigin origin, Evaluator* ev, Value* v) : Var(origin) {
105 v->Eval(ev, &v_);
106 }
107
Eval(Evaluator * ev,string * s) const108 void SimpleVar::Eval(Evaluator* ev, string* s) const {
109 ev->CheckStack();
110 *s += v_;
111 }
112
AppendVar(Evaluator * ev,Value * v)113 void SimpleVar::AppendVar(Evaluator* ev, Value* v) {
114 string buf;
115 v->Eval(ev, &buf);
116 v_.push_back(' ');
117 v_ += buf;
118 }
119
String() const120 StringPiece SimpleVar::String() const {
121 return v_;
122 }
123
DebugString() const124 string SimpleVar::DebugString() const {
125 return v_;
126 }
127
RecursiveVar(Value * v,VarOrigin origin,StringPiece orig)128 RecursiveVar::RecursiveVar(Value* v, VarOrigin origin, StringPiece orig)
129 : Var(origin), v_(v), orig_(orig) {}
130
Eval(Evaluator * ev,string * s) const131 void RecursiveVar::Eval(Evaluator* ev, string* s) const {
132 ev->CheckStack();
133 v_->Eval(ev, s);
134 }
135
AppendVar(Evaluator * ev,Value * v)136 void RecursiveVar::AppendVar(Evaluator* ev, Value* v) {
137 ev->CheckStack();
138 v_ = Value::NewExpr(v_, Value::NewLiteral(" "), v);
139 }
140
String() const141 StringPiece RecursiveVar::String() const {
142 return orig_;
143 }
144
DebugString() const145 string RecursiveVar::DebugString() const {
146 return Value::DebugString(v_);
147 }
148
UndefinedVar()149 UndefinedVar::UndefinedVar() {}
150
Eval(Evaluator *,string *) const151 void UndefinedVar::Eval(Evaluator*, string*) const {
152 // Nothing to do.
153 }
154
String() const155 StringPiece UndefinedVar::String() const {
156 return StringPiece("");
157 }
158
DebugString() const159 string UndefinedVar::DebugString() const {
160 return "*undefined*";
161 }
162
~Vars()163 Vars::~Vars() {
164 for (auto p : *this) {
165 delete p.second;
166 }
167 }
168
add_used_env_vars(Symbol v)169 void Vars::add_used_env_vars(Symbol v) {
170 used_env_vars_.insert(v);
171 }
172
Lookup(Symbol name) const173 Var* Vars::Lookup(Symbol name) const {
174 auto found = find(name);
175 if (found == end())
176 return Var::Undefined();
177 Var* v = found->second;
178 if (v->Origin() == VarOrigin::ENVIRONMENT ||
179 v->Origin() == VarOrigin::ENVIRONMENT_OVERRIDE) {
180 used_env_vars_.insert(name);
181 }
182 return v;
183 }
184
Peek(Symbol name) const185 Var* Vars::Peek(Symbol name) const {
186 auto found = find(name);
187 return found == end() ? Var::Undefined() : found->second;
188 }
189
Assign(Symbol name,Var * v,bool * readonly)190 void Vars::Assign(Symbol name, Var* v, bool* readonly) {
191 *readonly = false;
192 auto p = emplace(name, v);
193 if (!p.second) {
194 Var* orig = p.first->second;
195 if (orig->ReadOnly()) {
196 *readonly = true;
197 return;
198 }
199 if (orig->Origin() == VarOrigin::OVERRIDE ||
200 orig->Origin() == VarOrigin::ENVIRONMENT_OVERRIDE) {
201 return;
202 }
203 if (orig->Origin() == VarOrigin::AUTOMATIC) {
204 ERROR("overriding automatic variable is not implemented yet");
205 }
206 if (orig->IsDefined())
207 delete p.first->second;
208 p.first->second = v;
209 }
210 }
211
212 SymbolSet Vars::used_env_vars_;
213
ScopedVar(Vars * vars,Symbol name,Var * var)214 ScopedVar::ScopedVar(Vars* vars, Symbol name, Var* var)
215 : vars_(vars), orig_(NULL) {
216 auto p = vars->emplace(name, var);
217 iter_ = p.first;
218 if (!p.second) {
219 orig_ = iter_->second;
220 iter_->second = var;
221 }
222 }
223
~ScopedVar()224 ScopedVar::~ScopedVar() {
225 if (orig_) {
226 iter_->second = orig_;
227 } else {
228 vars_->erase(iter_);
229 }
230 }
231