diff --git a/Base/logog/CMakeLists.txt b/Base/logog/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..943a8ed25e829310ad98312edffc016e0eac6499
--- /dev/null
+++ b/Base/logog/CMakeLists.txt
@@ -0,0 +1,55 @@
+cmake_minimum_required (VERSION 2.8.4)
+enable_testing()
+project (logog)
+include(CTest)
+# logog needs thread support on linux
+find_package( Threads )
+set( RUNTIME_OUTPUT_DIRECTORY bin/ )
+set( ARCHIVE_OUTPUT_DIRECTORY bin/ )
+set( LIBRARY_OUTPUT_DIRECTORY bin/ )
+set( CMAKE_BINARY_DIR build/ )
+set( CMAKE_LEGACY_CYGWIN_WIN32 0 )
+if(MSVC)
+  # Force to always compile with W4
+  if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
+    string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+  else()
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
+  endif()
+elseif(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
+  # Update if necessary
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-variadic-macros -Wall -Wno-long-long")
+endif()
+include_directories( include )
+add_library( logog
+	src/api.cpp 
+	src/checkpoint.cpp
+	src/formatter.cpp
+	src/lobject.cpp
+	src/lstring.cpp
+	src/message.cpp
+	src/mutex.cpp
+	src/node.cpp
+	src/platform.cpp
+	src/socket.cpp
+	src/statics.cpp
+	src/target.cpp
+	src/timer.cpp
+	src/topic.cpp
+	src/unittest.cpp
+)
+set_target_properties(logog PROPERTIES DEBUG_POSTFIX "d")
+add_executable( test-logog test/test.cpp )
+target_link_libraries( test-logog logog ${CMAKE_THREAD_LIBS_INIT})
+add_test( NAME test-harness COMMAND test-logog )
+install(TARGETS logog ARCHIVE DESTINATION ${CMAKE_INSTALL_PREFIX}/lib)
+install(DIRECTORY include/ DESTINATION "${CMAKE_INSTALL_PREFIX}/include/logog"
+          FILES_MATCHING PATTERN "*.hpp")
+
+# Docs generation with Doxygen
+find_package( Doxygen )
+if( DOXYGEN_FOUND )
+	add_custom_target (doc ${DOXYGEN_EXECUTABLE} ${CMAKE_SOURCE_DIR}/doxyfile
+		WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+		COMMENT "Generating source code documentation with Doxygen." VERBATIM)
+endif() # DOXYGEN_FOUND
\ No newline at end of file
diff --git a/Base/logog/doc/make-doxygen.bat b/Base/logog/doc/make-doxygen.bat
new file mode 100644
index 0000000000000000000000000000000000000000..ec6f2db2a281b30389f824ef95bfd6ef90f026a5
--- /dev/null
+++ b/Base/logog/doc/make-doxygen.bat
@@ -0,0 +1,2 @@
+cd ..
+bin\win32\dev\doxygen.exe
\ No newline at end of file
diff --git a/Base/logog/doc/overview.dox b/Base/logog/doc/overview.dox
new file mode 100644
index 0000000000000000000000000000000000000000..0baf43db1b99c2dab35e61a0342f1c0d38dfa17e
--- /dev/null
+++ b/Base/logog/doc/overview.dox
@@ -0,0 +1,991 @@
+/*
+
+Online documentation is available at http://www.logog.org.
+
+This is a documentation file for logog, written in doxygen format.  It's not
+intended to be read by a human; rather, it's intended to be read by the 
+doxygen formatting tool to generate help in a number of user-readable formats.
+
+If you wish to generate a local copy of the html documentation, then 
+install the doxygen utility from http://www.doxygen.org , and run the 
+utility from the root of the logog installation folder.  A folder
+named doc/html will be created with complete html documentation for the
+current release of logog.
+
+*/
+
+namespace logog {
+
+/*!
+\mainpage logog - logger optimized for games
+
+\htmlonly
+<a href="http://www.github.com/johnwbyrd/logog">
+<img src="download.jpg" width=120 height=90 alt="Download logog" >
+</a>
+\endhtmlonly
+
+\section introduction Introduction 
+
+logog is a portable C++ library to 
+facilitate logging of real-time events in performance-oriented 
+applications, such as games. It is especially appropriate for projects 
+that have constrained memory and constrained CPU requirements. 
+
+The latest documentation for logog is online at <a href="http://www.logog.org">
+http://www.logog.org</a>.  You can download the latest tarball or zipfile 
+<a href="http://www.github.com/johnwbyrd/logog">here</a>.
+
+For the impatient, you can add logging functionality into your program
+within five minutes by reading the \ref quickstart section.
+
+\subsection gettingstarted Getting started
+
+- \ref quickstart
+- \ref requirements
+- \ref supportedplatforms
+- \ref features
+
+\subsection basic Basic functionality
+
+- \ref loggingevents
+- \ref levels 
+
+\subsection advancedfeatures Advanced functionality
+
+- \ref categoriesgroups
+- \ref multipletargets
+- \ref deferredoutput
+- \ref addingnewtargets
+- \ref customformatting
+- \ref memorymanager
+- \ref unicodesupport
+- \ref performance
+- \ref leakdetection
+
+\subsection relatedtopics Related topics
+
+- \ref porting
+- \ref unittesting 
+- \ref othersystems
+- \ref license
+
+\subsection gettinghelp Getting help
+
+- \ref community
+
+\htmlonly
+<table border=0 style="background-color: #fff; padding: 5px;" cellspacing=0>
+  <tr><td>
+  <img src="http://groups.google.com/intl/en/images/logos/groups_logo_sm.gif"
+         height=30 width=140 alt="Google Groups">
+  </td></tr>
+  <tr><td style="padding-left: 5px">
+  <b>Subscribe to Logog</b>
+  </td></tr>
+  <form action="http://groups.google.com/group/logog/boxsubscribe">
+  <input type=hidden name="hl" value="en">
+  <tr><td style="padding-left: 5px;">
+  Email: <input type=text name=email>
+  <input type=submit name="sub" value="Subscribe">
+  </td></tr>
+</form>
+<tr><td align=right>
+  <a href="http://groups.google.com/group/logog?hl=en">Visit this group</a>
+</td></tr>
+</table>
+\endhtmlonly
+
+
+\page features Features 
+
+Why yet another logging library?  Because professional games have
+very specific logging requirements that aren't met by any previous
+logging system.
+
+logog supports the following features: 
+
+- High performance. It is possible to disable all logging functionality 
+entirely within logog. In this case logog incurs zero performance 
+penalty on executing code. All logging functions compile to no-ops in 
+the case where the logging level is set to disabled. When logging is 
+enabled, the do-not-log control path requires exactly one boolean 
+comparison. All performance-critical operations have been constructed to 
+have constant time or near constant time performance. logog was designed 
+to assume that no memory or CPU time is available for logging on a final 
+release build of software. When compiling in final release mode, logog 
+is designed to compile completely away -- zero memory allocations, zero 
+CPU cycles spent.
+
+- Logging to arbitrary destinations. Log messages can be sent to stdout, 
+stderr, a log file or into memory, or any combination of these. Logging 
+classes are highly extensible, so logging to new destinations is easy to 
+add. 
+
+- Multiple simultaneous logging criteria. Messages can be simultaneously 
+logged to different log targets with different requirements: by file, by 
+category, by log level, or by group. Substring matching permits 
+regexp-like behavior on logging criteria. 
+
+- Limited external dependencies. logog only requires a reasonably modern 
+standards-compliant C++ compiler (tr1 or later). logog has limited 
+dependencies on STL.  Those dependencies have been orchestrated to mitigate
+the negative performance impacts of the STL.  Additionally, those dependencies
+have been abstracted into macros so that STL can easily be replaced with a somewhat
+compatible template library of your own choosing.
+
+- Highly granular control over which message types are logged.  Control 
+over these messages may be determined at compile-time for maximal 
+performance, or at run-time for interactively enabling or disabling log 
+message types during execution. Messages may be logged by source file, 
+group, category, or message contents. 
+
+- Support for advanced logging requirements. logog's pub-sub 
+architecture means that logging can occur simultaneously to multiple log 
+targets, each with its own logging criteria. Stable base classes permit 
+new logging targets to be easily added. 
+
+- Extremely configurable memory usage and policy. All memory allocations 
+happen after initialization time via a user-supplied memory manager (or 
+the default std::allocator). In other words, you can configure ALL 
+memory allocations to occur from custom malloc() and free() style 
+functions of your own authorship. 
+
+- All allocated memory is freed after the shutdown -- logog does not 
+leak memory.  A special compilation flag (LOGOG_LEAK_DETECTION) audits
+every allocation and free within logog to discover and fix memory leaks therein.
+Additionally, if you don't trust logog's internal leak detector, support exists
+for auditing leaks with Microsoft's CRT library with LOGOG_LEAK_DETECTION_MICROSOFT.
+
+- Support for POSIX-type and Windows-type operating systems.
+Support for proprietary game consoles is implicit or latent; the system
+has been demonstrated to work on Xbox 360 and PS3 (with certain proprietary header
+files).  Support for other OSes is straightforward; all OS dependencies are encapsulated in 
+macros.  
+
+- Support for multithreading. Multiple thread sources are permitted to 
+send logging messages at the same time. 
+
+- Support for re-entrancy. If triggering a log message indirectly causes 
+another log message to be triggered, either through the memory allocator 
+or some other user-based policy, logog is not permitted to hang in a 
+multithreaded environment. 
+
+- Unicode (wide-character) support for all strings; define LOGOG_UNICODE 
+and all strings go from char-based to wchar-based. 
+
+- Verbose documentation.  By far the best documented logging system
+available.  logog uses doxygen comments throughout.
+
+- Extremely permissive license. logog is released under the MIT License, 
+so it may be used freely in commercial as well as open-source projects, 
+with proper attribution to logog's authors (Gigantic Software). 
+
+\page quickstart Quick start 
+
+The logog system is a set of C++ header files and C++ source files.
+To use them, compile all the C++ source files into a single library.
+The compiler will need to reference the files in the include directory
+when compiling the logog library.
+
+\par Build the logog library
+
+To make this easier, logog has been set up to compile using CMake, available 
+at http://www.cmake.org/ .
+CMake is a free cross-platform build system, and executables are available for
+most major platforms and development environments.  Download and install CMake
+in order to generate a build for your platform.
+
+For example, to build the project and libraries on Visual Studio 2008, find and launch
+the Visual Studio 2008 Command Prompt at <b>Microsoft Visual Studio 2008 / Visual Studio Tools /
+Visual Studio 2008 Command Prompt.</b>
+
+Then, to create the appropriate project files, create an empty directory, make that 
+directory the current directory, and run the CMake command with the logog directory as 
+a parameter:
+
+\code
+mkdir logog-build
+cd logog-build
+cmake [path-to-logog-top-directory]
+\endcode
+
+At this point, your directory will contain appropriate project and solution files for your 
+platform.  Once the solution is building, the CMake program is no longer needed.
+Compile and link the library for your own platform using the makefile or project files generated
+for your platform.
+
+\par Your Hello, Logog! program
+
+Here is a working logog example that initializes logog, outputs some sample messages and then
+terminates.
+
+\snippet test.cpp HelloLogog
+
+The most common mistake when getting started with logog is creating a Cerr or Cout
+object and not destroying the object before LOGOG_SHUTDOWN().  This is a usage
+error and will be detected as heap corruption by most debuggers.
+
+\par Integrate logog into your own project
+
+To use the logging library in your own project, put the following line 
+at the top of your source file(s): 
+
+\code
+#include "logog.hpp"
+\endcode
+
+Additionally, make sure to add logog's /include path into the directories
+your build process searches.
+
+At the beginning of your program, initialize logog exactly once, with this
+macro:
+
+\code
+LOGOG_INITIALIZE();
+\endcode
+
+\par Choose one or more output types
+
+To tell logog what type of output should be logged, you must first create a logog::Cerr,
+a logog::Cout, or a logog::LogFile object.  Once this object is instantiated,
+all messages will be routed to that target.  For example:
+
+\code
+logog::Cerr errOutput;
+\endcode
+
+Or:
+
+\code
+logog::LogFile errFile("log.txt");
+\endcode
+
+It's only necessary to create one target per process, immediately after initializing
+logog; you don't need to instance a different Cout, Cerr or LogFile for each class or each file.
+
+\par Start logging events
+
+To log a message in your code, use one of the following macros, in order 
+of severity. Arguments are assumed to be sprintf-style varargs: 
+
+\snippet macro.hpp Shorthand
+
+Note the funny spellings on DBUG and ERR to avoid conflicting with existing macros
+on Windows platforms.
+
+If it turns out that the names of these macros conflict with your existing code,
+then before including the logog.hpp file, define the following constant:
+
+\code
+#define LOGOG_USE_PREFIX 1
+\endcode
+
+If you enable that prefix, you may log with the following macros instead:
+
+\code
+LOGOG_DEBUG( __VA_ARGS__ )
+LOGOG_INFO( __VA_ARGS__ )
+LOGOG_WARN3( __VA_ARGS__ )
+LOGOG_WARN2( __VA_ARGS__ )
+LOGOG_WARN1( __VA_ARGS__ )
+LOGOG_WARN( __VA_ARGS__ )
+LOGOG_ERROR( __VA_ARGS__ )
+LOGOG_ALERT( __VA_ARGS__ )
+LOGOG_CRITICAL( __VA_ARGS__ )
+LOGOG_EMERGENCY( __VA_ARGS__ )
+\endcode
+
+An example usage follows:
+
+\code 
+int foo = 9001;
+int maxfoo = 9000;
+
+if ( foo > maxfoo )
+{
+	WARN("Foo is over %d!  Current value is %d.", maxfoo, foo );
+	WARN("Since this is a warning, by default all builds will log this message!");
+}
+
+const char *pMessage = "message"
+INFO( "This is an informational %s.", pMessage );
+\endcode
+
+At this point, your Target object (in this case, the errOutput object) should
+be destroyed.  Falling out of scope is the easiest way to achieve this.
+
+Then, terminate your program and logging with the following message:
+
+\code
+LOGOG_SHUTDOWN();
+\endcode
+
+Lastly, compile and link with the logog library you created earlier.
+
+\page loggingevents Logging events in your code
+
+In order to log events in your code, it's important to first understand the logging
+levels that are available to you.  Out of the box, logog comes with these logging 
+levels, which are compatible with the syslog standard:
+
+\snippet const.hpp Level Constants
+
+So, the lower the level number is, the more important the logging message is.
+
+To log an event in your code, there exists macros for each of the logging
+levels.  So, for example, to log an event of level WARN3, you would use the 
+following macro in your code:
+
+\code
+LOGOG_WARN3("Disk reads are taking %d milliseconds to complete!", nMilliseconds );
+\endcode
+
+It can get laborious to type the LOGOG_ prefix on all log messages, so, if the
+LOGOG_USE_PREFIX macro is not defined, you may use these shorter alternate
+logging forms:
+
+\snippet macro.hpp Shorthand
+
+If you want to generate a log message of some user-specified level, check out
+the LOGOG_LEVEL_MESSAGE macro.
+
+Keep in mind that you must instantiate at least one Target object in your application
+for log messages to have any effect.
+
+\page levels Verbosity levels of logging
+
+During early stages of product development, you may want to spread DBUG()
+and INFO() type messages liberally across your code base in order to detect
+bugs earlier in the process.  However, as your code develops you will 
+want to omit these instructions entirely, as too many log messages will
+slow down your program.
+
+To omit all logging messages of lower than a specific level at compilation time,
+\#define the LOGOG_LEVEL constant to be some value from the following list:
+
+\snippet const.hpp Level Constants
+
+All logging macros of a lower level will be omitted.
+
+You may enable all logging messages in the following manner before loading 
+logog.hpp:
+
+\code
+#define LOGOG_LEVEL LOGOG_LEVEL_ALL
+\endcode
+
+And you may disable all logging messages with this before logog.hpp:
+
+\code
+#define LOGOG_LEVEL LOGOG_LEVEL_NONE
+\endcode
+
+The standard warnings apply to incrementing or changing variables within a macro.
+For example:
+
+\code
+INFO("The core has exploded %d times", nExploded++);
+\endcode
+
+The nExploded variable will only be incremented if LOGOG_LEVEL is set to LOGOG_LEVEL_INFO
+or lower.
+
+\page filters Filters and their uses
+
+A Filter is a special type of Topic that accepts messages from a publisher
+and routes them forward to another Topic, based on criteria decided by the Filter.
+When logog is initialized, it creates one default filter that automatically forwards
+all messages to all Target objects.  This default behavior can be modified in 
+to generate more complicated logging behaviors.
+
+You can get a reference to the default filter with GetDefaultFilter().  You
+can also instantiate your own filters before you start logging messages
+and messages will automatically find and route through them as well.
+
+Messages attempt to publish themselves to all filters when the message is 
+instantiated.  Filters automatically attempt to publish themselves
+to all targets when the filter is instantiated.
+
+\page categoriesgroups Organizing and filtering log messages by types
+
+Areas of a program such as a game can be broken down into a set of functional
+areas.  Some areas might include AI, audio, graphics, input and the file system.
+
+The logog system allows you to store two dimensions of information with each message
+that further type the message.  These dimensions are referred to as the 
+<b>category</b> and the <b>group</b> of the message.  The ultimate meaning of 
+these fields is up to you.
+
+To define the current group for all messages following a certain point in your
+code, \#define the LOGOG_GROUP constant to the name of the group, surrounded
+by double quotes.  Likewise \#define the LOGOG_CATEGORY constant to the name 
+of the category surrounded by double quotes.
+
+Your compiler may need the \#undef macro to undefine the previous setting of 
+a constant before \#define'ing it to something else.
+
+If you wish to set further messages to no specific category or group, \#define
+either LOGOG_CATEGORY or LOGOG_GROUP to NULL as necessary.
+
+\snippet test.cpp GroupCategory1
+
+A Filter can be told to route only messages matching a specified category or 
+group.  To do this, call the Filter::Category() or Filter::Group() methods on
+a specific filter.  That filter will then only pass messages matching 
+the criteria you've set.
+
+\snippet test.cpp GroupCategory2
+
+\page multipletargets Logging to permutations of multiple targets
+
+It's possible to create multiple filters with multiple criteria on each filter
+and then route each filter to a separate target.  This permits advanced logging
+of different types of events to different log targets.
+
+A filter will automatically attempt to publish itself to all targets.  You can
+change this behavior by calling UnpublishToMultiple( AllTargets() ) on that filter,
+followed by PublishTo() to publish that filter to an output of your choice.
+
+\snippet test.cpp GroupCategory4
+
+\page deferredoutput Deferring logging output
+
+Writing debug output can take a lot of time on most platforms.  
+Especially in programs that produce copious debug output, logging can slow 
+a program's operation considerably.
+
+To get around this behavior, use the LogBuffer class.  To Create a LogBuffer,
+you provide a pointer to the ultimate Target you want to write to, such as 
+a Cerr or a LogFile, as well as the size of the LogBuffer.  Logging then occurs
+solely to the LogBuffer, and no output is written to the Target until the 
+LogBuffer is destroyed, or the LogBuffer::Dump() method is called.
+
+\page customformatting Custom formatting of log messages
+
+The Formatter object is responsible for rendering a particular Topic into a human-readable
+format.  A default Formatter is created by default for you based on the flavor of the compile 
+target.  See FormatterGCC and FormatterMSVC objects for examples.
+
+If you want log messages in your own custom format, subclass the Formatter::Format 
+method into your own custom class, and write your own formatting function for a topic.
+See FormatterMSVC::Format and FormatterGCC::Format for examples.
+
+If all you want to do is enable or disable a certain type of output on your formatter -- for example, to remove file and line number information from
+all your output lines -- then there's a very simple way of doing this.
+The Formatter class implements a Formatter::GetTopicFlags() function that
+in the default case queries the topic in order to find out which fields
+to render.  You can if you wish override this default behavior for a custom
+formatter in order to always or never render specific fields.
+
+The following example overrides the standard FormatterMSVC formatter in
+order to never show file and line number information on the output.
+
+\snippet test.cpp FormatterCustom1
+
+If you wish, you can force a formatter to output the current date and time as 
+part of their format.  You can do this by calling the Formatter::SetShowTimeOfDay function
+with a value of true, as follows:
+
+\snippet test.cpp DateAndTimeLogging
+
+\page addingnewtargets Adding new logging output targets
+
+To add a new type of logging output, such as a network socket or a printer,
+create a subclass of the Target class, and implement your own Output()
+function that renders the information to your output device.
+
+\snippet target.cpp Cout
+
+Then, instance your new class after your call to LOGOG_INITIALIZE() but 
+before messages are invoked.
+
+\page memorymanager Implementing a custom memory manager
+
+All memory allocated by logog, by default, goes through the system malloc()
+and free() routines.  However, many games prefer to implement their
+own memory management systems in order to track memory usage in detail.
+
+In this case, logog can be made to allocate memory via a callback into 
+your own custom code.  In order to implement this callback, 
+allocate an INIT_PARAMS structure on the stack, and then replace
+the m_pfMalloc and m_pfFree pointers to pointers to your own custom
+allocation and free routines.  (It's fine to allocate an INIT_PARAMS structure
+on the stack.)
+Then, when calling the LOGOG_INITIALIZE() macro, provide the address
+of the INIT_PARAMS structure as a parameter.  The INIT_PARAMS structure
+may then be freed.
+
+\snippet api.hpp INIT_PARAMS
+
+\page leakdetection Memory leak detection
+
+A memory leak detection mechanism has been built into logog that tracks all
+internal memory allocations and matches them with corresponding frees.
+The system also detects incorrect reallocations and double frees.  This 
+system only needs to be enabled if you suspect that logog is leaking memory.
+
+To enable this checking, \#define the LOGOG_LEAK_DETECTION constant at compilation
+time before \#include'ing logog.hpp, and then recompile both the logog library and your 
+code.  Additionally, if you want a detailed report about memory allocations
+and frees at the time they occur, enable the LOGOG_REPORT_ALLOCATIONS flag during
+compilation for an action-packed report during run time.
+
+If you don't trust logog's built-in leak detector and are using a Microsoft
+toolset, Microsoft may have enabled support for your platform to detect
+leaks using the CRT library.  If you want to try to use the Microsoft leak
+detector to find leaks in logog, then \#define the LOGOG_LEAK_DETECTION_MICROSOFT constant at 
+compile time before \#include'ing logog, and recompile both the logog library
+and your application.  See http://msdn.microsoft.com/en-us/library/x98tx3cf.aspx
+for more details on how Microsoft implements CRT leak detection.
+
+It's not recommended to leave either of these options on for general use.
+Memory leak detection will slow down logog; additionally, memory leak 
+detection avoids logog's custom memory manager, in order
+to avoid an infinite recursion.
+
+Don't try to enable both LOGOG_LEAK_DETECTION and LOGOG_LEAK_DETECTION_MICROSOFT
+at the same time.
+
+\page unicodesupport Unicode support
+
+The logog library may be compiled either in ANSI mode or in Unicode mode.  By default,
+logog is compiled as an ANSI library.  In this case, multibyte characters are 
+not permitted in log messages.  To enable Unicode support, define the LOGOG_UNICODE
+flag in logog.hpp before compiling the logog library.
+
+Defining this flag sets wchar_t as the base type for all logog character operations.
+On Windows like platforms, a wchar_t is two bytes, and on Posix-like platforms this 
+may be two bytes or four bytes.
+
+Because Unicode support is based around wchar_t, the exact format of the Unicode 
+output depends on the endianness of the target platform as well as the size of 
+wchar_t.  If logog is creating a new output log file, logog tries to add a Unicode 
+BOM to the start of the file, if wchar_t is either two or four bytes in length.
+In this case, logog can write a UTF-16 or UTF-32 BOM, in either little or big 
+endian format.  See LogFile::WriteUnicodeBOM() for more information on how this 
+BOM is written.  More information on what a BOM does is available at 
+http://unicode.org/faq/utf_bom.html .
+
+Defining LOGOG_UNICODE has several effects on logog.  First, this forces all
+logging functions to expect to receive string parameters as arrays of the 
+local wchar_t type instead of char types.  In other words, the LOGOG_CHAR 
+base type is redefined to wchar_t instead of char.  Second, this forces logog to route all
+Cout messages to wcout, and all Cerr messages to wcerr.
+
+A convenience macro, _LG(), is available (if you haven't defined LOGOG_USE_PREFIX)
+for easily switching your constant strings from ANSI to Unicode, based on the compilation
+value of LOGOG_UNICODE.  To use this macro, and hence to have all your code compile
+in both ANSI and Unicode modes, log in the following fashion:
+
+\code
+INFO(_LG("This informational message is displayed in both ANSI and Unicode builds."));
+WARN(LOGOG_CONST_STRING("And this one works regardless of the LOGOG_USE_PREFIX setting."));
+\endcode
+
+Mixing and matching both Unicode and ANSI messages in one application is not currently
+supported, as most compilers do not implement this functionality.
+
+<b>Windows specific issues</b>
+
+Windows platforms have special considerations when logging to the console with 
+wide characters via wcout or wcerr.  Because logog shares the console with its
+host application, it does not initialize the console in any way.  On Windows
+flavored platforms, the console must be initialized in a Unicode-friendly way.
+See http://blogs.msdn.com/b/michkap/archive/2008/03/18/8306597.aspx for details
+about how this might work.  
+
+One way of initializing a Windows console for Unicode support, which seems to 
+work, is as follows:
+
+\snippet test.cpp WindowsUnicodeSetup
+
+See also Microsoft's documentation at http://msdn.microsoft.com/en-us/library/tw4k6df8.aspx .
+
+\page pubsub Publisher-subscriber functionality
+
+Topic objects are a base class that provides publisher-subscriber
+features to subclasses.  Most classes in logog descend from the
+Topic class.
+
+Topics are capable of sending other topics (or themselves) to other
+subscribers, as well as receiving another topic from a publisher.
+See Topic::Send() and Topic::Receive() for more details.
+
+You can cause a Topic to send itself to its subscribers by calling
+Topic::Transmit().
+
+Topics can publish, unpublish, subscribe and unsubscribe themselves
+from other topics.  See Topic::Publish(), Topic::Unpublish(),
+Topic::Subscribe(), Topic::Unsubscribe() for more details.
+
+Topics can also do all these tasks to lists of other topics.
+See Topic::PublishToMultiple(), Topic::UnpublishToMultiple(),
+Topic::SubscribeToMultiple(), Topic::UnsubscribeToMultiple().
+
+\snippet test.cpp Subscription
+
+\page architecture Internal architecture 
+
+The logog system uses a publisher-subscriber model in order to handle 
+message flow from source to destination. While the higher-level class 
+architecture takes care of typical message routing, the standard message 
+flow can be changed to support advanced logging models. 
+
+A key base class is the Topic class. Topics contain strings and numeric 
+information representing a file name, line number, a free-form group 
+name, a free-form category name, and a free-form message string. Topics 
+know how to transmit and receive themselves to and from other topics, 
+but they don't know how to discover those other topics. They do know how 
+to negotiate with another topic in order to discover whether they should 
+subscribe to that other topic -- see Topic::CanSubscribeCheckTopic() for 
+details. Topics implement the core functionality of subscribing and 
+publishing. Topics can subscribe to multiple other topics, and they can 
+publish to multiple other topics. 
+
+Some Topic behavior, especially the subscriber-publisher behavior and 
+cross-thread locking, is subsumed into the Node class. Nodes should 
+generally not be instanced by themselves, as they are not sufficiently 
+functional to be useful. 
+
+Topics are subclassed into TopicSource and TopicSink classes. 
+TopicSources can only publish, and TopicSinks can only subscribe. 
+
+A Target is a TopicSink that is capable of rendering its subscriptions 
+to a logical output device. Targets include the Cout, Cerr, and the 
+OutputDebug classes. To make logog send output to some arbitrary new 
+destination, create a new Target subclass and override the 
+Target::Output() method, and instance a new element of your class at the 
+top of your program. 
+
+A Filter is a Topic that functions basically as a subscriber and a 
+publisher. It's used to limit the scope of incoming messages to a 
+particular type, group, or category. For example, a Filter may be used 
+to permit only messages with a level of LOGOG_LEVEL_WARN or higher to be 
+logged. Other messages are dropped. By default a filter will attempt to 
+subscribe itself to all existing Targets; however, this behavior may be 
+changed by overriding the Initialize() method within your Target 
+subclass, or by manually calling Target::Unpublish() on each Target that 
+you want the Filter to not publish to. 
+
+This design permits more advanced logging models. For example, it's 
+possible to have two Filters, one which filters for error messages and 
+logs those to the console, versus informational and warning messages, 
+which are logged to a file. Note that the routing of any of the 
+higher-level classes such as Filter or Output by simply instantiating a 
+Topic and manually calling PublishTo() and SubscribeTo() to the desired 
+inputs and outputs. 
+
+A Message is a sub-sub-class of TopicSource that knows how to publish 
+itself automatically to any outstanding Filter objects. A program will 
+typically instance a set of static Message objects and use them to 
+indicate execution of a certain point in the program. 
+
+String types receive their own custom class. Since logog spends a lot of 
+time shuffling strings from class to class, this permits string copies 
+to be fast constant-time operations (a copy of pointers). 
+
+All statically allocated elements are stored inside the Statics class. 
+This permits all items to be tracked and freed, thus assuring no memory 
+leaks. 
+
+In order to support cross-platform, multithread-safe support, logog 
+implements a Thread class, a Timer class, and a Mutex class. These of 
+course can be customized to support future platforms. 
+
+\page performance Performance topics
+
+Multiple memory allocations and frees are the bane of performance-oriented
+code.  STL is particularly naughty in this regard.
+
+To that end, logog attempts to do as few allocations as possible at run-time.
+Message objects are allocated exactly once, when a message macro is run for
+the first time.  Publisher-subscriber negotiation occurs at this time
+as well, which is when the pub-sub lists in the Filter objects get updated.
+This process happens only once per message, regardless of the number of times
+the message is invoked.  Therefore, messages that are never executed never
+allocate any memory, and the memory-allocation penalty for a message is incurred
+exactly once, the first time the message is transmitted.
+
+A platform-specific vsprintf() type function is used to convert the varargs
+in a message into a final destination string.  I looked at this problem
+for quite a while, and it seems that this method provides the best performance
+guarantees without relying on a large external library, such as Boost, or
+increasing the code size significantly.  A template-based approach for 
+running vsprintf type functions would theoretically be faster than calling
+vsprintf(); however, this would require the inclusion of a significant
+amount of template-based code to handle all the possible situations that
+vsprintf() must deal with.  This would likely double the existing code size;
+so I erred on the size of keeping logog smaller and more self-contained.
+
+If, after all that, you want to replace vsprintf() for your platform, it is
+called in only one place in the logog source code (in String.cpp).
+
+Because logog spends so much time passing strings around, logog provides a
+custom string class that internally represents strings as fixed buffers.
+This helps reduce the repeated allocations and frees that std::string is notorious
+for.
+
+Because most logging outputs can be slow, logog provides a LogBuffer class to
+help with \ref deferredoutput .
+
+\page locking Multithread locking and mutexes
+
+The Mutex object is responsible for multithread safety in logog.  All
+platforms support a Mutex object.  Only one thread may acquire
+a Mutex object at one time.  Other threads fall into a wait state until
+the locking thread releases the Mutex.
+
+The ScopedLock object is a convenient way to represent a Mutex lock
+as part of an object's auto scope.  To use a ScopedLock, create 
+a Mutex lock on a known thread, then create a ScopedLock with the
+previously defined Lock as a parameter.  Code is guaranteed to be
+single threaded within the scope of the ScopedLock.
+
+\snippet test.cpp SimpleLocking
+
+\page porting Porting logog 
+
+Porting logog should be a straightforward affair, if you follow these 
+guidelines. 
+
+First of all, you'll need to choose a flavor of operating system for 
+your platform. Nearly all OSes will fall into one of two flavors: 
+POSIX-like and Windows-like. platform.hpp tries to detect the local OS 
+and compile for it; you may need to change the detection logic for your 
+new platform.  You'll need to set either LOGOG_FLAVOR_POSIX or LOGOG_FLAVOR_WINDOWS
+before loading platform.hpp.
+
+The files containing platform dependent code are as follows. 
+
+- platform.hpp. In addition to detecting the build flavor, platform.hpp 
+also sets some macros for STL usage. All STL calls are routed through 
+the macros in platform.hpp. As of this writing, the STL templates are 
+available in tr1; you may need to tweak this if you're depending on a C++x11
+compiler.
+
+\snippet platform.hpp STLTypes
+
+- mutex.hpp. You'll need to write macros for your own LOGOG_MUTEX_* 
+calls:
+
+\snippet mutex.hpp Mutex
+
+- thread.hpp.  Write macros for LOGOG_THREAD, LOGOG_THREAD_CREATE and 
+LOGOG_THREAD_JOIN.  Since logog does not actually initiate multiple threads,
+this step can technically be skipped; however, unless threads are implemented
+for a target platform, the unit tests will fail.
+
+\snippet thread.hpp Thread
+
+- timer.hpp. Add code for the Timer initializer and the Get() function. 
+
+\snippet timer.cpp TimerGet
+
+Lastly, verify that unittest.cpp compiles and executes with a zero 
+return code. 
+
+\page requirements Requirements 
+
+logog assumes the existence of a C99 compliant C++ compiler. It uses 
+variadic macros in the C99 style, so any compiler that does not understand
+__VA_ARGS__ style message passing will not work.  The vast majority of 
+semi-modern compilers do.
+
+logog also has limited dependencies on STL.  These dependencies are represented
+by \#defines in the file platform.hpp.  If your STL lacks support for any 
+of these containers, or if you're using another STL-like container system,
+you may replace these \#defines and they will be used as logog's standard
+containers.
+
+\snippet platform.hpp STLTypes
+
+\page supportedplatforms Supported platforms
+
+logog has been demonstrated to work with the following platforms:
+
+- Microsoft Visual Studio 2008
+- Microsoft Visual Studio 2010 (x64 and x86)
+- Ubuntu 10.04 LTS
+- MacOS 10.7
+- Xbox 360
+- Sony PlayStation 3
+
+It is expected that logog should work on any reasonably
+POSIX-compliant or Windows-compliant operating system with minimal changes.
+Please see \ref porting for more information on support for alternative platforms.
+
+Since the console implementations are proprietary to the 
+platform holders, implementation details for these platforms have not been
+publicly provided.  However they may be provided to authorized and licensed
+platform developers if the platform holder permits; contact us if you're a
+licensed developer.
+
+\page license License agreement 
+
+logog is Copyright (c) 2011, Gigantic Software. 
+
+Permission is hereby granted, free of charge, to any person obtaining a 
+copy of this software and associated documentation files (the 
+"Software"), to deal in the Software without restriction, including 
+without limitation the rights to use, copy, modify, merge, publish, 
+distribute, sublicense, and/or sell copies of the Software, and to 
+permit persons to whom the Software is furnished to do so, subject to 
+the following conditions: 
+
+The above copyright notice and this permission notice shall be included 
+in all copies or substantial portions of the Software. 
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
+
+\page community Community and support
+
+Two mailing lists exist for general support and development discussion related to
+logog.  The first is for general logog questions and answers.  This mailing list is
+visible at 
+<a href="http://groups.google.com/group/logog">http://groups.google.com/group/logog</a>.
+All users of logog are invited to join this mailing list for general discussion and help.
+
+\htmlonly
+<table border=0 style="background-color: #fff; padding: 5px;" cellspacing=0>
+  <tr><td>
+  <img src="http://groups.google.com/intl/en/images/logos/groups_logo_sm.gif"
+         height=30 width=140 alt="Google Groups">
+  </td></tr>
+  <tr><td style="padding-left: 5px">
+  <b>Subscribe to Logog</b>
+  </td></tr>
+  <form action="http://groups.google.com/group/logog/boxsubscribe">
+  <input type=hidden name="hl" value="en">
+  <tr><td style="padding-left: 5px;">
+  Email: <input type=text name=email>
+  <input type=submit name="sub" value="Subscribe">
+  </td></tr>
+</form>
+<tr><td align=right>
+  <a href="http://groups.google.com/group/logog?hl=en">Visit this group</a>
+</td></tr>
+</table>
+\endhtmlonly
+
+The second mailing list is for those who wish to actively participate in the
+development of logog.  The mailing list is visible at 
+<a href="http://groups.google.com/group/logog-devel">http://groups.google.com/group/logog-devel</a>.
+
+\htmlonly
+<table border=0 style="background-color: #fff; padding: 5px;" cellspacing=0>
+  <tr><td>
+  <img src="http://groups.google.com/intl/en/images/logos/groups_logo_sm.gif"
+         height=30 width=140 alt="Google Groups">
+  </td></tr>
+  <tr><td style="padding-left: 5px">
+  <b>Subscribe to Logog Development</b>
+  </td></tr>
+  <form action="http://groups.google.com/group/logog-devel/boxsubscribe">
+  <tr><td style="padding-left: 5px;">
+  Email: <input type=text name=email>
+  <input type=submit name="sub" value="Subscribe">
+  </td></tr>
+</form>
+<tr><td align=right>
+  <a href="http://groups.google.com/group/logog-devel">Visit this group</a>
+</td></tr>
+</table>
+\endhtmlonly
+
+The best way to get help with a specific problem is to submit an issue
+on Github.  You can review a list of current issues, or submit your own,
+<a href="https://github.com/johnwbyrd/logog/issues">here</a>.
+
+I'd REALLY like to get other developers involved in maintaining and further
+developing the code.  All sane developers encouraged to fork the <a href="https://github.com/johnwbyrd/logog">git repository</a> and 
+do bug fixing or new feature implementation.  Contact me at jbyrd at giganticsoftware dot com if you need administrative privileges on the master logog branch; I'm 
+actively looking to incorporate positive changes.
+
+\page othersystems Other logging frameworks and systems 
+
+Here are other logging and testing frameworks that have served as 
+inspiration (negative and/or positive) for logog. 
+
+\section pantheios Panetheios
+
+http://www.pantheios.org 
+
+Pantheios claims to compile to nothing in the final release case. 
+However, the Pantheios library depends on STLSoft, xTests, b64, and 
+shwild.
+
+\section marginean Petru Margenian's library in Dr. Dobb's Journal 
+
+http://drdobbs.com/cpp/201804215 
+
+Another interesting effort at a portable logging implementation. 
+This library depends on an atomic_ops library from HP, and 
+it won't mention this fact until you try to compile it.  Logging can be 
+enabled or disabled based on a single dimension ("level") and all 
+logging output ends up at stderr (there is no support for alternative 
+outputs). 
+
+\section glog glog, the Google logging library 
+
+http://code.google.com/p/google-glog/ 
+
+Provides logging to stderr, a file or syslog. Their ostream-style 
+logging methodology creates two sets of macros: one for macros that 
+compile away in release mode, one for macros that don't. Interesting (if 
+non portable) support for stack walking. 
+
+\section rlog rlog
+
+http://code.google.com/p/rlog/ 
+
+Uses a publisher-subscriber model for all objects, and demonstrated that 
+this basic architecture was highly appropriate for logging. Does not 
+play nicely with custom allocators.
+
+\section loki Loki
+
+http://loki-lib.sourceforge.net/ 
+
+The loki library demonstrates how to abstract platform-specific features
+like mutexes and threads in remarkably few lines of code.
+
+*/
+
+}
+
+/** \def LOGOG_UNICODE
+ ** Define this macro to enable Unicode support in logog.  The logog library works either in Unicode mode or not --
+ ** attempting to mix the two log types will have unexpected results.
+ **/
+#define LOGOG_UNICODE 1
+
+/** \def LOGOG_INTERNAL_DEBUGGING
+ ** Define this macro to debug logog itself.  This setting enables sanity checks on many logog functions.  This setting
+ ** is not very useful for end users of logog. */
+#define LOGOG_INTERNAL_DEBUGGING 1
+
+/** \def LOGOG_LEAK_DETECTION
+ ** Define this macro to check all memory allocations and frees.  This setting will check against double allocations
+ ** and double deletes as well.  Do not enable this on production code -- it'll slow down the performance considerably.
+ **/
+ #define LOGOG_LEAK_DETECTION 1
+
+/** \def LOGOG_REPORT_ALLOCATIONS
+ ** Define this macro to report on ALL allocations and frees that happen through logog.
+ ** Enable this if you get paid by lines of program output. */
+#define LOGOG_REPORT_ALLOCATIONS 1
+
+/** \def LOGOG_COUT 
+ ** This is equivalent to std::wcout if LOGOG_UNICODE is defined, and std::cout otherwise.
+ **/
+
+/** \def LOGOG_CERR
+ ** This is equivalent to std::wcerr if LOGOG_UNICODE is defined, and std::cerr otherwise.
+ **/
diff --git a/Base/logog/doxyfile b/Base/logog/doxyfile
new file mode 100644
index 0000000000000000000000000000000000000000..371353e1c5609e7839cd0878d80c93607666f216
--- /dev/null
+++ b/Base/logog/doxyfile
@@ -0,0 +1,1716 @@
+# Doxyfile 1.7.4
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a hash (#) is considered a comment and will be ignored.
+# The format is:
+#       TAG = value [value, ...]
+# For lists items can also be appended using:
+#       TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME           = logog
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER         =
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer
+# a quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF          = "logger optimized for games"
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is
+# included in the documentation. The maximum height of the logo should not
+# exceed 55 pixels and the maximum width should not exceed 200 pixels.
+# Doxygen will copy the logo to the output directory.
+
+PROJECT_LOGO           =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       = doc
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS         = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
+# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak,
+# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
+
+OUTPUT_LANGUAGE        = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF       =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES        = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH        =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH    =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful if your file system
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF      = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF           = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE               = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES                =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C  = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN   = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL   = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given extension.
+# Doxygen has a built-in mapping, but you can override or extend it using this
+# tag. The format is ext=language, where ext is a file extension, and language
+# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C,
+# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make
+# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
+# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions
+# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen.
+
+EXTENSION_MAPPING      =
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also makes the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT    = YES
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT            = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate getter
+# and setter methods for a property. Setting this option to YES (the default)
+# will make doxygen replace the get and set methods by a property in the
+# documentation. This will only work if the methods are indeed getting or
+# setting a simple type. If this is not the case, or you want to show the
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT   = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING            = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and
+# unions are shown inside the group in which they are included (e.g. using
+# @ingroup) instead of on a separate page (for HTML and Man pages) or
+# section (for LaTeX and RTF).
+
+INLINE_GROUPED_CLASSES = NO
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
+# is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically
+# be useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT   = NO
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
+# determine which symbols to keep in memory and which to flush to disk.
+# When the cache is full, less often used symbols will be written to disk.
+# For small to medium size projects (<1000 input files) the default value is
+# probably good enough. For larger projects a too small cache size can cause
+# doxygen to be busy swapping symbols to and from disk most of the time
+# causing a significant performance penalty.
+# If the system has enough physical memory increasing the cache will improve the
+# performance by keeping more symbols in memory. Note that the value works on
+# a logarithmic scale so increasing the size by one will roughly double the
+# memory usage. The cache size is given by this formula:
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols
+
+SYMBOL_CACHE_SIZE      = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL            = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC         = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base
+# name of the file that contains the anonymous namespace. By default
+# anonymous namespaces are hidden.
+
+EXTRACT_ANON_NSPACES   = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES       = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES       = YES
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
+# will list include files with double quotes in the documentation
+# rather than with sharp brackets.
+
+FORCE_LOCAL_INCLUDES   = NO
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
+# will sort the (brief and detailed) documentation of class members so that
+# constructors and destructors are listed first. If set to NO (the default)
+# the constructors will appear in the respective orders defined by
+# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
+# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
+# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
+# hierarchy of group names into alphabetical order. If set to NO (the default)
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES       = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to
+# do proper type resolution of all parameters of a function it will reject a
+# match between the prototype and the implementation of a member function even
+# if there is only one candidate or it is obvious which candidate to choose
+# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen
+# will still accept a match between prototype and implementation in such cases.
+
+STRICT_PROTO_MATCHING  = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS       =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or macro consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and macros in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES        =YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES       = NO
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
+# This will remove the Files entry from the Quick Index and from the
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES             = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
+# Namespaces page.
+# This will remove the Namespaces entry from the Quick Index
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES        = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER    =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. The create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option.
+# You can optionally specify a file name after the option, if omitted
+# DoxygenLayout.xml will be used as the name of the layout file.
+
+LAYOUT_FILE            =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS               = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR      = YES
+
+# The WARN_NO_PARAMDOC option can be enabled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC       = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT            = "$file($line) : $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE           =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT                  = include doc test
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. Doxygen uses libiconv (or the iconv built
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
+# the list of possible encodings.
+
+INPUT_ENCODING         = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh
+# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py
+# *.f90 *.f *.for *.vhd *.vhdl
+
+FILE_PATTERNS          = *.dox *.c *.cpp *.hpp *.h 
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE              = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE                =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS        =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH           = test/ include/ src/
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS       =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH             =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.
+# If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER           =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis.
+# Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match.
+# The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty or if
+# non of the patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS        =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES    = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any)
+# and it is also possible to disable source filtering for a specific pattern
+# using *.ext= (so without naming a filter). This option only has effect when
+# FILTER_SOURCE_FILES is enabled.
+
+FILTER_SOURCE_PATTERNS =
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER         = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION    = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code.
+# Otherwise they will link to the documentation.
+
+REFERENCES_LINK_SOURCE = NO
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX     = YES
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX          =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header. Note that when using a custom header you are responsible
+# for the proper inclusion of any scripts and style sheets that doxygen
+# needs, which is dependent on the configuration options used.
+# It is adviced to generate a default header using "doxygen -w html
+# header.html footer.html stylesheet.css YourConfigFile" and then modify
+# that header. Note that the header is subject to change so you typically
+# have to redo this when upgrading to a newer version of doxygen or when changing the value of configuration settings such as GENERATE_TREEVIEW!
+
+HTML_HEADER            =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER            =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET        =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that
+# the files will be copied as-is; there are no commands or markers available.
+
+HTML_EXTRA_FILES       =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
+# Doxygen will adjust the colors in the stylesheet and background images
+# according to this color. Hue is specified as an angle on a colorwheel,
+# see http://en.wikipedia.org/wiki/Hue for more information.
+# For instance the value 0 represents red, 60 is yellow, 120 is green,
+# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
+# The allowed range is 0 to 359.
+
+HTML_COLORSTYLE_HUE    = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
+# the colors in the HTML output. For a value of 0 the output will use
+# grayscales only. A value of 255 will produce the most vivid colors.
+
+HTML_COLORSTYLE_SAT    = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
+# the luminance component of the colors in the HTML output. Values below
+# 100 gradually make the output lighter, whereas values above 100 make
+# the output darker. The value divided by 100 is the actual gamma applied,
+# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
+# and 100 does not change the gamma.
+
+HTML_COLORSTYLE_GAMMA  = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting
+# this to NO can help when comparing the output of multiple runs.
+
+HTML_TIMESTAMP         = YES
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS     = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded. For this to work a browser that supports
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS  = YES
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files
+# will be generated that can be used as input for Apple's Xcode 3
+# integrated development environment, introduced with OSX 10.5 (Leopard).
+# To create a documentation set, doxygen will generate a Makefile in the
+# HTML output directory. Running make will produce the docset in that
+# directory and running "make install" will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
+# it at startup.
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+
+GENERATE_DOCSET        = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# feed. A documentation feed provides an umbrella under which multiple
+# documentation sets from a single provider (such as a company or product suite)
+# can be grouped.
+
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
+# should uniquely identify the documentation set bundle. This should be a
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID       = com.giganticsoftware.logog
+
+# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+
+DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
+
+# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
+
+DOCSET_PUBLISHER_NAME  = Gigantic Software
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP      = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE               =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION           =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI           = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING     =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND             = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated
+# that can be used as input for Qt's qhelpgenerator to generate a
+# Qt Compressed Help (.qch) of the generated HTML documentation.
+
+GENERATE_QHP           = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
+# be used to specify the file name of the resulting .qch file.
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE               =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#namespace
+
+QHP_NAMESPACE          = com.giganticsoftware.logog
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+
+QHP_VIRTUAL_FOLDER     = doc
+
+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to
+# add. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#custom-filters
+
+QHP_CUST_FILTER_NAME   =
+
+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see
+# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">
+# Qt Help Project / Custom Filters</a>.
+
+QHP_CUST_FILTER_ATTRS  =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's
+# filter section matches.
+# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">
+# Qt Help Project / Filter Attributes</a>.
+
+QHP_SECT_FILTER_ATTRS  =
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
+# be used to specify the location of Qt's qhelpgenerator.
+# If non-empty doxygen will try to run qhelpgenerator on the generated
+# .qhp file.
+
+QHG_LOCATION           =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
+#  will be generated, which together with the HTML files, form an Eclipse help
+# plugin. To install this plugin and make it available under the help contents
+# menu in Eclipse, the contents of the directory containing the HTML and XML
+# files needs to be copied into the plugins directory of eclipse. The name of
+# the directory within the plugins directory should be the same as
+# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before
+# the help appears.
+
+GENERATE_ECLIPSEHELP   = NO
+
+# A unique identifier for the eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have
+# this name.
+
+ECLIPSE_DOC_ID         = com.giganticsoftware.logog
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX          = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values
+# (range [0,1..20]) that doxygen will group on one line in the generated HTML
+# documentation. Note that a value of 0 will completely suppress the enum
+# values from appearing in the overview section.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information.
+# If the tag value is set to YES, a side panel will be generated
+# containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
+# Windows users are probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW      = YES
+
+# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories,
+# and Class Hierarchy pages using a tree view instead of an ordered list.
+
+USE_INLINE_TREES       = YES
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH         = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open
+# links to external symbols imported via tag files in a separate window.
+
+EXT_LINKS_IN_WINDOW    = NO
+
+# Use this tag to change the font size of Latex formulas included
+# as images in the HTML documentation. The default is 10. Note that
+# when you change the font size after a successful doxygen run you need
+# to manually remove any form_*.png images from the HTML output directory
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE       = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are
+# not supported properly for IE 6.0, but are supported on all modern browsers.
+# Note that when changing this option you need to delete any form_*.png files
+# in the HTML output before the changes have effect.
+
+FORMULA_TRANSPARENT    = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax
+# (see http://www.mathjax.org) which uses client side Javascript for the
+# rendering instead of using prerendered bitmaps. Use this if you do not
+# have LaTeX installed or if you want to formulas look prettier in the HTML
+# output. When enabled you also need to install MathJax separately and
+# configure the path to it using the MATHJAX_RELPATH option.
+
+USE_MATHJAX            = NO
+
+# When MathJax is enabled you need to specify the location relative to the
+# HTML output directory using the MATHJAX_RELPATH option. The destination
+# directory should contain the MathJax.js script. For instance, if the mathjax
+# directory is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the
+# mathjax.org site, so you can quickly see the result without installing
+# MathJax, but it is strongly recommended to install a local copy of MathJax
+# before deployment.
+
+MATHJAX_RELPATH        = http://www.mathjax.org/mathjax
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box
+# for the HTML output. The underlying search engine uses javascript
+# and DHTML and should work on any modern browser. Note that when using
+# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets
+# (GENERATE_DOCSET) there is already a search function so this one should
+# typically be disabled. For large projects the javascript based search engine
+# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
+
+SEARCHENGINE           = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a PHP enabled web server instead of at the web client
+# using Javascript. Doxygen will generate the search PHP script and index
+# file to put on the web server. The advantage of the server
+# based approach is that it scales better to large projects and allows
+# full text search. The disadvantages are that it is more difficult to setup
+# and does not have live searching capabilities.
+
+SERVER_BASED_SEARCH    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX         = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+# Note that when enabling USE_PDFLATEX this option is only used for
+# generating bitmaps for formulas in the HTML output, but not in the
+# Makefile that is written to the output directory.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE             = a4
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES         =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER           =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for
+# the generated latex document. The footer should contain everything after
+# the last chapter. If it is left blank doxygen will generate a
+# standard footer. Notice: only use this tag if you know what you are doing!
+
+LATEX_FOOTER           =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS         = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX           = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE        = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES     = NO
+
+# If LATEX_SOURCE_CODE is set to YES then doxygen will include
+# source code with syntax highlighting in the LaTeX output.
+# Note that which sources are shown also depends on other settings
+# such as SOURCE_BROWSER.
+
+LATEX_SOURCE_CODE      = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF            = YES
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE    =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE    =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION          = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA             =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD                =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader.
+# This is useful
+# if you want to understand what is going on.
+# On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF     = YES
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# pointed to by INCLUDE_PATH will be searched when a #include is found.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH           =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS  =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED             = DOXYGEN LOGOG_UNICODE=1 LOGOG_INTERNAL_DEBUGGING=1 LOGOG_LEAK_DETECTION=1 LOGOG_REPORT_ALLOCATIONS=1
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition that
+# overrules the definition found in the source code.
+
+EXPAND_AS_DEFINED      =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all references to function-like macros
+# that are alone on a line, have an all uppercase name, and do not end with a
+# semicolon, because these will confuse the parser if not removed.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+#
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+#
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES               =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE       =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS        = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option also works with HAVE_DOT disabled, but it is recommended to
+# install and use dot, since it yields more powerful graphs.
+
+CLASS_DIAGRAMS         = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH            =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT               = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
+# allowed to run in parallel. When set to 0 (the default) doxygen will
+# base this on the number of processors available in the system. You can set it
+# explicitly to a value larger than 0 to get control over the balance
+# between CPU load and processing speed.
+
+DOT_NUM_THREADS        = 0
+
+# By default doxygen will write a font called Helvetica to the output
+# directory and reference it in all dot files that doxygen generates.
+# When you want a differently looking font you can specify the font name
+# using DOT_FONTNAME. You need to make sure dot is able to find the font,
+# which can be done by putting it in a standard location or by setting the
+# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory
+# containing the font.
+
+DOT_FONTNAME           = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
+# The default size is 10pt.
+
+DOT_FONTSIZE           = 10
+
+# By default doxygen will tell dot to use the output directory to look for the
+# FreeSans.ttf font (which doxygen will put there itself). If you specify a
+# different font using DOT_FONTNAME you can set the path where dot
+# can find it using this tag.
+
+DOT_FONTPATH           =
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK               = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH          = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
+# doxygen will generate a call dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable call graphs
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH             = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
+# doxygen will generate a caller dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable caller
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH           = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will generate a graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are svg, png, jpg, or gif.
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT       = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH               =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS           =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the
+# \mscfile command).
+
+MSCFILE_DIRS           =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the
+# number of direct children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES    = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not
+# seem to support this out of the box. Warning: Depending on the platform used,
+# enabling this option may lead to badly anti-aliased labels on the edges of
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT        = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS      = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP            = YES
diff --git a/Base/logog/include/api.hpp b/Base/logog/include/api.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..6d98f4b343c987752c339b9fe4aad3022d93cc9d
--- /dev/null
+++ b/Base/logog/include/api.hpp
@@ -0,0 +1,47 @@
+/**
+ * \file api.hpp Initialization and shutdown functions for logog.
+ */
+
+#ifndef __LOGOG_API_HPP__
+#define __LOGOG_API_HPP__
+
+namespace logog
+{
+//! [INIT_PARAMS]
+/**
+ * To initialize the memory manager with non-default values, allocate a temporary INIT_PARAMS structure, fill it with
+ * zeros, and then change the individual entries in the INIT_PARAMS struct before passing as a parameter to Initialize().
+ * \sa Initialize
+ */
+struct INIT_PARAMS
+{
+    /** A pointer to a function that allocates memory.  By default logog allocates using malloc().  Change this pointer
+     ** before passing to Initialize() to use your own custom memory allocator.
+     * \sa logog::Initialize()
+     */
+    void *( *m_pfMalloc )( size_t );
+
+    /** A pointer to a function that frees memory.  By default logog frees using free().  Change this pointer
+     * before passing to Initialize() to use your own custom memory allocator.
+     * \sa logog::Initialize()
+     */
+    void ( *m_pfFree )( void * );
+};
+//! [INIT_PARAMS]
+
+/** Initializes the logog system.  No logog calls or allocations may be made before calling this function; expect
+ * crashes if you haven't called this at the top of your program.
+ * \param params The address of an INIT_PARAMS structure you have already allocated on the heap, or NULL to
+ * use default values.
+ * \sa INIT_PARAMS
+ */
+extern int Initialize( INIT_PARAMS *params = NULL );
+
+/** Shuts down the logog system and frees all memory allocated by logog.  Memory still allocated by the logog system after Shutdown() indicates
+ ** a bug.
+ **/
+extern int Shutdown( );
+
+}
+
+#endif // __LOGOG_API_HPP
diff --git a/Base/logog/include/checkpoint.hpp b/Base/logog/include/checkpoint.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..05c8ba1f7a43a06ad242bf0edd8fb93970bb3310
--- /dev/null
+++ b/Base/logog/include/checkpoint.hpp
@@ -0,0 +1,31 @@
+/**
+ * \file checkpoint.hpp Representations of a program counter reaching a specific point in code.
+ */
+
+#ifndef __LOGOG_CHECKPOINT_HPP__
+#define __LOGOG_CHECKPOINT_HPP__
+
+namespace logog
+{
+/** A checkpoint is a topic that fires when a specific section of code is executed.  The first time a bit of
+ ** code is executed, a Checkpoint is instanced, and when the code is executed again, the Checkpoint is
+ ** reused.
+ **/
+class Checkpoint : public TopicSource
+{
+public:
+    Checkpoint( const LOGOG_LEVEL_TYPE level = LOGOG_LEVEL_ALL,
+                const LOGOG_CHAR *sFileName = NULL,
+                const int nLineNumber = 0,
+                const LOGOG_CHAR *sGroup = NULL,
+                const LOGOG_CHAR *sCategory = NULL,
+                const LOGOG_CHAR *sMessage = NULL,
+                const double dTimestamp = 0.0f );
+
+    /** Sends the node in question.  Optionally updates the timestamp in this checkpoint before sending the node. */
+    virtual int Send( const Topic &node );
+
+};
+}
+
+#endif // __LOGOG_CHECKPOINT_HPP_
diff --git a/Base/logog/include/const.hpp b/Base/logog/include/const.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..2608447595d3e8034e054a0513522a28492acc4b
--- /dev/null
+++ b/Base/logog/include/const.hpp
@@ -0,0 +1,90 @@
+/**
+ * \file const.hpp Constants.
+ */
+
+#ifndef __LOGOG_CONST_HPP__
+#define __LOGOG_CONST_HPP__
+
+#ifndef LOGOG_FORMATTER_MAX_LENGTH
+/** The maximum length of a single line that a formatter may output, in LOGOG_CHAR units. */
+#define LOGOG_FORMATTER_MAX_LENGTH ( 1024 * 16 )
+#endif
+
+#ifndef LOGOG_DEFAULT_LOG_BUFFER_SIZE
+/** The default size of a RingBuffer object for buffering outputs. */
+#define LOGOG_DEFAULT_LOG_BUFFER_SIZE ( 4 * 1024 * 1024 )
+#endif
+
+
+/** \addtogroup levelsettings Level Settings
+ ** These are level settings for logog.  These settings are valid for the LOGOG_LEVEL compilation flag.  To enable
+ ** all logog messages, use the compilation flag -DLOGOG_LEVEL=LOGOG_LEVEL_ALL.  To disable all logog messages
+ ** (and effectively remove logog code from your executable) use the compilation flag -DLOGOG_LEVEL=LOGOG_LEVEL_NONE.
+ ** \sa LOGOG_LEVEL
+ ** @{
+ **/
+//! [Level Constants]
+#define LOGOG_LEVEL_NONE		0
+#define LOGOG_LEVEL_EMERGENCY	8
+#define LOGOG_LEVEL_ALERT		16
+#define LOGOG_LEVEL_CRITICAL	24
+#define LOGOG_LEVEL_ERROR		32
+#define LOGOG_LEVEL_WARN		40
+#define LOGOG_LEVEL_WARN1		48
+#define LOGOG_LEVEL_WARN2		56
+#define LOGOG_LEVEL_WARN3		64
+#define LOGOG_LEVEL_INFO		72
+#define LOGOG_LEVEL_DEBUG		80
+#define LOGOG_LEVEL_ALL			88
+//! [Level Constants]
+
+#define LOGOG_LEVEL_TYPE		int
+
+#ifndef LOGOG_LEVEL
+#define LOGOG_LEVEL LOGOG_LEVEL_DEBUG
+#endif
+
+/** @} */
+
+/** \addtogroup topicbitstype Topic Bits Type
+  * Bit flags representing whether a topic cares about a specific field or not.  1 = care, 0 = don't care.
+  * @{
+  */
+//! [Topic Bits]
+typedef enum
+{
+	TOPIC_LEVEL_FLAG =			0x01,
+	TOPIC_LINE_NUMBER_FLAG =	0x02,
+	TOPIC_FILE_NAME_FLAG =		0x04,
+	TOPIC_GROUP_FLAG =			0x08,
+	TOPIC_CATEGORY_FLAG =		0x10,
+	TOPIC_MESSAGE_FLAG =		0x20,
+	TOPIC_TIMESTAMP_FLAG =		0x40,
+	/** Bits 0 through TOPIC_COUNT turned on */
+	TOPIC_ALL = 0x7f
+} TopicBitsType;
+//! [Topic Bits]
+
+/** @} */
+
+typedef int TOPIC_FLAGS;
+
+//! [Topic Offsets]
+/** Offsets within the m_vIntProps and m_vStringProps arrays for this topic. */
+typedef enum
+{
+	TOPIC_LEVEL = 0,
+	TOPIC_LINE_NUMBER = 1,
+	/** This must be the number of integer fields. */
+	TOPIC_INT_COUNT = 2,
+
+	TOPIC_FILE_NAME = 0,
+	TOPIC_GROUP = 1,
+	TOPIC_CATEGORY = 2,
+	TOPIC_MESSAGE = 3,
+	/** This must be the number of string fields for this topic. */
+	TOPIC_STRING_COUNT = 4
+} TopicOffsetType;
+//! [Topic Offsets]
+
+#endif // __LOGOG_CONST_HPP__
diff --git a/Base/logog/include/formatter.hpp b/Base/logog/include/formatter.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..b3b8378290a854c2720d57ad2e712b1cc118cebc
--- /dev/null
+++ b/Base/logog/include/formatter.hpp
@@ -0,0 +1,89 @@
+/**
+ * \file formatter.hpp Formats a topic into human-readable, compiler lookalike format.
+ */
+
+#ifndef __LOGOG_FORMATTER_HPP__
+#define __LOGOG_FORMATTER_HPP__
+
+namespace logog
+{
+
+#define LOGOG_TIME_STRING_MAX 80
+
+/** A helper object for generating a current timestamp as a string. */
+class TimeStamp : public Object
+{
+public:
+	/** Returns a pointer to a string representing the current time.  Note!  This pointer is only
+	 ** valid while this object is valid -- if you destroy this object, this pointer is no longer
+	 ** valid.
+	 */
+	const char *Get();
+
+protected:
+	char cTimeString[ LOGOG_TIME_STRING_MAX ]; 
+};
+
+/** Converts a topic into a human-readable string for printing or otherwise rendering to a target. */
+class Formatter : public Object
+{
+public:
+	Formatter();
+
+    /** Causes this formatter to format a topic into its own m_sMessageBuffer field, and thence to
+     ** return a reference to that string.  This function must be written to be efficient; it will be called
+     ** for every logging operation.  It is strongly recommended not to allocate or free memory in this function.
+     **/
+    virtual LOGOG_STRING &Format( const Topic &topic, const Target &target ) = 0;
+
+	/** Causes the time of day to be rendered, if it needs to be rendered.  This function is only supported on
+	 ** ANSI builds, not Unicode, as the underlying functions are ANSI only.
+	 */
+	virtual void RenderTimeOfDay();
+
+	/** In the base case, this function calls GetTopicFlags() on the provided 
+	 ** topic in order to figure out which fields this formatter should render.
+	 ** However, subclasses of the Formatter class can override this function in order
+	 ** to change the default fields that the topic wants to be rendered.  For example,
+	 ** you can turn off the TOPIC_LINE_NUMBER_FLAG and the TOPIC_FILE_NAME_FLAG
+	 ** in order to disable these fields from being rendered in your own Formatter
+	 ** subclass.
+	 ** \param topic The topic whose flags are to be determined
+	 ** \return The set of flags representing the topics that really need to be rendered.
+	 **/
+	virtual TOPIC_FLAGS GetTopicFlags( const Topic &topic );
+
+	/** Should this formatter render the current time of day? */
+	bool GetShowTimeOfDay() const;
+
+	/** Sets whether this formatter renders the current time of day. */
+	void SetShowTimeOfDay(bool val);
+
+protected:
+    const LOGOG_CHAR *ErrorDescription( const LOGOG_LEVEL_TYPE level );
+
+    LOGOG_STRING m_sMessageBuffer;
+    LOGOG_STRING m_sIntBuffer;
+
+	bool m_bShowTimeOfDay;
+};
+
+class FormatterGCC : public Formatter
+{
+public:
+    virtual LOGOG_STRING &Format( const Topic &topic, const Target &target );
+
+};
+
+class FormatterMSVC : public Formatter
+{
+public:
+    virtual LOGOG_STRING &Format( const Topic &topic, const Target &target );
+};
+
+extern Formatter &GetDefaultFormatter();
+extern void DestroyDefaultFormatter();
+
+}
+
+#endif // __LOGOG_FORMATTER_HPP_
diff --git a/Base/logog/include/logog.hpp b/Base/logog/include/logog.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..e4c343c811f66843e7ab5b72e1a7e8712c204ee3
--- /dev/null
+++ b/Base/logog/include/logog.hpp
@@ -0,0 +1,36 @@
+/**
+ * \file logog.hpp Main include file for logog logging functionality.  Include this file to enable logging for your application.
+ */
+
+#ifndef __LOGOG_HPP__
+#define __LOGOG_HPP__
+
+/** \def LOGOG_UNICODE
+ ** Define this macro to enable Unicode support in logog.  The logog library works either in Unicode mode or not --
+ ** attempting to mix the two log types will have unexpected results.
+ **/
+// #define LOGOG_UNICODE 1
+
+#include "const.hpp"
+#include "platform.hpp"
+#include "statics.hpp"
+#include "object.hpp"
+#include "timer.hpp"
+#include "mutex.hpp"
+#include "string.hpp"
+#include "node.hpp"
+#include "topic.hpp"
+#include "formatter.hpp"
+#include "target.hpp"
+// #include "socket.hpp"
+#include "checkpoint.hpp"
+#include "api.hpp"
+#include "message.hpp"
+#include "macro.hpp"
+
+#ifdef LOGOG_UNIT_TESTING
+#include "thread.hpp"
+#include "unittest.hpp"
+#endif
+
+#endif // __LOGOG_HPP_
diff --git a/Base/logog/include/macro.hpp b/Base/logog/include/macro.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..97b661f8a3879f7fd1792f6cf0c8174b6efca5b8
--- /dev/null
+++ b/Base/logog/include/macro.hpp
@@ -0,0 +1,240 @@
+/**
+ * \file macro.hpp Macros for instantiation of a message.
+ */
+
+#ifndef __LOGOG_MACRO_HPP__
+#define __LOGOG_MACRO_HPP__
+
+namespace logog
+{
+#ifdef LOGOG_USE_PREFIX
+#define LOGOG_PREFIX LOGOG_
+#endif // LOGOG_USE_PREFIX
+
+#ifndef LOGOG_GROUP
+/** This is the current group for created messages.  Set this to NULL if you
+  * want messages to not be part of any specific group.
+  */
+#define LOGOG_GROUP NULL
+#endif
+
+#ifndef LOGOG_CATEGORY
+/** This is the current category for created messages.  Set this to NULL if you
+  * want messages to not be part of any specific group.
+  */
+#define LOGOG_CATEGORY NULL
+#endif
+
+/** When you have a macro replacement, the preprocessor will only expand the macros recursively
+ * if neither the stringizing operator # nor the token-pasting operator ## are applied to it.
+ * So, you have to use some extra layers of indirection, you can use the token-pasting operator
+ * with a recursively expanded argument.
+ */
+#define TOKENPASTE2(x, y) x ## y
+/** \sa TOKENPASTE2(x, y) */
+#define TOKENPASTE(x, y) TOKENPASTE2(x, y)
+
+/** This macro is used when a message is instantiated without any varargs
+  * provided by the user.  It locks a global mutex, creates the message,
+  * locks it, transmits it, and releases all locks.
+  */
+#define LOGOG_LEVEL_GROUP_CATEGORY_MESSAGE_NO_VA( level, group, cat, msg ) \
+{ \
+	Mutex *___pMCM = &GetMessageCreationMutex(); \
+	___pMCM->MutexLock(); \
+	static logog::Message *TOKENPASTE(_logog_,__LINE__) = new logog::Message( level, \
+		LOGOG_CONST_STRING( __FILE__ ), \
+		__LINE__ , \
+		LOGOG_CONST_STRING( group ), \
+		LOGOG_CONST_STRING( cat ), \
+		msg; \
+	___pMCM->MutexUnlock(); \
+	TOKENPASTE(_logog_,__LINE__)->m_Transmitting.MutexLock(); \
+	TOKENPASTE(_logog_,__LINE__)->Transmit(); \
+	TOKENPASTE(_logog_,__LINE__)->m_Transmitting.MutexUnlock(); \
+}
+
+/** This macro is used when a message is instantiated with varargs provided
+  * by the user.  It locks a global mutex, creates the message, locks it,
+  * formats the message string inside the message, transmits it, 
+  * and releases all locks.
+  * When logog is shut down, it may be started back up again later.  Therefore,
+  * logog needs a way to flag all static Message pointers that they need
+  * to be recreated.  We manually simulate a static Message pointer by 
+  * implementing it via a static bool.  The bool is turned on the first time
+  * this code is run.
+  * NOTE!  A subtle race condition exists in the following code, that will ONLY occur
+  * if logog is shut down at the same moment that a log message is processed from
+  * another thread than the one calling the shutdown.  The Message object could
+  * theoretically be destroyed from another thread just before it's locked
+  * in a thread that calls the Format() and Transmit() calls on it.  I'm not
+  * sure if this is really a bug -- technically, this race condition will
+  * occur only if you are calling log messages right on top of the SHUTDOWN
+  * call from the main thread.
+  */
+#define LOGOG_LEVEL_GROUP_CATEGORY_MESSAGE( level, group, cat, formatstring, ... ) \
+{ \
+	::logog::Mutex *___pMCM = &::logog::GetMessageCreationMutex(); \
+	___pMCM->MutexLock(); \
+	static bool TOKENPASTE(_logog_static_bool_,__LINE__) = false; \
+	static logog::Message * TOKENPASTE(_logog_,__LINE__); \
+	if ( TOKENPASTE(_logog_static_bool_,__LINE__) == false ) \
+	{ \
+		TOKENPASTE(_logog_,__LINE__) = \
+			new logog::Message( level, \
+				LOGOG_CONST_STRING( __FILE__ ), \
+				__LINE__ , \
+				LOGOG_CONST_STRING( group ), \
+				LOGOG_CONST_STRING( cat ), \
+				LOGOG_CONST_STRING( "" ), \
+				0.0f, \
+				& (TOKENPASTE(_logog_static_bool_,__LINE__)) ); \
+	} \
+	___pMCM->MutexUnlock(); \
+	/* A race condition could theoretically occur here if you are shutting down at the same instant as sending log messages. */ \
+	TOKENPASTE(_logog_,__LINE__)->m_Transmitting.MutexLock(); \
+	TOKENPASTE(_logog_,__LINE__)->Format( formatstring, ##__VA_ARGS__ ); \
+	TOKENPASTE(_logog_,__LINE__)->Transmit(); \
+	TOKENPASTE(_logog_,__LINE__)->m_Transmitting.MutexUnlock(); \
+}
+
+/** Calls LOGOG_LEVEL_GROUP_CATEGORY_MESSAGE with the current LOGOG_GROUP and
+  * LOGOG_CATEGORY setting.
+  */
+#define LOGOG_LEVEL_MESSAGE( level, formatstring, ... ) \
+	LOGOG_LEVEL_GROUP_CATEGORY_MESSAGE( level, LOGOG_GROUP, LOGOG_CATEGORY, formatstring, ##__VA_ARGS__ )
+
+/** Calls LOGOG_LEVEL_MESSAGE with the current LOGOG_LEVEL setting. */
+#define LOGOG_MESSAGE( formatstring, ... ) \
+	LOGOG_LEVEL_MESSAGE( LOGOG_LEVEL, formatstring, ##__VA_ARGS__ )
+
+
+#if LOGOG_LEVEL >= LOGOG_LEVEL_DEBUG
+/** Logs a message at the DEBUG reporting level. */
+#define LOGOG_DEBUG( formatstring, ... ) \
+	LOGOG_LEVEL_MESSAGE( LOGOG_LEVEL_DEBUG, formatstring, ##__VA_ARGS__ )
+#else
+#define LOGOG_DEBUG( formatstring, ... ) {};
+#endif
+
+#if LOGOG_LEVEL >= LOGOG_LEVEL_INFO
+/** Logs a message at the INFO reporting level. */
+#define LOGOG_INFO( formatstring, ... ) \
+	LOGOG_LEVEL_MESSAGE( LOGOG_LEVEL_INFO, formatstring, ##__VA_ARGS__ )
+#else
+#define LOGOG_INFO( formatstring, ... ) {};
+#endif
+
+#if LOGOG_LEVEL	>= LOGOG_LEVEL_WARN3
+/** Logs a message at the WARN3 reporting level. */
+#define LOGOG_WARN3( formatstring, ... ) \
+	LOGOG_LEVEL_MESSAGE( LOGOG_LEVEL_WARN3, formatstring, ##__VA_ARGS__ )
+#else
+#define LOGOG_WARN3( formatstring, ... ) {};
+#endif
+
+#if LOGOG_LEVEL	>= LOGOG_LEVEL_WARN2
+/** Logs a message at the WARN2 reporting level. */
+#define LOGOG_WARN2( formatstring, ... ) \
+	LOGOG_LEVEL_MESSAGE( LOGOG_LEVEL_WARN2, formatstring, ##__VA_ARGS__ )
+#else
+#define LOGOG_WARN2( formatstring, ... ) {};
+#endif
+
+#if LOGOG_LEVEL	>= LOGOG_LEVEL_WARN1
+/** Logs a message at the WARN1 reporting level. */
+#define LOGOG_WARN1( formatstring, ... ) \
+	LOGOG_LEVEL_MESSAGE( LOGOG_LEVEL_WARN1, formatstring, ##__VA_ARGS__ )
+#else
+#define LOGOG_WARN1( formatstring, ... ) {};
+#endif
+
+#if LOGOG_LEVEL	>= LOGOG_LEVEL_WARN
+/** Logs a message at the WARN reporting level. */
+#define LOGOG_WARN( formatstring, ... ) \
+	LOGOG_LEVEL_MESSAGE( LOGOG_LEVEL_WARN, formatstring, ##__VA_ARGS__ )
+#else
+#define LOGOG_WARN( formatstring, ... ) {};
+#endif
+
+#if LOGOG_LEVEL	>= LOGOG_LEVEL_ERROR
+/** Logs a message at the ERROR reporting level. */
+#define LOGOG_ERROR( formatstring, ... ) \
+	LOGOG_LEVEL_MESSAGE( LOGOG_LEVEL_ERROR, formatstring, ##__VA_ARGS__ )
+#else
+#define LOGOG_ERROR( formatstring, ... ) {};
+#endif
+
+#if LOGOG_LEVEL	>= LOGOG_LEVEL_CRITICAL
+/** Logs a message at the CRITICAL reporting level. */
+#define LOGOG_CRITICAL( formatstring, ... ) \
+	LOGOG_LEVEL_MESSAGE( LOGOG_LEVEL_CRITICAL, formatstring, ##__VA_ARGS__ )
+#else
+#define LOGOG_CRITICAL( formatstring, ... ) {};
+#endif
+
+#if LOGOG_LEVEL	>= LOGOG_LEVEL_ALERT
+/** Logs a message at the ALERT reporting level. */
+#define LOGOG_ALERT( formatstring, ... ) \
+	LOGOG_LEVEL_MESSAGE( LOGOG_LEVEL_ALERT, formatstring, ##__VA_ARGS__ )
+#else
+#define LOGOG_ALERT( formatstring, ... ) {};
+#endif
+
+#if LOGOG_LEVEL	>= LOGOG_LEVEL_EMERGENCY
+/** Logs a message at the EMERGENCY reporting level. */
+#define LOGOG_EMERGENCY( formatstring, ... ) \
+	LOGOG_LEVEL_MESSAGE( LOGOG_LEVEL_EMERGENCY, formatstring, ##__VA_ARGS__ )
+#else
+#define LOGOG_EMERGENCY( formatstring, ... ) {};
+#endif
+
+#define LOGOG_SET_LEVEL( level ) \
+	::logog::SetDefaultLevel( level );
+
+/** Define this compilation flag if your compilation environment conflicts with
+  * any of the shorthand logging macros in macro.hpp.
+  */
+#ifndef LOGOG_USE_PREFIX
+/* If you get compilation errors in this section, then define the flag LOGOG_USE_PREFIX during compilation, and these
+ * shorthand logging macros won't exist -- you'll need to use the LOGOG_* equivalents above.
+ */
+/* We can't use DEBUG in Win32 unfortunately, so we use DBUG for shorthand here. */
+//! [Shorthand]
+/** \sa LOGOG_DEBUG */
+#define DBUG(...) LOGOG_DEBUG( __VA_ARGS__ )
+/** \sa LOGOG_INFO */
+#define INFO(...) LOGOG_INFO( __VA_ARGS__ )
+/** \sa LOGOG_WARN3 */
+#define WARN3(...) LOGOG_WARN3( __VA_ARGS__ )
+/** \sa LOGOG_WARN2 */
+#define WARN2(...) LOGOG_WARN2( __VA_ARGS__ )
+/** \sa LOGOG_WARN1 */
+#define WARN1(...) LOGOG_WARN1( __VA_ARGS__ )
+/** \sa LOGOG_WARN */
+#define WARN(...) LOGOG_WARN( __VA_ARGS__ )
+/** \sa LOGOG_ERROR */
+#define ERR(...) LOGOG_ERROR( __VA_ARGS__ )
+/** \sa LOGOG_ALERT */
+#define ALERT(...) LOGOG_ALERT( __VA_ARGS__ )
+/** \sa LOGOG_CRITICAL */
+#define CRITICAL(...) LOGOG_CRITICAL( __VA_ARGS__ )
+/** \sa LOGOG_EMERGENCY */
+#define EMERGENCY(...) LOGOG_EMERGENCY( __VA_ARGS__ )
+//! [Shorthand]
+#endif
+
+/** Call this function to initialize logog and prepare for logging. 
+  * \sa logog::Initialize()
+  */
+#define LOGOG_INITIALIZE(...)  logog::Initialize( __VA_ARGS__ );
+
+/** Call this function to shut down logog and release all memory allocated.
+  * \sa logog::Shutdown()
+  */
+
+#define LOGOG_SHUTDOWN()   logog::Shutdown();
+
+} // namespace logog
+
+#endif // __LOGOG_MACRO_HPP_
diff --git a/Base/logog/include/message.hpp b/Base/logog/include/message.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..c7d7dc659c9f2ca706a99c34180712f727a01911
--- /dev/null
+++ b/Base/logog/include/message.hpp
@@ -0,0 +1,45 @@
+/**
+ * \file message.hpp Messages; items transmitted to a log.
+ */
+
+#ifndef __LOGOG_MESSAGE_HPP__
+#define __LOGOG_MESSAGE_HPP__
+
+namespace logog
+{
+
+/** A message is a piece of text that's actually transmitted to outputs.  Messages can be asked to 
+ ** Transmit() themselves once they are created.
+ **/
+class Message : public Checkpoint
+{
+public:
+    Message( const LOGOG_LEVEL_TYPE level = LOGOG_LEVEL_ALL,
+             const LOGOG_CHAR *sFileName = NULL,
+             const int nLineNumber = 0,
+             const LOGOG_CHAR *sGroup = NULL,
+             const LOGOG_CHAR *sCategory = NULL,
+             const LOGOG_CHAR *sMessage = NULL,
+             const double dTimestamp = 0.0f,
+			 bool *bIsCreated = NULL );
+
+	virtual ~Message();
+
+    /** Causes this checkpoint to republish itself to all existing filters after
+      * unpublishing itself.  This can be necessary if the message within this
+      * message has changed in such a way that the downstream Filter objects
+      * might react differently to it.
+      */
+    virtual bool Republish();
+
+	Mutex m_Transmitting;
+	bool *m_pbIsCreated;
+};
+
+extern Mutex &GetMessageCreationMutex();
+extern void DestroyMessageCreationMutex();
+
+}
+
+
+#endif // __LOGOG_MESSAGE_HPP_
diff --git a/Base/logog/include/mutex.hpp b/Base/logog/include/mutex.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..c9916f0eaa568e0c486d84036526289c34b64782
--- /dev/null
+++ b/Base/logog/include/mutex.hpp
@@ -0,0 +1,98 @@
+/**
+ * \file mutex.hpp Defines a mutual exclusion object for the current platform.
+ */
+
+#ifndef __LOGOG_MUTEX_HPP__
+#define __LOGOG_MUTEX_HPP__
+
+#ifdef LOGOG_FLAVOR_POSIX
+#include <pthread.h>
+#endif
+
+namespace logog
+{
+
+//! [Mutex]
+#ifndef LOGOG_MUTEX
+
+#ifdef LOGOG_FLAVOR_WINDOWS
+#define LOGOG_MUTEX(x)           CRITICAL_SECTION (x);
+#define LOGOG_MUTEX_INIT(x)      InitializeCriticalSection (x)
+#define LOGOG_MUTEX_DELETE(x)    DeleteCriticalSection (x)
+#define LOGOG_MUTEX_LOCK(x)      EnterCriticalSection (x)
+#define LOGOG_MUTEX_UNLOCK(x)    LeaveCriticalSection (x)
+#define LOGOG_MUTEX_CTOR(x)
+#endif // LOGOG_FLAVOR_WINDOWS
+
+#ifdef LOGOG_FLAVOR_POSIX
+#define LOGOG_MUTEX(x)           pthread_mutex_t (x);
+#define LOGOG_MUTEX_INIT(x)      pthread_mutex_init(x, 0)
+#define LOGOG_MUTEX_DELETE(x)    pthread_mutex_destroy (x)
+#define LOGOG_MUTEX_LOCK(x)      pthread_mutex_lock (x)
+#define LOGOG_MUTEX_UNLOCK(x)    pthread_mutex_unlock (x)
+#define LOGOG_MUTEX_CTOR(x)
+#endif // LOGOG_FLAVOR_POSIX
+#endif // LOGOG_MUTEX
+
+#ifndef LOGOG_MUTEX
+#error You need to define mutex macros for your platform; please see mutex.hpp
+#endif
+
+//! [Mutex]
+
+/** An object that can only be locked by one thread at a time.  Implement the LOGOG_MUTEX_* functions for your platform
+ * to support the Mutex object.
+ * A mutex is intended to be used with the ScopedLock object to implement critical sections within logog.
+ * \sa ScopedLock
+ */
+class Mutex : public Object
+{
+public:
+    Mutex();
+    ~Mutex();
+    /** Acquires a lock on the mutex.  Only one thread is permitted to lock the mutex at one time. */
+    void MutexLock();
+    /** Releases the lock on the mutex. */
+	void MutexUnlock();
+
+protected:
+    Mutex(const Mutex &);
+    Mutex & operator = (const Mutex &);
+
+    LOGOG_MUTEX( m_Mutex )
+};
+
+/** Asserts a lock while this object exists and is in scope.  A ScopedLock should be
+ * declared in "auto" format, typically on the stack.
+ */
+class ScopedLock : public Object
+{
+public :
+    /** Instances and locks a ScopedLock.
+     * \param mutex The mutex to attempt to lock.  Program execution halts at this point until the lock can be obtained.
+     */
+    ScopedLock( Mutex &mutex );
+    ~ScopedLock();
+protected:
+    /** A pointer to the lockable mutex. */
+    Mutex *m_pMutex;
+
+private:
+    /* no default constructor */
+    ScopedLock();
+    /* no copy constructor */
+    ScopedLock( const ScopedLock &other );
+};
+
+#ifdef LOGOG_LEAK_DETECTION
+extern Mutex s_AllocationsMutex;
+extern void LockAllocationsMutex();
+extern void UnlockAllocationsMutex();
+#endif // LOGOG_LEAK_DETECTION
+
+extern Mutex &GetStringSearchMutex();
+extern void DestroyStringSearchMutex();
+
+}
+
+#endif // __LOGOG_MUTEX_HPP_
diff --git a/Base/logog/include/node.hpp b/Base/logog/include/node.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..8174635b4821c521d681d8b77c73a0bcc655bf06
--- /dev/null
+++ b/Base/logog/include/node.hpp
@@ -0,0 +1,142 @@
+/**
+ * \file node.hpp Base class for higher-level logog objects.
+ */
+
+#ifndef __LOGOG_NODE_HPP__
+#define __LOGOG_NODE_HPP__
+
+namespace logog
+{
+/** The base class for most high-level logog objects.  Represents the publisher-subscriber
+ ** model within logog. */
+class Node;
+
+/** An aggregation of nodes.  Internally, we choose a set representation because we want to be able to traverse
+ ** the aggregation quickly while still looking up entries quickly.
+ **/
+typedef LOGOG_SET< Node *, std::less< Node * >, Allocator< Node * > > NodesType;
+
+/** A type that double inherits from NodesType and Mutex.  A lockable NodesType.  Handles the copy
+ ** case correctly.
+ **/
+class LockableNodesType : public NodesType, public Mutex
+{
+public:
+    /** A LockableNodesType shouldn't copy the internal Mutex when it is copied, but it
+     ** should copy all the internal nodes.
+     **/
+    LockableNodesType & operator = (const LockableNodesType &other);
+};
+
+extern LockableNodesType &GetStaticNodes( void ** pvLocation );
+
+/** Returns a reference to the global nodes group.  Allocates a new global node group if one does not already
+ ** exist.
+ */
+extern LockableNodesType &AllNodes();
+
+/** Returns a reference to the group of nodes that are capable of subscribing.  Allocates a new global subscriber
+ ** node group if one does not already exist.
+ */
+extern LockableNodesType &AllSubscriberNodes();
+
+/** Returns a reference to the group of nodes that are capable of both subscribing as well as publishing.  Allocates a new global subscriber
+ ** node group if one does not already exist.
+ */
+extern LockableNodesType &AllFilters();
+
+/** Returns a reference to the group of nodes that represent terminals in the graph, i.e. nodes that can't publish. */
+extern LockableNodesType &AllTargets();
+
+class Node : public Object
+{
+public:
+
+    /** All nodes self-register as part of the all-nodes database. */
+    Node();
+
+    ~Node();
+
+    /** Call this function immediately after creating a node (or any of the children of the node class.)  This function currently
+     ** registers the node as part of the list of subscriber nodes, if this node may in fact subscribe.
+     ** If this node is capable of subscribing at all, then this function registers this node as a possible subscriber.
+     ** Doing this helps to keep down the number of nodes we search, when we are determining which nodes a new node
+     ** might subscribe to.  We have to do this registration as a second step, after the node is completely
+     ** initialized, as subscriberness is determined late in initialization.
+     **/
+    virtual void Initialize();
+
+    /** Can a node send notifications?  By default they can; later subclasses may not be able to. */
+    virtual bool CanPublish() const;
+    /** Can a node receive notifications?  By default they can; later subclasses may not be able to. */
+    virtual bool CanSubscribe() const;
+    /** Is this node interested in receiving notifications from another topic? */
+    virtual bool CanSubscribeTo( const Node & );
+
+    /** In order to avoid bringing in a bunch of RTTI stuff, we permit nodes to be asked whether they're topics or not */
+    virtual bool IsTopic() const;
+
+    /** Causes this node to begin publishing events to the given subscriber.
+     ** \param subscriber The node to receive published events
+     ** \return true if the request was successful, false if the subscriber was already subscribed
+     **/
+    virtual bool PublishTo( Node &subscriber );
+
+    /** Causes this node to attempt to publish to some other nodes. */
+    virtual bool PublishToMultiple( LockableNodesType &nodes );
+
+    /** Causes this node to stop publishing events to this subscriber.
+     ** \param subscriber The node to stop receiving events
+     ** \return true if successful, false if the subscriber was not being published to in the first place
+     **/
+    virtual bool UnpublishTo( Node &subscriber );
+
+    /** Causes this node to attempt to unpublish to some other nodes. */
+    virtual bool UnpublishToMultiple( LockableNodesType &nodes );
+
+    /** Causes this node to start receiving events from the given publisher.
+     ** \param publisher The node to start receiving events from
+     ** \return true if successful, false if the publisher was already subscribed
+     **/
+    virtual bool SubscribeTo( Node &publisher );
+
+    /** Causes this node to attempt to subscribe to some other nodes. */
+    virtual bool SubscribeToMultiple( LockableNodesType &nodes );
+
+
+    /** Causes this node to unsubscribe from the given publisher's events.
+    ** \param publisher The publisher to unsubscribe from
+    ** \return true if successful, false if the node was already unsubscribed
+    **/
+    virtual bool UnsubscribeTo( Node &publisher );
+
+    /** Causes this node to attempt to unsubscribe to some other nodes. */
+    virtual bool UnsubscribeToMultiple( LockableNodesType &nodes );
+
+    void Clear();
+
+
+    /** A pointer to any custom data you need to store for a node. */
+    void *m_pUserData1;
+
+    /** A pointer to any custom data you need to store for a node. */
+    void *m_pUserData2;
+
+protected:
+    /** A bunch of nodes that are interested in what this node has to report. */
+    LockableNodesType	m_Subscribers;
+
+    /** A bunch of nodes that this node interested in hearing from. */
+    LockableNodesType	m_Publishers;
+};
+
+extern void DestroyNodesList( void **pvList );
+
+/** Destroys all nodes currently recorded.  This happens at shutdown time.  NOTE!  If you have allocated
+ ** your own logog items and free them yourself AFTER this call, exciting crashes will occur.
+ **/
+extern void DestroyAllNodes();
+
+}
+
+#endif // __LOGOG_NODE_HPP_
diff --git a/Base/logog/include/object.hpp b/Base/logog/include/object.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..2ecbf5806dae9e7c96f6406c677a426caeedb0c0
--- /dev/null
+++ b/Base/logog/include/object.hpp
@@ -0,0 +1,221 @@
+/**
+ * \file object.hpp Base class for all allocated logog objects.
+ */
+
+#ifndef __LOGOG_OBJECT_HPP__
+#define __LOGOG_OBJECT_HPP__
+
+namespace logog
+{
+
+#ifdef LOGOG_LEAK_DETECTION
+/** Iteration over an unordered map is slow, but we only do it at shutdown time.  Access to a lookup or insert
+ ** is very fast.  Additionally, we do not allocate leak detection records from our own heap; it saves us from
+ ** doing a recursive allocation.
+ **/
+typedef void *PointerType;
+
+/** A type describing the currently outstanding memory allocations.  Note that this type does not inherit from
+ ** Object, because to do so would create an infinite recursion when memory is allocated.
+ **/
+typedef LOGOG_UNORDERED_MAP< PointerType, size_t > AllocationsType;
+
+/** All currently outstanding memory allocations, including their size.  */
+extern AllocationsType s_Allocations;
+
+/** A global function to lock the global allocations mutex.  We must do this as a static
+ ** void because Mutexes depend on Objects.  This should probably belong in a class, but then
+ ** we get recursive class definitions.
+ ** */
+extern void LockAllocationsMutex();
+
+/** A global function to unlock the global allocations mutex.  We must do this as a static
+ ** void because Mutexes depend on Objects. */
+extern void UnlockAllocationsMutex();
+#endif // LOGOG_LEAK_DETECTION
+
+#ifdef new
+#define LOGOG_PREVIOUS_DEFINITION_OF_NEW new
+#undef new
+#endif
+#ifdef delete
+#define LOGOG_PREVIOUS_DEFINITION_OF_DELETE delete
+#undef delete
+#endif	//delete
+
+/** Base class for all objects allocated with logog. */
+class Object
+{
+public:
+    Object();
+	/* Some builds complain about ~Object() being virtual... sorry lint :( */
+    virtual ~Object();
+    /** Initializes an object of size new. */
+    void *operator new( size_t nSize );
+    /** Initializes an array of size new. */
+    void *operator new[](size_t nSize);
+
+	/* There's a wonderful behavior in Windows MFC in debug builds that causes it 
+	 * to attempt to redefine NEW with a macro if we're compiling in debug mode
+	 * and we're using Gdiplus as well.  In that case, Windows attempts to redefine
+	 * new with a macro for everything that has a new.  This wonderful behavior 
+	 * is worked around here.  See http://support.microsoft.com/kb/317799/EN-US/
+	 * and http://social.msdn.microsoft.com/Forums/en/vcgeneral/thread/0df13145-670e-4070-b0a1-61794b20dff7
+	 * for more exciting information.
+	 */
+#ifdef _DEBUG
+#ifdef LOGOG_FLAVOR_WINDOWS
+	void* operator new(size_t nSize, LPCSTR lpszFileName, int nLine);
+	void* operator new[](size_t nSize, LPCSTR lpszFileName, int nLine);
+	void  operator delete(void* ptr, LPCSTR lpszFileName, int nLine);
+	void  operator delete[](void* ptr, LPCSTR lpszFileName, int nLine);
+#endif // LOGOG_FLAVOR_WINDOWS
+#endif // _DEBUG
+
+    /** Deletes an object pointed to by ptr. */
+    void operator delete( void *ptr );
+    /** Deletes an object array pointed to by ptr. */
+    void operator delete[]( void *ptr );
+
+    /** Allocates nSize bytes of memory.  You must call logog::Initialize() before calling this function.
+     * \sa Initialize()
+     */
+    static void *Allocate( size_t nSize );
+
+    /** Deallocate a pointer previously acquired by Allocate(). */
+    static void Deallocate( void *ptr );
+ };
+
+#ifdef LOGOG_PREVIOUS_DEFINITION_OF_NEW
+#define new LOGOG_PREVIOUS_DEFINITION_OF_NEW
+#endif 
+
+#ifdef LOGOG_PREVIOUS_DEFINITION_OF_DELETE
+#define delete GA_PREVIOUS_DEFINITION_OF_DELETE
+#endif
+
+/** An STL-compatible allocator which redirects all memory requests to the logog allocator.  Used for all STL-like classes within logog. */
+template <class T>
+class Allocator
+{
+public:
+    /** Memory allocation size type. */
+    typedef size_t    size_type;
+    /** Memory allocation comparison type. */
+    typedef ptrdiff_t difference_type;
+    /** A pointer to T type. */
+    typedef T        *pointer;
+    /** A const pointer to T type. */
+    typedef const T  *const_pointer;
+    /** A reference to T type. */
+    typedef T        &reference;
+    /** A const reference to T type. */
+    typedef const T  &const_reference;
+    /** A value type (T itself). */
+    typedef T         value_type;
+
+    Allocator() {}
+    /** Not implemented here -- required by the STL standard though. */
+    Allocator( const Allocator & ) {}
+
+    /** Allocate and return n value_types of memory through this allocator.  Requires that logog::Initialize() has been called. */
+    pointer   allocate( size_type n, const void * = 0 )
+    {
+        T *t = ( T * ) Object::Allocate( n * sizeof( value_type ) );
+        return t;
+    }
+
+    /** Frees memory previously allocated by allocate(). */
+    void      deallocate( void *p, size_type )
+    {
+        if ( p )
+        {
+            Object::Deallocate( p );
+        }
+    }
+
+    /** Returns the address of a reference to T. */
+    pointer           address( reference x ) const
+    {
+        return &x;
+    }
+    /** Returns the address of a const reference to T. */
+    const_pointer     address( const_reference x ) const
+    {
+        return &x;
+    }
+    /** STL required override for = operator. */
+    Allocator<T>&  operator=( const Allocator & )
+    {
+        return *this;
+    }
+    /** Constructs a new T at location p with value val. */
+    void              construct( pointer p, const T &val )
+    {
+        new(( T * ) p ) T( val );
+    }
+    /** Destroys a T at location p. */
+    void              destroy( pointer p )
+    {
+#ifdef LOGOG_FLAVOR_WINDOWS
+        // MSVC tends to complain unless we reference this pointer here.
+        p;
+#endif // LOGOG_FLAVOR_WINDOWS
+        p->~T();
+    }
+
+    /** The largest size of an object that can be allocated with this allocator. */
+    size_type         max_size() const
+    {
+        return size_t( -1 );
+    }
+
+    /** Rebinding to permit allocations of unknown types.  Part of std::allocator definition.
+     * \param other The other "unknown" type to be permitted access to this allocator */
+    template <class U>
+    struct rebind
+    {
+        /** The "other" class that will use this allocator for its allocation. */
+        typedef Allocator<U> other;
+    };
+
+    /** Required by STL -- unused here. */
+    template <class U>
+    Allocator( const Allocator<U>& ) {}
+
+    /** Permit this allocator to be used for assignment in other classes */
+    template <class U>
+    Allocator &operator=( const Allocator<U>& )
+    {
+        return *this;
+    }
+};
+
+/* All specializations of this allocator are interchangeable. */
+template <class T1, class T2>
+bool operator== ( const Allocator<T1>&,
+                  const Allocator<T2>& )
+{
+    return true;
+}
+template <class T1, class T2>
+bool operator!= ( const Allocator <T1>&,
+                  const Allocator<T2>& )
+{
+    return false;
+}
+
+//
+
+/** Returns the current number of outstanding memory allocations in logog.  Returns -1 iff LOGOG_LEAK_DETECTION
+ ** has not been defined at compile time.
+ **/
+extern int MemoryAllocations();
+
+/** Sends a report to cout describing the current memory allocations that exist.  Returns the outstanding number of
+ ** memory allocations, or -1 iff LOGOG_LEAK_DETECTION is defined.
+ **/
+extern int ReportMemoryAllocations();
+
+}
+#endif // __LOGOG_OBJECT_HPP
diff --git a/Base/logog/include/platform.hpp b/Base/logog/include/platform.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..4f39ebe091b4fe6aee496b4af3c2e2c1f54eba87
--- /dev/null
+++ b/Base/logog/include/platform.hpp
@@ -0,0 +1,180 @@
+/**
+ * \file platform.hpp Platform specific detection and defines, including STL overrides
+ */
+
+#ifndef __LOGOG_PLATFORM_HPP__
+#define __LOGOG_PLATFORM_HPP__
+
+#ifdef DOXYGEN
+/** Set this compilation flag to 1 to indicate that this is a Windows-like platform, e.g. Win32, Win64, Xbox 360, etc. */
+#define LOGOG_FLAVOR_WINDOWS 1
+/**  Set this compilation flag to 1 to indicate that this is a Posix-like platform, e.g. Linux, PS3, etc. */
+#define LOGOG_FLAVOR_POSIX 1
+#endif
+
+#ifndef LOGOG_FLAVOR_WINDOWS
+#ifndef LOGOG_FLAVOR_POSIX
+
+/* The user hasn't told us which flavor we're running on, so we must make a guess as to which platform is valid. */
+
+/* If this is MSVC, then it's Windows like */
+#ifdef _MSC_VER
+#define LOGOG_FLAVOR_WINDOWS 1
+#endif // _MSC_VER
+
+/* gcc probably means Posix */
+#ifdef __GNUC__
+#define LOGOG_FLAVOR_POSIX 1
+#endif
+
+#ifdef __CYGWIN__
+#ifdef LOGOG_UNICODE
+#error LOGOG_UNICODE not supported on Cygwin platform because Cygwin does not support vsnwprintf
+#endif
+/* Cygwin lacks vsnprintf support in headers but it's in the libraries.  First we
+ * need to define the constants size_t and va_list, then define vsnprintf */
+#include <cstdio>
+#include <cstdlib>
+#include <cstdarg>
+extern int vsnprintf(char *str, size_t size, const char *format, va_list ap);
+#define LOGOG_USE_TR1 1
+#endif // __CYGWIN__
+
+#ifdef __linux__
+#define LOGOG_USE_TR1 1
+#endif
+
+#ifdef __APPLE__
+#define LOGOG_USE_TR1 1
+#endif
+
+/* If we've recognized it already, it's a relatively modern compiler */
+#if defined( LOGOG_FLAVOR_WINDOWS ) || defined( LOGOG_FLAVOR_POSIX )
+#define LOGOG_HAS_UNORDERED_MAP 1
+#endif // defined(...)
+
+/* PS3 */
+#ifdef SN_TARGET_PS3
+#include "proprietary/ps3.hpp"
+#endif
+
+#endif // LOGOG_FLAVOR_POSIX
+#endif // LOGOG_FLAVOR_WINDOWS
+
+#ifdef LOGOG_FLAVOR_WINDOWS
+/* Detect Xbox 360 */
+#if _XBOX_VER >= 200
+#include "proprietary/xbox360.hpp"
+#else
+/* Windows has been detected. */
+
+/** Microsoft's CRT library has its own leak detection mechanism.  If you don't trust logog's
+ ** LOGOG_LEAK_DETECTION, you can enable LOGOG_LEAK_DETECTION_WINDOWS to enable
+ ** Microsoft's version.  This really doesn't belong in platform.hpp -- feel
+ ** free to refactor this into a Windows-specific header.
+ **/
+#ifdef LOGOG_LEAK_DETECTION_WINDOWS
+#define _CRTDBG_MAP_ALLOC
+#include <stdlib.h>
+#include <crtdbg.h>
+
+#ifdef _DEBUG
+#ifndef DBG_NEW
+#define DBG_NEW new ( _NORMAL_BLOCK , __FILE__ , __LINE__ )
+#define new DBG_NEW
+#endif
+#endif  // _DEBUG
+#endif // LOGOG_LEAK_DETECTION_WINDOWS
+
+#include "windows.h"
+#endif // _XBOX_VER
+#endif // LOGOG_FLAVOR_WINDOWS
+
+#ifndef LOGOG_FLAVOR_WINDOWS
+#ifndef LOGOG_FLAVOR_POSIX
+#error Platform flavor not detected.  Please see platform.hpp to configure this platform.
+#endif
+#endif
+
+// For the FILE type.
+#include <cstdio>
+// For POSIX file access.
+#include <cstdlib>
+// For Ubuntu 11 and ptrdiff_t
+#include <cstddef>
+
+#include <ctime>
+
+#if defined(LOGOG_LEAK_DETECTION) || defined(LOGOG_INTERNAL_DEBUGGING)
+#include <cstdio>
+#include <iostream>
+#endif // LOGOG_LEAK_DETECTION || LOGOG_INTERNAL_DEBUGGING
+
+#ifdef LOGOG_FLAVOR_POSIX
+#include <sys/time.h>
+// for uint64_t
+#include <inttypes.h>
+#include <wchar.h>
+// for strstr support
+#include <cstring>
+#endif
+
+// For Unicode support
+#include <typeinfo>
+
+/* ----------------------------------------------------------- */
+/* Here's the stuff your compiler may have a problem with...   */
+
+//! [STLTypes]
+
+/** The definition for a hash type in logog.  You can replace it here with your own set compatible class if needed. */
+#define LOGOG_HASH			std::tr1::hash
+/** The definition for an unordered map type in logog.  You can replace it here with your own unordered_map compatible class if needed. */
+
+#ifdef LOGOG_HAS_UNORDERED_MAP
+#ifdef LOGOG_USE_TR1
+#include <tr1/unordered_map>
+#else
+#include <unordered_map>
+#endif // LOGOG_USE_TR1
+#ifdef _GLIBCXX_UNORDERED_MAP
+#define LOGOG_UNORDERED_MAP	std::unordered_map
+#else // _GLIBCXX_UNORDERED_MAP
+#define LOGOG_UNORDERED_MAP	std::tr1::unordered_map
+#endif  // _GLIBCXX_UNORDERED_MAP
+#else // LOGOG_HAS_UNORDERED_MAP
+#include <hash_map>
+#define LOGOG_UNORDERED_MAP std::hash_map
+#endif // LOGOG_HAS_UNORDERED_MAP
+
+/** An internal consistency error has been detected in logog.  */
+#define LOGOG_INTERNAL_FAILURE	abort();
+
+/* ----------------------------------------------- */
+/* Here's the stuff that's pretty standard in STL by now. */
+
+/** The definition for a pair type in logog.  You can replace it here with your own pair compatible class if needed. */
+#define LOGOG_PAIR			std::pair
+#include <list>
+/** The definition for a list type in logog.  You can replace it here with your own list compatible class if needed. */
+#define LOGOG_LIST			std::list
+#include <vector>
+/** The definition for a vector type in logog.  You can replace it here with your own vector compatible class if needed. */
+#define LOGOG_VECTOR		std::vector
+#include <set>
+/** The definition for a set type in logog.  You can replace it here with your own set compatible class if needed. */
+#define LOGOG_SET			std::set
+/** The definition for STL "equal to" in logog.  You can replace it here with your own set compatible class if needed. */
+#define LOGOG_EQUAL_TO		std::equal_to
+
+//! [STLTypes]
+
+/** The default port number that logog uses to communicate via TCP/UDP */
+#define LOGOG_DEFAULT_PORT	9987
+
+/** We use va_list for formatting messages. */
+#include <cstdarg>
+
+
+
+#endif // __LOGOG_PLATFORM_HPP
diff --git a/Base/logog/include/socket.hpp b/Base/logog/include/socket.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..8417eeb89f9d12328012e28419bc6eb405a9be0e
--- /dev/null
+++ b/Base/logog/include/socket.hpp
@@ -0,0 +1,150 @@
+/**
+ * \file socket.hpp Cross-platform socket abstractions
+ */
+
+/**
+ * \todo Socket support is unfinished and is not working yet.  Please review socket.hpp if you'd like to implement
+ * a cross-platform socket abstraction.
+ */
+#ifndef __LOGOG_SOCKET_HPP_
+#define __LOGOG_SOCKET_HPP_
+
+#ifdef LOGOG_FLAVOR_WINDOWS
+#pragma comment(lib, "wsock32.lib")
+#endif
+
+#include <memory.h>
+
+namespace logog
+{
+/** A sending or receiving socket to be used as a target. */
+class Socket : public Target
+{
+public:
+    static int Initialize()
+    {
+        static bool bInitialized = false;
+
+        if ( !bInitialized )
+        {
+#ifdef LOGOG_FLAVOR_WINDOWS
+            WORD wVersionRequested;
+            WSADATA wsaData;
+            int err;
+            wVersionRequested = MAKEWORD( 2, 2 );
+
+            err = WSAStartup( wVersionRequested, &wsaData );
+
+            if ( err != 0 )
+            {
+#ifdef LOGOG_INTERNAL_DEBUGGING
+                LOGOG_COUT << _LG("WSAStartup failed with error: ") <<  err << endl;
+#endif
+                return 1;
+            }
+
+#endif
+        }
+
+        bInitialized = true;
+
+        return 0;
+    }
+
+    static void Shutdown()
+    {
+#ifdef LOGOG_FLAVOR_WINDOWS
+        WSACleanup();
+#endif
+    }
+
+    static const int MAXHOSTNAME = 255;
+
+    Socket(
+        int type = SOCK_STREAM,
+        int port = LOGOG_DEFAULT_PORT
+    )
+    {
+        m_Socket = -1;
+        m_nType = type;
+        m_nPort = port;
+    }
+
+    virtual void Close()
+    {
+#ifdef LOGOG_FLAVOR_WINDOWS
+        closesocket( m_Socket );
+#endif
+#ifdef LOGOG_FLAVOR_POSIX
+        close( m_Socket );
+#endif
+    }
+
+#ifdef NYI
+    virtual int Create( int type,
+                        int port )
+    {
+        char myname[MAXHOSTNAME+1];
+        int err;
+        struct sockaddr_in sa;
+        struct hostent *hp;
+
+        memset( &sa, 0, sizeof( struct sockaddr_in ) ); /* clear our address */
+        gethostname( myname, MAXHOSTNAME );         /* who are we? */
+        hp= gethostbyname( myname );                /* get our address info */
+
+        if ( hp == NULL )                           /* we don't exist !? */
+            return -1;
+
+        sa.sin_family= hp->h_addrtype;              /* this is our host address */
+        sa.sin_port= (u_short)htons( (u_short)port );                /* this is our port number */
+
+        if (( m_Socket = socket( AF_INET, type, 0 ) ) < 0 ) /* create socket */
+            return -1;
+
+        if ( bind( m_Socket,  (struct sockaddr*) &sa, sizeof( struct sockaddr_in ) ) < 0 )
+        {
+            Close();
+            return -1;
+        }
+
+        if (( err = SetNonBlocking() ) != 0 )
+            return err;
+    }
+
+#endif // NYI
+
+    virtual int SetNonBlocking()
+    {
+        int err;
+
+#ifdef LOGOG_FLAVOR_POSIX
+        int flags;
+        flags = socket_fcntl( m_Socket, F_GETFL, 0 );
+        flags |= O_NONBLOCK;
+        err = socket_fcntl( m_Socket, F_SETFL, flags );
+#endif
+
+#ifdef LOGOG_FLAVOR_WINDOWS
+        unsigned long parg;
+        parg = 1;
+        err = ioctlsocket( m_Socket, FIONBIO, &parg );
+#endif
+        return err;
+    }
+
+    virtual int Output( const LOGOG_STRING &output ) = 0;
+
+protected:
+    int m_Socket;
+    int m_nType;
+    int m_nPort;
+};
+
+class SocketServer : Socket
+{
+
+};
+}
+
+#endif // __LOGOG_CHECKPOINT_HPP_
diff --git a/Base/logog/include/statics.hpp b/Base/logog/include/statics.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..938bd3d23a6f96921275a5aafe3501ad4b0780a6
--- /dev/null
+++ b/Base/logog/include/statics.hpp
@@ -0,0 +1,74 @@
+/*!
+ * \file statics.hpp Static variables simultaneously assigned for all instances of logog.
+ */
+
+#ifndef __LOGOG_STATICS_HPP__
+#define __LOGOG_STATICS_HPP__
+
+
+namespace logog
+{
+
+class Timer;
+class Formatter;
+class Target;
+class Mutex;
+
+extern void DestroyAllNodes();
+extern void DestroyGlobalTimer();
+extern void DestroyDefaultFormatter();
+extern void DestroyStringSearchMutex();
+extern void DestroyMessageCreationMutex();
+
+/* Technically this information should be in node.hpp but statics is responsible for
+ * this global list.
+ */
+class Statics
+{
+public:
+    /** A pointer to the malloc() compatible function used by logog.  See logog::Initialize()
+     ** for more details. */
+    void *(*s_pfMalloc)( size_t );
+    /** A pointer to the free() compatible function used by logog.  See logog::Initialize()
+     ** for more details. */
+    void (*s_pfFree)( void * );
+    /** Pointers to all the currently existing nodes in the network. */
+    void *s_pAllNodes;
+    /** Pointers to only those nodes that are capable of subscribing. */
+    void *s_pAllSubscriberNodes;
+    /** Pointers to only those nodes that are capable of subscribing and publishing. */
+    void *s_pAllFilterNodes;
+    /** Pointers to the group of all valid targets. */
+    void *s_pAllTargets;
+    /** Pointer to the default filter, if any. */
+    void *s_pDefaultFilter;
+    /** The default global shared timer.  All events are generally in reference to this timer, though yoy may create your own timers. */
+    Timer *s_pTimer;
+    /** A lock on the KMP search for all strings.  Prevents mutex explosions.  */
+    void *s_pStringSearchMutex;
+    /** A lock for creating messages.  Prevents dual message creation from multiple threads. */
+    Mutex *s_pMessageCreationMutex;
+    /** The default Formatter for all targets.  Targets may use their individual formatters as well if preferred. */
+    Formatter *s_pDefaultFormatter;
+    /** The number of sockets created. */
+    int s_nSockets;
+    /** A pointer to this object; used for final destruction. */
+    Statics *s_pSelf;
+
+    Statics();
+	~Statics();
+
+	/** Resets all statics to startup values.  Releases memory allocated by statics. */
+    void Reset();
+
+};
+
+extern Statics &Static();
+
+/** Destroys the Static() structure.  Calls to Static() after calling DestroyStatic() will probably crash your
+ ** program.
+ */
+extern void DestroyStatic();
+
+}
+#endif // __LOGOG_STATICS_HPP
diff --git a/Base/logog/include/string.hpp b/Base/logog/include/string.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..e069b3a26fc939f1163416b57e45710dea797a9e
--- /dev/null
+++ b/Base/logog/include/string.hpp
@@ -0,0 +1,115 @@
+/**
+ * \file string.hpp Defines the logog string class.
+ */
+#ifndef __LOGOG_STRING_HPP__
+#define __LOGOG_STRING_HPP__
+
+/** \def LOGOG_UNICODE
+ ** Define this typedef in order to support wide characters in all logog strings.
+ ** \sa _LG
+ ** */
+
+#ifdef LOGOG_UNICODE
+/** logog has detected Unicode; therefore a LOGOG_CHAR is a wide character. */
+typedef wchar_t LOGOG_CHAR;
+/** This is a naughty little hack.  If we're using Unicode, then we append an
+ * L to your const string.  However, we have several situations in which that string will actually be a NULL or 0
+ * value in code, and the string will be rendered as L0 or LNULL.  In that case, we catch it with yet another 
+ * macro.  Hacky, but seems to do the trick.  Beware of conflicts with existing code though...!
+ */
+#define L0 (const LOGOG_CHAR *)'\0'
+#define LNULL (const LOGOG_CHAR *)'\0'
+#define L__null (const LOGOG_CHAR *)'\0'
+
+/* Two indirect references are necessary in order to expand a string and append the L to it. */
+#define LOGOG_CONST_STRING_INDIRECT(x) L ## x
+/* This macro will cause a const string to be stored as a Unicode string on a Unicode build. */
+#define LOGOG_CONST_STRING(x) LOGOG_CONST_STRING_INDIRECT(x)
+#define LOGOG_COUT  std::wcout
+#define LOGOG_CERR  std::wcerr
+
+#else // LOGOG_UNICODE
+
+/** logog has not detected Unicode; therefore a LOGOG_CHAR is simply a char. */
+typedef char LOGOG_CHAR;
+/** This macro will cause a const string to be stored as an ANSI string on an ANSI build, and as a Unicode string
+ * on a Unicode build.
+ */
+#define LOGOG_CONST_STRING(x) (x)
+#define LOGOG_COUT  std::cout
+#define LOGOG_CERR  std::cerr
+#endif // LOGOG_UNICODE
+
+/** If this constant is defined, then you can use the shorthand macro _LG in your code to represent a constant
+  * string.
+  */
+#ifndef LOGOG_USE_PREFIX
+/** The _LG() macro is defined only if LOGOG_USE_PREFIX is not defined.  _LG() can be used to describe 
+ ** a const string that is compiled to either as Unicode
+ * or ANSI, based on the setting of the LOGOG_UNICODE flag.
+ * _LG() is not needed if you don't need Unicode support.  If you want your messages to work with both Unicode 
+ * as well as ANSI builds of logog, preface them like this: _LG("This const string works on Unicode as well as ANSI.")
+ */
+#define _LG( x ) LOGOG_CONST_STRING( x )
+#endif 
+
+namespace logog
+{
+	class String : public Object
+	{
+	public:
+
+		static const size_t npos = (size_t) -1;
+
+		String();
+		virtual ~String();
+		virtual void Free();
+		static size_t Length( const LOGOG_CHAR *chars );
+
+		String( const String &other );
+		String( const LOGOG_CHAR *pstr );
+		String & operator =( const String & other);
+		String & operator =( const LOGOG_CHAR *pstr );
+		size_t size() const;
+		virtual void clear();
+		virtual size_t reserve( size_t nSize );
+		virtual size_t reserve_for_int();
+		virtual operator const LOGOG_CHAR *() const;
+		virtual size_t assign( const String &other );
+		virtual size_t append( const String &other );
+		virtual size_t append( const LOGOG_CHAR *other );
+		virtual void reverse( LOGOG_CHAR* pStart, LOGOG_CHAR* pEnd);
+		virtual size_t assign( const int value );
+		virtual size_t append( const LOGOG_CHAR c );
+		virtual bool is_valid() const;
+		virtual size_t assign( const LOGOG_CHAR *other, const LOGOG_CHAR *pEnd = NULL );
+
+		virtual size_t find( String &other ) const;
+		virtual void format( const LOGOG_CHAR *cFormatString, ... );
+		virtual void format_va( const LOGOG_CHAR *cFormatString, va_list args );
+
+		virtual const LOGOG_CHAR* c_str() const;
+
+	protected:
+		virtual void Initialize();
+
+		/* Code modified from http://www-igm.univ-mlv.fr/~lecroq/string/node8.html#SECTION0080 */
+		void preKmp(size_t m);
+
+		size_t KMP( const LOGOG_CHAR *y, size_t n );
+
+#define LOGOG_MAX( a, b ) ( ( a > b ) ? a : b )
+
+		size_t BM(LOGOG_CHAR *y, size_t n);
+
+		LOGOG_CHAR *m_pBuffer;
+		LOGOG_CHAR *m_pOffset;
+		LOGOG_CHAR *m_pEndOfBuffer;
+		size_t *m_pKMP;
+		bool m_bIsConst;
+	};
+}
+
+#define LOGOG_STRING ::logog::String
+
+#endif // __LOGOG_STRING_HPP_
diff --git a/Base/logog/include/target.hpp b/Base/logog/include/target.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..a5844135013a3962aa20577df5e766ef400cdcfd
--- /dev/null
+++ b/Base/logog/include/target.hpp
@@ -0,0 +1,176 @@
+/**
+ * \file target.hpp Abstractions representing logging outputs.
+ */
+
+#ifndef __LOGOG_TARGET_HPP_
+#define __LOGOG_TARGET_HPP_
+
+namespace logog
+{
+/** A target is abstraction representing an output stream from logog.  cerr, cout, and syslog, and other logging formats are supported.
+ ** Targets do not validate their received data.  Their only job is to render it on a call to Receive() to their supported target
+ ** type.  Targets should generally make sure to handle calls on multiple threads -- they should make sure to avoid overlapping
+ ** outputs from multiple threads correctly.  This base class handles this serialization in the Receive() function.
+ ** Children of this class are expected to implement the Output() function to do the actual output.
+ **/
+class Target : public TopicSink
+{
+    friend class LogBuffer;
+public :
+    Target();
+	virtual ~Target();
+
+    /** Sets the current formatter for this target. */
+    void SetFormatter( Formatter &formatter );
+
+    /** Returns a reference to the current formatter for this target. */
+    Formatter &GetFormatter() const;
+
+    /** All targets must implement the Output function.  This function outputs the provided string to the
+      * output that the target represents.
+      * \return Zero if no error has occurred; an error code (generally propagated 
+      * from the operating system) if an error has occurred.
+      */
+    virtual int Output( const LOGOG_STRING &data ) = 0;
+
+    /** Receives a topic on behalf of this target.  A mutex prevents race conditions from occurring when 
+     ** multiple threads attempt to write to this target at the same time.
+     ** \return Zero if no error has occurred; an error code (generally propagated from the operating
+     ** system) if an error has occurred.
+     */
+    virtual int Receive( const Topic &topic );
+
+	/** Does this target want its formatter to null terminate its strings? */
+	bool GetNullTerminatesStrings() const { return m_bNullTerminatesStrings; }
+
+	/** Tells this target whether to request its formatter to null terminate its strings. */
+	void SetNullTerminatesStrings(bool val) { m_bNullTerminatesStrings = val; }
+
+
+protected:
+    /** A pointer to the formatter used for this output. */
+    Formatter *m_pFormatter;
+    /** A mutex on the Receive() function. */
+    Mutex m_MutexReceive;
+	/** Does this target cause its formatter to null-terminate its output strings?  File and buffer outputs 
+	 ** don't require null terminated strings, but line outputs do.
+	 **/
+	bool m_bNullTerminatesStrings;
+};
+
+/** A target representing the cerr stream. */
+class Cerr : public Target
+{
+    virtual int Output( const LOGOG_STRING &data );
+};
+
+/** A target representing the cout stream. */
+class Cout : public Target
+{
+    virtual int Output( const LOGOG_STRING &data );
+};
+
+/** A target representing the debugger stream on Win32 targets.  This only logs information
+  * on Windows like platforms.
+  */
+class OutputDebug : public Target
+{
+    virtual int Output( const LOGOG_STRING &data );
+};
+
+/** A LogFile renders received messages to a file.  Provide the name of the file to be rendered to as
+ * a parameter to the construction of the LogFile() object.  Destroying a LogFile object will cause the
+ * output file to be closed.  LogFile objects always append to the output file; they do not delete the previous
+ * log file.
+ */
+class LogFile : public Target
+{
+public:
+    /** Creates a LogFile object.
+     * \param sFileName The name of the file to be created.
+     * Since file names do not support Unicode on most systems, there is no option to create 
+     * a filename with a LOGOG_CHAR. 
+     */
+    LogFile(const char *sFileName);
+
+    /** Closes the log file. */
+    virtual ~LogFile();
+
+    /** Opens the log file on first write. */
+    virtual int Open();
+
+	/** This function makes a guess as to the correct BOM for this file, and attempts
+	 ** to write it into the file.  It does this by considering the size of LOGOG_CHAR
+	 ** as well as considering the current endianness of this system.  This guess
+	 ** may be incorrect.
+	 **/
+	virtual void WriteUnicodeBOM();
+
+    /** Writes the message to the log file. */
+    virtual int Output( const LOGOG_STRING &data );
+
+	/** Should a Unicode BOM be written to the beginning of this log file, if the log file
+	 * was previously empty?  By default a BOM is written to a log file if LOGOG_UNICODE
+	 * is enabled. */
+	bool m_bWriteUnicodeBOM;
+
+protected:
+    char *m_pFileName;
+    bool m_bFirstTime;
+	bool m_bOpenFailed;
+    FILE *m_pFile;
+
+	/** Does the actual fwrite to the file.  Call Output() instead to handle error conditions better. */
+	virtual int InternalOutput( size_t nSize, const LOGOG_CHAR *pData );
+
+private:
+    LogFile();
+};
+
+/** A buffering target.  Stores up to a fixed buffer size of output and then renders that output to another
+  * target.  Can be used for buffering log output in memory and then storing it to a log file upon program completion.
+  * To use, create another target (such as a LogFile) and then create a LogBuffer, providing the other target
+  * as a parameter to the creation function.
+  */
+class LogBuffer : public Target
+{
+public:
+    LogBuffer( Target *pTarget = NULL,
+               size_t s = LOGOG_DEFAULT_LOG_BUFFER_SIZE );
+    virtual ~LogBuffer();
+
+    /** Changes the current rendering target.  NOTE: This function does no locking on either the target or
+     * this object.  Program accordingly.
+     */
+    virtual void SetTarget( Target &t );
+
+    /** Inserts a range of LOGOG_CHAR objects into this buffer.  The characters should consist of a null-terminated
+     * string of length size.  Providing anything else as input creates undefined behavior.
+     */
+    virtual int Insert( const LOGOG_CHAR *pChars, size_t size );
+
+    /** Dumps the current contents of the buffer to the output target. */
+    virtual int Dump();
+
+    virtual int Output( const LOGOG_STRING &data );
+
+protected:
+    virtual void Allocate( size_t size );
+
+    virtual void Deallocate();
+
+    /** The non-changing pointer to the basic buffer. */
+    LOGOG_CHAR *m_pStart;
+    /** The current write offset into the buffer. */
+    LOGOG_CHAR *m_pCurrent;
+    /** The position in the buffer after which no data may be written. */
+    LOGOG_CHAR *m_pEnd;
+    /** The size of the buffer in LOGOG_CHAR primitives. */
+    size_t m_nSize;
+    /** A pointer to the target to which the buffer will be rendered upon calling Dump(). */
+    Target *m_pOutputTarget;
+};
+
+}
+
+#endif // __LOGOG_TARGET_HPP_
diff --git a/Base/logog/include/thread.hpp b/Base/logog/include/thread.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..c37e3045d464534c4d1ab17f83597ee1ad43ccc8
--- /dev/null
+++ b/Base/logog/include/thread.hpp
@@ -0,0 +1,121 @@
+/**
+ * \file thread.hpp Defines a thread object for the current platform.
+ */
+
+#ifndef __LOGOG_THREAD_HPP__
+#define __LOGOG_THREAD_HPP__
+
+//! [Thread]
+#ifndef LOGOG_THREAD
+#if defined(LOGOG_FLAVOR_WINDOWS)
+
+#include <process.h>
+
+typedef unsigned int (WINAPI * __logog_pThreadFn )(void *);
+
+#define LOGOG_THREAD HANDLE
+
+#define LOGOG_THREAD_CREATE(handle, attr, pStartFn, arg) \
+	(int)((*handle=(HANDLE) _beginthreadex (NULL,  /* security */ \
+			0, /* stack size */ \
+			(__logog_pThreadFn)pStartFn, /* start address */ \
+			arg, /* pv argument */ \
+			0, /* init flag */ \
+			NULL /*thread addr */ ))==NULL)
+
+#define LOGOG_THREAD_JOIN( thread ) \
+	( (WaitForSingleObject(( thread ),INFINITE)!=WAIT_OBJECT_0) \
+				|| !CloseHandle(thread) \
+				)
+#define LOGOG_THREAD_SELF (LOGOG_THREAD)GetCurrentThreadId()
+
+#endif // defined(LOGOG_FLAVOR_WINDOWS)
+
+#if defined(LOGOG_FLAVOR_POSIX)
+
+#define LOGOG_THREAD \
+	pthread_t
+
+#define LOGOG_THREAD_CREATE(handle, attr, pStartFn, arg) \
+	pthread_create(handle, attr, pStartFn, arg)
+
+#define LOGOG_THREAD_JOIN(thread) \
+	pthread_join(thread, NULL)
+
+#define LOGOG_THREAD_SELF \
+	pthread_self()
+
+#endif
+
+#endif // LOGOG_THREAD
+
+#ifndef LOGOG_THREAD
+#error You need to define mutex macros for your platform; please see mutex.hpp
+#endif
+
+//! [Thread]
+
+namespace logog
+{
+
+/** A thread abstraction.  Requires definition of macros to describe how to create, start, and wait for threads to terminate. */
+class Thread
+{
+public:
+
+    /** A type describing the entry point of a function. */
+    typedef void* (*ThreadStartLocationType)(void *);
+
+    /** Creating a new thread requires the starting location as well as a single void pointer to the argument to a function. */
+    Thread(ThreadStartLocationType fnThreadStart, void* pvParams)
+    {
+        m_pFnThreadStart = fnThreadStart;
+        m_pvThreadParams = pvParams;
+    }
+
+    /** Cause the created thread to commence execution asynchronously. */
+    int Start()
+    {
+        return LOGOG_THREAD_CREATE(&m_Thread, NULL, m_pFnThreadStart, m_pvThreadParams);
+    }
+
+    /** Causes the current thread to wait for completion of the provided thread.
+     ** \param thread The thread object to wait for
+     */
+    static int WaitFor(const Thread& thread)
+    {
+        return LOGOG_THREAD_JOIN(thread.m_Thread);
+    }
+
+#ifdef LOGOG_THREAD_JOIN_SUPPORT
+    static void Join(const std::vector<Thread*>& threads)
+    {
+        for(size_t i=0; i<threads.size(); i++)
+            WaitFor(*threads.at(i));
+    }
+
+    static void Delete(std::vector<Thread*>& threads)
+    {
+        for(size_t i=0; i<threads.size(); i++)
+            delete threads.at(i);
+        threads.clear();
+    }
+#endif // LOGOG_THREAD_JOIN_SUPPORT
+
+    /** Returns a LOGOG_THREAD representing the calling process. */
+    static LOGOG_THREAD GetCurrent()
+    {
+        return (LOGOG_THREAD) LOGOG_THREAD_SELF ;
+    }
+
+private:
+    /** A platform-specific identifier for the calling process. */
+    LOGOG_THREAD m_Thread;
+    /** The entry point for this thread. */
+    ThreadStartLocationType m_pFnThreadStart;
+    /** An arbitrary argument to the thread entry point. */
+    void* m_pvThreadParams;
+};
+}
+
+#endif // __LOGOG_THREAD_HPP_
\ No newline at end of file
diff --git a/Base/logog/include/timer.hpp b/Base/logog/include/timer.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..579103b2bb78f19eb0b794bb5ff16b9d20cd1643
--- /dev/null
+++ b/Base/logog/include/timer.hpp
@@ -0,0 +1,42 @@
+/**
+ * \file timer.hpp Time management.
+ */
+
+#ifndef __LOGOG_TIMER_HPP__
+#define __LOGOG_TIMER_HPP__
+
+namespace logog
+{
+/** A value for a high resolution timer on this platform.  Time representations are in seconds. */
+typedef double LOGOG_TIME;
+
+/** A high-resolution timer.  Reports in seconds. */
+class Timer : public Object
+{
+public:
+    Timer();
+
+    /** Returns the offset from the time since the creation of the timer, or the time set by the most
+     ** recent Set() call.  Time is assumed to be a value in LOGOG_TIME seconds.
+     ** \sa LOGOG_TIME
+     **/
+    LOGOG_TIME Get();
+
+    /** Sets the current time for this timer. */
+    void Set( LOGOG_TIME time );
+
+protected:
+#ifdef LOGOG_FLAVOR_WINDOWS
+    /** Windows only.  Stores the number of high resolution timer ticks per second. */
+    double m_fTicksPerMicrosecond;
+#endif
+    /** Zero, if no calls to Set() have been made; else the value of the previous call to Set(). */
+    LOGOG_TIME m_fStartTime;
+};
+
+extern Timer &GetGlobalTimer();
+extern void DestroyGlobalTimer();
+
+}
+
+#endif // __LOGOG_TIMER_HPP_
diff --git a/Base/logog/include/topic.hpp b/Base/logog/include/topic.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..ae3d6f3e5af801692354e7c8ebcd8c18a6e5916b
--- /dev/null
+++ b/Base/logog/include/topic.hpp
@@ -0,0 +1,203 @@
+/**
+ * \file topic.hpp Topics -- subjects of interests for publishers and
+ * subscribers to communicate about
+ */
+
+#ifndef __LOGOG_TOPIC_HPP__
+#define __LOGOG_TOPIC_HPP__
+
+namespace logog
+{
+
+/** A subject that nodes can choose to discuss with one another.
+ ** Subscribers generally have very general topics, while publishers generally have very specific topics.
+ **/
+class Topic : public Node
+{
+    friend class TopicLevel;
+    friend class TopicGroup;
+
+public:
+    /** Creates a topic.  Note the defaults for creating a topic -- these defaults are equivalent to "no setting"
+     ** for those fields.
+     **/
+    Topic( const LOGOG_LEVEL_TYPE level = LOGOG_LEVEL_ALL,
+           const LOGOG_CHAR *sFileName = NULL,
+           const int nLineNumber = 0,
+           const LOGOG_CHAR *sGroup = NULL,
+           const LOGOG_CHAR *sCategory = NULL,
+           const LOGOG_CHAR *sMessage = NULL,
+           const double dTimestamp = 0.0f );
+
+    /** Topics are always topics.  We use this to avoid any RTTI dependence. */
+    virtual bool IsTopic() const;
+
+    /** Causes this topic to publish another topic to all its subscribers.
+     ** \return 0 if successful, non-zero if this topic failed to send the publication to all subscribers */
+    virtual int Send( const Topic &node );
+
+    /** Causes this topic to publish itself to all its subscribers. */
+    virtual int Transmit();
+
+    /** Permits this node to receive a publication from another node, and act upon it.
+     ** \param node The node constituting the publication
+     ** \return 0 if successful, non-zero if this node failed to process the publication
+     **/
+    virtual int Receive( const Topic &node );
+
+    /** Is this topic interested in receiving notifications from another topic?  This function implements
+     ** a generic (slow) test that should work for all topic types.  This function only checks fields
+     ** that have previously been set on this topic -- fields that have not been set will not limit this
+     ** topic's ability to subscribe.  If any of the previously set fields does not "match" the other topic,
+     ** this function will return false.  The matching function behaves slightly differently from field to
+     ** field.
+     ** - In the topic level case, this function rejects a publisher with a lower topic level than our
+     ** own.
+     ** - In the group, category, file name and message case, this function rejects a publisher if our
+     ** own group/category/file name or message cannot be found as a substring in the possible publisher.
+     ** This functionality permits very simple pattern matching functionality (i.e. show me all the message
+     ** lines that have the word "upload" in them, regardless of their log level.)
+     ** - In the line number case, this function rejects a publisher unless the line number matches exactly.
+     ** - In the timestamp case, this function rejects a publisher if their timestamp is before our own.
+     ** \param otherNode The topic which we are considering subscribing to
+     **/
+    virtual bool CanSubscribeTo( const Node &otherNode );
+
+    virtual bool CanSubscribeCheckTopic( const Topic &other );
+
+    /** Causes this topic to begin publishing events to the given subscriber.
+     ** \param subscriber The node to receive published events
+     ** \return true if the request was successful, false if the subscriber was already subscribed
+     **/
+    virtual bool PublishTo( Node &subscriber );
+
+
+
+    /** Formats the message in this topic given a sprintf-style set of arguments.
+     ** This function can be used to set the current message in this topic to a string with a variable number of parameters.
+     **/
+    virtual void Format( const LOGOG_CHAR *cFormatMessage, ... );
+
+    const LOGOG_STRING &FileName() const;
+    void FileName( const LOGOG_STRING &s );
+
+    const LOGOG_STRING &Message() const;
+    void Message( const LOGOG_STRING &s );
+
+    const LOGOG_STRING &Category() const;
+    void Category( const LOGOG_STRING &s );
+
+    const LOGOG_STRING &Group() const;
+    void Group( const LOGOG_STRING &s );
+
+    int LineNumber() const;
+    void LineNumber( const int num );
+
+    LOGOG_LEVEL_TYPE Level() const;
+    void Level( LOGOG_LEVEL_TYPE level );
+
+    LOGOG_TIME Timestamp() const;
+    void Timestamp( const LOGOG_TIME t );
+
+    TOPIC_FLAGS GetTopicFlags() const;
+
+protected:
+    /** An array (not an STL vector) of string properties for this topic. */
+    LOGOG_STRING m_vStringProps[ TOPIC_STRING_COUNT ];
+    /** An array (not an STL vector) of integer properties for this topic. */
+    int m_vIntProps[ TOPIC_INT_COUNT ];
+    /** The time associated with this topic.  Usually this field is updated when a topic is triggered.  Times need not be associated
+     ** with a particular topic, in which case this value is zero.
+     ** */
+    LOGOG_TIME m_tTime;
+    /** A bitfield representing the "important" fields in this topic.  Not all fields are considered to contain important information
+     ** all the time.  A logical OR of the TOPIC_*_FLAG fields.
+     ** \sa TopicBitsType
+     **/
+    TOPIC_FLAGS m_TopicFlags;
+};
+
+/** A topic that permits both publishing as well as subscribing.  This class is functionally same as a Topic; we've added it
+ ** as a class for clarity when referring to different topic types.  Filters should be instantiated only after outputs are
+ ** instantiated, as they automatically search for and publish to targets.  If you instantiate a filter before you
+ ** instantiate a target, you will need to call PublishTo( theTarget ) yourself before using the target.
+ **/
+class Filter : public Topic
+{
+public:
+    Filter( const LOGOG_LEVEL_TYPE level = LOGOG_LEVEL_ALL,
+            const LOGOG_CHAR *sFileName = NULL,
+            const int nLineNumber = 0,
+            const LOGOG_CHAR *sGroup = NULL,
+            const LOGOG_CHAR *sCategory = NULL,
+            const LOGOG_CHAR *sMessage = NULL,
+            const double dTimestamp = 0.0f );
+};
+
+/** Returns a reference to the unique default filter instantiated with logog. */
+extern Filter &GetDefaultFilter();
+
+/** Sets the current reporting level for the default filter.  All messages
+  * connected to the filter after this point should obey this default
+  * level setting.
+  */
+void SetDefaultLevel( LOGOG_LEVEL_TYPE level );
+
+/** A topic with the group name being the only field of significance. */
+class TopicGroup : public Topic
+{
+public:
+    TopicGroup( const LOGOG_CHAR *sGroup = NULL );
+
+    virtual bool CanSubscribeCheckTopic( const Topic &other );
+};
+
+/** A topic with the level being the only field of significance. */
+class TopicLevel : public Topic
+{
+public:
+    TopicLevel( const LOGOG_LEVEL_TYPE level );
+    virtual bool CanSubscribeCheckTopic( const Topic &other );
+};
+
+/** A topic that is also a source. */
+class TopicSource : public Topic
+{
+public:
+    TopicSource( const LOGOG_LEVEL_TYPE level = LOGOG_LEVEL_ALL,
+                 const LOGOG_CHAR *sFileName = NULL,
+                 const int nLineNumber = 0,
+                 const LOGOG_CHAR *sGroup = NULL,
+                 const LOGOG_CHAR *sCategory = NULL,
+                 const LOGOG_CHAR *sMessage = NULL,
+                 const double dTimestamp = 0.0f );
+
+    /** Returns false.  Sources do not subscribe. */
+    virtual bool SubscribeTo( Node & );
+
+    /** Returns false.  Sources do not unsubscribe. */
+    virtual bool UnsubscribeTo( Node & );
+    virtual bool CanSubscribe() const;
+};
+
+/** A topic that is also a sink. */
+class TopicSink : public Topic
+{
+public:
+    virtual bool IsTopic() const;
+
+    /** Sinks do not add themselves to the list of interested subscribers.  That's up to intermediate topics to decide. */
+    virtual void Initialize();
+
+    /** Returns false.  Sinks do not publish. */
+    virtual bool PublishTo( Node & );
+
+    /** Returns false.  Sinks do not unpublish. */
+    virtual bool UnpublishTo( Node & );
+
+    /** Returns false.  Sinks do not publish. */
+    virtual bool CanPublish() const;
+};
+}
+
+#endif // __LOGOG_TOPIC_HPP_
diff --git a/Base/logog/include/unittest.hpp b/Base/logog/include/unittest.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..3441636bd56d41db50bcf2184402fe1639129496
--- /dev/null
+++ b/Base/logog/include/unittest.hpp
@@ -0,0 +1,151 @@
+/**
+ * \file unittest.hpp Unit testing interface; may be used for other programs as well.
+ */
+#ifndef __LOGOG_UNITTEST_HPP
+#define __LOGOG_UNITTEST_HPP
+
+#include <iostream>
+#include <string>
+
+namespace logog
+{
+
+/**
+ * \page unittesting Unit test framework
+ *
+ * A unit test framework is included with logog.  This framework was intended specifically to exercise logog functionality, but it may also
+ * be used as a general purpose test framework.
+ *
+ * A typical test program will look like this:
+ * \code
+ * int main( int argc, char *argv[] )
+ * {
+ *     int nResult;
+ *     nResult = RunAllTests();
+ *     ShutdownTests();
+ *     return nResult;
+ * }
+ * \endcode
+ *
+ * To define a unit test, create a function of the following form:
+ *
+ * \code
+ * UNITTEST( AdditionTest )
+ * {
+ *     logog::Initialize();
+ *
+ *     int nResult = 0;
+ *
+ *     if ( 2 + 2 == 4 )
+ *     {
+ *        LOGOG_COUT << _LG("Sane.") << endl;
+ *     }
+ *     else
+ *     {
+ *        LOGOG_COUT << _LG("Insane!") << endl;
+ *        nResult = 1;
+ *     }
+ *
+ *     logog::Shutdown();
+ *
+ *     return nResult;
+ *
+ * };
+ * \endcode
+ *
+ * The UNITTEST() macro defines a unique UnitTest object that encompasses your function.
+ * Your function should take no parameters and return an integer value.  It should return
+ * zero if the test was successful, and non-zero if the test was unsuccesful.  If any
+ * of your tests fail, the stub main() program will propagate that error to the operating
+ * system, which in turn can be used to halt an automated build system.
+ *
+ * The unit testing framework is known to leak memory.  However, the underlying logog macros are not known to leak memory (let us know
+ * if you find any leaks).
+ */
+
+/** A standard string type, used for labelling a test.  We don't use LOGOG_STRING here because that class is mutable
+ ** and it allocates memory.
+ **/
+typedef const char * TestNameType;
+class UnitTest;
+
+/** A registry for all tests.  All tests are instanced using the UNITTEST() macro and stored in the LogogTestRegistry.
+ ** \ref UNITTEST
+ **/
+typedef LOGOG_LIST< UnitTest * > TestRegistryType;
+
+/** All unit tests are registered in here at program initialization time. */
+extern TestRegistryType &LogogTestRegistry();
+
+/** A TestSignup is responsible for recording each instanced UnitTest in the test registry. */
+class TestSignup
+{
+public:
+    /** Creates a new TestSignup.  Only called from constructor for UnitTest. */
+    TestSignup( UnitTest *pTest );
+
+protected:
+    /** A pointer back to the UnitTest that created this TestSignup */
+    UnitTest *m_pTest;
+private:
+    TestSignup();
+};
+
+/** The base class for unit testing.  Children of UnitTest are instanced by the UNITTEST() macro. */
+class UnitTest
+{
+public:
+    /** Instances a test.  An instanced test is automatically executed when the RunAllTests() function is called.
+     * \param sTestName A string representing the name of this test.
+     */
+    UnitTest( const TestNameType &sTestName );
+
+	virtual ~UnitTest();
+    /** Returns the name of this UnitTest provided at construction time. */
+    virtual TestNameType &GetName();
+    /** Child classes of UnitTest() must provide a RunTest() function.  A RunTest() function must initialize logog, conduct its
+     ** tests, and return 0 if the test was successful, a non-0 value otherwise.  If any RunTest() function returns any value other than
+     ** zero, then the main RunAllTests() function will return non zero as well.
+     */
+    virtual int RunTest() = 0;
+
+	/** This function is called during ShutdownTests().  Its purpose is to free
+	 ** the internal structures allocated by the UnitTest without freeing 
+	 ** the UnitTest itself.  Microsoft's leak detector will flag the internals
+	 ** of a UnitTest as a leak unless these internals are explicitly destroyed
+	 ** prior to exit().
+	 **/
+	virtual void FreeInternals();
+
+protected:
+    /** The name of this particular test. */
+    TestNameType m_sTestName;
+    /** A pointer to the TestSignup constructed by this UnitTest. */
+    TestSignup *m_pTestSignup;
+private:
+    UnitTest();
+};
+
+/** Executes all currently registered tests and prints a report of success or failure. */
+extern int RunAllTests();
+
+/** Should remove all memory allocated during unit testing. */
+extern void ShutdownTests();
+
+/** This should be the function prefix for a unit test.  It defines a new class for the test inherited from UnitTest.  It instances
+ ** a member of the class at run-time (before main() starts).  Lastly it provides the function definition for the actual test class.
+ */
+#define UNITTEST( x ) class x : public UnitTest { \
+public: \
+	x( TestNameType name ) : \
+	  UnitTest( name ) \
+	  {} \
+	  virtual ~x() {}; \
+	  virtual int RunTest(); \
+	}; \
+	x __LogogTestInstance_ ## x ( #x ); \
+	int x::RunTest()
+
+}
+
+#endif // __LOGOG_UNITTEST_HPP
diff --git a/Base/logog/readme.txt b/Base/logog/readme.txt
new file mode 100644
index 0000000000000000000000000000000000000000..1c0339e148845dc6afeccff2a6870fcd5ff8560d
--- /dev/null
+++ b/Base/logog/readme.txt
@@ -0,0 +1,11 @@
+See http://www.logog.org or http://johnwbyrd.github.com/logog/ for more information and complete documentation.
+
+logog is a portable C++ library to facilitate logging of real-time events in performance-oriented applications, such as games. It is especially appropriate for projects that have constrained memory and constrained CPU requirements.
+
+General support and discussion is available at http://groups.google.com/group/logog .  Development support and discussion is available at http://groups.google.com/group/logog-devel .
+
+This project can be built using CMake, available from http://www.cmake.org .
+
+Local documentation can be generated with doxygen, available from  http://www.doxygen.org .
+
+The license agreement for logog is viewable at http://johnwbyrd.github.com/logog/license.html .
diff --git a/Base/logog/src/api.cpp b/Base/logog/src/api.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2b67c14051b29e29e3661aa5753b8bd1b51a3523
--- /dev/null
+++ b/Base/logog/src/api.cpp
@@ -0,0 +1,74 @@
+ /* 
+ * \file api.cpp
+ */
+
+#include "logog.hpp"
+
+#include <cstdlib>
+
+namespace logog {
+
+static Mutex s_mInitialization;
+static int s_nInitializations = 0;
+
+int Initialize( INIT_PARAMS *params )
+{
+	s_mInitialization.MutexLock();
+
+	if ( s_nInitializations++ == 0 )
+	{
+		if ( params == NULL )
+		{
+			Static().s_pfMalloc = malloc;
+			Static().s_pfFree = free;
+		}
+		else
+		{
+			if ( params->m_pfMalloc != NULL )
+			{
+				Static().s_pfMalloc = params->m_pfMalloc;
+				Static().s_pfFree = params->m_pfFree;
+			}
+			else
+			{
+				Static().s_pfMalloc = malloc;
+				Static().s_pfFree = free;
+			}
+		}
+
+		// Let's allocate a default filter here.
+		GetDefaultFilter();
+
+		// Socket::Initialize();
+	}
+
+	s_mInitialization.MutexUnlock();
+
+    return 0;
+}
+
+int Shutdown( )
+{
+	s_mInitialization.MutexLock();
+
+	if ( --s_nInitializations == 0 )
+	{
+		// Socket::Shutdown();
+
+#ifdef LOGOG_DESTROY_STATIC_AREA
+		delete &( Static() );
+#else
+		Static().Reset();
+#endif
+
+#ifdef LOGOG_LEAK_DETECTION
+		ReportMemoryAllocations();
+#endif
+	}
+
+	s_mInitialization.MutexUnlock();
+
+    return 0;
+}
+}
+
diff --git a/Base/logog/src/checkpoint.cpp b/Base/logog/src/checkpoint.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..45ecf39f5b0299ecc70a2c9e682ae2f1ca8dff15
--- /dev/null
+++ b/Base/logog/src/checkpoint.cpp
@@ -0,0 +1,30 @@
+ 
+/* 
+ * \file checkpoint.cpp
+ */
+
+#include "logog.hpp"
+
+namespace logog {
+
+	Checkpoint::Checkpoint( const LOGOG_LEVEL_TYPE level,
+		const LOGOG_CHAR *sFileName ,
+		const int nLineNumber,
+		const LOGOG_CHAR *sGroup,
+		const LOGOG_CHAR *sCategory,
+		const LOGOG_CHAR *sMessage,
+		const double dTimestamp ) :
+	TopicSource( level, sFileName, nLineNumber, sGroup, sCategory, sMessage, dTimestamp )
+	{
+	}
+
+	int Checkpoint::Send( const Topic &node )
+	{
+		/* Optionally update our own timestamp before we send on our information */
+		if (( m_TopicFlags & TOPIC_TIMESTAMP_FLAG ) != 0 )
+			m_tTime = GetGlobalTimer().Get();
+
+		return TopicSource::Send( node );
+	}
+}
+
diff --git a/Base/logog/src/formatter.cpp b/Base/logog/src/formatter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..22515f3c5a6cb9362b176aabeae462dc93202fa0
--- /dev/null
+++ b/Base/logog/src/formatter.cpp
@@ -0,0 +1,238 @@
+ 
+/* 
+ * \file formatter.cpp
+ */
+
+#include "logog.hpp"
+
+namespace logog {
+
+	Formatter::Formatter() :
+		m_bShowTimeOfDay( false )
+	{
+		m_sMessageBuffer.reserve( LOGOG_FORMATTER_MAX_LENGTH );
+		m_sIntBuffer.reserve_for_int();
+	}
+
+	void Formatter::RenderTimeOfDay()
+	{
+		if ( m_bShowTimeOfDay )
+		{
+#ifndef LOGOG_UNICODE
+			TimeStamp stamp;
+			m_sMessageBuffer.append( stamp.Get() );
+			m_sMessageBuffer.append(": ");
+#endif
+		}
+	}
+
+	const LOGOG_CHAR * Formatter::ErrorDescription( const LOGOG_LEVEL_TYPE level )
+	{
+		if ( level <= LOGOG_LEVEL_NONE )
+			return LOGOG_CONST_STRING("none");
+
+		if ( level <= LOGOG_LEVEL_EMERGENCY )
+			return LOGOG_CONST_STRING("emergency");
+
+		if ( level <= LOGOG_LEVEL_ALERT )
+			return LOGOG_CONST_STRING("alert");
+
+		if ( level <= LOGOG_LEVEL_CRITICAL )
+			return LOGOG_CONST_STRING("critical");
+
+		if ( level <= LOGOG_LEVEL_ERROR )
+			return LOGOG_CONST_STRING("error");
+
+		if ( level <= LOGOG_LEVEL_WARN )
+			return LOGOG_CONST_STRING("warning");
+
+		if ( level <= LOGOG_LEVEL_INFO )
+			return LOGOG_CONST_STRING("info");
+
+		if ( level <= LOGOG_LEVEL_DEBUG )
+			return LOGOG_CONST_STRING("debug");
+
+		return LOGOG_CONST_STRING("unknown");
+	}
+
+	bool Formatter::GetShowTimeOfDay() const
+	{
+		return m_bShowTimeOfDay;
+	}
+
+	void Formatter::SetShowTimeOfDay( bool val )
+	{
+		m_bShowTimeOfDay = val;
+	}
+
+	TOPIC_FLAGS Formatter::GetTopicFlags( const Topic &topic )
+	{
+		return topic.GetTopicFlags();
+	}
+
+	LOGOG_STRING &FormatterGCC::Format( const Topic &topic, const Target &target )
+	{
+		TOPIC_FLAGS flags;
+		flags = GetTopicFlags( topic );
+
+		m_sMessageBuffer.clear();
+
+		if ( flags & TOPIC_FILE_NAME_FLAG )
+		{
+			m_sMessageBuffer.append( topic.FileName() );
+			m_sMessageBuffer.append( ':' );
+		}
+
+		if ( flags & TOPIC_LINE_NUMBER_FLAG )
+		{
+			m_sIntBuffer.assign( topic.LineNumber() );
+			m_sMessageBuffer.append( m_sIntBuffer );
+
+			m_sMessageBuffer.append( LOGOG_CONST_STRING(": "));
+		}
+
+		RenderTimeOfDay();
+
+		if ( flags & TOPIC_LEVEL_FLAG )
+		{
+			m_sMessageBuffer.append( ErrorDescription( topic.Level()));
+			m_sMessageBuffer.append( LOGOG_CONST_STRING(": "));
+		}
+
+		if ( flags & TOPIC_GROUP_FLAG )
+		{
+			m_sMessageBuffer.append( LOGOG_CONST_STRING("{") );
+			m_sMessageBuffer.append( topic.Group() );
+			m_sMessageBuffer.append( LOGOG_CONST_STRING("} ") );
+		}
+
+		if ( flags & TOPIC_CATEGORY_FLAG )
+		{
+			m_sMessageBuffer.append( LOGOG_CONST_STRING("["));
+			m_sMessageBuffer.append( topic.Category() );
+			m_sMessageBuffer.append( LOGOG_CONST_STRING("] "));
+		}
+
+		if ( flags & TOPIC_MESSAGE_FLAG )
+		{
+			m_sMessageBuffer.append( topic.Message() );
+			m_sMessageBuffer.append( (LOGOG_CHAR)'\n' );
+		}
+
+		if ( target.GetNullTerminatesStrings() )
+			m_sMessageBuffer.append( (LOGOG_CHAR)NULL );
+
+		return m_sMessageBuffer;
+	}
+
+
+	LOGOG_STRING &FormatterMSVC::Format( const Topic &topic, const Target &target )
+    {
+        m_sMessageBuffer.clear();
+
+        TOPIC_FLAGS flags;
+        flags = GetTopicFlags( topic );
+
+        if ( flags & TOPIC_FILE_NAME_FLAG )
+        {
+            m_sMessageBuffer.append( topic.FileName() );
+            m_sMessageBuffer.append( '(' );
+        }
+
+        if ( flags & TOPIC_LINE_NUMBER_FLAG  )
+        {
+            m_sIntBuffer.assign( topic.LineNumber() );
+            m_sMessageBuffer.append( m_sIntBuffer );
+
+            m_sMessageBuffer.append( LOGOG_CONST_STRING(") : ") );
+        }
+
+		RenderTimeOfDay();
+
+        if ( flags & TOPIC_LEVEL_FLAG )
+        {
+            m_sMessageBuffer.append( ErrorDescription( topic.Level() ) );
+            m_sMessageBuffer.append( LOGOG_CONST_STRING(": "));
+        }
+
+        if ( flags & TOPIC_GROUP_FLAG )
+        {
+            m_sMessageBuffer.append( LOGOG_CONST_STRING("{"));
+            m_sMessageBuffer.append( topic.Group() );
+            m_sMessageBuffer.append( LOGOG_CONST_STRING("} "));
+        }
+
+        if ( flags & TOPIC_CATEGORY_FLAG )
+        {
+            m_sMessageBuffer.append( LOGOG_CONST_STRING("["));
+            m_sMessageBuffer.append( topic.Category() );
+            m_sMessageBuffer.append( LOGOG_CONST_STRING("] "));
+        }
+
+        if ( flags & TOPIC_MESSAGE_FLAG )
+        {
+            m_sMessageBuffer.append( topic.Message() );
+#ifdef LOGOG_FLAVOR_WINDOWS
+			m_sMessageBuffer.append( LOGOG_CONST_STRING("\r\n") );
+#else // LOGOG_FLAVOR_WINDOWS
+            m_sMessageBuffer.append( LOGOG_CONST_STRING("\n") );
+#endif // LOGOG_FLAVOR_WINDOWS
+        }
+
+		if ( target.GetNullTerminatesStrings() )
+			m_sMessageBuffer.append( LOGOG_CHAR( NULL ) );
+
+        return m_sMessageBuffer;
+    }
+
+	Formatter &GetDefaultFormatter()
+	{
+		Statics *pStatic = &Static();
+
+		if ( pStatic->s_pDefaultFormatter == NULL )
+		{
+#ifdef LOGOG_FLAVOR_WINDOWS
+			pStatic->s_pDefaultFormatter = new FormatterMSVC();
+#else
+			pStatic->s_pDefaultFormatter = new FormatterGCC();
+#endif
+		}
+
+		return *( pStatic->s_pDefaultFormatter );
+	}
+
+	void DestroyDefaultFormatter()
+	{
+		Statics *pStatic = &Static();
+		Formatter *pDefaultFormatter = pStatic->s_pDefaultFormatter;
+
+		if ( pDefaultFormatter != NULL )
+			delete pDefaultFormatter;
+
+		pStatic->s_pDefaultFormatter = NULL;
+}
+
+const char * TimeStamp::Get()
+{
+	time_t tRawTime;
+	struct tm * tmInfo;
+
+	time ( &tRawTime );
+
+#ifdef LOGOG_FLAVOR_WINDOWS
+#pragma warning( push )
+#pragma warning( disable : 4996 )
+#endif // LOGOG_FLAVOR_WINDOWS
+	/* Microsoft is afraid of this function; I'm not sure this warning is sensible */
+	tmInfo = localtime ( &tRawTime );
+#ifdef LOGOG_FLAVOR_WINDOWS
+#pragma warning( pop )
+#endif // LOGOG_FLAVOR_WINDOWS
+
+	strftime (cTimeString, LOGOG_TIME_STRING_MAX, "%c", tmInfo);
+
+	return cTimeString;
+}
+
+}
+
diff --git a/Base/logog/src/lobject.cpp b/Base/logog/src/lobject.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8fbce7755567d1b4b1e29df5f2ee6d7bf2cb6ab4
--- /dev/null
+++ b/Base/logog/src/lobject.cpp
@@ -0,0 +1,177 @@
+/* 
+ * \file object.cpp
+ */
+
+#include "logog.hpp"
+#ifdef LOGOG_LEAK_DETECTION
+#include <iostream>
+#endif // LOGOG_LEAK_DETECTION
+
+namespace logog {
+
+#ifdef LOGOG_LEAK_DETECTION
+AllocationsType s_Allocations;
+#endif
+
+	Object::Object() {}
+
+	Object::~Object()
+	{
+
+	}
+
+	void *Object::operator new( size_t nSize )
+	{
+		return Allocate( nSize );
+	}
+
+	void *Object::operator new[]( size_t nSize )
+	{
+		return Allocate( nSize );
+	}
+
+#ifdef _DEBUG
+#ifdef LOGOG_FLAVOR_WINDOWS
+
+	void *Object::operator new(size_t nSize, LPCSTR lpszFileName, int nLine)
+	{
+		/* avoid unref'd parameter warnings */
+		lpszFileName;
+		nLine;
+		return Allocate( nSize );
+	}
+
+	void *Object::operator new[](size_t nSize, LPCSTR lpszFileName, int nLine)
+	{
+		/* avoid unref'd parameter warnings */
+		lpszFileName;
+		nLine;
+		return Allocate( nSize );
+	}
+
+	void Object::operator delete(void *ptr, LPCSTR lpszFileName, int nLine)
+	{
+		lpszFileName;
+		nLine;
+		Deallocate( ptr );
+	}
+
+	void Object::operator delete[](void *ptr, LPCSTR lpszFileName, int nLine)
+	{
+		lpszFileName;
+		nLine;
+		Deallocate( ptr );
+	}
+
+#endif // LOGOG_FLAVOR_WINDOWS
+#endif // _DEBUG
+
+	    /** Deletes an object pointed to by ptr. */
+	void Object::operator delete( void *ptr )
+    {
+        Deallocate( ptr );
+    }
+    /** Deletes an object array pointed to by ptr. */
+	void Object::operator delete[]( void *ptr )
+    {
+        Deallocate( ptr );
+    }
+
+    /** Allocates nSize bytes of memory.  You must call logog::Initialize() before calling this function.
+     * \sa Initialize()
+     */
+	void *Object::Allocate( size_t nSize )
+    {
+        void *ptr = Static().s_pfMalloc( nSize );
+#ifdef LOGOG_REPORT_ALLOCATIONS
+        LOGOG_COUT << _LG("Allocated ") << nSize << _LG(" bytes of memory at ") << ptr << endl;
+#endif // LOGOG_REPORT_ALLOCATIONS
+#ifdef LOGOG_LEAK_DETECTION
+        AllocationsType::iterator it;
+
+        LockAllocationsMutex();
+        it = s_Allocations.find( ptr );
+
+        if ( it != s_Allocations.end() )
+        {
+            LOGOG_COUT << _LG("Reallocation detected in memory manager!  We seem to have allocated the same address twice ")
+                 << _LG("without freeing it!  Address = ") << ptr << std::endl;
+            UnlockAllocationsMutex();
+            LOGOG_INTERNAL_FAILURE;
+        }
+
+        s_Allocations.insert( LOGOG_PAIR< const PointerType, size_t >( ptr, nSize ) );
+        UnlockAllocationsMutex();
+#endif // LOGOG_LEAK_DETECTION
+        return ptr;
+    }
+
+    /** Deallocate a pointer previously acquired by Allocate(). */
+	void Object::Deallocate( void *ptr )
+    {
+#ifdef LOGOG_LEAK_DETECTION
+        LockAllocationsMutex();
+        AllocationsType::iterator it;
+
+        it = s_Allocations.find( ptr );
+
+        if ( it == s_Allocations.end() )
+        {
+            LOGOG_COUT << _LG("Freeing memory not previously allocated!  Address = ") << ptr << std::endl;
+            UnlockAllocationsMutex();
+            LOGOG_INTERNAL_FAILURE;
+        }
+
+#ifdef LOGOG_REPORT_ALLOCATIONS
+        LOGOG_COUT << _LG("Freeing ") << it->second << _LG(" bytes of memory at ") << it->first << endl;
+#endif // LOGOG_REPORT_ALLOCATIONS
+        s_Allocations.erase( ptr );
+        UnlockAllocationsMutex();
+#endif // LOGOG_LEAK_DETECTION
+        Static().s_pfFree( ptr );
+    }
+
+	int MemoryAllocations()
+	{
+#ifdef LOGOG_LEAK_DETECTION
+		LockAllocationsMutex();
+		size_t nSize = s_Allocations.size();
+
+		if ( nSize != 0 )
+			LOGOG_COUT << _LG("Total active allocations: ") << nSize << std::endl;
+
+		UnlockAllocationsMutex();
+		return (int)nSize;
+#else // LOGOG_LEAK_DETECTION
+		return -1;
+#endif // LOGOG_LEAK_DETECTION
+	}
+
+	int ReportMemoryAllocations()
+	{
+#ifdef LOGOG_LEAK_DETECTION
+		LockAllocationsMutex();
+
+		if ( s_Allocations.size() == 0 )
+		{
+			LOGOG_COUT << _LG("No memory allocations outstanding.") << std::endl;
+		}
+		else
+		{
+			for ( AllocationsType::iterator it = s_Allocations.begin();
+				it != s_Allocations.end();
+				it++ )
+			{
+				LOGOG_COUT << _LG("Memory allocated at ") << it->first << 
+					_LG(" with size ") << it->second << 
+					_LG(" bytes ") << std::endl;
+			}
+		}
+
+		UnlockAllocationsMutex();
+#endif
+		return MemoryAllocations();
+	}
+
+}
+
diff --git a/Base/logog/src/logog.vcproj b/Base/logog/src/logog.vcproj
new file mode 100644
index 0000000000000000000000000000000000000000..f80a5d75e08d9b275f30cc07e76f1944aa2fbcba
--- /dev/null
+++ b/Base/logog/src/logog.vcproj
@@ -0,0 +1,323 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="9.00"
+	Name="logog"
+	ProjectGUID="{85857E80-2122-4DD8-9BA9-B90CC10D65B0}"
+	RootNamespace="logog"
+	SccProjectName="Perforce Project"
+	SccLocalPath=".."
+	SccProvider="MSSCCI:Perforce SCM"
+	Keyword="Win32Proj"
+	TargetFrameworkVersion="196613"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="4"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../include"
+				PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="0"
+				WarningLevel="4"
+				WarnAsError="true"
+				DebugInformationFormat="4"
+				ShowIncludes="false"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="4"
+			CharacterSet="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				EnableIntrinsicFunctions="true"
+				AdditionalIncludeDirectories="../include"
+				PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+				RuntimeLibrary="2"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="4"
+				WarnAsError="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath=".\api.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\checkpoint.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\formatter.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\lobject.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\lstring.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\message.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\mutex.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\node.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\platform.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\socket.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\statics.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\target.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\timer.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\topic.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\unittest.cpp"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath="..\include\api.hpp"
+				>
+			</File>
+			<File
+				RelativePath="..\include\checkpoint.hpp"
+				>
+			</File>
+			<File
+				RelativePath="..\include\const.hpp"
+				>
+			</File>
+			<File
+				RelativePath="..\include\formatter.hpp"
+				>
+			</File>
+			<File
+				RelativePath="..\include\logog.hpp"
+				>
+			</File>
+			<File
+				RelativePath="..\include\macro.hpp"
+				>
+			</File>
+			<File
+				RelativePath="..\include\message.hpp"
+				>
+			</File>
+			<File
+				RelativePath="..\include\mutex.hpp"
+				>
+			</File>
+			<File
+				RelativePath="..\include\node.hpp"
+				>
+			</File>
+			<File
+				RelativePath="..\include\object.hpp"
+				>
+			</File>
+			<File
+				RelativePath="..\include\platform.hpp"
+				>
+			</File>
+			<File
+				RelativePath="..\include\socket.hpp"
+				>
+			</File>
+			<File
+				RelativePath="..\include\statics.hpp"
+				>
+			</File>
+			<File
+				RelativePath="..\include\string.hpp"
+				>
+			</File>
+			<File
+				RelativePath="..\include\target.hpp"
+				>
+			</File>
+			<File
+				RelativePath="..\include\thread.hpp"
+				>
+			</File>
+			<File
+				RelativePath="..\include\timer.hpp"
+				>
+			</File>
+			<File
+				RelativePath="..\include\topic.hpp"
+				>
+			</File>
+			<File
+				RelativePath="..\include\unittest.hpp"
+				>
+			</File>
+			<Filter
+				Name="Proprietary"
+				>
+				<File
+					RelativePath="..\include\proprietary\ps3.hpp"
+					>
+				</File>
+				<File
+					RelativePath="..\include\proprietary\xbox360.hpp"
+					>
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+			>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
diff --git a/Base/logog/src/lstring.cpp b/Base/logog/src/lstring.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5ab7c03112a9cdc8925f7d0fdd10ac8e24761a98
--- /dev/null
+++ b/Base/logog/src/lstring.cpp
@@ -0,0 +1,497 @@
+ /* 
+ * \file lstring.cpp
+ */
+
+#include "logog.hpp"
+
+namespace logog {
+
+	String::String()
+	{
+		Initialize();
+	}
+
+	String::~String()
+	{
+		Free();
+	}
+
+	void String::Free()
+	{
+		if ( m_pBuffer && ( m_bIsConst == false ))
+		{
+			Deallocate( (void *)m_pBuffer );
+			m_pBuffer = m_pEndOfBuffer = m_pOffset = NULL;
+		}
+
+		if ( m_pKMP )
+		{
+			Deallocate( (void *)m_pKMP );
+			m_pKMP = NULL;
+		}
+	}
+
+	size_t String::Length( const LOGOG_CHAR *chars )
+	{
+		unsigned int len = 0;
+
+		while ( *chars++ )
+			len++;
+
+		return len;
+	}
+
+	String & String::operator=( const String & other )
+	{
+		Free();
+		Initialize();
+		assign( other );
+		return *this;
+	}
+
+	String & String::operator=( const LOGOG_CHAR *pstr )
+	{
+		Free();
+		Initialize();
+		assign( pstr );
+		return *this;
+	}
+
+	String::String( const String &other )
+	{
+		Initialize();
+		assign( other );
+	}
+
+	String::String( const LOGOG_CHAR *pstr )
+	{
+		Initialize();
+		assign( pstr );
+	}
+
+	size_t String::size() const
+	{
+		return ( m_pOffset - m_pBuffer );
+	}
+
+	void String::clear()
+	{
+		m_pOffset = m_pBuffer;
+	}
+
+	size_t String::reserve( size_t nSize )
+	{
+		if ( nSize == (unsigned int)( m_pOffset - m_pBuffer ))
+			return nSize;
+
+		if ( nSize == 0 )
+		{
+			if ( m_pBuffer && ( *m_pBuffer != (LOGOG_CHAR)NULL ))
+				Deallocate( (void *)m_pBuffer );
+
+			Initialize();
+			return 0;
+		}
+
+		LOGOG_CHAR *pNewBuffer = (LOGOG_CHAR *)Allocate( sizeof( LOGOG_CHAR ) * nSize );
+		LOGOG_CHAR *pNewOffset = pNewBuffer;
+		LOGOG_CHAR *pNewEnd = pNewBuffer + nSize;
+
+		LOGOG_CHAR *pOldOffset = m_pOffset;
+
+		if ( pOldOffset != NULL )
+		{
+			while (( pNewOffset < pNewEnd ) && ( *pOldOffset != (LOGOG_CHAR)NULL ))
+				*pNewOffset++ = *pOldOffset++;
+		}
+
+		if (( m_pBuffer != NULL ) && ( m_bIsConst == false ))
+			Deallocate( m_pBuffer );
+
+		m_pBuffer = pNewBuffer;
+		m_pOffset = pNewBuffer;
+		m_pEndOfBuffer = pNewEnd;
+
+		return ( m_pOffset - m_pBuffer );
+	}
+
+	size_t String::reserve_for_int()
+	{
+		reserve( 32 );
+		return 32;
+	}
+
+	String::operator const LOGOG_CHAR *() const
+	{
+		return m_pBuffer;
+	}
+
+	const LOGOG_CHAR* String::c_str() const
+	{
+		return m_pBuffer;
+	}
+
+	size_t String::assign( const String &other )
+	{
+#ifdef LOGOG_INTERNAL_DEBUGGING
+		if ( m_bIsConst )
+			cout << "Can't reassign const string!" << endl;
+#endif
+		LOGOG_CHAR *pOther = other.m_pBuffer;
+
+		if ( pOther == NULL )
+			return 0;
+
+		size_t othersize = other.size();
+
+		reserve( othersize + 1 );
+		m_pOffset = m_pBuffer;
+
+		for ( unsigned int t = 0; t <= othersize ; t++ )
+			*m_pOffset++ = *pOther++;
+
+		return this->size();
+	}
+
+	size_t String::assign( const int value )
+	{
+#ifdef LOGOG_INTERNAL_DEBUGGING
+		if ( m_bIsConst )
+			cout << "Can't reassign const string!" << endl;
+#endif
+
+		int number = value;
+		m_pOffset = m_pBuffer;
+
+		int bSign = value;
+
+		if (( bSign = number) < 0)
+			number = -number;
+
+		do
+		{
+			*m_pOffset++ = _LG("0123456789")[ number % 10 ];
+		}
+		while( number /= 10 );
+
+		if (bSign < 0)
+			*m_pOffset++ = '-';
+
+		*m_pOffset = (LOGOG_CHAR)'\0';
+
+		reverse( m_pBuffer, m_pOffset - 1 );
+
+		return ( m_pOffset - m_pBuffer );
+	}
+
+	size_t String::assign( const LOGOG_CHAR *other, const LOGOG_CHAR *pEnd /*= NULL */ )
+	{
+		size_t len;
+
+		if ( pEnd == NULL )
+			len = Length( other );
+		else
+			len = ( pEnd - other );
+		/** This constant decides whether assigning a LOGOG_CHAR * to a String will cause the String to use the previous buffer
+		* in place, or create a new buffer and copy the results.
+		*/
+#ifdef LOGOG_COPY_CONST_CHAR_ARRAY_ON_ASSIGNMENT
+		reserve( len + 1 );
+
+		for (unsigned int t = 0; t <= len; t++ )
+			*m_pOffset++ = *other++;
+#else  // LOGOG_COPY_CONST_CHAR_ARRAY_ON_ASSIGNMENT
+
+#ifdef LOGOG_INTERNAL_DEBUGGING
+		if ( m_bIsConst )
+			cout << "Can't reassign const string!" << endl;
+#endif
+		/* In this case we don't copy the buffer, just reuse it */
+		m_pBuffer = const_cast< LOGOG_CHAR *>( other );
+		m_pOffset = m_pBuffer + len + 1;
+		m_pEndOfBuffer = m_pOffset;
+		m_bIsConst = true;
+
+#endif // LOGOG_COPY_CONST_CHAR_ARRAY_ON_ASSIGNMENT
+
+		return (int) len;
+	}
+	size_t String::append( const String &other )
+	{
+#ifdef LOGOG_INTERNAL_DEBUGGING
+		if ( m_bIsConst )
+			cout << "Can't reassign const string!" << endl;
+#endif
+
+		return append( other.m_pBuffer );
+	}
+
+	size_t String::append( const LOGOG_CHAR *other )
+	{
+#ifdef LOGOG_INTERNAL_DEBUGGING
+		if ( m_bIsConst )
+			cout << "Can't reassign const string!" << endl;
+#endif
+		if ( other == NULL )
+			return 0;
+
+		while (( m_pOffset < m_pEndOfBuffer ) && ( *other != (LOGOG_CHAR)NULL ))
+			*m_pOffset++ = *other++;
+
+		return ( m_pOffset - m_pBuffer );
+	}
+
+	size_t String::append( const LOGOG_CHAR c )
+	{
+		if ( m_pOffset < m_pEndOfBuffer )
+			*m_pOffset++ = c;
+
+		return ( m_pOffset - m_pBuffer );
+	}
+	void String::reverse( LOGOG_CHAR* pStart, LOGOG_CHAR* pEnd )
+	{
+		LOGOG_CHAR temp;
+
+		while( pEnd > pStart)
+		{
+			temp=*pEnd, *pEnd-- =*pStart, *pStart++=temp;
+		}
+	}
+
+	bool String::is_valid() const
+	{
+		return ( m_pBuffer != NULL );
+	}
+
+	size_t String::find( String &other ) const
+	{
+		if ( is_valid() && other.is_valid())
+		{
+			// KMP solution
+			// String *pThis = const_cast< String *>(this);
+			// return pThis->KMP( other.m_pBuffer, other.size());
+			LOGOG_CHAR *pFound;
+
+#ifdef LOGOG_UNICODE
+			pFound = wcsstr( m_pBuffer, other.m_pBuffer );
+#else // LOGOG_UNICODE
+			pFound = strstr( m_pBuffer, other.m_pBuffer );
+#endif
+
+			if ( pFound != NULL )
+			{
+				return ( pFound - m_pBuffer );
+			}
+
+			return npos;
+		}
+
+		return npos;
+	}
+
+	void String::format( const LOGOG_CHAR *cFormatString, ... )
+	{
+		va_list args;
+
+		va_start(args, cFormatString);
+		format_va( cFormatString, args );
+		va_end( args );
+	}
+
+	void String::format_va( const LOGOG_CHAR *cFormatString, va_list args )
+	{
+		int nActualSize = -1, nAttemptedSize;
+		LOGOG_CHAR *pszFormatted = NULL;
+
+		Free();
+
+		/* Estimate length of output; don't pull in strlen() if we can help it */
+		int nEstLength = 0;
+		const LOGOG_CHAR *pCurChar = cFormatString;
+		while ( *pCurChar++ )
+			nEstLength++;
+
+		if ( nEstLength == 0 )
+		{
+			clear();
+			return;
+		}
+
+		/** nAttemptedSize is now a guess at an appropriate size, which is about 
+		 ** two times the number of LOGOG_CHARs in the incoming format string.
+		 **/
+		nAttemptedSize = nEstLength * 2 * sizeof( LOGOG_CHAR );
+
+		/* Some *printf implementations, such as msvc's, return -1 on failure.  
+		 * Others, such as gcc, return the number
+		 * of characters actually formatted on failure.  Deal with either case here.
+		 */
+		for ( ; ; )
+		{
+			/** We'll allocate that number of bytes.  NOTE that this has less of a chance
+			 ** of working on a Unicode build.
+			 **/
+			pszFormatted = (LOGOG_CHAR *)Allocate( nAttemptedSize );
+			if ( !pszFormatted )
+			{
+				LOGOG_INTERNAL_FAILURE;
+			}
+
+			*pszFormatted = (LOGOG_CHAR)'\0';
+
+			va_list argsCopy;
+
+			/** The va_list structure is not standardized across all platforms; in particular
+			 ** Microsoft seems to have problem with the concept.
+			 **/
+#if defined( va_copy )
+			va_copy( argsCopy, args );
+#elif defined( __va_copy )
+			__va_copy( argsCopy, args );
+#else
+			memcpy( &argsCopy, &args, sizeof(va_list) );
+#endif
+
+#ifdef LOGOG_UNICODE
+			/** At this point, nSizeInWords will contain the number of words permitted in the
+			 ** output buffer.  It takes into account space for appending a null character in the output
+			 ** buffer as well.
+			 **/
+			int nSizeInWords = (nAttemptedSize / sizeof( LOGOG_CHAR ));
+#endif
+			/** The nActualSize value receives different things on different platforms.
+			 ** On some platforms it receives -1 on failure; on other platforms
+			 ** it receives the number of LOGOG_CHARs actually formatted (excluding
+			 ** the trailing NULL).
+			 **/
+
+#ifdef LOGOG_FLAVOR_WINDOWS
+#ifdef LOGOG_UNICODE
+			nActualSize = _vsnwprintf_s( pszFormatted, nSizeInWords, _TRUNCATE, cFormatString, argsCopy );
+#else // LOGOG_UNICODE
+			nActualSize = vsnprintf_s( pszFormatted, nAttemptedSize, _TRUNCATE, cFormatString, argsCopy );
+#endif // LOGOG_UNICODE
+#else // LOGOG_FLAVOR_WINDOWS
+#ifdef LOGOG_UNICODE
+			nActualSize = vswprintf( pszFormatted, nSizeInWords, cFormatString, argsCopy );
+#else // LOGOG_UNICODE
+			nActualSize = vsnprintf( pszFormatted, nAttemptedSize, cFormatString, argsCopy );
+#endif // LOGOG_UNICODE
+#endif // LOGOG_FLAVOR_WINDOWS
+
+			va_end( argsCopy );
+
+			/** Convert the number of LOGOG_CHARs actually formatted into bytes.  This
+			 ** does NOT include the trailing NULL.
+			 **/
+			if ( nActualSize != -1 )
+				nActualSize *= sizeof( LOGOG_CHAR );
+
+			/** When we're doing the compare, we have to keep in mind that the nActualSize
+			 ** does not include a null.  We need to verify that the nAttemptedSize can hold all
+			 ** of nActualSize PLUS the size of one null on this platform.  A LOGOG_CHAR could
+			 ** be 1, 2, or 4 bytes long.  So nAttemptedSize must be greater or equal to nActualSize
+			 ** less the size of one (null) LOGOG_CHAR in bytes.  Also, the last
+			 ** allocation may have failed altogether.
+			 ** 
+			 **/
+			if (( nAttemptedSize >= (nActualSize - (int)sizeof(LOGOG_CHAR))) && ( nActualSize != -1))
+				break;
+
+			/** That attempted allocation failed */
+			Deallocate( pszFormatted );
+
+			/** If nActualSize has a positive value, it includes the number of bytes needed to hold
+			 ** the formatted string; we'll add a LOGOG_CHAR size to the end for the next
+			 ** allocation.  If nActualSize has no meaningful value, we'll double the previous
+			 ** size and try again.
+			 **/
+			if (nActualSize > 0)
+			{
+				nAttemptedSize = nActualSize + sizeof( LOGOG_CHAR );
+			}
+			else
+			{
+				nAttemptedSize *= 2;
+			}
+
+		}
+
+		m_bIsConst = false;
+		assign( pszFormatted );
+		/* We just allocated this string, which means it needs to be deallocated
+		 * at shutdown time.  The previous function may have changed the const
+		 * setting for this string, which means we may need to change it back here... 
+		 * */
+		m_bIsConst = false;
+	}
+
+	void String::Initialize()
+	{
+		m_pBuffer = NULL;
+		m_pOffset = NULL;
+		m_pEndOfBuffer = NULL;
+		m_pKMP = NULL;
+		m_bIsConst = false;
+	}
+
+	void String::preKmp( size_t m )
+	{
+		ScopedLock sl( GetStringSearchMutex() );
+
+		size_t i, j;
+
+		if ( m_pBuffer == NULL )
+			return;
+
+		if ( m_pKMP == NULL )
+		{
+			m_pKMP = (size_t *)Allocate( sizeof( size_t ) * ( m + 1) );
+		}
+
+		i = 0;
+		j = *m_pKMP = (size_t)-1;
+
+		while (i < m)
+		{
+			while (j > (size_t)-1 && m_pBuffer[i] != m_pBuffer[j])
+				j = m_pKMP[j];
+			i++;
+			j++;
+			if (m_pBuffer[i] == m_pBuffer[j])
+				m_pKMP[i] = m_pKMP[j];
+			else
+				m_pKMP[i] = j;
+		}
+	}
+
+	size_t String::KMP( const LOGOG_CHAR *y, size_t n )
+	{
+		size_t i, j;
+
+		size_t m = size() - 1; // ignore NULL char
+
+		/* Preprocessing */
+		if ( m_pKMP == NULL )
+			preKmp( m );
+
+		/* Searching */
+		i = j = 0;
+		while (j < n)
+		{
+			while (i > (size_t)-1 && m_pBuffer[i] != y[j])
+				i = m_pKMP[i];
+			i++;
+			j++;
+			if (i >= m)
+			{
+				return (j - i);
+				// We would do this if we cared about multiple substrings
+				// i = m_pKMP[i];
+			}
+		}
+
+		return npos;
+	}
+}
+
diff --git a/Base/logog/src/message.cpp b/Base/logog/src/message.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ffc38891a973323ca6e67ffa36564288a317b095
--- /dev/null
+++ b/Base/logog/src/message.cpp
@@ -0,0 +1,69 @@
+/* 
+ * \file message.cpp
+ */
+
+#include "logog.hpp"
+
+namespace logog
+{
+	Message::Message( const LOGOG_LEVEL_TYPE level,
+             const LOGOG_CHAR *sFileName ,
+             const int nLineNumber,
+             const LOGOG_CHAR *sGroup,
+             const LOGOG_CHAR *sCategory,
+             const LOGOG_CHAR *sMessage,
+             const double dTimestamp,
+			 bool *pbIsCreated ) :
+        Checkpoint( level, sFileName, nLineNumber, sGroup, sCategory, sMessage, dTimestamp )
+    {
+		m_pbIsCreated = pbIsCreated;
+
+		if ( pbIsCreated != NULL )
+			*pbIsCreated = true;
+
+        /* Messages are always sources, so there's no need to call Initialize() here */
+        // Initialize();
+
+        /* NOTE!  The message is typically assigned to a checkpoint AFTER it's been published.
+         * Ergo a message needs to be unpublished from, and published to, all filters
+         * iff one of those filters is searching for a substring of that message.
+         */
+        PublishToMultiple( AllFilters() );
+    }
+
+	Message::~Message()
+	{
+		if ( m_pbIsCreated != NULL )
+			*m_pbIsCreated = false;
+	}
+
+
+	bool Message::Republish()
+	{
+		UnpublishToMultiple( AllFilters() );
+		return PublishToMultiple( AllFilters() );
+	}
+
+	Mutex &GetMessageCreationMutex()
+	{
+		Statics *pStatic = &Static();
+
+		if ( pStatic->s_pMessageCreationMutex == NULL )
+			pStatic->s_pMessageCreationMutex = new Mutex();
+
+		return *( pStatic->s_pMessageCreationMutex );
+	}
+
+	void DestroyMessageCreationMutex()
+	{
+		Statics *pStatic = &Static();
+
+		if ( pStatic->s_pMessageCreationMutex != NULL )
+		{
+			delete pStatic->s_pMessageCreationMutex;
+			pStatic->s_pMessageCreationMutex = NULL;
+		}
+	}
+}
+
+
diff --git a/Base/logog/src/mutex.cpp b/Base/logog/src/mutex.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..730a5c42d88e29ca2567db73ab9be70a036e2f40
--- /dev/null
+++ b/Base/logog/src/mutex.cpp
@@ -0,0 +1,92 @@
+ 
+/* 
+ * \file mutex.cpp
+ */
+
+#include "logog.hpp"
+
+namespace logog {
+
+	Mutex::Mutex() LOGOG_MUTEX_CTOR( m_Mutex )
+	{
+		LOGOG_MUTEX_INIT(&m_Mutex);
+	}
+
+	Mutex::Mutex( const Mutex & )
+	{
+		LOGOG_MUTEX_INIT(&m_Mutex);
+	}
+
+	Mutex & Mutex::operator = (const Mutex &)
+	{
+		LOGOG_MUTEX_INIT(&m_Mutex);
+		return *this;
+	}
+
+	Mutex::~Mutex()
+	{
+		LOGOG_MUTEX_DELETE(&m_Mutex);
+	}
+
+	void Mutex::MutexLock()
+	{
+		LOGOG_MUTEX_LOCK(&m_Mutex);
+	}
+
+	void Mutex::MutexUnlock()
+	{
+		LOGOG_MUTEX_UNLOCK(&m_Mutex);
+	}
+
+	ScopedLock::ScopedLock( Mutex &mutex )
+	{
+		m_pMutex = &mutex;
+		m_pMutex->MutexLock();
+	}
+
+	ScopedLock::~ScopedLock()
+	{
+		m_pMutex->MutexUnlock();
+	}
+
+#ifdef LOGOG_LEAK_DETECTION
+	Mutex s_AllocationsMutex;
+	void LockAllocationsMutex()
+	{
+		s_AllocationsMutex.MutexLock();
+	}
+	void UnlockAllocationsMutex()
+	{
+		s_AllocationsMutex.MutexUnlock();
+	}
+#endif // LOGOG_LEAK_DETECTION
+
+	Mutex &GetStringSearchMutex()
+	{
+		Statics *pStatic = &Static();
+		Mutex **ppStringSearchMutex = (Mutex **)&( pStatic->s_pStringSearchMutex );
+
+#ifdef LOGOG_INTERNAL_DEBUGGING
+		if ( pStatic == NULL )
+			LOGOG_INTERNAL_FAILURE;
+#endif
+		if ( *ppStringSearchMutex == NULL )
+			*ppStringSearchMutex = new Mutex();
+
+		return *(( Mutex *)( *ppStringSearchMutex ));
+	}
+
+	void DestroyStringSearchMutex()
+	{
+		Statics *pStatic = &Static();
+		Mutex **ppStringSearchMutex = (Mutex **)&( pStatic->s_pStringSearchMutex );
+
+		if ( *ppStringSearchMutex != NULL )
+		{
+			delete *ppStringSearchMutex;
+			*ppStringSearchMutex = NULL;
+		}
+	}
+
+}
+
diff --git a/Base/logog/src/node.cpp b/Base/logog/src/node.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2c161609be1bb54884a1f89bf9ca16272ec80d2c
--- /dev/null
+++ b/Base/logog/src/node.cpp
@@ -0,0 +1,351 @@
+ 
+/* 
+ * \file node.cpp
+ */
+
+#include "logog.hpp"
+
+namespace logog {
+
+	LockableNodesType & LockableNodesType::operator = (const LockableNodesType &other)
+	{
+		/* This function is only used at shutdown. */
+		LockableNodesType::const_iterator it;
+
+		it = other.begin();
+		while ( it != other.end())
+		{
+			this->insert( *it );
+			++it;
+		}
+
+		return *this;
+	}
+
+	LockableNodesType &GetStaticNodes( void ** pvLocation )
+	{
+		if ( *pvLocation == NULL )
+			*pvLocation = new LockableNodesType();
+
+		return *(( LockableNodesType *)( *pvLocation ));
+
+	}
+
+	LockableNodesType &AllNodes()
+	{
+	    return GetStaticNodes( &(Static().s_pAllNodes) );
+	}
+
+	LockableNodesType &AllSubscriberNodes()
+	{
+		return GetStaticNodes( &(Static().s_pAllSubscriberNodes ) );
+	}
+
+	LockableNodesType &AllFilters()
+	{
+		return GetStaticNodes( &(Static().s_pAllFilterNodes ) );
+	}
+
+	LockableNodesType &AllTargets()
+	{
+		return GetStaticNodes( &(Static().s_pAllTargets ) );
+	}
+
+	Node::Node()
+	{
+		AllNodes().insert( this );
+	}
+
+	Node::~Node()
+	{
+		Clear();
+		AllNodes().erase( this );
+	}
+
+	void Node::Initialize()
+	{
+		if ( CanSubscribe() )
+		{
+			LockableNodesType *pSubscriberNodes = &AllSubscriberNodes();
+
+			{
+				ScopedLock sl( *pSubscriberNodes );
+				pSubscriberNodes->insert( this );
+			}
+
+			/* This branch is taken iff this node can both subscribe and publish */
+			if ( CanPublish() )
+			{
+				LockableNodesType *pFilterNodes = &AllFilters();
+				{
+					ScopedLock sl( *pFilterNodes );
+					pFilterNodes->insert( this );
+				}
+			}
+		}
+	}
+
+	bool Node::CanPublish() const
+	{
+		return true;
+	}
+
+	bool Node::CanSubscribe() const
+	{
+		return true;
+	}
+
+	bool Node::CanSubscribeTo( const Node & )
+	{
+		return CanSubscribe();
+	}
+
+	bool Node::IsTopic() const
+	{
+		return false;
+	}
+
+	bool Node::PublishTo( Node &subscriber )
+	{
+#ifdef LOGOG_INTERNAL_DEBUGGING
+		if ( &subscriber == this )
+			LOGOG_INTERNAL_FAILURE;
+#endif
+		bool bWasInserted;
+
+		{
+			ScopedLock sl( m_Subscribers );
+			bWasInserted = ( m_Subscribers.insert( &subscriber ) ).second;
+		}
+
+		if ( bWasInserted )
+			subscriber.SubscribeTo( *this );
+
+		return bWasInserted;
+	}
+
+	bool Node::PublishToMultiple( LockableNodesType &nodes )
+	{
+		LockableNodesType::iterator it;
+
+		bool bWasPublished = false;
+
+		nodes.MutexLock();
+		it = nodes.begin();
+
+		while ( it != nodes.end() )
+		{
+			if ( PublishTo( **it ) == true )
+				bWasPublished = true;
+
+			it++;
+		}
+
+		nodes.MutexUnlock();
+
+		return bWasPublished;
+	}
+
+	bool Node::UnpublishTo( Node &subscriber )
+	{
+#ifdef LOGOG_INTERNAL_DEBUGGING
+		if ( &subscriber == this )
+			LOGOG_INTERNAL_FAILURE;
+#endif
+		bool bWasRemoved = false;
+
+		{
+			ScopedLock sl( m_Subscribers );
+			NodesType::iterator it;
+
+			if ( ( it = m_Subscribers.find( &subscriber) ) != m_Subscribers.end() )
+			{
+				bWasRemoved = true;
+				m_Subscribers.erase( it );
+			}
+		}
+
+		if ( bWasRemoved )
+			subscriber.UnsubscribeTo( *this );
+
+		return bWasRemoved;
+	}
+
+	bool Node::UnpublishToMultiple( LockableNodesType &nodes )
+	{
+		LockableNodesType::iterator it;
+
+		bool bWasUnpublished = false;
+
+		nodes.MutexLock();
+		it = nodes.begin();
+
+		while ( it != nodes.end() )
+		{
+			if ( UnpublishTo( **it ) == true )
+				bWasUnpublished = true;
+
+			it++;
+		}
+
+		nodes.MutexUnlock();
+
+		return bWasUnpublished;
+	}
+
+	bool Node::SubscribeTo( Node &publisher )
+	{
+#ifdef LOGOG_INTERNAL_DEBUGGING
+		if ( &publisher == this )
+			LOGOG_INTERNAL_FAILURE;
+#endif
+		bool bWasInserted;
+
+		{
+			ScopedLock sl( m_Publishers );
+			bWasInserted = ( m_Publishers.insert( &publisher ) ).second;
+		}
+
+		if ( bWasInserted )
+			publisher.PublishTo( *this );
+
+		return bWasInserted;
+	}
+
+	bool Node::SubscribeToMultiple( LockableNodesType &nodes )
+	{
+		LockableNodesType::iterator it;
+
+		bool bWasSubscribed = false;
+
+		nodes.MutexLock();
+		it = nodes.begin();
+
+		while ( it != nodes.end() )
+		{
+			if ( SubscribeTo( **it ) == true )
+				bWasSubscribed = true;
+
+			it++;
+		}
+
+		nodes.MutexUnlock();
+
+		return bWasSubscribed;
+	}
+
+	bool Node::UnsubscribeTo( Node &publisher )
+	{
+#ifdef LOGOG_INTERNAL_DEBUGGING
+		if ( &publisher == this )
+			LOGOG_INTERNAL_FAILURE;
+#endif
+		bool bWasRemoved = false;
+
+		{
+			ScopedLock sl( m_Publishers );
+			NodesType::iterator it;
+
+			if ( ( it = m_Publishers.find( &publisher ) ) != m_Publishers.end() )
+			{
+				bWasRemoved = true;
+				m_Publishers.erase( it );
+			}
+		}
+
+		if ( bWasRemoved )
+			publisher.UnpublishTo( *this );
+
+		return bWasRemoved;
+	}
+
+	bool Node::UnsubscribeToMultiple( LockableNodesType &nodes )
+	{
+		LockableNodesType::iterator it;
+
+		bool bWasUnsubscribed = false;
+
+		nodes.MutexLock();
+		it = nodes.begin();
+
+		while ( it != nodes.end() )
+		{
+			if ( UnsubscribeTo( **it ) == true )
+				bWasUnsubscribed = true;
+
+			it++;
+		}
+
+		nodes.MutexUnlock();
+
+		return bWasUnsubscribed;
+	}
+
+	void Node::Clear()
+	{
+		{
+			ScopedLock sl( m_Publishers );
+			m_Publishers.clear();
+		}
+		{
+			ScopedLock sl( m_Subscribers );
+			m_Publishers.clear();
+		}
+	}
+
+
+	void DestroyNodesList( void **pvList )
+	{
+		LockableNodesType **ppNodesList = (LockableNodesType **)pvList;
+
+		if ( *ppNodesList == NULL )
+			return;
+
+		(*ppNodesList)->clear();
+		delete *ppNodesList;
+		*ppNodesList = NULL;
+	}
+
+	void DestroyAllNodes()
+	{
+		Statics *pStatics = &Static();
+
+		LockableNodesType *pAllNodes = ( LockableNodesType *)pStatics->s_pAllNodes;
+
+		if ( pAllNodes == NULL )
+			return;
+
+		/** Destroy all the node groups, but don't destroy their contents -- we'll do that as the next step. */
+		DestroyNodesList( &(pStatics->s_pAllSubscriberNodes ));
+		DestroyNodesList( &(pStatics->s_pAllFilterNodes ));
+		DestroyNodesList( &(pStatics->s_pAllTargets ));
+
+		/* We have to copy the AllNodes because destroying each node will remove it from AllNodes.  Fortunately
+		 * this only happens at shutdown, so we don't have to worry about efficiency.
+		 */
+		LockableNodesType nodes = *pAllNodes;
+
+		LockableNodesType::iterator it;
+
+		it = nodes.begin();
+
+		while ( it != nodes.end() )
+		{
+			delete *it;
+			it++;
+		}
+
+		nodes.clear();
+
+	#ifdef LOGOG_INTERNAL_DEBUGGING
+		if ( pAllNodes->size() != 0 )
+			cout << "Not all nodes were deleted at shutdown -- memory leak may have occurred" << endl;
+	#endif
+
+		pAllNodes->clear(); // just in case
+		delete pAllNodes;
+		pStatics->s_pAllNodes = NULL;
+	}
+
+}
+
diff --git a/Base/logog/src/platform.cpp b/Base/logog/src/platform.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d191d10560bce86a951af98f73a881d67a57447f
--- /dev/null
+++ b/Base/logog/src/platform.cpp
@@ -0,0 +1,11 @@
+ /* 
+ * \file platform.cpp
+ */
+
+#include "logog.hpp"
+
+namespace logog {
+
+	bool sb_AvoidLinkError4221_platform_cpp = false;
+}
+
diff --git a/Base/logog/src/socket.cpp b/Base/logog/src/socket.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..533de0b7d8ddf86be880705cd30af791db5d0817
--- /dev/null
+++ b/Base/logog/src/socket.cpp
@@ -0,0 +1,10 @@
+/* 
+ * \file socket.cpp
+ */
+
+#include "logog.hpp"
+
+namespace logog {
+	bool sb_AvoidLinkError4221_socket_cpp = false;
+}
+
diff --git a/Base/logog/src/statics.cpp b/Base/logog/src/statics.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..05ec6bdcfdd88a922f7e2791f28e60d7852af7ca
--- /dev/null
+++ b/Base/logog/src/statics.cpp
@@ -0,0 +1,57 @@
+ /* 
+ * \file statics.cpp
+ */
+
+#include "logog.hpp"
+
+namespace logog {
+
+	Statics::Statics()
+	{
+		s_pAllNodes = NULL;
+		s_pAllSubscriberNodes = NULL;
+		s_pAllFilterNodes = NULL;
+		s_pAllTargets = NULL;
+		s_pTimer = NULL;
+		s_pDefaultFormatter = NULL;
+		s_pDefaultFilter = NULL;
+		s_pStringSearchMutex = NULL;
+		s_pMessageCreationMutex = NULL;
+		s_pfMalloc = NULL;
+		s_pfFree = NULL;
+		s_pSelf = this;
+		s_nSockets = 0;
+	}
+
+	void Statics::Reset()
+	{
+		DestroyGlobalTimer();
+		DestroyDefaultFormatter();
+		s_pDefaultFilter = NULL; // This will be destroyed on the next step
+		DestroyAllNodes();
+		DestroyStringSearchMutex();
+		DestroyMessageCreationMutex();
+		s_pfMalloc = NULL;
+		s_pfFree = NULL;
+		s_nSockets = 0;
+	}
+
+	Statics::~Statics()
+	{
+		Reset();
+	}
+
+	Statics s_Statics;
+
+	Statics &Static()
+	{
+		return s_Statics;
+	}
+
+	void DestroyStatic()
+	{
+		s_Statics.~Statics();
+	}
+
+}
+
diff --git a/Base/logog/src/target.cpp b/Base/logog/src/target.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7bc26943a0c5f7d3079e76418024b48b567d0e4b
--- /dev/null
+++ b/Base/logog/src/target.cpp
@@ -0,0 +1,342 @@
+ /* 
+ * \file target.cpp
+ */
+
+#include "logog.hpp"
+
+#include <iostream>
+
+namespace logog {
+
+	Target::Target() :
+		m_bNullTerminatesStrings( true )
+	{
+		SetFormatter( GetDefaultFormatter() );
+		LockableNodesType *pAllTargets = &AllTargets();
+
+		{
+			ScopedLock sl( *pAllTargets );
+			pAllTargets->insert( this );
+		}
+
+		SubscribeToMultiple( AllFilters() );
+	}
+
+
+	Target::~Target()
+	{
+		LockableNodesType *pAllTargets = &AllTargets();
+
+		UnsubscribeToMultiple( AllFilters() );
+
+		{
+			ScopedLock sl( *pAllTargets );
+			pAllTargets->erase( this );
+		}
+	}
+
+	void Target::SetFormatter( Formatter &formatter )
+	{
+		m_pFormatter = &formatter;
+	}
+
+	Formatter & Target::GetFormatter() const
+	{
+		return *m_pFormatter;
+	}
+
+	int Target::Receive( const Topic &topic )
+	{
+		ScopedLock sl( m_MutexReceive );
+		return Output( m_pFormatter->Format( topic, *this ) );
+	}
+
+	int Cerr::Output( const LOGOG_STRING &data )
+	{
+		LOGOG_CERR << (const LOGOG_CHAR *)data;
+
+		return 0;
+	}
+//! [Cout]
+	int Cout::Output( const LOGOG_STRING &data )
+	{
+		LOGOG_COUT << (const LOGOG_CHAR *)data;
+
+		return 0;
+	}
+//! [Cout]
+
+	int OutputDebug::Output( const LOGOG_STRING &data )
+	{
+#ifdef LOGOG_FLAVOR_WINDOWS
+#ifdef LOGOG_UNICODE
+		OutputDebugStringW( (const LOGOG_CHAR *)data );
+#else
+		OutputDebugStringA( (const LOGOG_CHAR *)data );
+#endif // LOGOG_UNICODE
+#endif // LOGOG_FLAVOR_WINDOWS
+		return 0;
+	}
+
+	LogFile::LogFile(const char *sFileName) :
+		m_bFirstTime( true ),
+		m_bOpenFailed( false ),
+		m_pFile( NULL )
+	{
+		m_bNullTerminatesStrings = false;
+
+#ifdef LOGOG_UNICODE
+		m_bWriteUnicodeBOM = true;
+#else // LOGOG_UNICODE
+		m_bWriteUnicodeBOM = false;
+#endif // LOGOG_UNICODE
+
+		int nNameLength = 0;
+
+		const char *sNameCount = sFileName;
+		while ( *sNameCount++ != '\0' )
+			nNameLength++;
+
+		// add one for trailing null
+		nNameLength++;
+
+		m_pFileName = (char *)Object::Allocate( nNameLength );
+
+		char *m_pOut = m_pFileName;
+		while ( ( *m_pOut++ = *sFileName++) != '\0' )
+			;
+	}
+
+	LogFile::~LogFile()
+	{
+		if ( m_pFile )
+			fclose( m_pFile );
+
+		Object::Deallocate( m_pFileName );
+	}
+
+	int LogFile::Open()
+	{
+		int nError = 1; // preset this in case LOGOG_FLAVOR_WINDOWS is not defined
+
+		bool bFileAlreadyExists = false;
+		FILE *fpTest;
+
+#ifdef LOGOG_FLAVOR_WINDOWS
+		nError = fopen_s( &fpTest, m_pFileName, "r"); // ignore the error code
+#else // LOGOG_FLAVOR_WINDOWS
+		fpTest = fopen( m_pFileName, "r");
+#endif // LOGOG_FLAVOR_WINDOWS
+
+		if ( fpTest != NULL )
+		{
+			fclose( fpTest );
+			bFileAlreadyExists = true;
+		}
+
+		/** Windows tries to be clever and help us with converting line feeds
+		 ** to carriage returns when writing a text file.  This causes problems
+		 ** when writing a Unicode file as Windows helpfully inserts a single-byte
+		 ** 0x0D between the return and line feed on write.  So we open and operate
+		 ** the output in binary mode only.
+		 **/
+#ifdef LOGOG_FLAVOR_WINDOWS
+#ifdef LOGOG_UNICODE
+		nError = fopen_s( &m_pFile, m_pFileName, "ab, ccs=UNICODE" );
+#else // LOGOG_UNICODE
+		nError = fopen_s( &m_pFile, m_pFileName, "ab" );
+#endif // LOGOG_UNICODE
+		if ( nError != 0 )
+			return nError;
+#else // LOGOG_FLAVOR_WINDOWS
+		m_pFile = fopen( m_pFileName, "ab+" );
+#endif // LOGOG_FLAVOR_WINDOWS
+
+		if ( m_pFile == NULL )
+			m_bOpenFailed = true; // and no further outputs will work
+		else
+		{
+#ifdef LOGOG_UNICODE
+			if ( !bFileAlreadyExists )
+			{
+				WriteUnicodeBOM();
+			}
+#endif
+		}
+
+		return ( m_pFile ? 0 : -1 );
+	}
+
+	int LogFile::Output( const LOGOG_STRING &data )
+	{
+		if ( m_bOpenFailed )
+			return -1;
+
+		int result = 0;
+		if ( m_bFirstTime )
+		{
+			result = Open();
+			if ( result != 0 )
+				return result;
+
+			m_bFirstTime = false;
+		}
+
+		return InternalOutput( data.size(), data.c_str());
+	}
+
+	int LogFile::InternalOutput( size_t nSize, const LOGOG_CHAR *pData )
+		{
+        size_t result;
+
+		result = fwrite( pData, sizeof( LOGOG_CHAR ), nSize, m_pFile );
+
+		if ( (size_t)result != nSize )
+			return -1;
+
+		return 0;
+	}
+
+	void LogFile::WriteUnicodeBOM()
+	{
+		static union {
+			int i;
+			char c[4];
+		} bDetectEndian = {0x01020304};
+
+		bool bIsLittleEndian = ( bDetectEndian.c[0] != 1 );
+
+		switch ( sizeof( LOGOG_CHAR ))
+		{
+		case 1:
+			// This could be a UTF-8 BOM but technically very few systems support
+			// sizeof( wchar_t ) == sizeof( char ).  So for now we're not going
+			// to write a BOM in these cases.
+			break;
+
+		case 2:
+			if ( bIsLittleEndian )
+				InternalOutput( 1, (const LOGOG_CHAR *)"\xFF\xFE" ); // little endian UTF-16LE
+			else
+				InternalOutput( 1, (const LOGOG_CHAR *)"\xFE\xFF" ); // big endian UTF-16BE
+
+			break;
+
+		case 4:
+			if ( bIsLittleEndian )
+				InternalOutput( 1, (const LOGOG_CHAR *)"\xFF\xFE\x00\x00" ); // little endian UTF-32LE
+			else
+				InternalOutput( 1, (const LOGOG_CHAR *)"\x00\x00\xFE\xFF" ); // big endian UTF-32BE
+
+			break;
+
+		default:
+			// No idea what that character size is; do nothing
+			break;
+		}
+	}
+
+	LogBuffer::LogBuffer( Target *pTarget ,
+		size_t s  ) :
+	m_pStart( NULL ),
+		m_nSize( 0 )
+	{
+		m_pOutputTarget = pTarget;
+		Allocate( s );
+	}
+
+	LogBuffer::~LogBuffer()
+	{
+		Dump();
+		Deallocate();
+	}
+
+	void LogBuffer::SetTarget( Target &t )
+	{
+		m_pOutputTarget = &t;
+	}
+
+	int LogBuffer::Insert( const LOGOG_CHAR *pChars, size_t size )
+	{
+		if (( m_pCurrent + size ) >= m_pEnd )
+			Dump();
+
+		if ( size > (size_t)( m_pEnd - m_pStart ))
+		{
+#ifdef LOGOG_INTERNAL_DEBUGGING
+			cerr << "Cannot insert string into buffer; string is larger than buffer.  Allocate a larger size for the LogBuffer." << endl;
+#endif
+			return -1; // can't fit this into buffer; punt it
+		}
+
+		// Store the size of this string in the buffer
+		size_t *pSize;
+		pSize = ( size_t *)m_pCurrent;
+		*pSize = size;
+		m_pCurrent = (LOGOG_CHAR *)++pSize;
+
+		while ( size-- )
+			*m_pCurrent++ = *pChars++;
+
+		return 0;
+	}
+
+	int LogBuffer::Dump()
+	{
+		LOGOG_CHAR *pCurrent = m_pStart;
+		size_t *pSize;
+		int nError;
+
+		if ( m_pOutputTarget == NULL )
+			return -1;
+
+		// We have to lock the output target here, as we do an end run around its Receive() function */
+		ScopedLock sl( m_pOutputTarget->m_MutexReceive );
+
+		while ( pCurrent < m_pCurrent )
+		{
+			String sOut;
+			// Get the size of this entry
+			pSize = ( size_t * )pCurrent;
+			// Move past that entry into the data area
+			pCurrent = ( LOGOG_CHAR * )( pSize + 1 );
+
+			sOut.assign( pCurrent, pCurrent + *pSize - 1 );
+
+			if ( m_pOutputTarget )
+			{
+				nError = m_pOutputTarget->Output( sOut );
+				if ( nError != 0 )
+					return nError;
+			}
+
+			pCurrent += *pSize;
+		}
+
+		// reset buffer
+		m_pCurrent = m_pStart;
+
+		return 0;
+	}
+
+	int LogBuffer::Output( const LOGOG_STRING &data )
+	{
+		return Insert( &(*data), data.size() );
+	}
+
+	void LogBuffer::Allocate( size_t size )
+	{
+		m_nSize = size;
+		m_pCurrent = m_pStart = (LOGOG_CHAR *)Object::Allocate( size * sizeof( LOGOG_CHAR ));
+		m_pEnd = m_pStart + size;
+	}
+
+	void LogBuffer::Deallocate()
+	{
+		if ( m_pStart )
+			Object::Deallocate( m_pStart );
+
+		m_nSize = 0;
+	}
+}
+
diff --git a/Base/logog/src/timer.cpp b/Base/logog/src/timer.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..accaacac1d6b128e9cccf70948f423777fc1f2d8
--- /dev/null
+++ b/Base/logog/src/timer.cpp
@@ -0,0 +1,80 @@
+ 
+/* 
+ * \file timer.cpp
+ */
+
+#include "logog.hpp"
+
+namespace logog {
+
+	Timer::Timer()
+	{
+		m_fStartTime = 0.0f;
+
+#ifdef LOGOG_FLAVOR_WINDOWS
+		LARGE_INTEGER TicksPerSecond;
+		QueryPerformanceFrequency( &TicksPerSecond );
+		m_fTicksPerMicrosecond = (DOUBLE)TicksPerSecond.QuadPart * 0.000001;
+#endif
+		Set( 0.0f );
+	}
+
+//! [TimerGet]
+	logog::LOGOG_TIME Timer::Get()
+	{
+#ifdef LOGOG_FLAVOR_WINDOWS
+		LARGE_INTEGER liTime;
+		QueryPerformanceCounter( &liTime );
+
+		double dusec;
+		dusec =( liTime.QuadPart / m_fTicksPerMicrosecond );
+
+		return ( dusec / 1000000.0f ) - m_fStartTime;
+#endif
+
+#ifdef LOGOG_FLAVOR_POSIX
+#ifdef LOGOG_TARGET_PS3
+		LOGOG_PS3_GET_TIME;
+#else // LOGOG_TARGET_PS3
+		// General Posix implementation
+		timeval tv;
+		gettimeofday( &tv, 0 );
+		return ((double) (tv.tv_sec) + ((double)(tv.tv_usec ) / 1000000.0 ) - m_fStartTime);
+#endif // LOGOG_TARGET_PS3
+#endif
+	}
+//! [TimerGet]
+
+	void Timer::Set( LOGOG_TIME time )
+	{
+		m_fStartTime = time + Get();
+	}
+
+	Timer &GetGlobalTimer()
+	{
+		Statics *pStatic = &Static();
+
+#ifdef LOGOG_INTERNAL_DEBUGGING
+		if ( pStatic == NULL )
+			LOGOG_INTERNAL_FAILURE;
+#endif
+
+		if ( pStatic->s_pTimer == NULL )
+			pStatic->s_pTimer = new Timer();
+
+		return *(pStatic->s_pTimer );
+	}
+
+	void DestroyGlobalTimer()
+	{
+		Statics *pStatic = &Static();
+		Timer *pGlobalTimer = pStatic->s_pTimer;
+
+		if ( pGlobalTimer != NULL )
+			delete pGlobalTimer;
+
+		pStatic->s_pTimer = NULL;
+	}
+
+}
+
diff --git a/Base/logog/src/topic.cpp b/Base/logog/src/topic.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..619aa305c745b1cbc4306e41491a65934c465283
--- /dev/null
+++ b/Base/logog/src/topic.cpp
@@ -0,0 +1,454 @@
+ 
+/* 
+ * \file topic.cpp
+ */
+
+#include "logog.hpp"
+
+namespace logog {
+
+	void SetDefaultLevel( LOGOG_LEVEL_TYPE level )
+	{
+		Filter *pDefaultFilter = &GetDefaultFilter();
+
+		pDefaultFilter->Level( level );
+	}
+
+	Topic::Topic( const LOGOG_LEVEL_TYPE level ,
+		const LOGOG_CHAR *sFileName ,
+		const int nLineNumber ,
+		const LOGOG_CHAR *sGroup ,
+		const LOGOG_CHAR *sCategory ,
+		const LOGOG_CHAR *sMessage ,
+		const double dTimestamp )
+	{
+		m_TopicFlags = 0;
+
+		if ( sFileName != NULL )
+		{
+			m_vStringProps[ TOPIC_FILE_NAME ] = sFileName;
+			m_TopicFlags |= TOPIC_FILE_NAME_FLAG;
+		}
+
+		if ( sGroup != NULL )
+		{
+			m_vStringProps[ TOPIC_GROUP ] = sGroup;
+			m_TopicFlags |= TOPIC_GROUP_FLAG;
+		}
+
+		if ( sCategory != NULL )
+		{
+			m_vStringProps[ TOPIC_CATEGORY ] = sCategory;
+			m_TopicFlags |= TOPIC_CATEGORY_FLAG;
+		}
+
+		if ( sMessage != NULL )
+		{
+			m_vStringProps[ TOPIC_MESSAGE ] = sMessage;
+			m_TopicFlags |= TOPIC_MESSAGE_FLAG;
+		}
+
+		m_vIntProps[ TOPIC_LEVEL ] = level;
+
+		if ( level != LOGOG_LEVEL_ALL )
+		{
+			m_TopicFlags |= TOPIC_LEVEL_FLAG;
+		}
+
+		m_vIntProps[ TOPIC_LINE_NUMBER ] = nLineNumber;
+
+		if ( nLineNumber != 0 )
+		{
+			m_TopicFlags |= TOPIC_LINE_NUMBER_FLAG;
+		}
+
+		m_tTime = dTimestamp;
+
+		if ( dTimestamp != 0.0f ) //-V550
+			m_TopicFlags |= TOPIC_TIMESTAMP_FLAG;
+	}
+
+	bool Topic::IsTopic() const
+	{
+		return true;
+	}
+
+	int Topic::Send( const Topic &node )
+	{
+		LockableNodesType::iterator it;
+
+		{
+			ScopedLock sl( m_Subscribers );
+			it = m_Subscribers.begin();
+		}
+
+		/* Iterate over the subscribers, but only addressing the subscribers group while locking it */
+		Topic *pCurrentTopic;
+		Node *pCurrentNode;
+		m_Subscribers.MutexLock();
+		int nError = 0;
+
+		while ( it != m_Subscribers.end() )
+		{
+			pCurrentNode = *it;
+
+			if ( pCurrentNode->IsTopic() == false )
+				continue;
+
+			pCurrentTopic = ( Topic * )pCurrentNode;
+
+			if ( pCurrentTopic )
+				nError += pCurrentTopic->Receive( node );
+
+			it++;
+		}
+
+		m_Subscribers.MutexUnlock();
+
+		return nError;
+	}
+
+	int Topic::Transmit()
+	{
+		return Send( *this );
+	}
+
+	int Topic::Receive( const Topic &node )
+	{
+		/* Default implementation -- send it on to all children */
+		return Send( node );
+	}
+
+	bool Topic::CanSubscribeTo( const Node &otherNode )
+	{
+		if ( CanSubscribe() == false )
+			return false;
+
+		if ( otherNode.IsTopic() == false )
+			return false;
+
+		Topic *pTopic = ( Topic * )&otherNode;
+
+		/* This function will change from topic class to topic class. */
+		return CanSubscribeCheckTopic( *pTopic );
+	}
+
+	bool Topic::CanSubscribeCheckTopic( const Topic &other )
+	{
+		/* This is the generic comparison case.  We'll want to optimize this function for other types
+		* of topics.
+		*/
+
+		/* Check topics in likely order of disinterest */
+		if ( m_TopicFlags & TOPIC_LEVEL_FLAG )
+		{
+			/* Topic levels are less interesting the larger the numbers are. */
+			if ( other.m_vIntProps[ TOPIC_LEVEL ] > m_vIntProps[ TOPIC_LEVEL ] )
+				return false;
+		}
+
+		if ( m_TopicFlags & TOPIC_GROUP_FLAG )
+		{
+			/* If our topic is not a substring of the publisher's topic, ignore this */
+			if (( other.m_vStringProps[ TOPIC_GROUP ] ).find( m_vStringProps[ TOPIC_GROUP ] ) == LOGOG_STRING::npos )
+				return false;
+		}
+
+		if ( m_TopicFlags & TOPIC_CATEGORY_FLAG )
+		{
+			/* If our topic is not a substring of the publisher's topic, ignore this */
+			if (( other.m_vStringProps[ TOPIC_CATEGORY ] ).find( m_vStringProps[ TOPIC_CATEGORY ] ) == LOGOG_STRING::npos )
+				return false;
+		}
+
+		if ( m_TopicFlags & TOPIC_FILE_NAME_FLAG )
+		{
+			/* If our topic is not a substring of the publisher's file name, ignore this. */
+			if (( other.m_vStringProps[ TOPIC_FILE_NAME ] ).find( m_vStringProps[ TOPIC_FILE_NAME ] ) == LOGOG_STRING::npos )
+				return false;
+		}
+
+		if ( m_TopicFlags & TOPIC_LINE_NUMBER_FLAG )
+		{
+			/* If our line number doesn't equal theirs, ignore this */
+			if ( other.m_vIntProps[ TOPIC_LINE_NUMBER ] != m_vIntProps[ TOPIC_LINE_NUMBER ] )
+				return false;
+		}
+
+		if ( m_TopicFlags & TOPIC_MESSAGE_FLAG )
+		{
+			/* If our topic is not a substring of the publisher's file name, ignore this. */
+			if (( other.m_vStringProps[ TOPIC_MESSAGE ] ).find( m_vStringProps[ TOPIC_MESSAGE ] ) == LOGOG_STRING::npos )
+				return false;
+		}
+
+		if ( m_TopicFlags & TOPIC_TIMESTAMP_FLAG )
+		{
+			/* Timestamps are only interesting if they're greater than or equal to ours. */
+			if ( other.m_tTime < m_tTime )
+				return false;
+		}
+
+		/* all tests passed */
+		return true;
+	}
+
+	bool Topic::PublishTo( Node &subscriber )
+	{
+#ifdef LOGOG_INTERNAL_DEBUGGING
+		if ( &subscriber == this )
+			LOGOG_INTERNAL_FAILURE;
+#endif
+		bool bWasInserted;
+
+		/** Additional checking may be required first -- can the subscriber handle this publishing? */
+		if ( subscriber.IsTopic() )
+		{
+			Topic *pSubscriber = (Topic *)&subscriber;
+
+			if ( pSubscriber->CanSubscribeTo( *this ) == false )
+				return false;
+		}
+
+		{
+			ScopedLock sl( m_Subscribers );
+			bWasInserted = ( m_Subscribers.insert( &subscriber ) ).second;
+		}
+
+		if ( bWasInserted )
+			subscriber.SubscribeTo( *this );
+
+		return bWasInserted;
+	}
+
+	void Topic::Format( const LOGOG_CHAR *cFormatMessage, ... )
+	{
+		va_list args;
+
+		va_start( args, cFormatMessage );
+		m_vStringProps[ TOPIC_MESSAGE ].format_va( cFormatMessage, args );
+		va_end( args );
+
+		m_TopicFlags |= TOPIC_MESSAGE_FLAG;
+	}
+
+	const LOGOG_STRING & Topic::FileName() const
+	{
+		return m_vStringProps[ TOPIC_FILE_NAME ];
+	}
+
+	void Topic::FileName( const LOGOG_STRING &s )
+	{
+		m_vStringProps[ TOPIC_FILE_NAME ] = s;
+		m_TopicFlags |= TOPIC_FILE_NAME_FLAG;
+	}
+
+	const LOGOG_STRING & Topic::Message() const
+	{
+		return m_vStringProps[ TOPIC_MESSAGE ];
+	}
+
+	void Topic::Message( const LOGOG_STRING &s )
+	{
+		m_vStringProps[ TOPIC_MESSAGE ] = s;
+		m_TopicFlags |= TOPIC_MESSAGE_FLAG;
+	}
+
+	const LOGOG_STRING & Topic::Category() const
+	{
+		return m_vStringProps[ TOPIC_CATEGORY ];
+	}
+
+	void Topic::Category( const LOGOG_STRING &s )
+	{
+		m_vStringProps[ TOPIC_CATEGORY ] = s;
+		m_TopicFlags |= TOPIC_CATEGORY_FLAG;
+	}
+
+	const LOGOG_STRING & Topic::Group() const
+	{
+		return m_vStringProps[ TOPIC_GROUP ];
+	}
+
+	void Topic::Group( const LOGOG_STRING &s )
+	{
+		m_vStringProps[ TOPIC_GROUP ] = s;
+		m_TopicFlags |= TOPIC_GROUP_FLAG;
+	}
+
+	int Topic::LineNumber() const
+	{
+		return m_vIntProps[ TOPIC_LINE_NUMBER ];
+	}
+
+	void Topic::LineNumber( const int num )
+	{
+		m_vIntProps[ TOPIC_LINE_NUMBER ] = num;
+		m_TopicFlags |= TOPIC_LINE_NUMBER_FLAG;
+	}
+
+	LOGOG_LEVEL_TYPE Topic::Level() const
+	{
+		return ( LOGOG_LEVEL_TYPE )m_vIntProps[ TOPIC_LEVEL ];
+	}
+
+	void Topic::Level( LOGOG_LEVEL_TYPE level )
+	{
+		m_vIntProps[ TOPIC_LEVEL ] = level;
+		m_TopicFlags |= TOPIC_LEVEL_FLAG;
+	}
+
+	logog::LOGOG_TIME Topic::Timestamp() const
+	{
+		return m_tTime;
+	}
+
+	void Topic::Timestamp( const LOGOG_TIME t )
+	{
+		m_tTime = t;
+		m_TopicFlags |= TOPIC_TIMESTAMP_FLAG;
+	}
+
+	TOPIC_FLAGS Topic::GetTopicFlags() const
+	{
+		return m_TopicFlags;
+	}
+
+
+/********************************************************/
+
+	Filter::Filter( const LOGOG_LEVEL_TYPE level ,
+		const LOGOG_CHAR *sFileName ,
+		const int nLineNumber ,
+		const LOGOG_CHAR *sGroup ,
+		const LOGOG_CHAR *sCategory ,
+		const LOGOG_CHAR *sMessage ,
+		const double dTimestamp ) :
+	Topic( level, sFileName, nLineNumber, sGroup, sCategory, sMessage, dTimestamp )
+	{
+		Statics *pStatic = &Static();
+
+#ifdef LOGOG_INTERNAL_DEBUGGING
+		if ( pStatic == NULL )
+			LOGOG_INTERNAL_FAILURE;
+#endif
+
+		if ( pStatic->s_pDefaultFilter == NULL )
+			pStatic->s_pDefaultFilter = this;
+
+		PublishToMultiple( AllTargets() );
+
+		LockableNodesType *pFilterNodes = &AllFilters();
+
+		{
+			ScopedLock sl( *pFilterNodes );
+			pFilterNodes->insert( this );
+		}
+	}
+
+	Filter &GetDefaultFilter()
+	{
+		Statics *pStatic = &Static();
+
+#ifdef LOGOG_INTERNAL_DEBUGGING
+		if ( pStatic == NULL )
+			LOGOG_INTERNAL_FAILURE;
+#endif
+
+		if ( pStatic->s_pDefaultFilter == NULL )
+		{
+			pStatic->s_pDefaultFilter = new Filter( LOGOG_LEVEL );
+		}
+
+		return *((Filter *)(pStatic->s_pDefaultFilter));
+	}
+
+	TopicGroup::TopicGroup( const LOGOG_CHAR *sGroup ) :
+		Topic( LOGOG_LEVEL_ALL, NULL, 0, sGroup )
+	{
+	}
+
+	bool TopicGroup::CanSubscribeCheckTopic( const Topic &other )
+	{
+		if ( m_TopicFlags & TOPIC_LEVEL_FLAG )
+		{
+			/* Topic levels are less interesting the larger the numbers are. */
+			if ( other.m_vIntProps[ TOPIC_LEVEL ] > m_vIntProps[ TOPIC_LEVEL ] )
+				return false;
+		}
+
+		return true;
+	}
+
+	TopicLevel::TopicLevel( const LOGOG_LEVEL_TYPE level ) :
+	Topic( level )
+	{
+	}
+
+
+	bool TopicLevel::CanSubscribeCheckTopic( const Topic &other )
+	{
+		/* Check topics in likely order of disinterest */
+		if ( m_TopicFlags & TOPIC_LEVEL_FLAG )
+		{
+			/* Topic levels are less interesting the larger the numbers are. */
+			if ( other.m_vIntProps[ TOPIC_LEVEL ] > m_vIntProps[ TOPIC_LEVEL ] )
+				return false;
+		}
+
+		/* all tests passed */
+		return true;
+	}
+
+	TopicSource::TopicSource( const LOGOG_LEVEL_TYPE level ,
+		const LOGOG_CHAR *sFileName,
+		const int nLineNumber,
+		const LOGOG_CHAR *sGroup,
+		const LOGOG_CHAR *sCategory,
+		const LOGOG_CHAR *sMessage,
+		const double dTimestamp ) :
+	Topic( level, sFileName, nLineNumber, sGroup, sCategory, sMessage, dTimestamp )
+	{
+	}
+
+	bool TopicSource::SubscribeTo( Node & )
+	{
+		return false;
+	}
+
+	bool TopicSource::UnsubscribeTo( Node & )
+	{
+		return false;
+	}
+
+	bool TopicSource::CanSubscribe() const
+	{
+		return false;
+	}
+
+	bool TopicSink::IsTopic() const
+	{
+		return true;
+	}
+
+	void TopicSink::Initialize()
+	{
+
+	}
+
+	bool TopicSink::PublishTo( Node & )
+	{
+		return false;
+	}
+
+	bool TopicSink::UnpublishTo( Node & )
+	{
+		return false;
+	}
+
+	bool TopicSink::CanPublish() const
+	{
+		return false;
+	}
+}
+
diff --git a/Base/logog/src/unittest.cpp b/Base/logog/src/unittest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c5863cff60de2194eb7db8ca0b63bf343f1b7d4e
--- /dev/null
+++ b/Base/logog/src/unittest.cpp
@@ -0,0 +1,128 @@
+
+/*
+ * \file unittest.cpp
+ */
+
+#define LOGOG_UNIT_TESTING 1
+
+#include "logog.hpp"
+
+namespace logog
+{
+
+TestRegistryType &LogogTestRegistry()
+{
+    static TestRegistryType *pRegistry = new TestRegistryType();
+    return *pRegistry;
+}
+
+TestSignup::TestSignup( UnitTest *pTest )
+{
+    m_pTest = pTest;
+    LogogTestRegistry().push_back( pTest );
+}
+
+UnitTest::UnitTest( const TestNameType &sTestName )
+{
+    m_sTestName = sTestName;
+    m_pTestSignup = new TestSignup( this );
+}
+
+UnitTest::~UnitTest()
+{
+	FreeInternals();
+}
+
+void UnitTest::FreeInternals()
+{
+	if ( m_pTestSignup )
+		delete m_pTestSignup;
+
+	m_pTestSignup = NULL;
+}
+
+/** Returns the name of this UnitTest provided at construction time. */
+TestNameType &UnitTest::GetName()
+{
+	return m_sTestName;
+}
+
+/** Executes all currently registered tests and prints a report of success or failure. */
+int RunAllTests()
+{
+    using namespace std;
+
+    int nTests = 0, nTestsSucceeded = 0;
+    int nTestResult;
+    int nFailures = 0;
+
+#ifdef LOGOG_UNICODE
+    wostream *pOut;
+#else // LOGOG_UNICODE
+	ostream *pOut;	
+#endif // LOGOG_UNICODE
+
+	pOut = &(LOGOG_COUT);
+
+    nTests = (int) LogogTestRegistry().size();
+
+    if ( nTests == 0 )
+    {
+		*pOut << _LG("No tests currently defined.") << endl;
+        return 1;
+    }
+
+    for ( TestRegistryType::iterator it = LogogTestRegistry().begin();
+            it != LogogTestRegistry().end();
+            ++it )
+    {
+        (*pOut) << _LG("Test ") << (*it)->GetName() << _LG(" running... ") << endl;
+        nTestResult = (*it)->RunTest();
+
+        (*pOut) << _LG("Test ") << (*it)->GetName();
+
+        if ( nTestResult == 0 )
+        {
+            *pOut << _LG(" successful.") << endl;
+            nTestsSucceeded++;
+        }
+        else
+        {
+            *pOut << _LG(" failed!") << endl;
+            nFailures++;
+        }
+
+        /* Validate that no allocations are currently outstanding.  Make sure to handle the case
+         * where leak detection is disabled */
+        int nMemoryTestResult = ReportMemoryAllocations();
+
+        if ( nMemoryTestResult != -1 )
+        {
+            (*pOut) << _LG("Test ") << (*it)->GetName() << _LG(" has ") << nMemoryTestResult <<
+				_LG(" memory allocations outstanding at end of test.") << endl;
+            nFailures += nMemoryTestResult;
+        }
+    }
+
+    *pOut << _LG("Testing complete, ")
+          << nTests << _LG(" total tests, ")
+          << nTestsSucceeded << _LG(" tests succeeded, ")
+          << ( nTests - nTestsSucceeded ) << _LG(" failed")
+          << endl;
+
+    return nFailures;
+}
+
+/** Should remove all memory allocated during unit testing. */
+void ShutdownTests()
+{
+	TestRegistryType::iterator it;
+
+	for ( it = LogogTestRegistry().begin(); it != LogogTestRegistry().end(); it++ )
+		(*it)->FreeInternals();
+
+    delete &LogogTestRegistry();
+}
+
+}
+
diff --git a/Base/logog/test/CMakeLists.txt b/Base/logog/test/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..f818a2e4fb04e7a99e7909fd43aa88df3890225f
--- /dev/null
+++ b/Base/logog/test/CMakeLists.txt
@@ -0,0 +1,2 @@
+add_executable( test test.cpp )
+
diff --git a/Base/logog/test/test.cpp b/Base/logog/test/test.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3bb34ebeb2271ae16cc8ba365bc6078ac1cf33a8
--- /dev/null
+++ b/Base/logog/test/test.cpp
@@ -0,0 +1,837 @@
+/** Only define this macro in source files that create unit tests.  This setting brings in the std namespace, so its
+ ** use is not recommended outside of unit tests. */
+#define LOGOG_UNIT_TESTING 1
+
+/** Change this to higher constants to exponentially increase test difficulty. */
+const int TEST_STRESS_LEVEL = 1;
+
+#include "logog.hpp"
+
+#include <cstdio>
+
+#include <fcntl.h>
+
+#ifdef LOGOG_FLAVOR_WINDOWS
+#include <io.h>
+#endif
+
+using namespace logog;
+using namespace std;
+
+UNITTEST( SimpleLocking )
+{
+//! [SimpleLocking]
+    LOGOG_INITIALIZE();
+
+    {
+        logog::Mutex m;
+
+        {
+            logog::ScopedLock s1( m );
+            LOGOG_COUT << _LG("Lock is on") << endl;
+        }
+
+        logog::Mutex *pM = new logog::Mutex();
+
+        {
+            logog::ScopedLock s1( *pM );
+            LOGOG_COUT << _LG("Lock is on") << endl;
+        }
+
+        delete pM;
+
+        LOGOG_COUT << _LG("Lock unlocked") << endl;
+
+        logog::Message m1;
+
+    }
+
+    LOGOG_SHUTDOWN();
+
+    return 0;
+//! [SimpleLocking]
+}
+
+int _s_ThreadLockingTest = 0;
+
+void LockingThread( void *pvMutex )
+{
+    const int NUM_TRIALS = 10 * TEST_STRESS_LEVEL;
+    Mutex *pMutex = (Mutex *)pvMutex;
+
+    if ( pMutex == NULL )
+    {
+        _s_ThreadLockingTest = 1;
+        LOGOG_COUT << _LG("LockingThread received a NULL argument!") << endl;
+        return;
+    }
+
+    for ( int t = 0; t < NUM_TRIALS; t++ )
+    {
+        {
+            ScopedLock sl( *pMutex );
+            INFO( _LG("Thread acquired lock on trial %d"), t);
+        }
+
+        INFO( _LG("Thread released lock %d"), t );
+    }
+}
+
+
+UNITTEST( Subscription )
+{
+    int nResult = 0;
+
+//! [Subscription]
+    LOGOG_INITIALIZE();
+
+    {
+        Topic n1, n2;
+
+        // should succeed
+        if ( n1.SubscribeTo( n2 ) != true )
+            nResult++;
+
+        // should indicate no insertion took place
+        if ( n2.PublishTo( n1 ) != false )
+            nResult++;
+
+        n2.Transmit();
+
+        if ( n2.UnpublishTo( n1 ) != true )
+            nResult++;
+
+        if ( n1.UnsubscribeTo( n2 ) != false )
+            nResult++;
+    }
+
+    LOGOG_SHUTDOWN();
+
+//! [Subscription]
+
+    return nResult;
+}
+
+UNITTEST( GlobalNodelist )
+{
+    LOGOG_INITIALIZE();
+
+    const int MAX_NODES = 10 * TEST_STRESS_LEVEL;
+
+    LOGOG_VECTOR< Topic *> vTopics;
+
+    for (int t = 0; t < MAX_NODES; t++ )
+        vTopics.push_back( new Topic );
+
+    for ( int i = 0; i < MAX_NODES; i++ )
+        for ( int j = i + 1; j < MAX_NODES; j++ )
+            vTopics.at( i )->SubscribeTo( *vTopics.at( j ) );
+
+    LockableNodesType *pNodes = ( LockableNodesType * )Static().s_pAllNodes;
+
+    // For this test we assume that the default Filter has always been created.
+    if ( pNodes->size() != ( MAX_NODES + 1))
+    {
+        LOGOG_COUT << _LG("Incorrect number of nodes!") << endl;
+        return 1;
+    }
+
+    // Try having that master node send a message to all other nodes!
+    vTopics.at( MAX_NODES - 1)->Transmit();
+
+    // Let's try leaving all the nodes allocated and let logog clean them all up.
+    LOGOG_SHUTDOWN();
+
+    if ( Static().s_pAllNodes != NULL )
+    {
+        LOGOG_COUT << _LG("Could not delete all nodes!") << endl;
+        return 1;
+    }
+
+    return 0;
+}
+
+
+UNITTEST( TimerTest )
+{
+    const int NUM_TRIALS = 10 * TEST_STRESS_LEVEL;
+    const int WAIT_TIME = 1000000 * TEST_STRESS_LEVEL;
+
+    Timer time;
+    LOGOG_TIME fCurrent = time.Get();
+
+    for ( int t = 0; t < NUM_TRIALS; t++  )
+    {
+        /* do busy work */
+        int k = 0;
+        for ( int i = 0; i < WAIT_TIME; i++ )
+            k = k + 1;  // fixes a lint warning
+
+        if ( time.Get() < fCurrent )
+        {
+            LOGOG_COUT << _LG("Timer error!  Non monotonic timer behavior") << endl;
+            return 1;
+        }
+        fCurrent = time.Get();
+        LOGOG_COUT << _LG("Current reported time: ") << fCurrent << endl;
+    }
+
+    return 0;
+}
+
+UNITTEST( TopicTest1 )
+{
+    LOGOG_INITIALIZE();
+
+    {
+        Topic t1( LOGOG_LEVEL_WARN,
+                  _LG( "file1.cpp" ), 50 );
+        Topic t2( LOGOG_LEVEL_WARN );
+        Topic t3( LOGOG_LEVEL_ERROR,
+                  _LG( "file2.cpp" ), 100 );
+        Topic t4( LOGOG_LEVEL_WARN, NULL, 0,
+                  _LG( "Group" ),
+                  _LG( "Category" ),
+                  _LG( "Message" ),
+                  30.0f);
+        Topic t5( LOGOG_LEVEL_CRITICAL, NULL, 0,
+                  _LG( "GroupGROUP" ),
+                  _LG( "Important Category" ),
+                  _LG( "Your Message Here"),
+                  150.0f);
+
+        if (t1.CanSubscribeTo( t2 ) == true)
+        {
+            LOGOG_COUT << _LG("Subscription test failed; t1 can subscribe to t2") << endl;
+            return 1;
+        }
+
+        if (t2.CanSubscribeTo( t1 ) == false )
+        {
+            LOGOG_COUT << _LG("Subscription test failed; t2 can't subscribe to t1") << endl;
+            return 1;
+        }
+
+        if ( t1.CanSubscribeTo( t3 ) == true )
+        {
+            LOGOG_COUT << _LG("Subscription test failed; t1 can subscribe to t3") << endl;
+            return 1;
+        }
+
+        if (t2.CanSubscribeTo( t3 ) == false )
+        {
+            LOGOG_COUT << _LG("Subscription test failed; t2 can't subscribe to t3") << endl;
+            return 1;
+        }
+
+        if (t4.CanSubscribeTo( t5 ) == false )
+        {
+            LOGOG_COUT << _LG("Subscription test failed; t4 can't subscribe to t5") << endl;
+            return 1;
+        }
+
+        if ( t5.CanSubscribeTo( t4 ) == true )
+        {
+            LOGOG_COUT << _LG("Subscription test failed; t5 can subscribe to t4") << endl;
+            return 1;
+        }
+    }
+
+    LOGOG_SHUTDOWN();
+
+    return 0;
+}
+
+UNITTEST( Checkpoint1 )
+{
+    LOGOG_INITIALIZE();
+
+    {
+        Checkpoint check( LOGOG_LEVEL_ALL, _LG( __FILE__ ), __LINE__,
+                          _LG("Group"), _LG("Category"), _LG("Message"), 1.0f );
+
+        Topic t;
+
+        Cerr cerrobj;
+        Cerr cerrgnu;
+        OutputDebug outdebug;
+
+        FormatterGCC f;
+        cerrgnu.SetFormatter( f );
+
+        check.PublishTo( t );
+        t.PublishToMultiple( AllTargets() );
+
+        LOGOG_COUT << _LG("Setup complete; ready to transmit ") << endl;
+        check.Transmit();
+    }
+
+    LOGOG_SHUTDOWN();
+
+    return 0;
+}
+
+UNITTEST( FormatString1 )
+{
+    LOGOG_INITIALIZE();
+    {
+        String s;
+
+        s.format( _LG("This is a test message.\n"));
+        LOGOG_COUT << s.c_str();
+
+        s.format( _LG("This is a test message: %d %x %f\n"), 1234, 0xf00d, 1.234f );
+        LOGOG_COUT << s.c_str();
+
+        const LOGOG_CHAR *p = _LG("Here is a string");
+
+#ifdef LOGOG_UNICODE
+        s.format( _LG("Here are six strings: %ls %ls %ls %ls %ls %ls \n"), p,p,p,p,p,p );
+#else // LOGOG_UNICODE
+        s.format( _LG("Here are six strings: %s %s %s %s %s %s \n"), p,p,p,p,p,p );
+#endif
+
+        LOGOG_COUT << s.c_str();
+    }
+
+    LOGOG_SHUTDOWN();
+
+    return 0;
+}
+
+UNITTEST( FormatTopic1 )
+{
+    LOGOG_INITIALIZE();
+    {
+        Cout out;
+        LogFile f( "log.txt");
+        Message m;
+
+        m.PublishToMultiple( AllTargets() );
+
+        m.Format( _LG("This is a test message: %d %x %f"), 1234, 0xf00d, 1.234f );
+        m.Transmit();
+
+        const char *p = "Here is a string";
+
+        m.Format( _LG("Here are six strings: %s %s %s %s %s %s"), p,p,p,p,p,p );
+        m.Transmit();
+    }
+
+    LOGOG_SHUTDOWN();
+
+    return 0;
+}
+
+UNITTEST( ThreadLocking )
+{
+    LOGOG_INITIALIZE();
+    {
+        Cout out; // only one of these please
+
+        const int NUM_THREADS = 10 * TEST_STRESS_LEVEL;
+
+        LOGOG_VECTOR< Thread *> vpThreads;
+        Mutex mSharedMutex;
+
+        for ( int t = 0; t < NUM_THREADS; t++ )
+            vpThreads.push_back( new Thread( (Thread::ThreadStartLocationType) LockingThread,&mSharedMutex ));
+
+        for ( int t = 0; t < NUM_THREADS; t++ )
+            vpThreads[ t ]->Start();
+
+        for ( int t = 0; t < NUM_THREADS; t++ )
+            Thread::WaitFor( *vpThreads[ t ]);
+
+		for ( int t = 0; t < NUM_THREADS; t++ )
+			delete vpThreads[t];
+
+    }
+
+    LOGOG_SHUTDOWN();
+
+    return _s_ThreadLockingTest;
+}
+
+//! [FormatterCustom1]
+class FormatterCustom : public FormatterMSVC
+{
+    virtual TOPIC_FLAGS GetTopicFlags( const Topic &topic )
+    {
+        return ( Formatter::GetTopicFlags( topic ) &
+                 ~( TOPIC_FILE_NAME_FLAG | TOPIC_LINE_NUMBER_FLAG ));
+    }
+};
+
+UNITTEST( CustomFormatter )
+{
+    LOGOG_INITIALIZE();
+    {
+        Cout out;
+        FormatterCustom customFormat;
+
+        out.SetFormatter( customFormat );
+
+        INFO( _LG( "No file and line number info is provided with this output.") );
+
+        /* The following output is produced:
+         * info: No file and line number info is provided with this output.
+         */
+    }
+    LOGOG_SHUTDOWN();
+
+    return 0;
+}
+//! [FormatterCustom1]
+
+UNITTEST( HelloLogog )
+{
+    //! [HelloLogog]
+
+    /* The LOGOG_INITIALIZE() function must be called before we call
+     * any other logog functions.
+     */
+    LOGOG_INITIALIZE();
+
+    {
+        /* In order to see any output, we have to instance a Target object,
+         * such as a Cerr or a Cout.  Additionally, we have to destroy
+         * this object before calling LOGOG_SHUTDOWN().  This
+         * is why we have this object within these enclosing brackets.
+         */
+        Cout out;
+
+        /* Send some debugging information to any targets that have
+         * been instanced.
+         */
+        /* If you're just getting started, and you haven't defined
+         * LOGOG_UNICODE, then ASCII logging is easy and works
+         * out of the box.
+         */
+#ifndef LOGOG_UNICODE
+        INFO("Hello, logog!");
+        WARN("This is a warning");
+#endif // !LOGOG_UNICODE
+
+        /* The _LG() macro around static text permits the given text to
+         * display correctly in both Unicode and ASCII builds of the
+         * logog library.
+         */
+        ERR( _LG( "This is an error") );
+        DBUG( _LG( "This is debugging info") );
+
+        /* The Cout object is destroyed here because it falls out of
+         * scope. */
+    }
+
+    /* Call LOGOG_SHUTDOWN() at the termination of your program to free
+     * all memory allocated by logog.  Make sure no logog objects exist
+     * when you call LOGOG_SHUTDOWN().
+     */
+    LOGOG_SHUTDOWN();
+
+    /* Depending on your compiler, the output of the preceding code is
+     * something like:
+     *
+     * test.cpp(373) : info: Hello, logog!
+     * test.cpp(374) : warning: This is a warning
+     * test.cpp(375) : error: This is an error
+     * test.cpp(376) : debug: This is debugging info
+     */
+    //! [HelloLogog]
+    return 0;
+}
+
+
+
+UNITTEST( GroupCategory1 )
+{
+//! [GroupCategory1]
+    /*
+    The following example produces something like:
+    .\test.cpp(364) : emergency: {Graphics} [Unrecoverable] The graphics card has been destroyed
+    .\test.cpp(368) : warning: {Graphics} [Recoverable] The graphics card has been replaced
+    .\test.cpp(372) : warning: {Audio} [Recoverable] The headphones are unplugged
+    .\test.cpp(377) : info: Everything's back to normal
+    */
+
+    LOGOG_INITIALIZE();
+
+    {
+        Cerr err;
+
+#undef LOGOG_GROUP
+#undef LOGOG_CATEGORY
+#define LOGOG_GROUP  "Graphics"
+#define LOGOG_CATEGORY "Unrecoverable"
+
+        EMERGENCY(_LG("The graphics card has been destroyed"));
+
+#undef LOGOG_CATEGORY
+#define LOGOG_CATEGORY	"Recoverable"
+
+        WARN(_LG("The graphics card has been replaced"));
+
+#undef LOGOG_GROUP
+#define LOGOG_GROUP "Audio"
+
+        WARN(_LG("The headphones are unplugged"));
+
+#undef LOGOG_CATEGORY
+#undef LOGOG_GROUP
+#define LOGOG_CATEGORY NULL
+#define LOGOG_GROUP NULL
+
+        INFO(_LG("Everything's back to... %s!"), _LG("normal"));
+    }
+
+    LOGOG_SHUTDOWN();
+    //! [GroupCategory1]
+    return 0;
+}
+
+UNITTEST( GroupCategory2 )
+{
+//! [GroupCategory2]
+    LOGOG_INITIALIZE();
+
+    {
+        GetDefaultFilter().Category(_LG("Unrecoverable"));
+        Cerr err;
+
+        WARN(_LG("Logging messages in the Unrecoverable category..."));
+
+
+#undef LOGOG_GROUP
+#undef LOGOG_CATEGORY
+#define LOGOG_GROUP  "Graphics"
+#define LOGOG_CATEGORY "Unrecoverable"
+
+        EMERGENCY(_LG("The graphics card has been destroyed"));
+
+#undef LOGOG_CATEGORY
+#define LOGOG_CATEGORY	"Recoverable"
+
+        WARN(_LG("The graphics card has been replaced"));
+
+#undef LOGOG_GROUP
+#define LOGOG_GROUP "Audio"
+
+        WARN(_LG("The headphones are unplugged"));
+
+#undef LOGOG_CATEGORY
+#undef LOGOG_GROUP
+#define LOGOG_CATEGORY NULL
+#define LOGOG_GROUP NULL
+
+    }
+
+    LOGOG_SHUTDOWN();
+//! [GroupCategory2]
+    return 0;
+}
+
+UNITTEST( GroupCategory3 )
+{
+    LOGOG_INITIALIZE();
+
+    {
+		/* Assigning a group twice does not leak memory. */
+		GetDefaultFilter().Group( _LG( "Controller" ));
+        GetDefaultFilter().Group( _LG( "Graphics" ));
+
+        Cerr err;
+        WARN(_LG("This message won't happen because it's not in the Graphics group"));
+
+#undef LOGOG_GROUP
+#undef LOGOG_CATEGORY
+#define LOGOG_GROUP  "Graphics"
+#define LOGOG_CATEGORY "Unrecoverable"
+
+        EMERGENCY(_LG("The graphics card has been destroyed"));
+
+#undef LOGOG_CATEGORY
+#define LOGOG_CATEGORY	"Recoverable"
+
+        WARN(_LG("The graphics card has been replaced"));
+
+#undef LOGOG_GROUP
+#define LOGOG_GROUP "Audio"
+
+        WARN(_LG("The headphones are unplugged"));
+
+#undef LOGOG_CATEGORY
+#undef LOGOG_GROUP
+#define LOGOG_CATEGORY NULL
+#define LOGOG_GROUP NULL
+    }
+
+    LOGOG_SHUTDOWN();
+    return 0;
+}
+
+UNITTEST( GroupCategory4 )
+{
+//! [GroupCategory4]
+    LOGOG_INITIALIZE();
+
+    {
+        GetDefaultFilter().Group(_LG("Graphics"));
+        Filter filter;
+        filter.Group(_LG("Audio"));
+        Cerr err;
+
+        WARN(_LG("This message won't happen because it's not in the Graphics group"));
+
+#undef LOGOG_GROUP
+#undef LOGOG_CATEGORY
+#define LOGOG_GROUP  "Graphics"
+#define LOGOG_CATEGORY "Unrecoverable"
+
+        EMERGENCY(_LG("The graphics card has been destroyed"));
+
+#undef LOGOG_CATEGORY
+#define LOGOG_CATEGORY	"Recoverable"
+
+        WARN(_LG("The graphics card has been replaced"));
+
+#undef LOGOG_GROUP
+#define LOGOG_GROUP "Audio"
+
+        WARN(_LG("The headphones are unplugged"));
+
+#undef LOGOG_GROUP
+#define LOGOG_GROUP "Inputs"
+
+        WARN(_LG("The inputs have been yanked off but this fact won't be reported!"));
+
+#undef LOGOG_CATEGORY
+#undef LOGOG_GROUP
+#define LOGOG_CATEGORY NULL
+#define LOGOG_GROUP NULL
+    }
+
+    LOGOG_SHUTDOWN();
+//! [GroupCategory4]
+    return 0;
+}
+
+
+UNITTEST( Info1 )
+{
+    LOGOG_INITIALIZE();
+    {
+        Cout out;
+
+        for ( int i = 0; i < 2; i++ )
+        {
+            for ( int t = 0; t < 10; t++ )
+            {
+                INFO( _LG("t is now: %d"), t );
+                if ( t > 8 )
+                    WARN(_LG("t is pretty high now!"));
+            }
+
+            DBUG(_LG("This warning isn't very interesting"));
+            EMERGENCY(_LG("THIS IS SUPER IMPORTANT!"));
+        }
+
+        LOGOG_SET_LEVEL( LOGOG_LEVEL_DEBUG );
+        LOGOG_DEBUG(_LG("Messages instantiated for the first time will be called now.  However, debug messages"));
+        LOGOG_DEBUG(_LG("instantiated before the LOGOG_SET_LEVEL won't be transmitted."));
+
+    }
+
+    LOGOG_SHUTDOWN();
+
+    return 0;
+}
+
+void GeneratePseudoRandomErrorMessages()
+{
+    int pr = 0xf8d92347;
+    int ps;
+
+    for ( int t = 0; t < TEST_STRESS_LEVEL * 10; t++ )
+    {
+        pr = pr * 0xd9381381 + 0x13d7b;
+        ps = pr % ( (1 << 19) - 1 );
+
+        ERR( _LG("We must inform you of this pseudo-random error code: %d"), ps );
+
+        // Do a non specific amount of busy work.
+        int swap1 = 0, swap2 = 1;
+        for ( int i = 0; i < ps; i++ )
+        {
+            int swap3 = swap1;
+            swap1 = swap2;
+            swap2 = swap3;
+        }
+    }
+
+}
+
+UNITTEST( ImmediateLogging )
+{
+    LOGOG_INITIALIZE();
+
+    {
+        LogFile logFile( "log.txt" );
+
+        GeneratePseudoRandomErrorMessages();
+    }
+
+    LOGOG_SHUTDOWN();
+
+    return 0;
+}
+
+#ifdef LOGOG_UNICODE
+UNITTEST( UnicodeLogFile )
+{
+    LOGOG_INITIALIZE();
+
+    {
+        LogFile logFile( "unicode.txt" );
+
+        // see http://blogs.msdn.com/b/michkap/archive/2008/03/18/8306597.aspx
+        INFO(L"\x043a\x043e\x0448\x043a\x0430 \x65e5\x672c\x56fd");
+        WARN(L"\x043a\x043e\x0448\x043a\x0430 \x65e5\x672c\x56fd");
+        ERR(L"\x043a\x043e\x0448\x043a\x0430 \x65e5\x672c\x56fd");
+    }
+
+    LOGOG_SHUTDOWN();
+
+    return 0;
+}
+#endif // LOGOG_UNICODE
+
+UNITTEST( DeferredCoutLogging )
+{
+    LOGOG_INITIALIZE();
+
+    {
+        Cout out;
+        LogBuffer logBuffer( &out );
+
+        // Make sure that out does not receive messages via the general filter mechanism.
+        out.UnsubscribeToMultiple( AllFilters() );
+
+        for ( int i = 1; i <= 10; i++ )
+        {
+            ERR(_LG("This is error %d of 10"), i);
+
+            int q = 27832;
+
+            for ( int j = 0; j < TEST_STRESS_LEVEL * 10000000; j++ )
+                q *= q;
+        }
+    }
+
+    LOGOG_SHUTDOWN();
+
+    return 0;
+}
+
+UNITTEST( DeferredFileLogging )
+{
+//! [DeferredFileLogging]
+    LOGOG_INITIALIZE();
+
+    {
+        LogFile logFile( "log.txt" );
+        LogBuffer logBuffer( &logFile );
+
+        /* Because the LogBuffer is not writing to a line device a la stdout or stderr, it does not need to
+         * send null terminated strings to its destination (the LogFile).  This is a particular peculiarity
+         * of having a buffering target to a serial-type target, such as a socket or a file.
+         */
+        logBuffer.SetNullTerminatesStrings( false );
+
+        // Make sure that the log file does not receive messages via the general filter mechanism.
+        logFile.UnsubscribeToMultiple( AllFilters() );
+
+        for ( int i = 1; i <= 20; i++ )
+        {
+            WARN(_LG("This is warning %d of 20"), i);
+
+            int q = 27832;
+            for ( int j = 0; j < TEST_STRESS_LEVEL * 10000000; j++ )
+                q *= q;
+        }
+    }
+
+    LOGOG_SHUTDOWN();
+//! [DeferredFileLogging]
+    return 0;
+}
+
+UNITTEST( DateAndTime )
+{
+//! [DateAndTimeLogging]
+    LOGOG_INITIALIZE();
+
+    {
+        Cerr err;
+
+        Formatter *pFormatter = &GetDefaultFormatter();
+
+        pFormatter->SetShowTimeOfDay( true );
+
+        for ( int i = 1; i <= 20; i++ )
+        {
+            WARN(_LG("This is warning %d of 20... but with time!"), i);
+
+            int q = 27832;
+            for ( int j = 0; j < TEST_STRESS_LEVEL * 10000000; j++ )
+                q *= q;
+        }
+    }
+
+    LOGOG_SHUTDOWN();
+//! [DateAndTimeLogging]
+
+    return 0;
+}
+
+
+#ifndef LOGOG_TARGET_PS3
+int DoPlatformSpecificTestInitialization()
+{
+    return 0;
+}
+#endif
+int main( int , char ** )
+{
+#ifdef LOGOG_LEAK_DETECTION_WINDOWS
+	_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF | _CRTDBG_CHECK_ALWAYS_DF );
+#endif // LOGOG_LEAK_DETECTION_WINDOWS
+
+//! [WindowsUnicodeSetup]
+#ifdef LOGOG_UNICODE
+#ifdef LOGOG_FLAVOR_WINDOWS
+    _setmode(_fileno(stdout), _O_U16TEXT);
+    _setmode(_fileno(stderr), _O_U16TEXT);
+#endif // LOGOG_FLAVOR_WINDOWS
+#endif // LOGOG_UNICODE
+//! [WindowsUnicodeSetup]
+
+    int nPlatformSpecific;
+    nPlatformSpecific = DoPlatformSpecificTestInitialization();
+    if ( nPlatformSpecific != 0)
+        return nPlatformSpecific;
+
+    int nResult;
+    nResult = RunAllTests();
+    ShutdownTests();
+
+#ifdef LOGOG_LEAK_DETECTION_WINDOWS
+	_CrtMemState crtMemState;
+	_CrtMemCheckpoint( &crtMemState );
+	_CrtMemDumpStatistics( &crtMemState );
+	_CrtDumpMemoryLeaks();
+#endif // LOGOG_LEAK_DETECTION_WINDOWS
+
+    return nResult;
+}
+
diff --git a/Base/logog/test/test.sln b/Base/logog/test/test.sln
new file mode 100644
index 0000000000000000000000000000000000000000..5e7b2d0feb6b733d20d3f852e2b3d25e9ccd7b8a
--- /dev/null
+++ b/Base/logog/test/test.sln
@@ -0,0 +1,41 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test.vcproj", "{FFD188AD-0FE5-4808-90E0-EC528324FFAD}"
+	ProjectSection(ProjectDependencies) = postProject
+		{85857E80-2122-4DD8-9BA9-B90CC10D65B0} = {85857E80-2122-4DD8-9BA9-B90CC10D65B0}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "logog", "..\src\logog.vcproj", "{85857E80-2122-4DD8-9BA9-B90CC10D65B0}"
+EndProject
+Global
+	GlobalSection(SourceCodeControl) = preSolution
+		SccNumberOfProjects = 2
+		SccProjectUniqueName0 = test.vcproj
+		SccProjectName0 = Perforce\u0020Project
+		SccLocalPath0 = .
+		SccProvider0 = MSSCCI:Perforce\u0020SCM
+		SccProjectUniqueName1 = ..\\src\\logog.vcproj
+		SccProjectName1 = Perforce\u0020Project
+		SccLocalPath1 = ..
+		SccProvider1 = MSSCCI:Perforce\u0020SCM
+		SccProjectFilePathRelativizedFromConnection1 = src\\
+	EndGlobalSection
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		Release|Win32 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{FFD188AD-0FE5-4808-90E0-EC528324FFAD}.Debug|Win32.ActiveCfg = Debug|Win32
+		{FFD188AD-0FE5-4808-90E0-EC528324FFAD}.Debug|Win32.Build.0 = Debug|Win32
+		{FFD188AD-0FE5-4808-90E0-EC528324FFAD}.Release|Win32.ActiveCfg = Release|Win32
+		{FFD188AD-0FE5-4808-90E0-EC528324FFAD}.Release|Win32.Build.0 = Release|Win32
+		{85857E80-2122-4DD8-9BA9-B90CC10D65B0}.Debug|Win32.ActiveCfg = Debug|Win32
+		{85857E80-2122-4DD8-9BA9-B90CC10D65B0}.Debug|Win32.Build.0 = Debug|Win32
+		{85857E80-2122-4DD8-9BA9-B90CC10D65B0}.Release|Win32.ActiveCfg = Release|Win32
+		{85857E80-2122-4DD8-9BA9-B90CC10D65B0}.Release|Win32.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/Base/logog/test/test.vcproj b/Base/logog/test/test.vcproj
new file mode 100644
index 0000000000000000000000000000000000000000..8b14c91680cd2955a83cc9e5847e690fa57137ca
--- /dev/null
+++ b/Base/logog/test/test.vcproj
@@ -0,0 +1,231 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="9.00"
+	Name="test"
+	ProjectGUID="{FFD188AD-0FE5-4808-90E0-EC528324FFAD}"
+	RootNamespace="test"
+	SccProjectName="Perforce Project"
+	SccLocalPath="."
+	SccProvider="MSSCCI:Perforce SCM"
+	Keyword="Win32Proj"
+	TargetFrameworkVersion="196613"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\include"
+				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="0"
+				WarningLevel="4"
+				Detect64BitPortabilityProblems="false"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="2"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				RandomizedBaseAddress="0"
+				DataExecutionPrevention="0"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+				HeapVerification="2"
+				HandleVerification="2"
+				LocksVerification="2"
+				PageHeapConserveMemory="false"
+				PageHeapProtectionLocation="1"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				EnableIntrinsicFunctions="true"
+				AdditionalIncludeDirectories="..\include"
+				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+				RuntimeLibrary="2"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="4"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="1"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath=".\test.cpp"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+			>
+		</Filter>
+		<File
+			RelativePath="..\doc\overview.dox"
+			>
+			<FileConfiguration
+				Name="Debug|Win32"
+				>
+				<Tool
+					Name="VCCustomBuildTool"
+					Description="Generating doxygen output"
+					CommandLine="$(InputDir)make-doxygen.bat&#x0D;&#x0A;"
+					Outputs="$(InputDir)html\index.html"
+				/>
+			</FileConfiguration>
+			<FileConfiguration
+				Name="Release|Win32"
+				ExcludedFromBuild="true"
+				>
+				<Tool
+					Name="VCCustomBuildTool"
+					Description="Generating doxygen output"
+					CommandLine="$(InputDir)make-doxygen.bat&#x0D;&#x0A;"
+					Outputs="$(InputDir)html\index.html"
+				/>
+			</FileConfiguration>
+		</File>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
diff --git a/Base/logog/test/test.vcproj.lnt b/Base/logog/test/test.vcproj.lnt
new file mode 100644
index 0000000000000000000000000000000000000000..5fd30307fecb5cefe593734b3dc23ed815f10632
--- /dev/null
+++ b/Base/logog/test/test.vcproj.lnt
@@ -0,0 +1,11 @@
+/* -dConfiguration= ... none provided  */
+-D_UNICODE                     //  27: CharacterSet = "1" 
+-DUNICODE                      //  27: CharacterSet = "" 
+-i"..\include"                 //  47: AdditionalIncludeDirectories = "..\include" 
+-DWIN32                        //  48: PreprocessorDefinitions = "WIN32;_DEBUG;_CONSOLE" 
+-D_DEBUG                       //  48: PreprocessorDefinitions = "" 
+-D_CONSOLE                     //  48: PreprocessorDefinitions = "" 
+-D_MT                          //  51: RuntimeLibrary = "3" 
+-D_DEBUG                       //  51: RuntimeLibrary = "" 
+-D_DLL                         //  51: RuntimeLibrary = "" 
+.\test.cpp                     // 180: RelativePath = ".\test.cpp"