// Copyright (c) 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "tools/gn/scope.h" #include "base/logging.h" #include "base/stl_util.h" #include "tools/gn/parse_tree.h" #include "tools/gn/template.h" namespace { // FLags set in the mode_flags_ of a scope. If a bit is set, it applies // recursively to all dependent scopes. const unsigned kProcessingBuildConfigFlag = 1; const unsigned kProcessingImportFlag = 2; } // namespace Scope::Scope(const Settings* settings) : const_containing_(NULL), mutable_containing_(NULL), settings_(settings), mode_flags_(0) { } Scope::Scope(Scope* parent) : const_containing_(NULL), mutable_containing_(parent), settings_(parent->settings()), mode_flags_(0) { } Scope::Scope(const Scope* parent) : const_containing_(parent), mutable_containing_(NULL), settings_(parent->settings()), mode_flags_(0) { } Scope::~Scope() { STLDeleteContainerPairSecondPointers(target_defaults_.begin(), target_defaults_.end()); STLDeleteContainerPairSecondPointers(templates_.begin(), templates_.end()); } const Value* Scope::GetValue(const base::StringPiece& ident, bool counts_as_used) { // First check for programatically-provided values. for (ProviderSet::const_iterator i = programmatic_providers_.begin(); i != programmatic_providers_.end(); ++i) { const Value* v = (*i)->GetProgrammaticValue(ident); if (v) return v; } RecordMap::iterator found = values_.find(ident); if (found != values_.end()) { if (counts_as_used) found->second.used = true; return &found->second.value; } // Search in the parent scope. if (const_containing_) return const_containing_->GetValue(ident); if (mutable_containing_) return mutable_containing_->GetValue(ident, counts_as_used); return NULL; } Value* Scope::GetMutableValue(const base::StringPiece& ident, bool counts_as_used) { // Don't do programatic values, which are not mutable. RecordMap::iterator found = values_.find(ident); if (found != values_.end()) { if (counts_as_used) found->second.used = true; return &found->second.value; } // Search in the parent mutable scope, but not const one. if (mutable_containing_) return mutable_containing_->GetMutableValue(ident, counts_as_used); return NULL; } Value* Scope::GetValueForcedToCurrentScope(const base::StringPiece& ident, const ParseNode* set_node) { RecordMap::iterator found = values_.find(ident); if (found != values_.end()) return &found->second.value; // Already have in the current scope. // Search in the parent scope. if (containing()) { const Value* in_containing = containing()->GetValue(ident); if (in_containing) { // Promote to current scope. return SetValue(ident, *in_containing, set_node); } } return NULL; } const Value* Scope::GetValue(const base::StringPiece& ident) const { RecordMap::const_iterator found = values_.find(ident); if (found != values_.end()) return &found->second.value; if (containing()) return containing()->GetValue(ident); return NULL; } Value* Scope::SetValue(const base::StringPiece& ident, const Value& v, const ParseNode* set_node) { Record& r = values_[ident]; // Clears any existing value. r.value = v; r.value.set_origin(set_node); return &r.value; } bool Scope::AddTemplate(const std::string& name, scoped_ptr