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 "expr.h"
20#include "log.h"
21
22UndefinedVar kUndefinedBuf;
23UndefinedVar* kUndefined = &kUndefinedBuf;
24
25const char* GetOriginStr(VarOrigin origin) {
26  switch (origin) {
27    case VarOrigin::UNDEFINED: return "undefined";
28    case VarOrigin::DEFAULT: return "default";
29    case VarOrigin::ENVIRONMENT: return "environment";
30    case VarOrigin::ENVIRONMENT_OVERRIDE: return "environment override";
31    case VarOrigin::FILE: return "file";
32    case VarOrigin::COMMAND_LINE: return "command line";
33    case VarOrigin::OVERRIDE: return "override";
34    case VarOrigin::AUTOMATIC: return "automatic";
35  }
36  CHECK(false);
37  return "*** broken origin ***";
38}
39
40Var::Var() : readonly_(false) {
41}
42
43Var::~Var() {
44}
45
46void Var::AppendVar(Evaluator*, Value*) {
47  CHECK(false);
48}
49
50SimpleVar::SimpleVar(VarOrigin origin)
51    : origin_(origin) {
52}
53
54SimpleVar::SimpleVar(const string& v, VarOrigin origin)
55    : v_(v), origin_(origin) {
56}
57
58void SimpleVar::Eval(Evaluator*, string* s) const {
59  *s += v_;
60}
61
62void SimpleVar::AppendVar(Evaluator* ev, Value* v) {
63  string buf;
64  v->Eval(ev, &buf);
65  v_.push_back(' ');
66  v_ += buf;
67}
68
69StringPiece SimpleVar::String() const {
70  return v_;
71}
72
73string SimpleVar::DebugString() const {
74  return v_;
75}
76
77RecursiveVar::RecursiveVar(Value* v, VarOrigin origin, StringPiece orig)
78    : v_(v), origin_(origin), orig_(orig) {
79}
80
81void RecursiveVar::Eval(Evaluator* ev, string* s) const {
82  v_->Eval(ev, s);
83}
84
85void RecursiveVar::AppendVar(Evaluator*, Value* v) {
86  v_ = NewExpr3(v_, NewLiteral(" "), v);
87}
88
89StringPiece RecursiveVar::String() const {
90  return orig_;
91}
92
93string RecursiveVar::DebugString() const {
94  return v_->DebugString();
95}
96
97UndefinedVar::UndefinedVar() {}
98
99void UndefinedVar::Eval(Evaluator*, string*) const {
100  // Nothing to do.
101}
102
103StringPiece UndefinedVar::String() const {
104  return StringPiece("");
105}
106
107string UndefinedVar::DebugString() const {
108  return "*undefined*";
109}
110
111Vars::~Vars() {
112  for (auto p : *this) {
113    delete p.second;
114  }
115}
116
117void Vars::add_used_env_vars(Symbol v) {
118  used_env_vars_.insert(v);
119}
120
121Var* Vars::Lookup(Symbol name) const {
122  auto found = find(name);
123  if (found == end())
124    return kUndefined;
125  Var* v = found->second;
126  if (v->Origin() == VarOrigin::ENVIRONMENT ||
127      v->Origin() == VarOrigin::ENVIRONMENT_OVERRIDE) {
128    used_env_vars_.insert(name);
129  }
130  return v;
131}
132
133void Vars::Assign(Symbol name, Var* v, bool* readonly) {
134  *readonly = false;
135  auto p = emplace(name, v);
136  if (!p.second) {
137    Var* orig = p.first->second;
138    if (orig->ReadOnly()) {
139      *readonly = true;
140      return;
141    }
142    if (orig->Origin() == VarOrigin::OVERRIDE ||
143        orig->Origin() == VarOrigin::ENVIRONMENT_OVERRIDE) {
144      return;
145    }
146    if (orig->Origin() == VarOrigin::AUTOMATIC) {
147      ERROR("overriding automatic variable is not implemented yet");
148    }
149    if (orig->IsDefined())
150      delete p.first->second;
151    p.first->second = v;
152  }
153}
154
155unordered_set<Symbol> Vars::used_env_vars_;
156
157ScopedVar::ScopedVar(Vars* vars, Symbol name, Var* var)
158    : vars_(vars), orig_(NULL) {
159  auto p = vars->emplace(name, var);
160  iter_ = p.first;
161  if (!p.second) {
162    orig_ = iter_->second;
163    iter_->second = var;
164  }
165}
166
167ScopedVar::~ScopedVar() {
168  if (orig_) {
169    iter_->second = orig_;
170  } else {
171    vars_->erase(iter_);
172  }
173}
174