summaryrefslogtreecommitdiffstats
path: root/Source/cmDefinitions.cxx
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2009-07-22 18:22:45 (GMT)
committerBrad King <brad.king@kitware.com>2009-07-22 18:22:45 (GMT)
commitfd10589995fe942ceecbc0e1d5f869a534abdbba (patch)
treeccf5fcb2f87b072108fb9f859d311e345720007a /Source/cmDefinitions.cxx
parent267085f338c917f72950ca55f5cc09760cb4a894 (diff)
downloadCMake-fd10589995fe942ceecbc0e1d5f869a534abdbba.zip
CMake-fd10589995fe942ceecbc0e1d5f869a534abdbba.tar.gz
CMake-fd10589995fe942ceecbc0e1d5f869a534abdbba.tar.bz2
ENH: Improve dynamic variable scope implementation
Previously each new variable scope (subdirectory or function call) in the CMake language created a complete copy of the key->value definition map. This avoids the copy using transitive lookups up the scope stack. Results of queries answered by parents are stored locally to maintain locality of reference. The class cmDefinitions replaces cmMakefile::DefinitionsMap, and is aware of its enclosing scope. Each scope stores only the definitions set (or unset!) inside it relative to the enclosing scope.
Diffstat (limited to 'Source/cmDefinitions.cxx')
-rw-r--r--Source/cmDefinitions.cxx167
1 files changed, 167 insertions, 0 deletions
diff --git a/Source/cmDefinitions.cxx b/Source/cmDefinitions.cxx
new file mode 100644
index 0000000..13bfc6a
--- /dev/null
+++ b/Source/cmDefinitions.cxx
@@ -0,0 +1,167 @@
+/*=========================================================================
+
+ Program: CMake - Cross-Platform Makefile Generator
+ Module: $RCSfile$
+ Language: C++
+ Date: $Date$
+ Version: $Revision$
+
+ Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
+ See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the above copyright notices for more information.
+
+=========================================================================*/
+#include "cmDefinitions.h"
+
+//----------------------------------------------------------------------------
+cmDefinitions::Def cmDefinitions::NoDef;
+
+//----------------------------------------------------------------------------
+cmDefinitions::cmDefinitions(cmDefinitions* parent): Up(parent)
+{
+}
+
+//----------------------------------------------------------------------------
+void cmDefinitions::Reset(cmDefinitions* parent)
+{
+ this->Up = parent;
+ this->Map.clear();
+}
+
+//----------------------------------------------------------------------------
+cmDefinitions::Def const&
+cmDefinitions::GetInternal(const char* key)
+{
+ MapType::const_iterator i = this->Map.find(key);
+ if(i != this->Map.end())
+ {
+ return i->second;
+ }
+ else if(cmDefinitions* up = this->Up)
+ {
+ // Query the parent scope and store the result locally.
+ Def def = up->GetInternal(key);
+ return this->Map.insert(MapType::value_type(key, def)).first->second;
+ }
+ return this->NoDef;
+}
+
+//----------------------------------------------------------------------------
+cmDefinitions::Def const&
+cmDefinitions::SetInternal(const char* key, Def const& def)
+{
+ if(this->Up || def.Exists)
+ {
+ // In lower scopes we store keys, defined or not.
+ MapType::iterator i = this->Map.find(key);
+ if(i == this->Map.end())
+ {
+ i = this->Map.insert(MapType::value_type(key, def)).first;
+ }
+ else
+ {
+ i->second = def;
+ }
+ return i->second;
+ }
+ else
+ {
+ // In the top-most scope we need not store undefined keys.
+ this->Map.erase(key);
+ return this->NoDef;
+ }
+}
+
+//----------------------------------------------------------------------------
+const char* cmDefinitions::Get(const char* key)
+{
+ Def const& def = this->GetInternal(key);
+ return def.Exists? def.c_str() : 0;
+}
+
+//----------------------------------------------------------------------------
+const char* cmDefinitions::Set(const char* key, const char* value)
+{
+ Def const& def = this->SetInternal(key, Def(value));
+ return def.Exists? def.c_str() : 0;
+}
+
+//----------------------------------------------------------------------------
+cmDefinitions cmDefinitions::Closure() const
+{
+ return cmDefinitions(ClosureTag(), this);
+}
+
+//----------------------------------------------------------------------------
+cmDefinitions::cmDefinitions(ClosureTag const&, cmDefinitions const* root):
+ Up(0)
+{
+ std::set<cmStdString> undefined;
+ this->ClosureImpl(undefined, root);
+}
+
+//----------------------------------------------------------------------------
+void cmDefinitions::ClosureImpl(std::set<cmStdString>& undefined,
+ cmDefinitions const* defs)
+{
+ // Consider local definitions.
+ for(MapType::const_iterator mi = defs->Map.begin();
+ mi != defs->Map.end(); ++mi)
+ {
+ // Use this key if it is not already set or unset.
+ if(this->Map.find(mi->first) == this->Map.end() &&
+ undefined.find(mi->first) == undefined.end())
+ {
+ if(mi->second.Exists)
+ {
+ this->Map.insert(*mi);
+ }
+ else
+ {
+ undefined.insert(mi->first);
+ }
+ }
+ }
+
+ // Traverse parents.
+ if(cmDefinitions const* up = defs->Up)
+ {
+ this->ClosureImpl(undefined, up);
+ }
+}
+
+//----------------------------------------------------------------------------
+std::set<cmStdString> cmDefinitions::ClosureKeys() const
+{
+ std::set<cmStdString> defined;
+ std::set<cmStdString> undefined;
+ this->ClosureKeys(defined, undefined);
+ return defined;
+}
+
+//----------------------------------------------------------------------------
+void cmDefinitions::ClosureKeys(std::set<cmStdString>& defined,
+ std::set<cmStdString>& undefined) const
+{
+ // Consider local definitions.
+ for(MapType::const_iterator mi = this->Map.begin();
+ mi != this->Map.end(); ++mi)
+ {
+ // Use this key if it is not already set or unset.
+ if(defined.find(mi->first) == defined.end() &&
+ undefined.find(mi->first) == undefined.end())
+ {
+ std::set<cmStdString>& m = mi->second.Exists? defined : undefined;
+ m.insert(mi->first);
+ }
+ }
+
+ // Traverse parents.
+ if(cmDefinitions const* up = this->Up)
+ {
+ up->ClosureKeys(defined, undefined);
+ }
+}