1695b41eeSopenharmony_ci// Copyright 2011 Google Inc. All Rights Reserved.
2695b41eeSopenharmony_ci//
3695b41eeSopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License");
4695b41eeSopenharmony_ci// you may not use this file except in compliance with the License.
5695b41eeSopenharmony_ci// You may obtain a copy of the License at
6695b41eeSopenharmony_ci//
7695b41eeSopenharmony_ci//     http://www.apache.org/licenses/LICENSE-2.0
8695b41eeSopenharmony_ci//
9695b41eeSopenharmony_ci// Unless required by applicable law or agreed to in writing, software
10695b41eeSopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS,
11695b41eeSopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12695b41eeSopenharmony_ci// See the License for the specific language governing permissions and
13695b41eeSopenharmony_ci// limitations under the License.
14695b41eeSopenharmony_ci
15695b41eeSopenharmony_ci#include <assert.h>
16695b41eeSopenharmony_ci
17695b41eeSopenharmony_ci#include "eval_env.h"
18695b41eeSopenharmony_ci
19695b41eeSopenharmony_ciusing namespace std;
20695b41eeSopenharmony_ci
21695b41eeSopenharmony_cistring BindingEnv::LookupVariable(const string& var) {
22695b41eeSopenharmony_ci  map<string, string>::iterator i = bindings_.find(var);
23695b41eeSopenharmony_ci  if (i != bindings_.end())
24695b41eeSopenharmony_ci    return i->second;
25695b41eeSopenharmony_ci  if (parent_)
26695b41eeSopenharmony_ci    return parent_->LookupVariable(var);
27695b41eeSopenharmony_ci  return "";
28695b41eeSopenharmony_ci}
29695b41eeSopenharmony_ci
30695b41eeSopenharmony_civoid BindingEnv::AddBinding(const string& key, const string& val) {
31695b41eeSopenharmony_ci  bindings_[key] = val;
32695b41eeSopenharmony_ci}
33695b41eeSopenharmony_ci
34695b41eeSopenharmony_civoid BindingEnv::AddRule(const Rule* rule) {
35695b41eeSopenharmony_ci  assert(LookupRuleCurrentScope(rule->name()) == NULL);
36695b41eeSopenharmony_ci  rules_[rule->name()] = rule;
37695b41eeSopenharmony_ci}
38695b41eeSopenharmony_ci
39695b41eeSopenharmony_ciconst Rule* BindingEnv::LookupRuleCurrentScope(const string& rule_name) {
40695b41eeSopenharmony_ci  map<string, const Rule*>::iterator i = rules_.find(rule_name);
41695b41eeSopenharmony_ci  if (i == rules_.end())
42695b41eeSopenharmony_ci    return NULL;
43695b41eeSopenharmony_ci  return i->second;
44695b41eeSopenharmony_ci}
45695b41eeSopenharmony_ci
46695b41eeSopenharmony_ciconst Rule* BindingEnv::LookupRule(const string& rule_name) {
47695b41eeSopenharmony_ci  map<string, const Rule*>::iterator i = rules_.find(rule_name);
48695b41eeSopenharmony_ci  if (i != rules_.end())
49695b41eeSopenharmony_ci    return i->second;
50695b41eeSopenharmony_ci  if (parent_)
51695b41eeSopenharmony_ci    return parent_->LookupRule(rule_name);
52695b41eeSopenharmony_ci  return NULL;
53695b41eeSopenharmony_ci}
54695b41eeSopenharmony_ci
55695b41eeSopenharmony_civoid Rule::AddBinding(const string& key, const EvalString& val) {
56695b41eeSopenharmony_ci  bindings_[key] = val;
57695b41eeSopenharmony_ci}
58695b41eeSopenharmony_ci
59695b41eeSopenharmony_ciconst EvalString* Rule::GetBinding(const string& key) const {
60695b41eeSopenharmony_ci  Bindings::const_iterator i = bindings_.find(key);
61695b41eeSopenharmony_ci  if (i == bindings_.end())
62695b41eeSopenharmony_ci    return NULL;
63695b41eeSopenharmony_ci  return &i->second;
64695b41eeSopenharmony_ci}
65695b41eeSopenharmony_ci
66695b41eeSopenharmony_ci// static
67695b41eeSopenharmony_cibool Rule::IsReservedBinding(const string& var) {
68695b41eeSopenharmony_ci  return var == "command" ||
69695b41eeSopenharmony_ci      var == "depfile" ||
70695b41eeSopenharmony_ci      var == "dyndep" ||
71695b41eeSopenharmony_ci      var == "description" ||
72695b41eeSopenharmony_ci      var == "deps" ||
73695b41eeSopenharmony_ci      var == "generator" ||
74695b41eeSopenharmony_ci      var == "pool" ||
75695b41eeSopenharmony_ci      var == "restat" ||
76695b41eeSopenharmony_ci      var == "rspfile" ||
77695b41eeSopenharmony_ci      var == "rspfile_content" ||
78695b41eeSopenharmony_ci      var == "msvc_deps_prefix";
79695b41eeSopenharmony_ci}
80695b41eeSopenharmony_ci
81695b41eeSopenharmony_ciconst map<string, const Rule*>& BindingEnv::GetRules() const {
82695b41eeSopenharmony_ci  return rules_;
83695b41eeSopenharmony_ci}
84695b41eeSopenharmony_ci
85695b41eeSopenharmony_cistring BindingEnv::LookupWithFallback(const string& var,
86695b41eeSopenharmony_ci                                      const EvalString* eval,
87695b41eeSopenharmony_ci                                      Env* env) {
88695b41eeSopenharmony_ci  map<string, string>::iterator i = bindings_.find(var);
89695b41eeSopenharmony_ci  if (i != bindings_.end())
90695b41eeSopenharmony_ci    return i->second;
91695b41eeSopenharmony_ci
92695b41eeSopenharmony_ci  if (eval)
93695b41eeSopenharmony_ci    return eval->Evaluate(env);
94695b41eeSopenharmony_ci
95695b41eeSopenharmony_ci  if (parent_)
96695b41eeSopenharmony_ci    return parent_->LookupVariable(var);
97695b41eeSopenharmony_ci
98695b41eeSopenharmony_ci  return "";
99695b41eeSopenharmony_ci}
100695b41eeSopenharmony_ci
101695b41eeSopenharmony_cistring EvalString::Evaluate(Env* env) const {
102695b41eeSopenharmony_ci  string result;
103695b41eeSopenharmony_ci  for (TokenList::const_iterator i = parsed_.begin(); i != parsed_.end(); ++i) {
104695b41eeSopenharmony_ci    if (i->second == RAW)
105695b41eeSopenharmony_ci      result.append(i->first);
106695b41eeSopenharmony_ci    else
107695b41eeSopenharmony_ci      result.append(env->LookupVariable(i->first));
108695b41eeSopenharmony_ci  }
109695b41eeSopenharmony_ci  return result;
110695b41eeSopenharmony_ci}
111695b41eeSopenharmony_ci
112695b41eeSopenharmony_civoid EvalString::AddText(StringPiece text) {
113695b41eeSopenharmony_ci  // Add it to the end of an existing RAW token if possible.
114695b41eeSopenharmony_ci  if (!parsed_.empty() && parsed_.back().second == RAW) {
115695b41eeSopenharmony_ci    parsed_.back().first.append(text.str_, text.len_);
116695b41eeSopenharmony_ci  } else {
117695b41eeSopenharmony_ci    parsed_.push_back(make_pair(text.AsString(), RAW));
118695b41eeSopenharmony_ci  }
119695b41eeSopenharmony_ci}
120695b41eeSopenharmony_civoid EvalString::AddSpecial(StringPiece text) {
121695b41eeSopenharmony_ci  parsed_.push_back(make_pair(text.AsString(), SPECIAL));
122695b41eeSopenharmony_ci}
123695b41eeSopenharmony_ci
124695b41eeSopenharmony_cistring EvalString::Serialize() const {
125695b41eeSopenharmony_ci  string result;
126695b41eeSopenharmony_ci  for (TokenList::const_iterator i = parsed_.begin();
127695b41eeSopenharmony_ci       i != parsed_.end(); ++i) {
128695b41eeSopenharmony_ci    result.append("[");
129695b41eeSopenharmony_ci    if (i->second == SPECIAL)
130695b41eeSopenharmony_ci      result.append("$");
131695b41eeSopenharmony_ci    result.append(i->first);
132695b41eeSopenharmony_ci    result.append("]");
133695b41eeSopenharmony_ci  }
134695b41eeSopenharmony_ci  return result;
135695b41eeSopenharmony_ci}
136695b41eeSopenharmony_ci
137695b41eeSopenharmony_cistring EvalString::Unparse() const {
138695b41eeSopenharmony_ci  string result;
139695b41eeSopenharmony_ci  for (TokenList::const_iterator i = parsed_.begin();
140695b41eeSopenharmony_ci       i != parsed_.end(); ++i) {
141695b41eeSopenharmony_ci    bool special = (i->second == SPECIAL);
142695b41eeSopenharmony_ci    if (special)
143695b41eeSopenharmony_ci      result.append("${");
144695b41eeSopenharmony_ci    result.append(i->first);
145695b41eeSopenharmony_ci    if (special)
146695b41eeSopenharmony_ci      result.append("}");
147695b41eeSopenharmony_ci  }
148695b41eeSopenharmony_ci  return result;
149695b41eeSopenharmony_ci}
150