diff --git a/src/OpenFOAM/Make/files b/src/OpenFOAM/Make/files
index 4a6adb98a168b649b741bef57c8856c2fc0b3c4e..80b6239039a430e2cda592d14270063ba35262fc 100644
--- a/src/OpenFOAM/Make/files
+++ b/src/OpenFOAM/Make/files
@@ -203,6 +203,7 @@ $(Pstreams)/PstreamBuffers.C
 dictionary = db/dictionary
 $(dictionary)/dictionary.C
 $(dictionary)/dictionaryIO.C
+$(dictionary)/dictionarySearch.C
 
 entry = $(dictionary)/entry
 $(entry)/entry.C
diff --git a/src/OpenFOAM/db/dictionary/dictionary.C b/src/OpenFOAM/db/dictionary/dictionary.C
index 33acac0ace16db6be191887197ced5c8fb35133a..46cee88d67d7fac7e4ee1927df06be696f80cd2c 100644
--- a/src/OpenFOAM/db/dictionary/dictionary.C
+++ b/src/OpenFOAM/db/dictionary/dictionary.C
@@ -45,157 +45,6 @@ bool Foam::dictionary::writeOptionalEntries
 );
 
 
-// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
-
-namespace Foam
-{
-    // file-scope
-    //- Walk lists of patterns and regexps for an exact match
-    //  or regular expression match
-    template<class WcIterator, class ReIterator>
-    static bool findInPatterns
-    (
-        const bool patternMatch,
-        const word& keyword,
-        WcIterator& wcIter,
-        ReIterator& reIter
-    )
-    {
-        while (wcIter.found())
-        {
-            if
-            (
-                patternMatch
-              ? reIter()->match(keyword)
-              : wcIter()->keyword() == keyword
-            )
-            {
-                return true;
-            }
-
-            ++reIter;
-            ++wcIter;
-        }
-
-        return false;
-    }
-}
-
-
-// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
-
-const Foam::entry* Foam::dictionary::lookupScopedSubEntryPtr
-(
-    const word& keyword,
-    bool recursive,
-    bool patternMatch
-) const
-{
-    string::size_type dotPos = keyword.find('.');
-
-    if (dotPos == string::npos)
-    {
-        // Non-scoped lookup
-        return lookupEntryPtr(keyword, recursive, patternMatch);
-    }
-    else if (dotPos == 0)
-    {
-        // Starting with a '.' -> go up for every further '.' found
-        ++dotPos;
-
-        const dictionary* dictPtr = this;
-        for
-        (
-            string::const_iterator it = keyword.begin()+1;
-            it != keyword.end() && *it == '.';
-            ++dotPos, ++it
-        )
-        {
-            // Go to parent
-            if (&dictPtr->parent_ != &dictionary::null)
-            {
-                dictPtr = &dictPtr->parent_;
-            }
-            else
-            {
-                FatalIOErrorInFunction
-                (
-                    *this
-                )   << "No parent of current dictionary when searching for "
-                    << keyword.substr(1)
-                    << exit(FatalIOError);
-
-                return nullptr;
-            }
-        }
-
-        return dictPtr->lookupScopedSubEntryPtr
-        (
-            keyword.substr(dotPos),
-            false,
-            patternMatch
-        );
-    }
-    else
-    {
-        // The first word
-        const entry* entPtr = lookupScopedSubEntryPtr
-        (
-            keyword.substr(0, dotPos),
-            false,
-            patternMatch
-        );
-
-        if (!entPtr)
-        {
-            // Fall back to finding key with '.' so e.g. if keyword is
-            // a.b.c.d it would try
-            // a.b, a.b.c, a.b.c.d
-
-            while (true)
-            {
-                dotPos = keyword.find('.', dotPos+1);
-
-                entPtr = lookupEntryPtr
-                (
-                    keyword.substr(0, dotPos),
-                    false,
-                    patternMatch
-                );
-
-                if (dotPos == string::npos)
-                {
-                    // Parsed the whole word. Return entry or null.
-                    return entPtr;
-                }
-
-                if (entPtr && entPtr->isDict())
-                {
-                    return entPtr->dict().lookupScopedSubEntryPtr
-                    (
-                        keyword.substr(dotPos),
-                        false,
-                        patternMatch
-                    );
-                }
-            }
-        }
-
-        if (entPtr->isDict())
-        {
-            return entPtr->dict().lookupScopedSubEntryPtr
-            (
-                keyword.substr(dotPos),
-                false,
-                patternMatch
-            );
-        }
-    }
-
-    return nullptr;
-}
-
-
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
 Foam::dictionary::dictionary()
@@ -395,29 +244,7 @@ bool Foam::dictionary::found
     bool patternMatch
 ) const
 {
-    if (hashedEntries_.found(keyword))
-    {
-        return true;
-    }
-
-    if (patternMatch && patterns_.size())
-    {
-        pattern_const_iterator wcLink = patterns_.begin();
-        regexp_const_iterator  reLink = regexps_.begin();
-
-        // Find in patterns using regular expressions only
-        if (findInPatterns(patternMatch, keyword, wcLink, reLink))
-        {
-            return true;
-        }
-    }
-
-    if (recursive && &parent_ != &dictionary::null)
-    {
-        return parent_.found(keyword, recursive, patternMatch);
-    }
-
-    return false;
+    return csearch(keyword, recursive, patternMatch).found();
 }
 
 
@@ -428,31 +255,7 @@ const Foam::entry* Foam::dictionary::lookupEntryPtr
     bool patternMatch
 ) const
 {
-    auto iter = hashedEntries_.cfind(keyword);
-
-    if (iter.found())
-    {
-        return iter();
-    }
-
-    if (patternMatch && patterns_.size())
-    {
-        pattern_const_iterator wcLink = patterns_.begin();
-        regexp_const_iterator  reLink = regexps_.begin();
-
-        // Find in patterns using regular expressions only
-        if (findInPatterns(patternMatch, keyword, wcLink, reLink))
-        {
-            return wcLink();
-        }
-    }
-
-    if (recursive && &parent_ != &dictionary::null)
-    {
-        return parent_.lookupEntryPtr(keyword, recursive, patternMatch);
-    }
-
-    return nullptr;
+    return csearch(keyword, recursive, patternMatch).ptr();
 }
 
 
@@ -463,36 +266,7 @@ Foam::entry* Foam::dictionary::lookupEntryPtr
     bool patternMatch
 )
 {
-    auto iter = hashedEntries_.find(keyword);
-
-    if (iter.found())
-    {
-        return iter();
-    }
-
-    if (patternMatch && patterns_.size())
-    {
-        pattern_iterator wcLink = patterns_.begin();
-        regexp_iterator  reLink = regexps_.begin();
-
-        // Find in patterns using regular expressions only
-        if (findInPatterns(patternMatch, keyword, wcLink, reLink))
-        {
-            return wcLink();
-        }
-    }
-
-    if (recursive && &parent_ != &dictionary::null)
-    {
-        return const_cast<dictionary&>(parent_).lookupEntryPtr
-        (
-            keyword,
-            recursive,
-            patternMatch
-        );
-    }
-
-    return nullptr;
+    return search(keyword, recursive, patternMatch).ptr();
 }
 
 
@@ -503,9 +277,9 @@ const Foam::entry& Foam::dictionary::lookupEntry
     bool patternMatch
 ) const
 {
-    const entry* entryPtr = lookupEntryPtr(keyword, recursive, patternMatch);
+    auto finder = csearch(keyword, recursive, patternMatch);
 
-    if (entryPtr == nullptr)
+    if (!finder.found())
     {
         FatalIOErrorInFunction
         (
@@ -515,7 +289,7 @@ const Foam::entry& Foam::dictionary::lookupEntry
             << exit(FatalIOError);
     }
 
-    return *entryPtr;
+    return finder.ref();
 }
 
 
@@ -537,29 +311,37 @@ const Foam::entry* Foam::dictionary::lookupScopedEntryPtr
     bool patternMatch
 ) const
 {
-    if ((keyword[0] == ':' || keyword[0] == '^'))
+    return csearchScoped(keyword, recursive, patternMatch).ptr();
+}
+
+
+bool Foam::dictionary::substituteKeyword(const word& keyword, bool mergeEntry)
+{
+    if (keyword.size() < 2)
     {
-        // Go up to top level
-        const dictionary* dictPtr = this;
-        while (&dictPtr->parent_ != &dictionary::null)
+        return false;
+    }
+
+    // Drop leading '$' to get the var-name, already validated as word.
+    const word varName(keyword.substr(1), false);
+
+    // Lookup the variable name in the given dictionary
+    const_searcher finder = csearch(varName, true, true);
+
+    // If defined insert its entries into this dictionary
+    if (finder.found())
+    {
+        const dictionary& addDict = finder.dict();
+
+        forAllConstIters(addDict, iter)
         {
-            dictPtr = &dictPtr->parent_;
+            add(iter(), mergeEntry);
         }
 
-        return dictPtr->lookupScopedSubEntryPtr
-        (
-            keyword.substr(1),
-            false,
-            patternMatch
-        );
+        return true;
     }
 
-    return lookupScopedSubEntryPtr
-    (
-        keyword,
-        recursive,
-        patternMatch
-    );
+    return false;
 }
 
 
@@ -569,16 +351,21 @@ bool Foam::dictionary::substituteScopedKeyword
     bool mergeEntry
 )
 {
-    // Drop first character of keyword to get the var-name, already validated.
+    if (keyword.size() < 2)
+    {
+        return false;
+    }
+
+    // Drop leading '$' to get the var-name, already validated as word.
     const word varName(keyword.substr(1), false);
 
     // Lookup the variable name in the given dictionary
-    const entry* ePtr = lookupScopedEntryPtr(varName, true, true);
+    const_searcher finder = csearchScoped(varName, true, true);
 
     // If defined insert its entries into this dictionary
-    if (ePtr != nullptr)
+    if (finder.found())
     {
-        const dictionary& addDict = ePtr->dict();
+        const dictionary& addDict = finder.dict();
 
         forAllConstIter(parent_type, addDict, iter)
         {
@@ -595,54 +382,30 @@ bool Foam::dictionary::substituteScopedKeyword
 bool Foam::dictionary::isDict(const word& keyword) const
 {
     // Find non-recursive with patterns
-    const entry* entryPtr = lookupEntryPtr(keyword, false, true);
-
-    if (entryPtr)
-    {
-        return entryPtr->isDict();
-    }
-    else
-    {
-        return false;
-    }
+    return csearch(keyword, false, true).isDict();
 }
 
 
 const Foam::dictionary* Foam::dictionary::subDictPtr(const word& keyword) const
 {
-    const entry* entryPtr = lookupEntryPtr(keyword, false, true);
-
-    if (entryPtr)
-    {
-        return &entryPtr->dict();
-    }
-    else
-    {
-        return nullptr;
-    }
+    // Find non-recursive with patterns
+    return csearch(keyword, false, true).dictPtr();
 }
 
 
 Foam::dictionary* Foam::dictionary::subDictPtr(const word& keyword)
 {
-    entry* entryPtr = lookupEntryPtr(keyword, false, true);
-
-    if (entryPtr)
-    {
-        return &entryPtr->dict();
-    }
-    else
-    {
-        return nullptr;
-    }
+    // Find non-recursive with patterns
+    return search(keyword, false, true).dictPtr();
 }
 
 
 const Foam::dictionary& Foam::dictionary::subDict(const word& keyword) const
 {
-    const entry* entryPtr = lookupEntryPtr(keyword, false, true);
+    // Find non-recursive with patterns
+    auto finder = csearch(keyword, false, true);
 
-    if (entryPtr == nullptr)
+    if (!finder.found())
     {
         FatalIOErrorInFunction
         (
@@ -651,15 +414,17 @@ const Foam::dictionary& Foam::dictionary::subDict(const word& keyword) const
             << name()
             << exit(FatalIOError);
     }
-    return entryPtr->dict();
+
+    return finder.dict();
 }
 
 
 Foam::dictionary& Foam::dictionary::subDict(const word& keyword)
 {
-    entry* entryPtr = lookupEntryPtr(keyword, false, true);
+    // Find non-recursive with patterns
+    auto finder = search(keyword, false, true);
 
-    if (entryPtr == nullptr)
+    if (!finder.found())
     {
         FatalIOErrorInFunction
         (
@@ -668,7 +433,8 @@ Foam::dictionary& Foam::dictionary::subDict(const word& keyword)
             << name()
             << exit(FatalIOError);
     }
-    return entryPtr->dict();
+
+    return finder.dict();
 }
 
 
@@ -678,29 +444,35 @@ Foam::dictionary Foam::dictionary::subOrEmptyDict
     const bool mustRead
 ) const
 {
-    const entry* entryPtr = lookupEntryPtr(keyword, false, true);
+    // Find non-recursive with patterns
+    auto finder = csearch(keyword, false, true);
 
-    if (entryPtr == nullptr)
+    if (finder.isDict())
     {
-        if (mustRead)
-        {
-            FatalIOErrorInFunction
-            (
-                *this
-            )   << "keyword " << keyword << " is undefined in dictionary "
-                << name()
-                << exit(FatalIOError);
-            return entryPtr->dict();
-        }
-        else
-        {
-            return dictionary(*this, dictionary(name() + '.' + keyword));
-        }
+        // Found and a sub-dictionary
+        return finder.dict();
     }
-    else
+
+    if (mustRead)
     {
-        return entryPtr->dict();
+        FatalIOErrorInFunction
+        (
+            *this
+        )   << "keyword " << keyword
+            << " is not a sub-dictionary in dictionary "
+            << name()
+            << exit(FatalIOError);
     }
+
+    if (finder.found())
+    {
+        IOWarningInFunction((*this))
+            << "keyword " << keyword
+            << " found but not a sub-dictionary in dictionary "
+            << name() << endl;
+    }
+
+    return dictionary(*this, dictionary(name() + '.' + keyword));
 }
 
 
@@ -709,16 +481,23 @@ const Foam::dictionary& Foam::dictionary::optionalSubDict
     const word& keyword
 ) const
 {
-    const entry* entryPtr = lookupEntryPtr(keyword, false, true);
+    auto finder = csearch(keyword, false, true);
 
-    if (entryPtr)
+    if (finder.isDict())
     {
-        return entryPtr->dict();
+        // Found and a sub-dictionary
+        return finder.dict();
     }
-    else
+
+    if (finder.found())
     {
-        return *this;
+        IOWarningInFunction((*this))
+            << "keyword " << keyword
+            << " found but not a sub-dictionary in dictionary "
+            << name() << endl;
     }
+
+    return *this;
 }
 
 
@@ -726,10 +505,10 @@ Foam::wordList Foam::dictionary::toc() const
 {
     wordList keys(size());
 
-    label nKeys = 0;
-    forAllConstIter(parent_type, *this, iter)
+    label n = 0;
+    forAllConstIters(*this, iter)
     {
-        keys[nKeys++] = iter().keyword();
+        keys[n++] = iter().keyword();
     }
 
     return keys;
@@ -746,15 +525,15 @@ Foam::List<Foam::keyType> Foam::dictionary::keys(bool patterns) const
 {
     List<keyType> keys(size());
 
-    label nKeys = 0;
-    forAllConstIter(parent_type, *this, iter)
+    label n = 0;
+    forAllConstIters(*this, iter)
     {
         if (iter().keyword().isPattern() ? patterns : !patterns)
         {
-            keys[nKeys++] = iter().keyword();
+            keys[n++] = iter().keyword();
         }
     }
-    keys.setSize(nKeys);
+    keys.setSize(n);
 
     return keys;
 }
@@ -844,55 +623,55 @@ void Foam::dictionary::add(const entry& e, bool mergeEntry)
 }
 
 
-void Foam::dictionary::add(const keyType& k, const word& w, bool overwrite)
+void Foam::dictionary::add(const keyType& k, const word& v, bool overwrite)
 {
-    add(new primitiveEntry(k, token(w)), overwrite);
+    add(new primitiveEntry(k, token(v)), overwrite);
 }
 
 
 void Foam::dictionary::add
 (
     const keyType& k,
-    const Foam::string& s,
+    const Foam::string& v,
     bool overwrite
 )
 {
-    add(new primitiveEntry(k, token(s)), overwrite);
+    add(new primitiveEntry(k, token(v)), overwrite);
 }
 
 
-void Foam::dictionary::add(const keyType& k, const label l, bool overwrite)
+void Foam::dictionary::add(const keyType& k, const label v, bool overwrite)
 {
-    add(new primitiveEntry(k, token(l)), overwrite);
+    add(new primitiveEntry(k, token(v)), overwrite);
 }
 
 
-void Foam::dictionary::add(const keyType& k, const scalar s, bool overwrite)
+void Foam::dictionary::add(const keyType& k, const scalar v, bool overwrite)
 {
-    add(new primitiveEntry(k, token(s)), overwrite);
+    add(new primitiveEntry(k, token(v)), overwrite);
 }
 
 
 void Foam::dictionary::add
 (
     const keyType& k,
-    const dictionary& d,
+    const dictionary& v,
     bool mergeEntry
 )
 {
-    add(new dictionaryEntry(k, *this, d), mergeEntry);
+    add(new dictionaryEntry(k, *this, v), mergeEntry);
 }
 
 
 void Foam::dictionary::set(entry* entryPtr)
 {
     // Find non-recursive with patterns
-    entry* existingPtr = lookupEntryPtr(entryPtr->keyword(), false, true);
+    auto finder = search(entryPtr->keyword(), false, true);
 
     // Clear dictionary so merge acts like overwrite
-    if (existingPtr && existingPtr->isDict())
+    if (finder.isDict())
     {
-        existingPtr->dict().clear();
+        finder.dict().clear();
     }
     add(entryPtr, true);
 }
@@ -904,134 +683,14 @@ void Foam::dictionary::set(const entry& e)
 }
 
 
-void Foam::dictionary::set(const keyType& k, const dictionary& d)
-{
-    set(new dictionaryEntry(k, *this, d));
-}
-
-
-bool Foam::dictionary::remove(const word& keyword)
+void Foam::dictionary::set(const keyType& k, const dictionary& v)
 {
-    auto iter = hashedEntries_.find(keyword);
-
-    if (iter.found())
-    {
-        // Delete from patterns
-        pattern_iterator wcLink = patterns_.begin();
-        regexp_iterator  reLink = regexps_.begin();
-
-        // Find in pattern using exact match only
-        if (findInPatterns(false, keyword, wcLink, reLink))
-        {
-            patterns_.remove(wcLink);
-            regexps_.remove(reLink);
-        }
-
-        parent_type::remove(iter());
-        delete iter();
-        hashedEntries_.erase(iter);
-
-        return true;
-    }
-    else
-    {
-        return false;
-    }
-}
-
-
-bool Foam::dictionary::changeKeyword
-(
-    const keyType& oldKeyword,
-    const keyType& newKeyword,
-    bool forceOverwrite
-)
-{
-    // No change
-    if (oldKeyword == newKeyword)
-    {
-        return false;
-    }
-
-    // Check that oldKeyword exists and can be changed
-    auto iter = hashedEntries_.find(oldKeyword);
-
-    if (!iter.found())
-    {
-        return false;
-    }
-
-    if (iter()->keyword().isPattern())
-    {
-        FatalIOErrorInFunction
-        (
-            *this
-        )   << "Old keyword "<< oldKeyword
-            << " is a pattern."
-            << "Pattern replacement not yet implemented."
-            << exit(FatalIOError);
-    }
-
-
-    auto iter2 = hashedEntries_.find(newKeyword);
-
-    // newKeyword already exists
-    if (iter2.found())
-    {
-        if (forceOverwrite)
-        {
-            if (iter2()->keyword().isPattern())
-            {
-                // Delete from patterns
-                pattern_iterator wcLink = patterns_.begin();
-                regexp_iterator  reLink = regexps_.begin();
-
-                // Find in patterns using exact match only
-                if (findInPatterns(false, iter2()->keyword(), wcLink, reLink))
-                {
-                    patterns_.remove(wcLink);
-                    regexps_.remove(reLink);
-                }
-            }
-
-            parent_type::replace(iter2(), iter());
-            delete iter2();
-            hashedEntries_.erase(iter2);
-        }
-        else
-        {
-            IOWarningInFunction
-            (
-                *this
-            )   << "cannot rename keyword "<< oldKeyword
-                << " to existing keyword " << newKeyword
-                << " in dictionary " << name() << endl;
-            return false;
-        }
-    }
-
-    // Change name and HashTable, but leave DL-List untouched
-    iter()->keyword() = newKeyword;
-    iter()->name() = name() + '.' + newKeyword;
-    hashedEntries_.erase(oldKeyword);
-    hashedEntries_.insert(newKeyword, iter());
-
-    if (newKeyword.isPattern())
-    {
-        patterns_.insert(iter());
-        regexps_.insert
-        (
-            autoPtr<regExp>(new regExp(newKeyword))
-        );
-    }
-
-    return true;
+    set(new dictionaryEntry(k, *this, v));
 }
 
 
 bool Foam::dictionary::merge(const dictionary& dict)
 {
-    // Check for assignment to self
     if (this == &dict)
     {
         FatalIOErrorInFunction(*this)
@@ -1041,7 +700,7 @@ bool Foam::dictionary::merge(const dictionary& dict)
 
     bool changed = false;
 
-    forAllConstIter(parent_type, dict, iter)
+    forAllConstIters(dict, iter)
     {
         auto fnd = hashedEntries_.find(iter().keyword());
 
@@ -1112,7 +771,6 @@ Foam::ITstream& Foam::dictionary::operator[](const word& keyword) const
 
 void Foam::dictionary::operator=(const dictionary& rhs)
 {
-    // Check for assignment to self
     if (this == &rhs)
     {
         FatalIOErrorInFunction(*this)
@@ -1126,7 +784,7 @@ void Foam::dictionary::operator=(const dictionary& rhs)
     // Create clones of the entries in the given dictionary
     // resetting the parentDict to this dictionary
 
-    forAllConstIter(parent_type, rhs, iter)
+    forAllConstIters(rhs, iter)
     {
         add(iter().clone(*this).ptr());
     }
@@ -1135,7 +793,6 @@ void Foam::dictionary::operator=(const dictionary& rhs)
 
 void Foam::dictionary::operator+=(const dictionary& rhs)
 {
-    // Check for assignment to self
     if (this == &rhs)
     {
         FatalIOErrorInFunction(*this)
@@ -1143,7 +800,7 @@ void Foam::dictionary::operator+=(const dictionary& rhs)
             << abort(FatalIOError);
     }
 
-    forAllConstIter(parent_type, rhs, iter)
+    forAllConstIters(rhs, iter)
     {
         add(iter().clone(*this).ptr());
     }
@@ -1152,7 +809,6 @@ void Foam::dictionary::operator+=(const dictionary& rhs)
 
 void Foam::dictionary::operator|=(const dictionary& rhs)
 {
-    // Check for assignment to self
     if (this == &rhs)
     {
         FatalIOErrorInFunction(*this)
@@ -1160,7 +816,7 @@ void Foam::dictionary::operator|=(const dictionary& rhs)
             << abort(FatalIOError);
     }
 
-    forAllConstIter(parent_type, rhs, iter)
+    forAllConstIters(rhs, iter)
     {
         if (!found(iter().keyword()))
         {
@@ -1172,7 +828,6 @@ void Foam::dictionary::operator|=(const dictionary& rhs)
 
 void Foam::dictionary::operator<<=(const dictionary& rhs)
 {
-    // Check for assignment to self
     if (this == &rhs)
     {
         FatalIOErrorInFunction(*this)
@@ -1180,7 +835,7 @@ void Foam::dictionary::operator<<=(const dictionary& rhs)
             << abort(FatalIOError);
     }
 
-    forAllConstIter(parent_type, rhs, iter)
+    forAllConstIters(rhs, iter)
     {
         set(iter().clone(*this).ptr());
     }
diff --git a/src/OpenFOAM/db/dictionary/dictionary.H b/src/OpenFOAM/db/dictionary/dictionary.H
index f0c66b97a856272fdf046408ba576cc83b87f2fb..783c64365638e2c64d8bbd45083d9ee365d566d2 100644
--- a/src/OpenFOAM/db/dictionary/dictionary.H
+++ b/src/OpenFOAM/db/dictionary/dictionary.H
@@ -41,10 +41,13 @@ Description
 
 Note
     Within dictionaries, entries can be referenced by using the '$' syntax
-    familiar from shell programming. A '.' separator is used when referencing
-    sub-dictionary entries. Leading '.' prefixes can be used to specify
-    an entry from a parent directory. A leading ':' or '^' prefix specifies
-    starting from the top-level entry. For example,
+    familiar from shell programming.
+    A '.' separator is used when referencing sub-dictionary entries.
+    Leading '.' prefixes can be used to specify an entry from a parent
+    dictionary.
+    An initial '^' anchor (or ':' for backward compatibility) specifies
+    starting from the top-level entry.
+    For example,
 
     \verbatim
     key1        val1;
@@ -70,6 +73,7 @@ Note
 SourceFiles
     dictionary.C
     dictionaryIO.C
+    dictionarySearch.C
 
 SeeAlso
     - Foam::entry
@@ -89,6 +93,7 @@ SeeAlso
 #include "HashTable.H"
 #include "wordList.H"
 #include "className.H"
+#include <type_traits>
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
@@ -148,22 +153,20 @@ public:
         const word dictName() const
         {
             const word scopedName = name_.name();
-            const std::string::size_type i = scopedName.rfind('.');
+            const auto i = scopedName.rfind('.');
 
             if (i == std::string::npos)
             {
                 return scopedName;
             }
-            else
-            {
-                return scopedName.substr(i+1);
-            }
+
+            return scopedName.substr(i+1);
         }
 };
 
 
 /*---------------------------------------------------------------------------*\
-                           Class dictionary Declaration
+                         Class dictionary Declaration
 \*---------------------------------------------------------------------------*/
 
 class dictionary
@@ -171,15 +174,157 @@ class dictionary
     public dictionaryName,
     public IDLList<entry>
 {
+public:
+
+    // Searching
+
+        //- Generic const/non-const dictionary entry %searcher.
+        //  A %searcher provides a uniform means of finding and returning
+        //  an entry pointer as well as the dictionary \a context in which
+        //  the entry was located.
+        //
+        //  Note that the constructors and set methods are protected such
+        //  that only friends of the class can set things. This safeguards
+        //  against inconsistencies in context/entry.
+        template<bool Const>
+        class Searcher
+        {
+        public:
+            friend dictionary;
+
+            //- The const/non-const type for the context and sub-dictionaries
+            typedef typename std::conditional
+                <Const, const dictionary, dictionary>::type dict_type;
+
+            //- The const/non-const type for entries
+            typedef typename std::conditional
+                <Const, const entry, entry>::type value_type;
+
+            //- A pointer to a const/non-const dictionary
+            typedef dict_type* dict_pointer;
+
+            //- A reference to a const/non-const dictionary
+            typedef dict_type& dict_reference;
+
+            //- A pointer to a const/non-const entry
+            typedef value_type* pointer;
+
+            //- A reference to a const/non-const entry
+            typedef value_type& reference;
+
+
+        protected:
+
+            //- The dictionary context for the entry
+            dict_pointer dict_;
+
+            //- The entry or nullptr
+            pointer eptr_;
+
+
+            //- Construct null
+            Searcher()
+            :
+                dict_(nullptr),
+                eptr_(nullptr)
+            {}
+
+            //- Construct for the given dictionary context
+            Searcher(dict_pointer dict)
+            :
+                dict_(dict),
+                eptr_(nullptr)
+            {}
+
+            //- Assign the entry
+            void set(pointer eptr)
+            {
+                eptr_ = eptr;
+            }
+
+
+        public:
+
+            //- Entry was found.
+            inline bool found() const
+            {
+                return eptr_;
+            }
+
+            //- The containing dictionary context
+            inline dict_reference context() const
+            {
+                return *dict_;
+            }
+
+            //- A pointer to the entry (nullptr if not found)
+            inline pointer ptr() const
+            {
+                return eptr_;
+            }
+
+            //- A reference to the entry (Error if not found)
+            inline reference ref() const
+            {
+                return *eptr_;
+            }
+
+            //- True if found entry is a dictionary.
+            inline bool isDict() const
+            {
+                return eptr_ && eptr_->isDict();
+            }
+
+            //- Pointer to the found entry as a dictionary or nullptr otherwise.
+            inline dict_pointer dictPtr() const
+            {
+                return eptr_ && eptr_->isDict() ? eptr_->dictPtr() : nullptr;
+            }
+
+            //- Reference the found entry as a dictionary.
+            //  (Error if not found, or not a dictionary).
+            inline dict_reference dict() const
+            {
+                return eptr_->dict();
+            }
+
+            //- Permit an explicit cast to the other (const/non-const) searcher
+            inline explicit operator const Searcher<!Const>&() const
+            {
+                return *reinterpret_cast<const Searcher<!Const>*>(this);
+            }
+        };
+
+
+        //- Searcher with const access
+        typedef Searcher<true> const_searcher;
+
+        //- Searcher with non-const access
+        typedef Searcher<false> searcher;
+
+
+    // Friends
+
+        //- Declare friendship with the entry class for IO
+        friend class entry;
+
+        //- Declare friendship with the searcher classes
+        friend const_searcher;
+        friend searcher;
+
+
+private:
+
     // Private data
 
         //- Report optional keywords and values if not present in dictionary
+        //  Set/unset via an InfoSwitch
         static bool writeOptionalEntries;
 
         //- Parent dictionary
         const dictionary& parent_;
 
-        //- HashTable of the entries held on the IDLList for quick lookup
+        //- Quick lookup of the entries held on the IDLList
         HashTable<entry*> hashedEntries_;
 
         //- Entries of matching patterns
@@ -196,27 +341,48 @@ class dictionary
 
         typedef DLList<entry*>::iterator pattern_iterator;
         typedef DLList<entry*>::const_iterator pattern_const_iterator;
+
         typedef DLList<autoPtr<regExp>>::iterator regexp_iterator;
         typedef DLList<autoPtr<regExp>>::const_iterator regexp_const_iterator;
 
 
     // Private Member Functions
 
-        //- Find and return an entry data stream pointer if present
-        //  otherwise return nullptr. Allows scoping using '.'
-        const entry* lookupScopedSubEntryPtr
+        //- Search using a '.' for scoping.
+        //  A leading dot means to use the parent dictionary.
+        //  An intermediate dot separates a sub-dictionary or sub-entry.
+        //  However, the use of dots is unfortunately ambiguous.
+        //  The value "a.b.c.d" could be a first-level entry, a second-level
+        //  entry (eg, "a" with "b.c.d", "a.b" with "c.d" etc),
+        //  or just about any other combination.
+        //  The heuristic tries sucessively longer top-level entries
+        //  until there is a suitable match.
+        //
+        //  \param recursive search parent dictionaries
+        //  \param patternMatch use regular expressions
+        const_searcher csearchDotScoped
         (
             const word& keyword,
             bool recursive,
             bool patternMatch
         ) const;
 
+        //- Search using a '/' for scoping.
+        //  Semantics as per normal files: an intermediate "." is the current
+        //  dictionary level, an intermediate ".." is the parent dictionary.
+        //  Note that since a slash is not a valid word character, there is no
+        //  ambiguity between separator and content.
+        //  No possibility or need for recursion.
+        //
+        //  \param patternMatch use regular expressions
+        const_searcher csearchSlashScoped
+        (
+            const word& keyword,
+            bool patternMatch
+        ) const;
 
-public:
-
-    //- Declare friendship with the entry class for IO
-    friend class entry;
 
+public:
 
     // Declare name of the class and its debug switch
     ClassName("dictionary");
@@ -234,7 +400,7 @@ public:
         explicit dictionary(const fileName& name);
 
         //- Construct given the entry name, parent dictionary and Istream,
-        //  reading entries until lastEntry or EOF
+        //  reading entries until EOF
         dictionary
         (
             const fileName& name,
@@ -251,7 +417,7 @@ public:
         dictionary(Istream& is, const bool keepHeader);
 
         //- Construct as copy given the parent dictionary
-        dictionary(const dictionary& parentDict, const dictionary&);
+        dictionary(const dictionary& parentDict, const dictionary& dict);
 
         //- Construct top-level dictionary as copy
         dictionary(const dictionary& dict);
@@ -303,284 +469,413 @@ public:
         tokenList tokens() const;
 
 
-        // Search and lookup
-
-            //- Search dictionary for given keyword
-            //  If recursive, search parent dictionaries
-            //  If patternMatch, use regular expressions
-            bool found
-            (
-                const word& keyword,
-                bool recursive = false,
-                bool patternMatch = true
-            ) const;
-
-            //- Find and return an entry data stream pointer if present
-            //  otherwise return nullptr.
-            //  If recursive, search parent dictionaries.
-            //  If patternMatch, use regular expressions
-            const entry* lookupEntryPtr
-            (
-                const word& keyword,
-                bool recursive,
-                bool patternMatch
-            ) const;
-
-            //- Find and return an entry data stream pointer for manipulation
-            //  if present otherwise return nullptr.
-            //  If recursive, search parent dictionaries.
-            //  If patternMatch, use regular expressions.
-            entry* lookupEntryPtr
-            (
-                const word& keyword,
-                bool recursive,
-                bool patternMatch
-            );
-
-            //- Find and return an entry data stream if present otherwise error.
-            //  If recursive, search parent dictionaries.
-            //  If patternMatch, use regular expressions.
-            const entry& lookupEntry
-            (
-                const word& keyword,
-                bool recursive,
-                bool patternMatch
-            ) const;
-
-            //- Find and return an entry data stream
-            //  If recursive, search parent dictionaries.
-            //  If patternMatch, use regular expressions.
-            ITstream& lookup
-            (
-                const word& keyword,
-                bool recursive = false,
-                bool patternMatch = true
-            ) const;
-
-            //- Find and return a T,
-            //  if not found throw a fatal error.
-            //  If recursive, search parent dictionaries.
-            //  If patternMatch, use regular expressions.
-            template<class T>
-            T lookupType
-            (
-                const word&,
-                bool recursive=false,
-                bool patternMatch=true
-            ) const;
-
-            //- Find and return a T, or return the given default value
-            //  If recursive, search parent dictionaries.
-            //  If patternMatch, use regular expressions.
-            template<class T>
-            T lookupOrDefault
-            (
-                const word& keyword,
-                const T& deflt,
-                bool recursive = false,
-                bool patternMatch = true
-            ) const;
-
-            //- Find and return a T, if not found return the given
-            //  default value, and add to dictionary.
-            //  If recursive, search parent dictionaries.
-            //  If patternMatch, use regular expressions.
-            template<class T>
-            T lookupOrAddDefault
-            (
-                const word& keyword,
-                const T& deflt,
-                bool recursive = false,
-                bool patternMatch = true
-            );
-
-            //- Find an entry if present, and assign to T
-            //  Returns true if the entry was found.
-            //  If recursive, search parent dictionaries.
-            //  If patternMatch, use regular expressions.
-            template<class T>
-            bool readIfPresent
-            (
-                const word& keyword,
-                T& val,
-                bool recursive = false,
-                bool patternMatch = true
-            ) const;
-
-            //- Find and return an entry data stream pointer if present
-            //  otherwise return nullptr. Allows scoping using '.'.
-            //  Special handling for ':' at start of keyword and '..'.
-            const entry* lookupScopedEntryPtr
-            (
-                const word& keyword,
-                bool recursive,
-                bool patternMatch
-            ) const;
-
-            //- Check if entry is a sub-dictionary
-            bool isDict(const word& keyword) const;
-
-            //- Find and return a sub-dictionary pointer if present
-            //  otherwise return nullptr.
-            const dictionary* subDictPtr(const word& keyword) const;
-
-            //- Find and return a sub-dictionary pointer if present
-            //  otherwise return nullptr.
-            dictionary* subDictPtr(const word& keyword);
-
-            //- Find and return a sub-dictionary
-            const dictionary& subDict(const word& keyword) const;
-
-            //- Find and return a sub-dictionary for manipulation
-            dictionary& subDict(const word& keyword);
-
-            //- Find and return a sub-dictionary as a copy, or
-            //  return an empty dictionary if the sub-dictionary does not exist
-            dictionary subOrEmptyDict
-            (
-                const word& keyword,
-                const bool mustRead = false
-            ) const;
-
-            //- Find and return a sub-dictionary if found
-            //  otherwise return this dictionary
-            const dictionary& optionalSubDict(const word&) const;
-
-            //- Return the table of contents
-            wordList toc() const;
-
-            //- Return the sorted table of contents
-            wordList sortedToc() const;
-
-            //- Return table of contents sorted using the specified comparator
-            template<class Compare>
-            wordList sortedToc(const Compare& comp) const;
-
-            //- Return the list of available keys or patterns
-            List<keyType> keys(bool patterns = false) const;
-
-
-        // Editing
-
-            //- Substitute the given keyword prepended by '$' with the
-            //  corresponding sub-dictionary entries
-            bool substituteKeyword(const word& keyword, bool mergeEntry=false);
-
-            //- Substitute the given scoped keyword prepended by '$' with the
-            //  corresponding sub-dictionary entries
-            bool substituteScopedKeyword
-            (
-                const word& keyword,
-                bool mergeEntry=false
-            );
-
-            //- Add a new entry
-            //  With the merge option, dictionaries are interwoven and
-            //  primitive entries are overwritten
-            bool add(entry* entryPtr, bool mergeEntry=false);
-
-            //- Add an entry
-            //  With the merge option, dictionaries are interwoven and
-            //  primitive entries are overwritten
-            void add(const entry& e, bool mergeEntry=false);
-
-            //- Add a word entry
-            //  optionally overwrite an existing entry
-            void add(const keyType& k, const word& w, bool overwrite=false);
-
-            //- Add a string entry
-            //  optionally overwrite an existing entry
-            void add(const keyType& k, const string& s, bool overwrite=false);
+      // Search and lookup
 
-            //- Add a label entry
-            //  optionally overwrite an existing entry
-            void add(const keyType&, const label l, bool overwrite=false);
+        //- Search dictionary for given keyword
+        //  If recursive, search parent dictionaries
+        //  If patternMatch, use regular expressions
+        //  (default search: non-recursive with patterns).
+        bool found
+        (
+            const word& keyword,
+            bool recursive = false,
+            bool patternMatch = true
+        ) const;
 
-            //- Add a scalar entry
-            //  optionally overwrite an existing entry
-            void add(const keyType&, const scalar s, bool overwrite=false);
+        //- Find and return an entry data stream pointer if present
+        //  otherwise return nullptr.
+        //  If recursive, search parent dictionaries.
+        //  If patternMatch, use regular expressions
+        const entry* lookupEntryPtr
+        (
+            const word& keyword,
+            bool recursive,
+            bool patternMatch
+        ) const;
 
-            //- Add a dictionary entry
-            //  optionally merge with an existing sub-dictionary
-            void add
-            (
-                const keyType& k,
-                const dictionary& d,
-                bool mergeEntry = false
-            );
+        //- Find and return an entry data stream pointer for manipulation
+        //  if present otherwise return nullptr.
+        //  If recursive, search parent dictionaries.
+        //  If patternMatch, use regular expressions.
+        entry* lookupEntryPtr
+        (
+            const word& keyword,
+            bool recursive,
+            bool patternMatch
+        );
 
-            //- Add a T entry
-            //  optionally overwrite an existing entry
-            template<class T>
-            void add(const keyType& k, const T& t, bool overwrite=false);
+        //- Find and return an entry data stream if present otherwise error.
+        //  If recursive, search parent dictionaries.
+        //  If patternMatch, use regular expressions.
+        const entry& lookupEntry
+        (
+            const word& keyword,
+            bool recursive,
+            bool patternMatch
+        ) const;
 
-            //- Assign a new entry, overwrite any existing entry
-            void set(entry* entryPtr);
+        //- Find and return an entry data stream
+        //  If recursive, search parent dictionaries.
+        //  If patternMatch, use regular expressions.
+        //  (default search: non-recursive with patterns).
+        ITstream& lookup
+        (
+            const word& keyword,
+            bool recursive = false,
+            bool patternMatch = true
+        ) const;
 
-            //- Assign a new entry, overwrite any existing entry
-            void set(const entry& e);
+        //- Find and return a T,
+        //  if not found throw a fatal error.
+        //  If recursive, search parent dictionaries.
+        //  If patternMatch, use regular expressions.
+        //  (default search: non-recursive with patterns).
+        template<class T>
+        T lookupType
+        (
+            const word& keyword,
+            bool recursive = false,
+            bool patternMatch = true
+        ) const;
+
+        //- Find and return a T, or return the given default value
+        //  If recursive, search parent dictionaries.
+        //  If patternMatch, use regular expressions.
+        //  (default search: non-recursive with patterns).
+        template<class T>
+        T lookupOrDefault
+        (
+            const word& keyword,
+            const T& deflt,
+            bool recursive = false,
+            bool patternMatch = true
+        ) const;
+
+        //- Find and return a T, if not found return the default value
+        //  and add it to dictionary.
+        //  Default search: non-recursive with patterns.
+        //
+        //  \param recursive search parent dictionaries
+        //  \param patternMatch use regular expressions
+        template<class T>
+        T lookupOrAddDefault
+        (
+            const word& keyword,
+            const T& deflt,
+            bool recursive = false,
+            bool patternMatch = true
+        );
+
+        //- Find an entry if present, and assign to T val.
+        //  Default search: non-recursive with patterns.
+        //
+        //  \param val the value to read
+        //  \param recursive search parent dictionaries
+        //  \param patternMatch use regular expressions
+        //
+        //  \return true if the entry was found.
+        template<class T>
+        bool readIfPresent
+        (
+            const word& keyword,
+            T& val,
+            bool recursive = false,
+            bool patternMatch = true
+        ) const;
+
+        //- Find and return an entry pointer if present, or return a nullptr.
+        //  Allows scoping using '.'.
+        //  Special handling for an absolute anchor (^) at start of the keyword
+        //  and for '..' to ascend into the parent dictionaries.
+        //
+        //  \param recursive search parent dictionaries
+        //  \param patternMatch use regular expressions
+        const entry* lookupScopedEntryPtr
+        (
+            const word& keyword,
+            bool recursive,
+            bool patternMatch
+        ) const;
+
+        //- Check if entry exists and is a sub-dictionary.
+        //  (search type: non-recursive with patterns)
+        bool isDict(const word& keyword) const;
+
+        //- Find and return a sub-dictionary pointer if present
+        //  (and a sub-dictionary) otherwise return nullptr.
+        //  (search type: non-recursive with patterns)
+        const dictionary* subDictPtr(const word& keyword) const;
+
+        //- Find and return a sub-dictionary pointer if present
+        //  (and a sub-dictionary) otherwise return nullptr.
+        //
+        //  Search type: non-recursive with patterns.
+        dictionary* subDictPtr(const word& keyword);
+
+        //- Find and return a sub-dictionary.
+        //  Fatal if the entry does not exist or is not a sub-dictionary.
+        //  (search type: non-recursive with patterns)
+        const dictionary& subDict(const word& keyword) const;
+
+        //- Find and return a sub-dictionary for manipulation.
+        //  Fatal if the entry does not exist or is not a sub-dictionary.
+        //  (search type: non-recursive with patterns)
+        dictionary& subDict(const word& keyword);
+
+        //- Find and return a sub-dictionary as a copy, otherwise return
+        //  an empty dictionary.
+        //  Warn if the entry exists but is not a sub-dictionary.
+        //  (search type: non-recursive with patterns)
+        dictionary subOrEmptyDict
+        (
+            const word& keyword,
+            const bool mustRead = false
+        ) const;
+
+        //- Find and return a sub-dictionary, otherwise return this dictionary.
+        //  Warn if the entry exists but is not a sub-dictionary.
+        //  (search type: non-recursive with patterns)
+        const dictionary& optionalSubDict(const word& keyword) const;
+
+        //- Return the table of contents
+        wordList toc() const;
+
+        //- Return the sorted table of contents
+        wordList sortedToc() const;
+
+        //- Return table of contents sorted using the specified comparator
+        template<class Compare>
+        wordList sortedToc(const Compare& comp) const;
+
+        //- Return the list of available keys or patterns
+        List<keyType> keys(bool patterns = false) const;
+
+
+      // Editing
+
+        //- Substitute the given keyword (which is prefixed by '$')
+        //  with the corresponding sub-dictionary entries
+        bool substituteKeyword
+        (
+            const word& keyword,
+            bool mergeEntry = false
+        );
+
+        //- Substitute the given scoped keyword (which is prefixed by '$')
+        //  with the corresponding sub-dictionary entries
+        bool substituteScopedKeyword
+        (
+            const word& keyword,
+            bool mergeEntry = false
+        );
+
+        //- Add a new entry
+        //  With the merge option, dictionaries are interwoven and
+        //  primitive entries are overwritten
+        bool add(entry* entryPtr, bool mergeEntry=false);
+
+        //- Add an entry
+        //  With the merge option, dictionaries are interwoven and
+        //  primitive entries are overwritten
+        void add(const entry& e, bool mergeEntry=false);
+
+        //- Add a word entry
+        //  optionally overwrite an existing entry
+        void add(const keyType& k, const word& v, bool overwrite=false);
+
+        //- Add a string entry
+        //  optionally overwrite an existing entry
+        void add(const keyType& k, const string& v, bool overwrite=false);
+
+        //- Add a label entry
+        //  optionally overwrite an existing entry
+        void add(const keyType& k, const label v, bool overwrite=false);
+
+        //- Add a scalar entry
+        //  optionally overwrite an existing entry
+        void add(const keyType& k, const scalar v, bool overwrite=false);
 
-            //- Assign a dictionary entry, overwrite any existing entry
-            void set(const keyType& k, const dictionary& d);
+        //- Add a dictionary entry
+        //  optionally merge with an existing sub-dictionary
+        void add
+        (
+            const keyType& k,
+            const dictionary& d,
+            bool mergeEntry = false
+        );
+
+        //- Add a T entry
+        //  optionally overwrite an existing entry
+        template<class T>
+        void add(const keyType& k, const T& v, bool overwrite=false);
+
+        //- Assign a new entry, overwrite any existing entry
+        void set(entry* entryPtr);
+
+        //- Assign a new entry, overwrite any existing entry
+        void set(const entry& e);
+
+        //- Assign a dictionary entry, overwrite any existing entry
+        void set(const keyType& k, const dictionary& v);
 
-            //- Assign a T entry, overwrite any existing entry
-            template<class T>
-            void set(const keyType& k, const T& t);
+        //- Assign a T entry, overwrite any existing entry
+        template<class T>
+        void set(const keyType& k, const T& v);
 
-            //- Remove an entry specified by keyword
-            bool remove(const word& Keyword);
+        //- Remove an entry specified by keyword
+        bool remove(const word& keyword);
 
-            //- Change the keyword for an entry,
-            //  optionally forcing overwrite of an existing entry
-            bool changeKeyword
-            (
-                const keyType& oldKeyword,
-                const keyType& newKeyword,
-                bool forceOverwrite=false
-            );
+        //- Change the keyword for an entry,
+        //  optionally forcing overwrite of an existing entry
+        bool changeKeyword
+        (
+            const keyType& oldKeyword,
+            const keyType& newKeyword,
+            bool forceOverwrite=false
+        );
+
+        //- Merge entries from the given dictionary.
+        //  Also merge sub-dictionaries as required.
+        bool merge(const dictionary& dict);
 
-            //- Merge entries from the given dictionary.
-            //  Also merge sub-dictionaries as required.
-            bool merge(const dictionary& dict);
+        //- Clear the dictionary
+        void clear();
 
-            //- Clear the dictionary
-            void clear();
+        //- Transfer the contents of the argument and annul the argument.
+        void transfer(dictionary& dict);
 
-            //- Transfer the contents of the argument and annul the argument.
-            void transfer(dictionary& dict);
+        //- Transfer contents to the Xfer container
+        Xfer<dictionary> xfer();
 
-            //- Transfer contents to the Xfer container
-            Xfer<dictionary> xfer();
 
+      // Read
+
+        //- Read dictionary from Istream
+        bool read(Istream& is);
+
+        //- Read dictionary from Istream, optionally keeping the header
+        bool read(Istream& is, const bool keepHeader);
 
-        // Read
 
-            //- Read dictionary from Istream
-            bool read(Istream& is);
+      // Write
 
-            //- Read dictionary from Istream, optionally keeping the header
-            bool read(Istream& is, const bool keepHeader);
+        //- Write sub-dictionary with the keyword as its header
+        void writeEntry(const keyType& keyword, Ostream& os) const;
 
+        //- Write dictionary entries.
+        //  Optionally with extra new line between entries for
+        //  "top-level" dictionaries
+        void writeEntries(Ostream& os, const bool extraNewLine=false) const;
+
+        //- Write dictionary, normally with sub-dictionary formatting
+        void write(Ostream& os, const bool subDict=true) const;
+
+
+      // Searching
+
+        //- Search dictionary for given keyword
+        //  If recursive, search parent dictionaries
+        //  If patternMatch, use regular expressions
+        //  (default search: non-recursive with patterns).
+        const_searcher csearch
+        (
+            const word& keyword,
+            bool recursive = false,
+            bool patternMatch = true
+        ) const;
+
+        //- Search dictionary for given keyword
+        //  If recursive, search parent dictionaries
+        //  If patternMatch, use regular expressions
+        //  (default search: non-recursive with patterns).
+        const_searcher search
+        (
+            const word& keyword,
+            bool recursive = false,
+            bool patternMatch = true
+        ) const;
+
+        //- Search dictionary for given keyword
+        //  If recursive, search parent dictionaries
+        //  If patternMatch, use regular expressions
+        //  (default search: non-recursive with patterns).
+        searcher search
+        (
+            const word& keyword,
+            bool recursive = false,
+            bool patternMatch = true
+        );
+
+        //- Search using scoping.
+        //  There are two types of scoping available:
+        //  -# dot-scoping, where a '.' is used to delineate the scope
+        //  -# slash-scoping, where a '/' is used to delineate the scope
+        //
+        //  For dot-scoping, a leading '^' traverses to the top-level
+        //  dictionary, leading dots mean use the parent dictionary and an
+        //  intermediate dot separates a sub-dictionary or sub-entry.
+        //  However, since the use of dots is ambiguous ("a.b.c" could be
+        //  an entry itself or represent a "bc" entry from dictionary "a" etc),
+        //  the heuristic backtracks and attempts successively longer
+        //  top-level entries until a suitable match is found.
+        //
+        //  For slash-scoping, semantics similar to directory structures are
+        //  used. A leading '/' traverses to the top-level dictionary,
+        //  a single leading or intermediate '.' references the current
+        //  dictionary level. A '..' pair references the parent dictionary.
+        //  Any doubled slashes are silently ignored.
+        //  Since a slash is not a valid keyword character, there is no
+        //  ambiguity between separator and content.
+        const_searcher csearchScoped
+        (
+            const word& keyword,
+            bool recursive,
+            bool patternMatch
+        ) const;
+
+        //- Search using dot or slash scoping.
+        const_searcher searchScoped
+        (
+            const word& keyword,
+            bool recursive,
+            bool patternMatch
+        ) const;
+
+        //- Search using dot or slash scoping.
+        searcher searchScoped
+        (
+            const word& keyword,
+            bool recursive,
+            bool patternMatch
+        );
 
-        // Write
+        //- Locate a sub-dictionary using slash-scoping
+        //  \return nullptr if the dictionary path does not exist
+        const dictionary* cfindScopedDictPtr(const fileName& dictPath) const;
 
-            //- Write sub-dictionary with the keyword as its header
-            void writeEntry(const keyType& keyword, Ostream& os) const;
+        //- Locate a sub-dictionary using slash-scoping
+        //  \return nullptr if the dictionary path does not exist
+        const dictionary* findScopedDictPtr(const fileName& dictPath) const;
 
-            //- Write dictionary entries.
-            //  Optionally with extra new line between entries for
-            //  "top-level" dictionaries
-            void writeEntries(Ostream& os, const bool extraNewLine=false) const;
+        //- Locate a sub-dictionary using slash-scoping
+        //  \return nullptr if the dictionary path does not exist
+        dictionary* findScopedDictPtr(const fileName& dictPath);
 
-            //- Write dictionary, normally with sub-dictionary formatting
-            void write(Ostream& os, const bool subDict=true) const;
+        //- Locate existing or create sub-dictionary using slash-scoping
+        //  \return nullptr if the dictionary path could not be created
+        dictionary* makeScopedDictPtr(const fileName& dictPath);
 
 
     // Member Operators
 
-        //- Find and return entry
+        //- Find and return an entry data stream (identical to #lookup method).
+        //  Default search: non-recursive with patterns.
+        //
+        //  \param recursive search parent dictionaries
+        //  \param patternMatch use regular expressions
         ITstream& operator[](const word& keyword) const;
 
+        //- Copy assignment
         void operator=(const dictionary& rhs);
 
         //- Include entries from the given dictionary.
diff --git a/src/OpenFOAM/db/dictionary/dictionaryIO.C b/src/OpenFOAM/db/dictionary/dictionaryIO.C
index ddc505c661e8df646e8b50f21b98d19973156d97..9c1e36c1b525285374c613e9e21ab10f605ff134 100644
--- a/src/OpenFOAM/db/dictionary/dictionaryIO.C
+++ b/src/OpenFOAM/db/dictionary/dictionaryIO.C
@@ -128,30 +128,6 @@ bool Foam::dictionary::read(Istream& is)
 }
 
 
-bool Foam::dictionary::substituteKeyword(const word& keyword, bool mergeEntry)
-{
-    const word varName = keyword.substr(1);
-
-    // Lookup the variable name in the given dictionary
-    const entry* ePtr = lookupEntryPtr(varName, true, true);
-
-    // If defined insert its entries into this dictionary
-    if (ePtr != nullptr)
-    {
-        const dictionary& addDict = ePtr->dict();
-
-        forAllConstIter(parent_type, addDict, iter)
-        {
-            add(iter(), mergeEntry);
-        }
-
-        return true;
-    }
-
-    return false;
-}
-
-
 // * * * * * * * * * * * * * * Istream Operator  * * * * * * * * * * * * * * //
 
 Foam::Istream& Foam::operator>>(Istream& is, dictionary& dict)
diff --git a/src/OpenFOAM/db/dictionary/dictionarySearch.C b/src/OpenFOAM/db/dictionary/dictionarySearch.C
new file mode 100644
index 0000000000000000000000000000000000000000..93c5bcb884a3675433e63463d55be25bf9a417ee
--- /dev/null
+++ b/src/OpenFOAM/db/dictionary/dictionarySearch.C
@@ -0,0 +1,719 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2017 OpenCFD Ltd.
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "dictionary.H"
+#include "dictionaryEntry.H"
+#include "stringOps.H"
+
+/* * * * * * * * * * * * * * * Static Member Data  * * * * * * * * * * * * * */
+
+namespace Foam
+{
+    // file-scope
+    //- Walk lists of patterns and regexps for an exact match
+    //  or regular expression match
+    template<class WcIterator, class ReIterator>
+    static bool findInPatterns
+    (
+        const bool patternMatch,
+        const word& keyword,
+        WcIterator& wcIter,
+        ReIterator& reIter
+    )
+    {
+        while (wcIter.found())
+        {
+            if
+            (
+                patternMatch
+              ? reIter()->match(keyword)
+              : wcIter()->keyword() == keyword
+            )
+            {
+                return true;
+            }
+
+            ++reIter;
+            ++wcIter;
+        }
+
+        return false;
+    }
+}
+
+
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+Foam::dictionary::const_searcher Foam::dictionary::csearchDotScoped
+(
+    const word& keyword,
+    bool recursive,
+    bool patternMatch
+) const
+{
+    std::string::size_type scopePos = keyword.find('.');
+
+    if (scopePos == string::npos)
+    {
+        // Normal, non-scoped search
+        return csearch(keyword, recursive, patternMatch);
+    }
+
+    if (scopePos == 0)
+    {
+        // Starting with a '.' -> go up for every further '.' found
+        ++scopePos;
+
+        const dictionary* dictPtr = this;
+        for
+        (
+            string::const_iterator it = keyword.begin()+1;
+            it != keyword.end() && *it == '.';
+            ++scopePos, ++it
+        )
+        {
+            // Go to parent
+            if (&dictPtr->parent_ != &dictionary::null)
+            {
+                dictPtr = &dictPtr->parent_;
+            }
+            else
+            {
+                FatalIOErrorInFunction
+                (
+                    *this
+                )   << "No parent of current dictionary when searching for "
+                    << keyword.substr(1)
+                    << exit(FatalIOError);
+
+                return nullptr;
+            }
+        }
+
+        return dictPtr->csearchDotScoped
+        (
+            keyword.substr(scopePos),
+            false,
+            patternMatch
+        );
+    }
+
+    // The first word
+    const_searcher finder = csearchDotScoped
+    (
+        keyword.substr(0, scopePos),
+        false,
+        patternMatch
+    );
+
+    // Fall back to finding key with '.' so e.g. if keyword is
+    // a.b.c.d it would try
+    // a.b, a.b.c, a.b.c.d
+
+    if (!finder.found())
+    {
+        while (!finder.isDict())
+        {
+            scopePos = keyword.find('.', scopePos+1);
+
+            // Local entry:
+            finder = csearch(keyword.substr(0, scopePos), false, patternMatch);
+
+            if (scopePos == string::npos)
+            {
+                // Parsed the whole word. Return entry or null.
+                return finder;
+            }
+        }
+    }
+
+    if (finder.isDict())
+    {
+        return finder.dict().csearchDotScoped
+        (
+            keyword.substr(scopePos),
+            false,
+            patternMatch
+        );
+    }
+
+    return finder;
+}
+
+
+Foam::dictionary::const_searcher Foam::dictionary::csearchSlashScoped
+(
+    const word& keyword,
+    bool patternMatch
+) const
+{
+    const dictionary* dictPtr = this;
+
+    const auto slash = keyword.find('/');
+
+    if (slash == string::npos)
+    {
+        // No slashes:
+        // Can use normal (non-scoped) search at the current dictionary level
+        return csearch(keyword, false, patternMatch);
+    }
+    else if (slash == 0)
+    {
+        // (isAbsolute)
+        // Ascend to top-level
+        while (&dictPtr->parent_ != &dictionary::null)
+        {
+            dictPtr = &dictPtr->parent_;
+        }
+    }
+
+    // Split on '/'
+    auto cmpts = stringOps::split<std::string>(keyword, '/');
+    auto remaining = cmpts.size();
+
+    for (const auto& cmpt : cmpts)
+    {
+        --remaining; // Decrement now so we can check (remaining == 0)
+
+        if (cmpt == ".")
+        {
+            // "." - ignore
+        }
+        else if (cmpt == "..")
+        {
+            // ".." - go to parent
+            if (&dictPtr->parent_ != &dictionary::null)
+            {
+                dictPtr = &dictPtr->parent_;
+            }
+            else
+            {
+                FatalIOErrorInFunction
+                (
+                    *dictPtr
+                )   << "No parent of current dictionary when searching for "
+                    << keyword << " at " << cmpt
+                    << exit(FatalIOError);
+                break;
+            }
+        }
+        else
+        {
+            // Find entry
+            const word key = word::validate(cmpt);
+
+            auto finder = dictPtr->csearch(key, false, patternMatch);
+
+            if (finder.found())
+            {
+                if (remaining)
+                {
+                    // Intermediate must be a dictionary
+                    if (finder.isDict())
+                    {
+                        dictPtr = finder.dictPtr();
+                    }
+                    else
+                    {
+                        return const_searcher(dictPtr);
+                    }
+                }
+                else
+                {
+                    // Last entry - done
+                    return finder;
+                }
+            }
+            else
+            {
+                break;
+            }
+        }
+    }
+
+    // Failed at this dictionary level
+    return const_searcher(dictPtr);
+}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+Foam::dictionary::const_searcher Foam::dictionary::csearch
+(
+    const word& keyword,
+    bool recursive,
+    bool patternMatch
+) const
+{
+    const_searcher finder(this);
+
+    auto iter = hashedEntries_.cfind(keyword);
+
+    if (iter.found())
+    {
+        finder.set(iter.object());
+        return finder;
+    }
+
+    if (patternMatch && patterns_.size())
+    {
+        pattern_const_iterator wcLink = patterns_.begin();
+        regexp_const_iterator  reLink = regexps_.begin();
+
+        // Find in patterns using regular expressions only
+        if (findInPatterns(patternMatch, keyword, wcLink, reLink))
+        {
+            finder.set(*wcLink);
+            return finder;
+        }
+    }
+
+    if (recursive && &parent_ != &dictionary::null)
+    {
+        return parent_.csearch
+        (
+            keyword,
+            recursive,
+            patternMatch
+        );
+    }
+
+    return finder;
+}
+
+
+Foam::dictionary::const_searcher Foam::dictionary::search
+(
+    const word& keyword,
+    bool recursive,
+    bool patternMatch
+) const
+{
+    return csearch(keyword, recursive, patternMatch);
+}
+
+
+Foam::dictionary::searcher Foam::dictionary::search
+(
+    const word& keyword,
+    bool recursive,
+    bool patternMatch
+)
+{
+    const_searcher finder = csearch(keyword, recursive, patternMatch);
+
+    return static_cast<const searcher&>(finder);
+}
+
+
+Foam::dictionary::const_searcher Foam::dictionary::csearchScoped
+(
+    const word& keyword,
+    bool recursive,
+    bool patternMatch
+) const
+{
+    if (keyword.find('/') != string::npos)
+    {
+        return csearchSlashScoped(keyword, patternMatch);
+    }
+
+    if (keyword[0] == ':' || keyword[0] == '^')
+    {
+        // Ascend to top-level
+        const dictionary* dictPtr = this;
+        while (&dictPtr->parent_ != &dictionary::null)
+        {
+            dictPtr = &dictPtr->parent_;
+        }
+
+        return dictPtr->csearchDotScoped
+        (
+            keyword.substr(1),
+            false,
+            patternMatch
+        );
+    }
+
+    return csearchDotScoped(keyword, recursive, patternMatch);
+}
+
+
+Foam::dictionary::const_searcher Foam::dictionary::searchScoped
+(
+    const word& keyword,
+    bool recursive,
+    bool patternMatch
+) const
+{
+    return csearchScoped(keyword, recursive, patternMatch);
+}
+
+
+Foam::dictionary::searcher Foam::dictionary::searchScoped
+(
+    const word& keyword,
+    bool recursive,
+    bool patternMatch
+)
+{
+    const_searcher finder = csearchScoped(keyword, recursive, patternMatch);
+
+    return static_cast<const searcher&>(finder);
+}
+
+
+const Foam::dictionary* Foam::dictionary::cfindScopedDictPtr
+(
+    const fileName& dictPath
+) const
+{
+    // Or warning
+    if (dictPath.empty())
+    {
+        return nullptr;
+    }
+
+    const dictionary* dictPtr = this;
+    if (fileName::isAbsolute(dictPath))
+    {
+        // Ascend to top-level
+        while (&dictPtr->parent_ != &dictionary::null)
+        {
+            dictPtr = &dictPtr->parent_;
+        }
+    }
+
+    fileName path = dictPath.clean();
+    const wordList cmpts = path.components();
+
+    for (const word& cmpt : cmpts)
+    {
+        if (cmpt == ".")
+        {
+            // "." - ignore
+        }
+        else if (cmpt == "..")
+        {
+            // ".." - go to parent
+            if (&dictPtr->parent_ != &dictionary::null)
+            {
+                dictPtr = &dictPtr->parent_;
+            }
+            else
+            {
+                FatalIOErrorInFunction
+                (
+                    *dictPtr
+                )   << "No parent for dictionary while searching "
+                    << path
+                    << exit(FatalIOError);
+
+                return nullptr;
+            }
+        }
+        else
+        {
+            // Non-recursive, no patternMatch
+            // -> can do direct lookup, without csearch(cmpt, false, false);
+
+            auto iter = dictPtr->hashedEntries_.cfind(cmpt);
+
+            if (iter.found())
+            {
+                const entry *eptr = iter.object();
+
+                if (eptr->isDict())
+                {
+                    dictPtr = eptr->dictPtr();
+                }
+                else
+                {
+                    FatalIOErrorInFunction
+                    (
+                        *dictPtr
+                    )   << "Found entry '" << cmpt
+                        << "' but not a dictionary, while searching scoped"
+                        << nl
+                        << "    " << path
+                        << exit(FatalIOError);
+
+                    return nullptr;
+                }
+            }
+            else
+            {
+                return nullptr;
+            }
+        }
+    }
+
+    return dictPtr;
+}
+
+
+const Foam::dictionary* Foam::dictionary::findScopedDictPtr
+(
+    const fileName& dictPath
+) const
+{
+    return cfindScopedDictPtr(dictPath);
+}
+
+
+Foam::dictionary* Foam::dictionary::findScopedDictPtr
+(
+    const fileName& dictPath
+)
+{
+    const dictionary* ptr = cfindScopedDictPtr(dictPath);
+    return const_cast<dictionary*>(ptr);
+}
+
+
+Foam::dictionary* Foam::dictionary::makeScopedDictPtr(const fileName& dictPath)
+{
+    // Or warning
+    if (dictPath.empty())
+    {
+        return nullptr;
+    }
+
+    dictionary* dictPtr = this;
+    if (fileName::isAbsolute(dictPath))
+    {
+        // Ascend to top-level
+        while (&dictPtr->parent_ != &dictionary::null)
+        {
+            dictPtr = const_cast<dictionary*>(&dictPtr->parent_);
+        }
+    }
+
+    // Work on a copy, without any assumptions
+    std::string path = dictPath;
+    fileName::clean(path);
+
+    // Split on '/'
+    auto cmpts = stringOps::split(path, '/');
+
+    for (const auto& cmpt : cmpts)
+    {
+        if (cmpt == ".")
+        {
+            // "." - ignore
+        }
+        else if (cmpt == "..")
+        {
+            // ".." - go to parent
+            if (&dictPtr->parent_ != &dictionary::null)
+            {
+                dictPtr = const_cast<dictionary*>(&dictPtr->parent_);
+            }
+            else
+            {
+                FatalIOErrorInFunction
+                (
+                    *dictPtr
+                )   << "No parent for dictionary while searching "
+                    << path
+                    << exit(FatalIOError);
+
+                return nullptr;
+            }
+        }
+        else
+        {
+            // Non-recursive, no patternMatch
+            // -> can do direct lookup, without csearch(cmptName, false, false);
+            const word cmptName(cmpt.str(), false);
+
+            auto iter = dictPtr->hashedEntries_.find(cmptName);
+
+            if (iter.found())
+            {
+                entry *eptr = iter.object();
+
+                if (eptr->isDict())
+                {
+                    dictPtr = eptr->dictPtr();
+                }
+                else
+                {
+                    FatalIOErrorInFunction
+                    (
+                        *dictPtr
+                    )   << "Cannot create sub-dictionary entry '" << cmptName
+                        << "' - a non-dictionary entry is in the way"
+                        << nl << "Encountered in scope" << nl
+                        << "    " << path
+                        << exit(FatalIOError);
+
+                    return nullptr;
+                }
+            }
+            else
+            {
+                dictionaryEntry *eptr =
+                    new dictionaryEntry(cmptName, *dictPtr, dictionary());
+
+                // Add *without* merging, since we just checked that the entry
+                // doesn't exist and to ensure that the pointer remains valid.
+
+                if (dictPtr->add(eptr, false))  // NO merge
+                {
+                    dictPtr = eptr;
+                }
+                else
+                {
+                    return nullptr;
+                }
+            }
+        }
+    }
+
+    return dictPtr;
+}
+
+
+bool Foam::dictionary::remove(const word& keyword)
+{
+    auto iter = hashedEntries_.find(keyword);
+
+    if (iter.found())
+    {
+        // Delete from patterns
+        pattern_iterator wcLink = patterns_.begin();
+        regexp_iterator  reLink = regexps_.begin();
+
+        // Find in pattern using exact match only
+        if (findInPatterns(false, keyword, wcLink, reLink))
+        {
+            patterns_.remove(wcLink);
+            regexps_.remove(reLink);
+        }
+
+        parent_type::remove(iter());
+        delete iter();
+        hashedEntries_.erase(iter);
+
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+
+
+bool Foam::dictionary::changeKeyword
+(
+    const keyType& oldKeyword,
+    const keyType& newKeyword,
+    bool forceOverwrite
+)
+{
+    // No change
+    if (oldKeyword == newKeyword)
+    {
+        return false;
+    }
+
+    // Check that oldKeyword exists and can be changed
+    auto iter = hashedEntries_.find(oldKeyword);
+
+    if (!iter.found())
+    {
+        return false;
+    }
+
+    if (iter()->keyword().isPattern())
+    {
+        FatalIOErrorInFunction
+        (
+            *this
+        )   << "Old keyword "<< oldKeyword
+            << " is a pattern."
+            << "Pattern replacement not yet implemented."
+            << exit(FatalIOError);
+    }
+
+
+    auto iter2 = hashedEntries_.find(newKeyword);
+
+    // newKeyword already exists
+    if (iter2.found())
+    {
+        if (forceOverwrite)
+        {
+            if (iter2()->keyword().isPattern())
+            {
+                // Delete from patterns
+                pattern_iterator wcLink = patterns_.begin();
+                regexp_iterator  reLink = regexps_.begin();
+
+                // Find in patterns using exact match only
+                if (findInPatterns(false, iter2()->keyword(), wcLink, reLink))
+                {
+                    patterns_.remove(wcLink);
+                    regexps_.remove(reLink);
+                }
+            }
+
+            parent_type::replace(iter2(), iter());
+            delete iter2();
+            hashedEntries_.erase(iter2);
+        }
+        else
+        {
+            IOWarningInFunction
+            (
+                *this
+            )   << "cannot rename keyword "<< oldKeyword
+                << " to existing keyword " << newKeyword
+                << " in dictionary " << name() << endl;
+            return false;
+        }
+    }
+
+    // Change name and HashTable, but leave DL-List untouched
+    iter()->keyword() = newKeyword;
+    iter()->name() = name() + '.' + newKeyword;
+    hashedEntries_.erase(oldKeyword);
+    hashedEntries_.insert(newKeyword, iter());
+
+    if (newKeyword.isPattern())
+    {
+        patterns_.insert(iter());
+        regexps_.insert
+        (
+            autoPtr<regExp>(new regExp(newKeyword))
+        );
+    }
+
+    return true;
+}
+
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/db/dictionary/dictionaryTemplates.C b/src/OpenFOAM/db/dictionary/dictionaryTemplates.C
index 1e46e5da33bbcd9f195951425ddb5eede5f54e6a..d0446b6770f8645a411cac9c62ab549600c33a43 100644
--- a/src/OpenFOAM/db/dictionary/dictionaryTemplates.C
+++ b/src/OpenFOAM/db/dictionary/dictionaryTemplates.C
@@ -43,9 +43,9 @@ T Foam::dictionary::lookupType
     bool patternMatch
 ) const
 {
-    const entry* entryPtr = lookupEntryPtr(keyword, recursive, patternMatch);
+    auto finder = csearch(keyword, recursive, patternMatch);
 
-    if (entryPtr == nullptr)
+    if (!finder.found())
     {
         FatalIOErrorInFunction
         (
@@ -55,7 +55,7 @@ T Foam::dictionary::lookupType
             << exit(FatalIOError);
     }
 
-    return pTraits<T>(entryPtr->stream());
+    return pTraits<T>(finder.ptr()->stream());
 }
 
 
@@ -68,11 +68,11 @@ T Foam::dictionary::lookupOrDefault
     bool patternMatch
 ) const
 {
-    const entry* entryPtr = lookupEntryPtr(keyword, recursive, patternMatch);
+    auto finder = csearch(keyword, recursive, patternMatch);
 
-    if (entryPtr)
+    if (finder.found())
     {
-        return pTraits<T>(entryPtr->stream());
+        return pTraits<T>(finder.ptr()->stream());
     }
     else
     {
@@ -98,11 +98,11 @@ T Foam::dictionary::lookupOrAddDefault
     bool patternMatch
 )
 {
-    const entry* entryPtr = lookupEntryPtr(keyword, recursive, patternMatch);
+    auto finder = csearch(keyword, recursive, patternMatch);
 
-    if (entryPtr)
+    if (finder.found())
     {
-        return pTraits<T>(entryPtr->stream());
+        return pTraits<T>(finder.ptr()->stream());
     }
     else
     {
@@ -129,11 +129,11 @@ bool Foam::dictionary::readIfPresent
     bool patternMatch
 ) const
 {
-    const entry* entryPtr = lookupEntryPtr(keyword, recursive, patternMatch);
+    auto finder = csearch(keyword, recursive, patternMatch);
 
-    if (entryPtr)
+    if (finder.found())
     {
-        entryPtr->stream() >> val;
+        finder.ptr()->stream() >> val;
         return true;
     }
     else
@@ -152,16 +152,16 @@ bool Foam::dictionary::readIfPresent
 
 
 template<class T>
-void Foam::dictionary::add(const keyType& k, const T& t, bool overwrite)
+void Foam::dictionary::add(const keyType& k, const T& v, bool overwrite)
 {
-    add(new primitiveEntry(k, t), overwrite);
+    add(new primitiveEntry(k, v), overwrite);
 }
 
 
 template<class T>
-void Foam::dictionary::set(const keyType& k, const T& t)
+void Foam::dictionary::set(const keyType& k, const T& v)
 {
-    set(new primitiveEntry(k, t));
+    set(new primitiveEntry(k, v));
 }
 
 
diff --git a/src/OpenFOAM/db/dictionary/entry/entryIO.C b/src/OpenFOAM/db/dictionary/entry/entryIO.C
index b8a75380ab5f36192d7f426e1dfecaa559a553c3..f6879570d23738b7b2ecc1cfd081007a108d2f47 100644
--- a/src/OpenFOAM/db/dictionary/entry/entryIO.C
+++ b/src/OpenFOAM/db/dictionary/entry/entryIO.C
@@ -224,17 +224,12 @@ bool Foam::entry::New
             const word varName = keyword.substr(1);
 
             // Lookup the variable name in the given dictionary
-            const entry* ePtr = parentDict.lookupScopedEntryPtr
-            (
-                varName,
-                true,
-                true
-            );
+            const auto finder = parentDict.csearchScoped(varName, true, true);
 
-            if (ePtr)
+            if (finder.found())
             {
                 // Read as primitiveEntry
-                const keyType newKeyword(ePtr->stream());
+                const keyType newKeyword(finder.ptr()->stream());
 
                 return parentDict.add
                 (
@@ -285,14 +280,9 @@ bool Foam::entry::New
         bool mergeEntry = false;
 
         // See (using exact match) if entry already present
-        entry* existingPtr = parentDict.lookupEntryPtr
-        (
-            keyword,
-            false,
-            false
-        );
+        auto finder = parentDict.search(keyword, false, false);
 
-        if (existingPtr)
+        if (finder.found())
         {
             if (mode == inputMode::MERGE)
             {
@@ -301,9 +291,9 @@ bool Foam::entry::New
             else if (mode == inputMode::OVERWRITE)
             {
                 // Clear existing dictionary so merge acts like overwrite
-                if (existingPtr->isDict())
+                if (finder.isDict())
                 {
-                    existingPtr->dict().clear();
+                    finder.dict().clear();
                 }
                 mergeEntry = true;
             }