mirror of
https://github.com/reactos/CMake.git
synced 2024-11-29 22:40:25 +00:00
fd10589995
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.
168 lines
4.8 KiB
C++
168 lines
4.8 KiB
C++
/*=========================================================================
|
|
|
|
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);
|
|
}
|
|
}
|