1// Copyright 2011 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 NINJA_EVAL_ENV_H_ 16#define NINJA_EVAL_ENV_H_ 17 18#include <map> 19#include <string> 20#include <vector> 21 22#include "string_piece.h" 23 24struct Rule; 25 26/// An interface for a scope for variable (e.g. "$foo") lookups. 27struct Env { 28 virtual ~Env() {} 29 virtual std::string LookupVariable(const std::string& var) = 0; 30}; 31 32/// A tokenized string that contains variable references. 33/// Can be evaluated relative to an Env. 34struct EvalString { 35 /// @return The evaluated string with variable expanded using value found in 36 /// environment @a env. 37 std::string Evaluate(Env* env) const; 38 39 /// @return The string with variables not expanded. 40 std::string Unparse() const; 41 42 void Clear() { parsed_.clear(); } 43 bool empty() const { return parsed_.empty(); } 44 45 void AddText(StringPiece text); 46 void AddSpecial(StringPiece text); 47 48 /// Construct a human-readable representation of the parsed state, 49 /// for use in tests. 50 std::string Serialize() const; 51 52private: 53 enum TokenType { RAW, SPECIAL }; 54 typedef std::vector<std::pair<std::string, TokenType> > TokenList; 55 TokenList parsed_; 56}; 57 58/// An invocable build command and associated metadata (description, etc.). 59struct Rule { 60 explicit Rule(const std::string& name) : name_(name) {} 61 62 const std::string& name() const { return name_; } 63 64 void AddBinding(const std::string& key, const EvalString& val); 65 66 static bool IsReservedBinding(const std::string& var); 67 68 const EvalString* GetBinding(const std::string& key) const; 69 70 private: 71 // Allow the parsers to reach into this object and fill out its fields. 72 friend struct ManifestParser; 73 74 std::string name_; 75 typedef std::map<std::string, EvalString> Bindings; 76 Bindings bindings_; 77}; 78 79/// An Env which contains a mapping of variables to values 80/// as well as a pointer to a parent scope. 81struct BindingEnv : public Env { 82 BindingEnv() : parent_(NULL) {} 83 explicit BindingEnv(BindingEnv* parent) : parent_(parent) {} 84 85 virtual ~BindingEnv() {} 86 virtual std::string LookupVariable(const std::string& var); 87 88 void AddRule(const Rule* rule); 89 const Rule* LookupRule(const std::string& rule_name); 90 const Rule* LookupRuleCurrentScope(const std::string& rule_name); 91 const std::map<std::string, const Rule*>& GetRules() const; 92 93 void AddBinding(const std::string& key, const std::string& val); 94 95 /// This is tricky. Edges want lookup scope to go in this order: 96 /// 1) value set on edge itself (edge_->env_) 97 /// 2) value set on rule, with expansion in the edge's scope 98 /// 3) value set on enclosing scope of edge (edge_->env_->parent_) 99 /// This function takes as parameters the necessary info to do (2). 100 std::string LookupWithFallback(const std::string& var, const EvalString* eval, 101 Env* env); 102 103private: 104 std::map<std::string, std::string> bindings_; 105 std::map<std::string, const Rule*> rules_; 106 BindingEnv* parent_; 107}; 108 109#endif // NINJA_EVAL_ENV_H_ 110