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 VAR_H_
16 #define VAR_H_
17 
18 #include <memory>
19 #include <string>
20 #include <unordered_map>
21 #include <unordered_set>
22 
23 #include "eval.h"
24 #include "expr.h"
25 #include "log.h"
26 #include "stmt.h"
27 #include "string_piece.h"
28 #include "symtab.h"
29 
30 using namespace std;
31 
32 class Evaluator;
33 class Value;
34 
35 enum struct VarOrigin {
36   UNDEFINED,
37   DEFAULT,
38   ENVIRONMENT,
39   ENVIRONMENT_OVERRIDE,
40   FILE,
41   COMMAND_LINE,
42   OVERRIDE,
43   AUTOMATIC,
44 };
45 
46 const char* GetOriginStr(VarOrigin origin);
47 
48 class Var : public Evaluable {
49  public:
50   virtual ~Var();
51 
52   virtual const char* Flavor() const = 0;
53   virtual VarOrigin Origin() const = 0;
IsDefined()54   virtual bool IsDefined() const { return true; }
55 
56   virtual void AppendVar(Evaluator* ev, Value* v);
57 
58   virtual StringPiece String() const = 0;
59 
60   virtual string DebugString() const = 0;
61 
ReadOnly()62   bool ReadOnly() const { return readonly_; }
SetReadOnly()63   void SetReadOnly() { readonly_ = true; }
64 
Deprecated()65   bool Deprecated() const { return message_ && !error_; }
SetDeprecated(StringPiece msg)66   void SetDeprecated(StringPiece msg) {
67     message_.reset(new string(msg.as_string()));
68   }
69 
Obsolete()70   bool Obsolete() const { return error_; }
SetObsolete(StringPiece msg)71   void SetObsolete(StringPiece msg) {
72     message_.reset(new string(msg.as_string()));
73     error_ = true;
74   }
75 
DeprecatedMessage()76   const string& DeprecatedMessage() const { return *message_; }
77 
78   // This variable was used (either written or read from)
Used(Evaluator * ev,const Symbol & sym)79   void Used(Evaluator* ev, const Symbol& sym) const {
80     if (!message_) {
81       return;
82     }
83 
84     if (error_) {
85       ev->Error(StringPrintf("*** %s is obsolete%s.", sym.c_str(),
86                              message_->c_str()));
87     } else {
88       WARN_LOC(ev->loc(), "%s has been deprecated%s.", sym.c_str(),
89                message_->c_str());
90     }
91   }
92 
93  protected:
94   Var();
95 
96  private:
97   bool readonly_;
98   unique_ptr<string> message_;
99   bool error_;
100 };
101 
102 class SimpleVar : public Var {
103  public:
104   explicit SimpleVar(VarOrigin origin);
105   SimpleVar(const string& v, VarOrigin origin);
106 
Flavor()107   virtual const char* Flavor() const override { return "simple"; }
Origin()108   virtual VarOrigin Origin() const override { return origin_; }
109 
110   virtual void Eval(Evaluator* ev, string* s) const override;
111 
112   virtual void AppendVar(Evaluator* ev, Value* v) override;
113 
114   virtual StringPiece String() const override;
115 
116   virtual string DebugString() const override;
117 
mutable_value()118   string* mutable_value() { return &v_; }
119 
120  private:
121   string v_;
122   VarOrigin origin_;
123 };
124 
125 class RecursiveVar : public Var {
126  public:
127   RecursiveVar(Value* v, VarOrigin origin, StringPiece orig);
128 
Flavor()129   virtual const char* Flavor() const override { return "recursive"; }
Origin()130   virtual VarOrigin Origin() const override { return origin_; }
131 
132   virtual void Eval(Evaluator* ev, string* s) const override;
133 
134   virtual void AppendVar(Evaluator* ev, Value* v) override;
135 
136   virtual StringPiece String() const override;
137 
138   virtual string DebugString() const override;
139 
140  private:
141   Value* v_;
142   VarOrigin origin_;
143   StringPiece orig_;
144 };
145 
146 class UndefinedVar : public Var {
147  public:
148   UndefinedVar();
149 
Flavor()150   virtual const char* Flavor() const override { return "undefined"; }
Origin()151   virtual VarOrigin Origin() const override { return VarOrigin::UNDEFINED; }
IsDefined()152   virtual bool IsDefined() const override { return false; }
153 
154   virtual void Eval(Evaluator* ev, string* s) const override;
155 
156   virtual StringPiece String() const override;
157 
158   virtual string DebugString() const override;
159 };
160 
161 extern UndefinedVar* kUndefined;
162 
163 class RuleVar : public Var {
164  public:
RuleVar(Var * v,AssignOp op)165   RuleVar(Var* v, AssignOp op) : v_(v), op_(op) {}
~RuleVar()166   virtual ~RuleVar() { delete v_; }
167 
Flavor()168   virtual const char* Flavor() const override { return v_->Flavor(); }
Origin()169   virtual VarOrigin Origin() const override { return v_->Origin(); }
IsDefined()170   virtual bool IsDefined() const override { return v_->IsDefined(); }
Eval(Evaluator * ev,string * s)171   virtual void Eval(Evaluator* ev, string* s) const override {
172     v_->Eval(ev, s);
173   }
AppendVar(Evaluator * ev,Value * v)174   virtual void AppendVar(Evaluator* ev, Value* v) override {
175     v_->AppendVar(ev, v);
176   }
String()177   virtual StringPiece String() const override { return v_->String(); }
DebugString()178   virtual string DebugString() const override { return v_->DebugString(); }
179 
v()180   Var* v() const { return v_; }
op()181   AssignOp op() const { return op_; }
182 
183  private:
184   Var* v_;
185   AssignOp op_;
186 };
187 
188 class Vars : public unordered_map<Symbol, Var*> {
189  public:
190   ~Vars();
191 
192   Var* Lookup(Symbol name) const;
193   Var* Peek(Symbol name) const;
194 
195   void Assign(Symbol name, Var* v, bool* readonly);
196 
197   static void add_used_env_vars(Symbol v);
198 
used_env_vars()199   static const unordered_set<Symbol>& used_env_vars() { return used_env_vars_; }
200 
201  private:
202   static unordered_set<Symbol> used_env_vars_;
203 };
204 
205 class ScopedVar {
206  public:
207   // Does not take ownerships of arguments.
208   ScopedVar(Vars* vars, Symbol name, Var* var);
209   ~ScopedVar();
210 
211  private:
212   Vars* vars_;
213   Var* orig_;
214   Vars::iterator iter_;
215 };
216 
217 #endif  // VAR_H_
218