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; 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 62 bool ReadOnly() const { return readonly_; } 63 void SetReadOnly() { readonly_ = true; } 64 65 bool Deprecated() const { return message_ && !error_; } 66 void SetDeprecated(StringPiece msg) { 67 message_.reset(new string(msg.as_string())); 68 } 69 70 bool Obsolete() const { return error_; } 71 void SetObsolete(StringPiece msg) { 72 message_.reset(new string(msg.as_string())); 73 error_ = true; 74 } 75 76 const string& DeprecatedMessage() const { return *message_; } 77 78 // This variable was used (either written or read from) 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 107 virtual const char* Flavor() const override { return "simple"; } 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 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 129 virtual const char* Flavor() const override { return "recursive"; } 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 150 virtual const char* Flavor() const override { return "undefined"; } 151 virtual VarOrigin Origin() const override { return VarOrigin::UNDEFINED; } 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: 165 RuleVar(Var* v, AssignOp op) : v_(v), op_(op) {} 166 virtual ~RuleVar() { delete v_; } 167 168 virtual const char* Flavor() const override { return v_->Flavor(); } 169 virtual VarOrigin Origin() const override { return v_->Origin(); } 170 virtual bool IsDefined() const override { return v_->IsDefined(); } 171 virtual void Eval(Evaluator* ev, string* s) const override { 172 v_->Eval(ev, s); 173 } 174 virtual void AppendVar(Evaluator* ev, Value* v) override { 175 v_->AppendVar(ev, v); 176 } 177 virtual StringPiece String() const override { return v_->String(); } 178 virtual string DebugString() const override { return v_->DebugString(); } 179 180 Var* v() const { return v_; } 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 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