From 4ab3dc1b297a2d50cab81656f39449779a83caf0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Emmanuel=20Beno=C3=AEt?= <tseeker@nocternity.net>
Date: Wed, 1 Nov 2017 23:21:01 +0100
Subject: [PATCH] Finished importing the good bits from LW's library

---
 include/ebcl/DynLib.hh                 |    8 +-
 include/ebcl/GameLoop.hh               |   30 -
 include/ebcl/Messages.hh               |  282 ---
 include/ebcl/Mods.hh                   |  247 ---
 include/ebcl/Pointers.hh               |   18 +-
 include/ebcl/SRDBinary.hh              |   14 +-
 include/ebcl/SRDData.hh                |   19 +-
 include/ebcl/SRDDefinitions.hh         |   14 +-
 include/ebcl/SRDIO.hh                  |   12 +-
 include/ebcl/SRDPPCommands.hh          |  101 -
 include/ebcl/SRDParser.hh              |   12 +-
 include/ebcl/SRDParserConfig.hh        |   14 +-
 include/ebcl/SRDText.hh                |   12 +-
 include/ebcl/Version.hh                |   19 -
 include/ebcl/Version.hh.in             |   19 -
 include/ebcl/inline/DynLib.hh          |   10 +-
 include/ebcl/inline/Messages.hh        |  154 --
 include/ebcl/inline/Mods.hh            |   59 -
 include/ebcl/inline/SRDBinary.hh       |   10 +-
 include/ebcl/inline/SRDData.hh         |   10 +-
 include/ebcl/inline/SRDDefinitions.hh  |   10 +-
 include/ebcl/inline/SRDIO.hh           |   10 +-
 include/ebcl/inline/SRDParserConfig.hh |   10 +-
 include/ebcl/inline/SRDText.hh         |   10 +-
 src/Console-Unix.hh                    |  667 ------
 src/Console.cc                         | 1346 ------------
 src/ConsoleLogWriter.cc                |   83 -
 src/CwdFileLogger.cc                   |  153 --
 src/DynLib.cc                          |    6 +-
 src/GameLoop.cc                        |  140 --
 src/LW.cc                              |  603 ------
 src/Log.cc                             | 1041 ----------
 src/Messages.cc                        |   86 -
 src/ModInterface.cc                    |   20 -
 src/Mods.cc                            | 2646 ------------------------
 src/SRDBinary.cc                       |    6 +-
 src/SRDData.cc                         |   37 +-
 src/SRDDefinitions.cc                  |   10 +-
 src/SRDIO.cc                           |    6 +-
 src/SRDPPCommands.cc                   | 2518 ----------------------
 src/SRDParser.cc                       |    4 +-
 src/SRDParserConfig.cc                 |    4 +-
 src/SRDPreproc.cc                      | 1416 -------------
 src/SRDText.cc                         |   14 +-
 src/TemplateInstantiation.cc           |    4 +
 src/TextFileLogger.cc                  |  159 --
 src/VFS.cc                             |  930 ---------
 src/VFSDrivers.cc                      |  614 ------
 src/files.mk                           |   32 +-
 tests/alloc-pool.cc                    |    6 +-
 tests/console-edit.cc                  |  468 -----
 tests/console-text.cc                  |  405 ----
 tests/list.mk                          |   42 +-
 tests/log-data.cc                      |  649 ------
 tests/ring-buffer.cc                   |    4 +-
 tests/run-test.cc                      |    2 +-
 tests/srd-bin-reader.cc                |    6 +-
 tests/srd-bin-writer.cc                |    6 +-
 tests/srd-lexer.cc                     |    4 +-
 tests/srd-mem-target.cc                |    4 +-
 tests/srd-parser-cfg.cc                |    4 +-
 tests/srd-parser-defs.cc               |    4 +-
 tests/srd-parser.cc                    |    8 +-
 tests/srd-preproc-cmd-arithmetic.cc    |  877 --------
 tests/srd-preproc-cmd-casts.cc         | 1100 ----------
 tests/srd-preproc-cmd-common.hh        |  108 -
 tests/srd-preproc-cmd-compare.cc       |  340 ---
 tests/srd-preproc-cmd-core.cc          | 1303 ------------
 tests/srd-preproc-cmd-functions.cc     |  441 ----
 tests/srd-preproc-cmd-input.cc         |  543 -----
 tests/srd-preproc-cmd-introspect.cc    |  322 ---
 tests/srd-preproc-cmd-logic.cc         |  609 ------
 tests/srd-preproc-cmd-macros.cc        |  243 ---
 tests/srd-preproc-cmd-misc.cc          |  165 --
 tests/srd-preproc-cmd-strings.cc       |  931 ---------
 tests/srd-preproc-cmd-variables.cc     |  372 ----
 tests/srd-preproc-core.cc              |  245 ---
 tests/srd-preproc-location.hh          |  133 --
 tests/srd-preproc-tracking.cc          |  676 ------
 tests/srd-text-writer.cc               |    6 +-
 tests/stream-file-input.cc             |  268 ---
 tests/vfs.cc                           |  318 ---
 82 files changed, 177 insertions(+), 24084 deletions(-)
 delete mode 100644 include/ebcl/GameLoop.hh
 delete mode 100644 include/ebcl/Messages.hh
 delete mode 100644 include/ebcl/Mods.hh
 delete mode 100644 include/ebcl/SRDPPCommands.hh
 delete mode 100644 include/ebcl/Version.hh
 delete mode 100644 include/ebcl/Version.hh.in
 delete mode 100644 include/ebcl/inline/Messages.hh
 delete mode 100644 include/ebcl/inline/Mods.hh
 delete mode 100644 src/Console-Unix.hh
 delete mode 100644 src/Console.cc
 delete mode 100644 src/ConsoleLogWriter.cc
 delete mode 100644 src/CwdFileLogger.cc
 delete mode 100644 src/GameLoop.cc
 delete mode 100644 src/LW.cc
 delete mode 100644 src/Log.cc
 delete mode 100644 src/Messages.cc
 delete mode 100644 src/ModInterface.cc
 delete mode 100644 src/Mods.cc
 delete mode 100644 src/SRDPPCommands.cc
 delete mode 100644 src/SRDPreproc.cc
 delete mode 100644 src/TextFileLogger.cc
 delete mode 100644 src/VFS.cc
 delete mode 100644 src/VFSDrivers.cc
 delete mode 100644 tests/console-edit.cc
 delete mode 100644 tests/console-text.cc
 delete mode 100644 tests/log-data.cc
 delete mode 100644 tests/srd-preproc-cmd-arithmetic.cc
 delete mode 100644 tests/srd-preproc-cmd-casts.cc
 delete mode 100644 tests/srd-preproc-cmd-common.hh
 delete mode 100644 tests/srd-preproc-cmd-compare.cc
 delete mode 100644 tests/srd-preproc-cmd-core.cc
 delete mode 100644 tests/srd-preproc-cmd-functions.cc
 delete mode 100644 tests/srd-preproc-cmd-input.cc
 delete mode 100644 tests/srd-preproc-cmd-introspect.cc
 delete mode 100644 tests/srd-preproc-cmd-logic.cc
 delete mode 100644 tests/srd-preproc-cmd-macros.cc
 delete mode 100644 tests/srd-preproc-cmd-misc.cc
 delete mode 100644 tests/srd-preproc-cmd-strings.cc
 delete mode 100644 tests/srd-preproc-cmd-variables.cc
 delete mode 100644 tests/srd-preproc-core.cc
 delete mode 100644 tests/srd-preproc-location.hh
 delete mode 100644 tests/srd-preproc-tracking.cc
 delete mode 100644 tests/stream-file-input.cc
 delete mode 100644 tests/vfs.cc

diff --git a/include/ebcl/DynLib.hh b/include/ebcl/DynLib.hh
index 642f7e4..9fe8d03 100644
--- a/include/ebcl/DynLib.hh
+++ b/include/ebcl/DynLib.hh
@@ -5,9 +5,9 @@
 #ifndef _H_EBCL_DYNLIB
 #define _H_EBCL_DYNLIB
 
-#include <lw/lib/Strings.hh>
-#include <lw/lib/Utilities.hh>
-namespace lw {
+#include <ebcl/Strings.hh>
+#include <ebcl/Utilities.hh>
+namespace ebcl {
 
 
 /*= DYNAMIC LIBRARY SUPPORT ==================================================*/
@@ -45,4 +45,4 @@ M_CLASS_POINTERS( DynLib );
 
 } // namespace lw
 #endif // _H_EBCL_DYNLIB
-#include <lw/lib/inline/DynLib.hh>
+#include <ebcl/inline/DynLib.hh>
diff --git a/include/ebcl/GameLoop.hh b/include/ebcl/GameLoop.hh
deleted file mode 100644
index f82677a..0000000
--- a/include/ebcl/GameLoop.hh
+++ /dev/null
@@ -1,30 +0,0 @@
-/******************************************************************************/
-/* GAME'S MAIN LOOP ***********************************************************/
-/******************************************************************************/
-
-#ifndef _H_LW_LIB_GAMELOOP
-#define _H_LW_LIB_GAMELOOP
-#include <lw/lib/Messages.hh>
-namespace lw {
-
-
-/*= GAME LOOP ================================================================*/
-
-class T_GameLoop : public A_PrivateImplementation
-{
-    public:
-	T_GameLoop( ) noexcept;
-	T_GameLoop( T_GameLoop const& ) = delete;
-	T_GameLoop( T_GameLoop&& ) = delete;
-
-	bool active( ) const noexcept;
-	void start( ) noexcept;
-	void shutdown( ) noexcept;
-
-	void putMessage( T_UIMessage&& message ) noexcept;
-};
-M_CLASS_POINTERS( GameLoop );
-
-
-}
-#endif // _H_LW_LIB_GAMELOOP
diff --git a/include/ebcl/Messages.hh b/include/ebcl/Messages.hh
deleted file mode 100644
index 4e288c2..0000000
--- a/include/ebcl/Messages.hh
+++ /dev/null
@@ -1,282 +0,0 @@
-/******************************************************************************/
-/* UI<=>GAME MESSAGES *********************************************************/
-/******************************************************************************/
-
-#ifndef _H_LW_LIB_MESSAGES
-#define _H_LW_LIB_MESSAGES
-#include <lw/lib/Strings.hh>
-#include <lw/lib/Types.hh>
-namespace lw {
-
-
-/*= VIEWS ====================================================================*/
-
-/* Empty abstract class that serves as a base for game views */
-class A_GameView
-{
-    public:
-	virtual ~A_GameView( ) = 0;
-};
-M_ABSTRACT_POINTERS( GameView );
-
-
-/* Abstract class for a view builder
- *
- * User interfaces need to access the game's data in order to display it. View
- * builders provide a way to do that; they are passed to the game's main loop
- * by the UI. Once set, they will be used to create and update view data.
- */
-class A_ViewBuilder
-{
-    public:
-	virtual ~A_ViewBuilder( ) = 0;
-
-	/* This method creates a view instance. It is called twice when the
-	 * builder is installed, in order to create a "double buffer" - one
-	 * view can be sent to the UI while the other is being updated.
-	 */
-	virtual OP_GameView createView( ) = 0;
-
-	/* This method is responsible for updating a view instance. */
-	virtual void updateView( OP_GameView view ) = 0;
-};
-M_ABSTRACT_POINTERS( ViewBuilder );
-
-
-/*= GAME STATE ===============================================================*/
-
-/* State of the main loop */
-enum class E_GameState {
-	NO_GAME ,		// No game loaded
-	GAME_PAUSED ,		// Game is loaded but not running
-	GAME_SLOW ,		// Game is running at slow speed
-	GAME_NORMAL ,		// Game is running at normal speed
-	GAME_FAST		// Game is running at high speed
-};
-M_LSHIFT_OP( T_StringBuilder , E_GameState );
-
-
-/*= PROGRESS INFORMATION =====================================================*/
-
-/* Progress information for long operations - part (main or sub) */
-class T_ProgressInfoPart
-{
-    private:
-	T_String text_;
-	uint32_t progress_;
-	uint32_t total_;
-
-    public:
-	T_ProgressInfoPart( ) = delete;
-	T_ProgressInfoPart( T_String text , uint32_t progress , uint32_t total ) noexcept;
-	T_ProgressInfoPart( T_ProgressInfoPart&& other ) noexcept;
-	T_ProgressInfoPart( T_ProgressInfoPart const& other );
-
-	T_String const& text( ) const noexcept;
-	uint32_t progress( ) const noexcept;
-	uint32_t total( ) const noexcept;
-};
-
-/* Progress information for long operations - main */
-class T_ProgressInfo
-{
-    private:
-	T_ProgressInfoPart main_;
-	T_Optional< T_ProgressInfoPart > sub_;
-
-    public:
-	T_ProgressInfo( ) = delete;
-	T_ProgressInfo( T_String text , uint32_t progress , uint32_t total ) noexcept;
-	explicit T_ProgressInfo( T_ProgressInfoPart main ) noexcept;
-	T_ProgressInfo( T_ProgressInfoPart main , T_ProgressInfoPart sub ) noexcept;
-	T_ProgressInfo( T_ProgressInfoPart main ,
-			T_String sText , uint32_t sProgress , uint32_t sTotal ) noexcept;
-	T_ProgressInfo( T_String text , uint32_t progress , uint32_t total ,
-			T_String sText , uint32_t sProgress , uint32_t sTotal ) noexcept;
-	T_ProgressInfo( T_ProgressInfo&& other ) noexcept;
-	T_ProgressInfo( T_ProgressInfo const& other ) = delete;
-
-	T_ProgressInfoPart const& main( ) const noexcept;
-	bool hasSub( ) const noexcept;
-	T_ProgressInfoPart const& sub( ) const;
-};
-M_CLASS_POINTERS( ProgressInfo );
-
-
-/*= MESSAGES =================================================================*/
-
-/* Types of messages sent by the UI to the game */
-enum class E_GameUIMessage {
-	/* Create a new game
-	 * Data: XXX
-	 */
-	NEW ,
-	/* Load an existing game
-	 * Data: uint32_t - game identifier
-	 */
-	LOAD ,
-	/* Save the current game
-	 * Data: none
-	 */
-	SAVE ,
-	/* Quit the current game
-	 * Data: none
-	 */
-	STOP ,
-	/* Quit current game (if any) the exit the main loop
-	 * Data: none
-	 */
-	QUIT ,
-
-	/* Abort the current operation
-	 * Data: none
-	 */
-	ABORT ,
-
-	/* Delete a saved game
-	 * Data: uint32_t - game identifier
-	 */
-	DELETE ,
-	/* Copy or rename a saved game
-	 * Data: XXX
-	 */
-	COPY_OR_RENAME ,
-
-	/* Set the current game's speed
-	 * Data: E_GameState (but NO_GAME will be ignored)
-	 */
-	SET_SPEED ,
-	/* Execute computation steps
-	 * Data: XXX
-	 */
-	STEPS ,
-	/* Set a view builder
-	 * Data: XXX
-	 */
-	SET_VIEW ,
-	/* Indicate that a view has been displayed
-	 * Data: T_String - identifier of the view
-	 */
-	VIEW_DISPLAYED ,
-	/* Send a query to the game
-	 * Data: XXX
-	 */
-	QUERY ,
-	/* Send a command to the game
-	 * Data: XXX
-	 */
-	COMMAND
-};
-M_LSHIFT_OP( T_StringBuilder , E_GameUIMessage );
-
-/*----------------------------------------------------------------------------*/
-
-/* Types of messages sent by the main loop to the UI */
-enum class E_GameLoopMessage {
-	/* Main loop exiting
-	 * Data: none
-	 */
-	TERMINATED ,
-	/* Progress information
-	 * Data: T_ProgressInfo
-	 */
-	PROGRESS ,
-	/* Operation completed
-	 * Data: none
-	 */
-	DONE ,
-	/* State changed
-	 * Data: E_GameState
-	 */
-	STATE_CHANGED ,
-	/* Indicate that a view is available
-	 * Data: XXX
-	 */
-	VIEW_AVAILABLE ,
-	/* Query response
-	 * Data: XXX
-	 */
-	QUERY_RESPONSE ,
-	/* Command execution - success
-	 * Data: none
-	 */
-	COMMAND_OK ,
-	/* Command execution - syntax error
-	 * Data: XXX
-	 */
-	COMMAND_SYNTAX ,
-	/* Command execution - error
-	 * Data: XXX
-	 */
-	COMMAND_ERROR ,
-};
-M_LSHIFT_OP( T_StringBuilder , E_GameLoopMessage );
-
-/*----------------------------------------------------------------------------*/
-
-/* Types for message data */
-using T_GameUIMessageData = T_Union<
-		uint32_t ,
-		T_String ,
-		E_GameState
-	>;
-using T_GameLoopMessageData = T_Union<
-		T_ProgressInfo ,
-		E_GameState
-	>;
-
-/*----------------------------------------------------------------------------*/
-
-/* Message direction */
-enum class E_MessageDirection {
-	FROM_UI_TO_GAME ,
-	FROM_GAME_TO_UI
-};
-
-/* Message class template, can be used for both directions */
-template<
-	E_MessageDirection Direction ,
-	typename EType = std::conditional_t<
-		Direction == E_MessageDirection::FROM_UI_TO_GAME ,
-		E_GameUIMessage , E_GameLoopMessage > ,
-	typename DType = std::conditional_t<
-		Direction == E_MessageDirection::FROM_UI_TO_GAME ,
-		T_GameUIMessageData , T_GameLoopMessageData >
->
-class T_GameMessage
-{
-    public:
-	using T_Type = EType;
-	using T_Data = DType;
-
-    private:
-	using T_Self_ = T_GameMessage< Direction >;
-	T_Optional< T_Type > type_;
-	T_Optional< T_Data > data_;
-
-    public:
-	constexpr T_GameMessage( ) noexcept;
-	constexpr T_GameMessage( T_Type type ) noexcept;
-	T_GameMessage( T_Type type , T_Data data ) noexcept;
-	T_GameMessage( T_Self_ const& ) = delete;
-	T_GameMessage( T_Self_&& other ) noexcept;
-
-	T_Self_& operator =( T_Self_ const& ) = delete;
-	T_Self_& operator =( T_Self_&& other ) noexcept;
-
-	constexpr bool hasMessage( ) const noexcept;
-	constexpr T_Type type( ) const noexcept;
-
-	template< typename T >
-	constexpr T const& data( ) const;
-};
-
-/*----------------------------------------------------------------------------*/
-
-using T_UIMessage = T_GameMessage< E_MessageDirection::FROM_UI_TO_GAME >;
-using T_LoopMessage = T_GameMessage< E_MessageDirection::FROM_GAME_TO_UI >;
-
-
-} // namespace lw
-#endif // _H_LW_LIB_MESSAGES
-#include <lw/lib/inline/Messages.hh>
diff --git a/include/ebcl/Mods.hh b/include/ebcl/Mods.hh
deleted file mode 100644
index 88572b2..0000000
--- a/include/ebcl/Mods.hh
+++ /dev/null
@@ -1,247 +0,0 @@
-/******************************************************************************/
-/* MODDING SYSTEM *************************************************************/
-/******************************************************************************/
-
-#ifndef _H_LW_LIB_MODS
-#define _H_LW_LIB_MODS
-#include <lw/lib/Log.hh>
-#include <lw/lib/ModInterface.hh>
-namespace lw {
-
-
-/*= MOD INFORMATION ==========================================================*/
-
-/* Mod identifier (name + version) */
-struct T_ModIdentifier {
-	T_String name;
-	uint32_t version;	// Main version number used for dependencies
-
-	bool operator ==( T_ModIdentifier const& other ) const noexcept;
-	bool operator !=( T_ModIdentifier const& other ) const noexcept;
-
-	int compare( T_ModIdentifier const& other ) const noexcept;
-};
-M_CLASS_POINTERS( ModIdentifier );
-M_DECLARE_HASH( T_ModIdentifier );
-M_DECLARE_COMPARATOR( T_ModIdentifier );
-M_LSHIFT_OP( T_StringBuilder , T_ModIdentifier const& );
-
-/* Types of mods */
-enum class E_ModType {
-	DATA ,		// This mod consists of data only
-	NATIVE ,	// This mod consists of native code
-	UI ,		// This mod is an user interface
-};
-
-/*----------------------------------------------------------------------------*/
-
-/* Mod information record */
-struct T_ModInfo
-{
-	T_String path;
-	E_ModType type;
-
-	/* Mod name, version and revision (the latter is for changes that don't
-	 * affect the interface).
-	 */
-	T_ModIdentifier identifier;
-	uint32_t revision;
-
-	/* Required library version number */
-	uint32_t libVersion;
-
-	/* List of dependencies */
-	T_Array< T_ModIdentifier > modDeps;
-
-	/* Is this mod an user interface mod? */
-	bool isUserInterface( ) const noexcept;
-};
-M_CLASS_POINTERS( ModInfo );
-M_LSHIFT_OP( T_StringBuilder , T_ModInfo const& );
-
-
-/*= MODS MANAGER CONFIGURATION ===============================================*/
-
-/* Loading mode for a mod */
-enum class E_ModMode {
-	EXCLUDE ,	// Never load this mod
-	AUTO ,		// Load the most appropriate version of the mod
-	VERSION ,	// Load a specific version of the mod, fails
-			// if the mod in the specified version is not
-			// present
-	REQUIRE		// Require that the specified mod be present
-
-	// Note that both VERSION and REQUIRE can apply to an UI-specific mod;
-	// while the mod will not be loaded if the corresponding UI isn't,
-	// its presence will still be required.
-};
-
-/* Mods manager configuration */
-class T_ModsManagerConfiguration : public A_PrivateImplementation
-{
-    public:
-	T_ModsManagerConfiguration( ) noexcept;
-
-	T_ModsManagerConfiguration(
-			T_ModsManagerConfiguration const& ) = delete;
-	T_ModsManagerConfiguration& operator =(
-			T_ModsManagerConfiguration const& ) = delete;
-
-	T_ModsManagerConfiguration(
-			T_ModsManagerConfiguration&& ) noexcept;
-	T_ModsManagerConfiguration& operator =(
-			T_ModsManagerConfiguration&& other ) noexcept;
-
-	// ---------------------------------------------------------------------
-
-	/* Set a mod configuration entry */
-	void setAuto( T_String const& name ) noexcept;
-	void setRequired( T_String const& name ) noexcept;
-	void setExcluded( T_String const& name ) noexcept;
-	void setVersion( T_String const& name ,
-			uint32_t version ) noexcept;
-	void setVersion( T_String const& name ,
-			uint32_t version ,
-			uint32_t revision ) noexcept;
-
-	/* Query mod configuration */
-	T_Array< T_String > configured( ) const noexcept;
-	E_ModMode modeFor( T_String const& name ) const noexcept;
-	uint32_t requiredVersion( T_String const& name ) const noexcept;
-	T_Optional< uint32_t > requiredRevision(
-			T_String const& name ) const noexcept;
-
-	// ---------------------------------------------------------------------
-
-	/* Set or clear an UI preference */
-	void setUIPreference(
-			T_String const& name ,
-			int32_t weight ) noexcept;
-	void clearUIPreference(
-			T_String const& name ) noexcept;
-
-	/* List UI preferences */
-	T_Array< T_String > uiPreferences( ) const noexcept;
-	/* Get the preference for an UI */
-	int32_t uiPreference(
-			T_String const& name ) const noexcept;
-
-	// ---------------------------------------------------------------------
-
-	/* Filter a list of mods using the configuration's exclusions and
-	 * version limits.
-	 */
-	T_Array< RPC_ModInfo > filterMods(
-			T_Array< RPC_ModInfo > const& mods ) const noexcept;
-	/* Generate the list of required mods. This includes all mods that
-	 * have been set as required, and all mods that have a version
-	 * requirement.
-	 */
-	T_Array< T_String > requiredMods( ) const noexcept;
-
-	// ---------------------------------------------------------------------
-
-	/* Get a default configuration */
-	static T_ModsManagerConfiguration DefaultConfiguration( ) noexcept;
-
-	/* Get the parser's configuration used to load mods manager configuration */
-	static T_SRDParserConfig GetParserConfig( );
-};
-M_CLASS_POINTERS( ModsManagerConfiguration );
-
-
-/*= MODS DEPENDENCY GRAPH ====================================================*/
-
-class T_ModsDependencies : public A_PrivateImplementation
-{
-    public:
-	T_ModsDependencies( ) noexcept;
-	T_ModsDependencies(
-			T_Logger& logger ,
-			T_Array< RPC_ModInfo > const& mods ,
-			T_ModsManagerConfiguration const& config ) noexcept;
-
-	T_ModsDependencies(
-			T_ModsDependencies const& other ) noexcept;
-	T_ModsDependencies& operator =(
-			T_ModsDependencies const& other ) noexcept;
-
-	T_ModsDependencies(
-			T_ModsDependencies&& other ) noexcept;
-	T_ModsDependencies& operator =(
-			T_ModsDependencies&& other ) noexcept;
-
-	friend M_DECLARE_SWAP( T_ModsDependencies );
-
-	// ---------------------------------------------------------------------
-
-	bool resolved( ) const;
-	bool ambiguous( ) const;
-	T_Array< T_String > userInterfaces( ) const;
-	T_Array< RPC_ModInfo > const& commonMods( ) const;
-	T_Array< RPC_ModInfo >::RPC forUserInterface(
-			T_String const& name ) const;
-};
-M_CLASS_POINTERS( ModsDependencies );
-M_DECLARE_SWAP( T_ModsDependencies );
-
-
-/*= MODS MANAGER =============================================================*/
-
-/* Function type for a function that generates a feedback function used to
- * update the initialisation progress when the mods are being initialised.
- */
-using F_CreateInitUpdater = std::function< F_UpdateInitProgress( RPC_ModInfo ) >;
-
-class T_ModsManager : public A_PrivateImplementation
-{
-    public:
-	T_ModsManager( ) = delete;
-	T_ModsManager( T_ModsManager const& ) = delete;
-	T_ModsManager( T_ModsManager&& ) noexcept = delete;
-
-	T_ModsManager( T_ModsManagerConfiguration&& config ) noexcept;
-
-	// ---------------------------------------------------------------------
-
-	/* Find available mods, load their descriptions */
-	bool scanForMods( );
-	/* Get the list of available mods */
-	T_Array< RPC_ModInfo > availableMods( ) const noexcept;
-
-	/* Resolve dependencies between mods using the configuration;
-	 * returns true if there is a valid set of mods.
-	 */
-	bool resolveDependencies( ) noexcept;
-
-	// ---------------------------------------------------------------------
-
-	/* Pre-initialise common mods */
-	bool preinitCommon( ) noexcept;
-	/* Pre-initialise UI mods and try to start the user interface. */
-	OP_UserInterface preinitUIMods(
-			T_String const& ui ) noexcept;
-	/* Try to pre-initialise an UI mod. */
-	OP_UserInterface preinitUIMods( ) noexcept;
-
-	// ---------------------------------------------------------------------
-
-	/* Get the amount of loaded mods */
-	uint32_t modsCount( ) const noexcept;
-	/* Initialise the mods, sending progress updates along the way */
-	bool initialise(
-			F_CreateInitUpdater const& fciu ) noexcept;
-
-	// ---------------------------------------------------------------------
-
-	/* Shutdown all initialised mods. */
-	void shutdown( ) noexcept;
-	/* Unload all mods, calling post-shutdown routines if available */
-	void unload( ) noexcept;
-};
-M_CLASS_POINTERS( ModsManager );
-
-
-} // namespace lw
-#endif // _H_LW_LIB_MODS
-#include <lw/lib/inline/Mods.hh>
diff --git a/include/ebcl/Pointers.hh b/include/ebcl/Pointers.hh
index 1cf6952..3f3b8b2 100644
--- a/include/ebcl/Pointers.hh
+++ b/include/ebcl/Pointers.hh
@@ -399,23 +399,23 @@ template<
 #define M_CLASS_POINTERS( NAME ) \
 	typedef T_ ## NAME* RP_ ## NAME; \
 	typedef T_ ## NAME const* RPC_ ## NAME; \
-	typedef T_OwnPtr< T_ ## NAME > OP_ ## NAME; \
-	typedef T_SharedPtr< T_ ## NAME > SP_ ## NAME; \
-	typedef T_WeakPtr< T_ ## NAME > WP_ ## NAME
+	typedef ::ebcl::T_OwnPtr< T_ ## NAME > OP_ ## NAME; \
+	typedef ::ebcl::T_SharedPtr< T_ ## NAME > SP_ ## NAME; \
+	typedef ::ebcl::T_WeakPtr< T_ ## NAME > WP_ ## NAME
 
 #define M_ABSTRACT_POINTERS( NAME ) \
 	typedef A_ ## NAME* RP_ ## NAME; \
 	typedef A_ ## NAME const* RPC_ ## NAME; \
-	typedef T_OwnPtr< A_ ## NAME > OP_ ## NAME; \
-	typedef T_SharedPtr< A_ ## NAME > SP_ ## NAME; \
-	typedef T_WeakPtr< A_ ## NAME > WP_ ## NAME
+	typedef ::ebcl::T_OwnPtr< A_ ## NAME > OP_ ## NAME; \
+	typedef ::ebcl::T_SharedPtr< A_ ## NAME > SP_ ## NAME; \
+	typedef ::ebcl::T_WeakPtr< A_ ## NAME > WP_ ## NAME
 
 #define M_TEMPLATE_POINTERS( NAME ) \
 	typedef NAME* RP; \
 	typedef NAME const* RPC; \
-	typedef T_OwnPtr< NAME > OP; \
-	typedef T_SharedPtr< NAME > SP; \
-	typedef T_WeakPtr< NAME > WP
+	typedef ::ebcl::T_OwnPtr< NAME > OP; \
+	typedef ::ebcl::T_SharedPtr< NAME > SP; \
+	typedef ::ebcl::T_WeakPtr< NAME > WP
 
 
 } // namespace
diff --git a/include/ebcl/SRDBinary.hh b/include/ebcl/SRDBinary.hh
index 2fc8612..7185723 100644
--- a/include/ebcl/SRDBinary.hh
+++ b/include/ebcl/SRDBinary.hh
@@ -2,11 +2,11 @@
 /* SRD - BINARY STORAGE *******************************************************/
 /******************************************************************************/
 
-#ifndef _H_LW_LIB_SRDBINARY
-#define _H_LW_LIB_SRDBINARY
-#include <lw/lib/SRDIO.hh>
-#include <lw/lib/HashIndex.hh>
-namespace lw {
+#ifndef _H_EBCL_SRDBINARY
+#define _H_EBCL_SRDBINARY
+#include <ebcl/SRDIO.hh>
+#include <ebcl/HashIndex.hh>
+namespace ebcl {
 
 
 /*= WRITER ===================================================================*/
@@ -74,5 +74,5 @@ T_SRDList SRDBinaryReadFrom( T_String const& name , A_InputStream& input , bool
 
 
 } // namespace
-#include <lw/lib/inline/SRDBinary.hh>
-#endif // _H_LW_LIB_SRDBINARY
+#include <ebcl/inline/SRDBinary.hh>
+#endif // _H_EBCL_SRDBINARY
diff --git a/include/ebcl/SRDData.hh b/include/ebcl/SRDData.hh
index 54fa63d..7ff86a6 100644
--- a/include/ebcl/SRDData.hh
+++ b/include/ebcl/SRDData.hh
@@ -2,12 +2,12 @@
 /* SRD - DATA *****************************************************************/
 /******************************************************************************/
 
-#ifndef _H_LW_LIB_SRDDATA
-#define _H_LW_LIB_SRDDATA
-#include <lw/lib/Externals.hh>
-#include <lw/lib/Strings.hh>
-#include <lw/lib/Types.hh>
-namespace lw {
+#ifndef _H_EBCL_SRDDATA
+#define _H_EBCL_SRDDATA
+#include <ebcl/Externals.hh>
+#include <ebcl/Strings.hh>
+#include <ebcl/Types.hh>
+namespace ebcl {
 
 class T_Logger;
 
@@ -206,9 +206,6 @@ class X_SRDErrors : public std::exception
 	const T_SRDErrors errors;
 	X_SRDErrors( T_SRDErrors const& errors );
 	char const * what( ) const noexcept override;
-#ifndef LW_MINLIB
-	void log( T_Logger& logger ) const;
-#endif // LW_MINLIB
 };
 
 
@@ -357,5 +354,5 @@ extern template class T_Array< T_SRDToken >;
 
 
 } // namespace
-#include <lw/lib/inline/SRDData.hh>
-#endif // _H_LW_LIB_SRDDATA
+#include <ebcl/inline/SRDData.hh>
+#endif // _H_EBCL_SRDDATA
diff --git a/include/ebcl/SRDDefinitions.hh b/include/ebcl/SRDDefinitions.hh
index aa70321..afc9c3c 100644
--- a/include/ebcl/SRDDefinitions.hh
+++ b/include/ebcl/SRDDefinitions.hh
@@ -2,11 +2,11 @@
 /* SRD - PARSER DEFINITIONS ***************************************************/
 /******************************************************************************/
 
-#ifndef _H_LW_LIB_SRDDEFINITIONS
-#define _H_LW_LIB_SRDDEFINITIONS
-#include <lw/lib/SRDData.hh>
-#include <lw/lib/HashTables.hh>
-namespace lw {
+#ifndef _H_EBCL_SRDDEFINITIONS
+#define _H_EBCL_SRDDEFINITIONS
+#include <ebcl/SRDData.hh>
+#include <ebcl/HashTables.hh>
+namespace ebcl {
 
 
 /*= DEFINITION DATA ==========================================================*/
@@ -317,5 +317,5 @@ T_SRDInputRule::T_SetContextExecutor OnExit( F_SRDHandler f );
 
 
 } // namespace
-#include <lw/lib/inline/SRDDefinitions.hh>
-#endif // _H_LW_LIB_SRDDEFINITIONS
+#include <ebcl/inline/SRDDefinitions.hh>
+#endif // _H_EBCL_SRDDEFINITIONS
diff --git a/include/ebcl/SRDIO.hh b/include/ebcl/SRDIO.hh
index d2b02ca..3c53dfd 100644
--- a/include/ebcl/SRDIO.hh
+++ b/include/ebcl/SRDIO.hh
@@ -2,10 +2,10 @@
 /* SRD - INPUT AND OUTPUT *****************************************************/
 /******************************************************************************/
 
-#ifndef _H_LW_LIB_SRDIO
-#define _H_LW_LIB_SRDIO
-#include <lw/lib/SRDData.hh>
-namespace lw {
+#ifndef _H_EBCL_SRDIO
+#define _H_EBCL_SRDIO
+#include <ebcl/SRDData.hh>
+namespace ebcl {
 
 
 /*= INPUT / OUTPUT ABSTRACTIONS ==============================================*/
@@ -183,5 +183,5 @@ M_CLASS_POINTERS( SRDWriterTarget );
 
 
 } // namespace
-#include <lw/lib/inline/SRDIO.hh>
-#endif // _H_LW_LIB_SRDIO
+#include <ebcl/inline/SRDIO.hh>
+#endif // _H_EBCL_SRDIO
diff --git a/include/ebcl/SRDPPCommands.hh b/include/ebcl/SRDPPCommands.hh
deleted file mode 100644
index c66beb8..0000000
--- a/include/ebcl/SRDPPCommands.hh
+++ /dev/null
@@ -1,101 +0,0 @@
-/******************************************************************************/
-/* SRD - PREPROCESSOR COMMANDS ************************************************/
-/******************************************************************************/
-
-#ifndef _H_LW_LIB_SRDPPCOMMANDS
-#define _H_LW_LIB_SRDPPCOMMANDS
-#include <lw/lib/SRDPreproc.hh>
-namespace lw {
-
-
-M_SRDPP_COMMAND_DECL( Add ); M_SRDPP_COMMAND_INIT( Add , "add" );
-M_SRDPP_COMMAND_DECL( And ); M_SRDPP_COMMAND_INIT( And , "and" );
-
-M_SRDPP_COMMAND_DECL( Bless ); M_SRDPP_COMMAND_INIT( Bless , "bless" );
-M_SRDPP_COMMAND_DECL( Break ); M_SRDPP_COMMAND_INIT( Break , "break" );
-M_SRDPP_COMMAND_DECL( BwAnd ); M_SRDPP_COMMAND_INIT( BwAnd , "bw-and" );
-M_SRDPP_COMMAND_DECL( BwNot ); M_SRDPP_COMMAND_INIT( BwNot , "bw-not" );
-M_SRDPP_COMMAND_DECL( BwOr ); M_SRDPP_COMMAND_INIT( BwOr , "bw-or" );
-M_SRDPP_COMMAND_DECL( BwXor ); M_SRDPP_COMMAND_INIT( BwXor , "bw-xor" );
-
-M_SRDPP_COMMAND_DECL( Call ); M_SRDPP_COMMAND_INIT( Call , "call" );
-M_SRDPP_COMMAND_DECL( CastString ); M_SRDPP_COMMAND_INIT( CastString , "to-string" );
-M_SRDPP_COMMAND_DECL( CastWord ); M_SRDPP_COMMAND_INIT( CastWord , "to-word" );
-M_SRDPP_COMMAND_DECL( CastInt ); M_SRDPP_COMMAND_INIT( CastInt , "to-integer" );
-M_SRDPP_COMMAND_DECL( CastLong ); M_SRDPP_COMMAND_INIT( CastLong , "to-long" );
-M_SRDPP_COMMAND_DECL( CastBestInt ); M_SRDPP_COMMAND_INIT( CastBestInt , "to-best-integer" );
-M_SRDPP_COMMAND_DECL( CastReal ); M_SRDPP_COMMAND_INIT( CastReal , "to-real" );
-M_SRDPP_COMMAND_DECL( CastVar ); M_SRDPP_COMMAND_INIT( CastVar , "to-variable" );
-M_SRDPP_COMMAND_DECL( CastList ); M_SRDPP_COMMAND_INIT( CastList , "to-list" );
-M_SRDPP_COMMAND_DECL( ClearScope ); M_SRDPP_COMMAND_INIT_N( ClearScope , "clear-scope" , 0 );
-M_SRDPP_COMMAND_DECL( Cmp ); M_SRDPP_COMMAND_INIT( Cmp , "cmp" );
-M_SRDPP_COMMAND_DECL( CmpEq ); M_SRDPP_COMMAND_INIT( CmpEq , "eq" );
-M_SRDPP_COMMAND_DECL( CmpNe ); M_SRDPP_COMMAND_INIT( CmpNe , "ne" );
-M_SRDPP_COMMAND_DECL( CmpLt ); M_SRDPP_COMMAND_INIT( CmpLt , "lt" );
-M_SRDPP_COMMAND_DECL( CmpGt ); M_SRDPP_COMMAND_INIT( CmpGt , "gt" );
-M_SRDPP_COMMAND_DECL( CmpLe ); M_SRDPP_COMMAND_INIT( CmpLe , "le" );
-M_SRDPP_COMMAND_DECL( CmpGe ); M_SRDPP_COMMAND_INIT( CmpGe , "ge" );
-M_SRDPP_COMMAND_DECL( Concat ); M_SRDPP_COMMAND_INIT( Concat , "concat" );
-
-M_SRDPP_COMMAND_DECL( Div ); M_SRDPP_COMMAND_INIT( Div , "div" );
-
-M_SRDPP_COMMAND_DECL( EndsWith ); M_SRDPP_COMMAND_INIT( EndsWith , "ends-with" );
-M_SRDPP_COMMAND_DECL( Eval ); M_SRDPP_COMMAND_INIT( Eval , "eval" );
-M_SRDPP_COMMAND_DECL( Error ); M_SRDPP_COMMAND_INIT( Error , "error" );
-
-M_SRDPP_COMMAND_DECL( FromSource ); M_SRDPP_COMMAND_INIT( FromSource , "from-source" );
-M_SRDPP_COMMAND_DECL( FromSRB ); M_SRDPP_COMMAND_INIT( FromSRB , "from-srb" );
-
-M_SRDPP_COMMAND_DECL( Get ); M_SRDPP_COMMAND_INIT( Get , "get" );
-
-M_SRDPP_COMMAND_DECL( If ); M_SRDPP_COMMAND_INIT_N( If , "if" , 1 );
-M_SRDPP_COMMAND_DECL( Ignore ); M_SRDPP_COMMAND_INIT_N( Ignore , "ignore" , 0 );
-M_SRDPP_COMMAND_DECL( IsBlessed ); M_SRDPP_COMMAND_INIT( IsBlessed , "is-blessed" );
-M_SRDPP_COMMAND_DECL( IsMacro ); M_SRDPP_COMMAND_INIT( IsMacro , "is-macro" );
-M_SRDPP_COMMAND_DECL( IsSet ); M_SRDPP_COMMAND_INIT( IsSet , "is-set" );
-
-M_SRDPP_COMMAND_DECL( Length ); M_SRDPP_COMMAND_INIT( Length , "length" );
-M_SRDPP_COMMAND_DECL( ListMacros ); M_SRDPP_COMMAND_INIT_N( ListMacros , "ls-macros" , 0 );
-M_SRDPP_COMMAND_DECL( ListVariables ); M_SRDPP_COMMAND_INIT_N( ListVariables , "ls-variables" , 0 );
-
-M_SRDPP_COMMAND_DECL( Mod ); M_SRDPP_COMMAND_INIT( Mod , "mod" );
-M_SRDPP_COMMAND_DECL( Mul ); M_SRDPP_COMMAND_INIT( Mul , "mul" );
-
-M_SRDPP_COMMAND_DECL( Neg ); M_SRDPP_COMMAND_INIT( Neg , "neg" );
-M_SRDPP_COMMAND_DECL( Not ); M_SRDPP_COMMAND_INIT( Not , "not" );
-
-M_SRDPP_COMMAND_DECL( Or ); M_SRDPP_COMMAND_INIT( Or , "or" );
-M_SRDPP_COMMAND_DECL( Output ); M_SRDPP_COMMAND_INIT( Output , "output" );
-
-M_SRDPP_COMMAND_DECL( Raw ); M_SRDPP_COMMAND_INIT_N( Raw , "raw" , 0 );
-M_SRDPP_COMMAND_DECL( Rethrow ); M_SRDPP_COMMAND_INIT( Rethrow , "rethrow" );
-
-M_SRDPP_COMMAND_DECL( Scope ); M_SRDPP_COMMAND_INIT_N( Scope , "scope" , 0 );
-M_SRDPP_COMMAND_DECL( Set ); M_SRDPP_COMMAND_INIT( Set , "set" );
-M_SRDPP_COMMAND_DECL( SetMacro ); M_SRDPP_COMMAND_INIT( SetMacro , "set-macro" );
-M_SRDPP_COMMAND_DECL( StartsWith ); M_SRDPP_COMMAND_INIT( StartsWith , "starts-with" );
-M_SRDPP_COMMAND_DECL( StrFind ); M_SRDPP_COMMAND_INIT( StrFind , "str-find" );
-M_SRDPP_COMMAND_DECL( StrSplit ); M_SRDPP_COMMAND_INIT( StrSplit , "str-split" );
-M_SRDPP_COMMAND_DECL( Sub ); M_SRDPP_COMMAND_INIT( Sub , "sub" );
-M_SRDPP_COMMAND_DECL( Substr ); M_SRDPP_COMMAND_INIT( Substr , "substr" );
-
-M_SRDPP_COMMAND_DECL( ToSource ); M_SRDPP_COMMAND_INIT( ToSource , "to-source" );
-M_SRDPP_COMMAND_DECL( Try ); M_SRDPP_COMMAND_INIT_N( Try , "try" , 0 );
-M_SRDPP_COMMAND_DECL( TypeOf ); M_SRDPP_COMMAND_INIT( TypeOf , "type-of" );
-
-M_SRDPP_COMMAND_DECL( Unset ); M_SRDPP_COMMAND_INIT( Unset , "unset" );
-M_SRDPP_COMMAND_DECL( UnsetMacro ); M_SRDPP_COMMAND_INIT( UnsetMacro , "unset-macro" );
-M_SRDPP_COMMAND_DECL( Unwrap ); M_SRDPP_COMMAND_INIT( Unwrap , "unwrap" );
-
-M_SRDPP_COMMAND_DECL_OBJ( VFSList , T_VFS& , vfs_ );
-M_SRDPP_COMMAND_INIT_OBJ( VFSList , "vfs-list" , T_VFS& , vfs_ );
-M_SRDPP_COMMAND_DECL_OBJ( VFSLoad , T_VFS& , vfs_ );
-M_SRDPP_COMMAND_INIT_OBJ( VFSLoad , "vfs-load" , T_VFS& , vfs_ );
-M_SRDPP_COMMAND_DECL_OBJ( VFSType , T_VFS& , vfs_ );
-M_SRDPP_COMMAND_INIT_OBJ( VFSType , "vfs-type" , T_VFS& , vfs_ );
-
-M_SRDPP_COMMAND_DECL( Xor ); M_SRDPP_COMMAND_INIT( Xor , "xor" );
-
-
-} // namespace lw
-#endif // _H_LW_LIB_SRDPPCOMMANDS
diff --git a/include/ebcl/SRDParser.hh b/include/ebcl/SRDParser.hh
index 6a3d037..4cbd08c 100644
--- a/include/ebcl/SRDParser.hh
+++ b/include/ebcl/SRDParser.hh
@@ -1,11 +1,12 @@
 /******************************************************************************/
-/* SRD PARSER AND PREPROCESSOR ************************************************/
+/* SRD PARSER *****************************************************************/
 /******************************************************************************/
 
-#pragma once
-#include <lw/lib/SRDIO.hh>
-#include <lw/lib/SRDParserConfig.hh>
-namespace lw {
+#ifndef _H_EBCL_SRDPARSER
+#define _H_EBCL_SRDPARSER
+#include <ebcl/SRDIO.hh>
+#include <ebcl/SRDParserConfig.hh>
+namespace ebcl {
 
 
 // T_SRDParserData - Run-time data passed to the handlers when parsing
@@ -88,3 +89,4 @@ inline T const& T_SRDParser::getData( ) const
 
 
 } // namespace
+#endif // _H_EBCL_SRDPARSER
diff --git a/include/ebcl/SRDParserConfig.hh b/include/ebcl/SRDParserConfig.hh
index 3e55026..43c3f1b 100644
--- a/include/ebcl/SRDParserConfig.hh
+++ b/include/ebcl/SRDParserConfig.hh
@@ -2,11 +2,11 @@
 /* SRD - PARSER CONFIGURATION *************************************************/
 /******************************************************************************/
 
-#ifndef _H_LW_LIB_SRDPARSERCONFIG
-#define _H_LW_LIB_SRDPARSERCONFIG
-#include <lw/lib/SRDDefinitions.hh>
-#include <lw/lib/Types.hh>
-namespace lw {
+#ifndef _H_EBCL_SRDPARSERCONFIG
+#define _H_EBCL_SRDPARSERCONFIG
+#include <ebcl/SRDDefinitions.hh>
+#include <ebcl/Types.hh>
+namespace ebcl {
 
 
 /*= PROCESSED PARSER CONFIGURATION ===========================================*/
@@ -95,5 +95,5 @@ class X_SRDParserConfig : public std::exception
 
 
 } // namespace
-#include <lw/lib/inline/SRDParserConfig.hh>
-#endif // _H_LW_LIB_SRDPARSERCONFIG
+#include <ebcl/inline/SRDParserConfig.hh>
+#endif // _H_EBCL_SRDPARSERCONFIG
diff --git a/include/ebcl/SRDText.hh b/include/ebcl/SRDText.hh
index ac22677..2b307f8 100644
--- a/include/ebcl/SRDText.hh
+++ b/include/ebcl/SRDText.hh
@@ -2,10 +2,10 @@
 /* SRD - TEXT STORAGE *********************************************************/
 /******************************************************************************/
 
-#ifndef _H_LW_LIB_SRDTEXT
-#define _H_LW_LIB_SRDTEXT
-#include <lw/lib/SRDIO.hh>
-namespace lw {
+#ifndef _H_EBCL_SRDTEXT
+#define _H_EBCL_SRDTEXT
+#include <ebcl/SRDIO.hh>
+namespace ebcl {
 
 
 /*= READER ===================================================================*/
@@ -89,5 +89,5 @@ void SRDWriteAsText( A_OutputStream& output , T_SRDList const& data );
 
 
 } // namespace
-#include <lw/lib/inline/SRDText.hh>
-#endif // _H_LW_LIB_SRDTEXT
+#include <ebcl/inline/SRDText.hh>
+#endif // _H_EBCL_SRDTEXT
diff --git a/include/ebcl/Version.hh b/include/ebcl/Version.hh
deleted file mode 100644
index 9f19f80..0000000
--- a/include/ebcl/Version.hh
+++ /dev/null
@@ -1,19 +0,0 @@
-/******************************************************************************/
-/* VERSION NUMBERS ************************************************************/
-/******************************************************************************/
-
-#ifndef _H_LW_LIB_VERSION
-#define _H_LW_LIB_VERSION
-#include <lw/lib/Externals.hh>
-namespace lw {
-
-
-static constexpr inline uint32_t LibVersion( )
-	{ return 0; }
-
-static constexpr inline uint32_t LibRevision( )
-	{ return 0; }
-
-
-}
-#endif // _H_LW_LIB_VERSION
diff --git a/include/ebcl/Version.hh.in b/include/ebcl/Version.hh.in
deleted file mode 100644
index 06b6645..0000000
--- a/include/ebcl/Version.hh.in
+++ /dev/null
@@ -1,19 +0,0 @@
-/******************************************************************************/
-/* VERSION NUMBERS ************************************************************/
-/******************************************************************************/
-
-#ifndef _H_LW_LIB_VERSION
-#define _H_LW_LIB_VERSION
-#include <lw/lib/Externals.hh>
-namespace lw {
-
-
-static constexpr inline uint32_t LibVersion( )
-	{ return __VERSION__; }
-
-static constexpr inline uint32_t LibRevision( )
-	{ return __REVISION__; }
-
-
-}
-#endif // _H_LW_LIB_VERSION
diff --git a/include/ebcl/inline/DynLib.hh b/include/ebcl/inline/DynLib.hh
index 81d61da..2e7baca 100644
--- a/include/ebcl/inline/DynLib.hh
+++ b/include/ebcl/inline/DynLib.hh
@@ -2,11 +2,11 @@
 /* DYNAMIC LIBRARIES - INLINE CODE ********************************************/
 /******************************************************************************/
 
-#ifndef _H_LW_LIB_INLINE_DYNLIB
-#define _H_LW_LIB_INLINE_DYNLIB
+#ifndef _H_EBCL_INLINE_DYNLIB
+#define _H_EBCL_INLINE_DYNLIB
 
-#include <lw/lib/DynLib.hh>
-namespace lw {
+#include <ebcl/DynLib.hh>
+namespace ebcl {
 
 
 /*= T_DynLib =================================================================*/
@@ -27,4 +27,4 @@ inline std::function< T > T_DynLib::getFunction(
 
 
 }
-#endif // _H_LW_LIB_INLINE_DYNLIB
+#endif // _H_EBCL_INLINE_DYNLIB
diff --git a/include/ebcl/inline/Messages.hh b/include/ebcl/inline/Messages.hh
deleted file mode 100644
index a77a05f..0000000
--- a/include/ebcl/inline/Messages.hh
+++ /dev/null
@@ -1,154 +0,0 @@
-/******************************************************************************/
-/* UI<=>GAME MESSAGES - INLINE CODE *******************************************/
-/******************************************************************************/
-
-#ifndef _H_LW_LIB_INLINE_MESSAGES
-#define _H_LW_LIB_INLINE_MESSAGES
-#include <lw/lib/GameLoop.hh>
-namespace lw {
-
-
-/*= T_ProgressInfoPart =======================================================*/
-
-inline T_ProgressInfoPart::T_ProgressInfoPart( T_String text ,
-		uint32_t progress , uint32_t total ) noexcept
-	: text_( std::move( text ) ) , progress_( progress ) , total_( total )
-{ }
-
-inline T_ProgressInfoPart::T_ProgressInfoPart( T_ProgressInfoPart&& other ) noexcept
-	: text_( std::move( other.text_ ) ) , progress_( other.progress_ ) ,
-		total_( other.total_ )
-{ }
-
-inline T_ProgressInfoPart::T_ProgressInfoPart( T_ProgressInfoPart const& other )
-	: text_( other.text_ ) , progress_( other.progress_ ) , total_( other.total_ )
-{ }
-
-/*----------------------------------------------------------------------------*/
-
-inline T_String const& T_ProgressInfoPart::text( ) const noexcept
-{
-	return text_;
-}
-
-inline uint32_t T_ProgressInfoPart::progress( ) const noexcept
-{
-	return progress_;
-}
-
-inline uint32_t T_ProgressInfoPart::total( ) const noexcept
-{
-	return total_;
-}
-
-
-/*= T_ProgressInfo ===========================================================*/
-
-inline T_ProgressInfo::T_ProgressInfo( T_String text , uint32_t progress , uint32_t total ) noexcept
-	: main_( std::move( text ) , progress , total ) , sub_( )
-{ }
-
-inline T_ProgressInfo::T_ProgressInfo( T_ProgressInfoPart main ) noexcept
-	: main_( std::move( main ) )
-{ }
-
-inline T_ProgressInfo::T_ProgressInfo(
-		T_ProgressInfoPart main ,
-		T_ProgressInfoPart sub ) noexcept
-	: main_( std::move( main ) ) ,
-		sub_( std::move( sub ) )
-{ }
-
-inline T_ProgressInfo::T_ProgressInfo( T_ProgressInfoPart main ,
-		T_String sText , uint32_t sProgress , uint32_t sTotal ) noexcept
-	: main_( std::move( main ) ) ,
-		sub_( T_ProgressInfoPart{ std::move( sText ) , sProgress , sTotal } )
-{ }
-
-inline T_ProgressInfo::T_ProgressInfo( T_String text , uint32_t progress , uint32_t total ,
-		T_String sText , uint32_t sProgress , uint32_t sTotal ) noexcept
-	: main_( std::move( text ) , progress , total ) ,
-		sub_( T_ProgressInfoPart{ std::move( sText ) , sProgress , sTotal } )
-{ }
-
-inline T_ProgressInfo::T_ProgressInfo( T_ProgressInfo&& other ) noexcept
-	: main_( std::move( other.main_ ) ) , sub_( std::move( other.sub_ ) )
-{ }
-
-/*----------------------------------------------------------------------------*/
-
-inline T_ProgressInfoPart const& T_ProgressInfo::main( ) const noexcept
-{
-	return main_;
-}
-
-inline bool T_ProgressInfo::hasSub( ) const noexcept
-{
-	return sub_.present( );
-}
-
-inline T_ProgressInfoPart const& T_ProgressInfo::sub( ) const
-{
-	return (T_ProgressInfoPart const&) sub_;
-}
-
-
-/*= T_GameMessage ============================================================*/
-
-template< E_MessageDirection D , typename MT , typename MD >
-inline constexpr T_GameMessage< D , MT , MD >::T_GameMessage( ) noexcept
-	: type_( ) , data_( )
-{ }
-
-template< E_MessageDirection D , typename MT , typename MD >
-inline constexpr T_GameMessage< D , MT , MD >::T_GameMessage(
-		T_Type type ) noexcept
-	: type_( type ) , data_( )
-{ }
-
-template< E_MessageDirection D , typename MT , typename MD >
-inline T_GameMessage< D , MT , MD >::T_GameMessage(
-		T_Type type ,
-		T_Data data ) noexcept
-	: type_( type ) , data_( data )
-{ }
-
-template< E_MessageDirection D , typename MT , typename MD >
-inline T_GameMessage< D , MT , MD >::T_GameMessage(
-		T_Self_&& other ) noexcept
-	: type_( other.type_ ) , data_( std::move( other.data_ ) )
-{ }
-
-template< E_MessageDirection D , typename MT , typename MD >
-inline T_GameMessage< D >& T_GameMessage< D , MT , MD >::operator =(
-		T_Self_&& other ) noexcept
-{
-	type_ = other.type_;
-	data_ = std::move( other.data_ );
-	return *this;
-}
-
-/*----------------------------------------------------------------------------*/
-
-template< E_MessageDirection D , typename MT , typename MD >
-inline constexpr bool T_GameMessage< D , MT , MD >::hasMessage( ) const noexcept
-{
-	return type_.present( );
-}
-
-template< E_MessageDirection D , typename MT , typename MD >
-inline constexpr MT T_GameMessage< D , MT , MD >::type( ) const noexcept
-{
-	return type_;
-}
-
-template< E_MessageDirection D , typename MT , typename MD >
-template< typename T >
-constexpr T const& T_GameMessage< D , MT , MD >::data( ) const
-{
-	return (T const&)( (MD const&) data_ );
-}
-
-
-} // namespace lw
-#endif // _H_LW_LIB_INLINE_MESSAGES
diff --git a/include/ebcl/inline/Mods.hh b/include/ebcl/inline/Mods.hh
deleted file mode 100644
index 2e16087..0000000
--- a/include/ebcl/inline/Mods.hh
+++ /dev/null
@@ -1,59 +0,0 @@
-/******************************************************************************/
-/* MODDING SYSTEM - INLINE CODE ***********************************************/
-/******************************************************************************/
-
-#ifndef _H_LW_LIB_INLINE_MODS
-#define _H_LW_LIB_INLINE_MODS
-#include <lw/lib/Mods.hh>
-namespace lw {
-
-
-/*= T_ModIdentifier ==========================================================*/
-
-inline bool T_ModIdentifier::operator ==(
-		T_ModIdentifier const& other ) const noexcept
-{
-	return &other == this || ( name == other.name
-			&& version == other.version );
-}
-
-inline bool T_ModIdentifier::operator !=(
-		T_ModIdentifier const& other ) const noexcept
-{
-	return &other != this && ( name != other.name
-			|| version != other.version );
-}
-
-inline M_DEFINE_HASH( T_ModIdentifier )
-{
-	return ComputeHash( item.name ) * 47 + item.version;
-}
-
-inline M_DEFINE_COMPARATOR( T_ModIdentifier )
-{
-	return a.compare( b );
-}
-
-inline M_LSHIFT_OP( T_StringBuilder , T_ModIdentifier const& )
-{
-	obj << value.name << ':' << value.version;
-	return obj;
-}
-
-
-/*= T_ModInfo ================================================================*/
-
-inline bool T_ModInfo::isUserInterface( ) const noexcept
-{
-	return type == E_ModType::UI;
-}
-
-inline M_LSHIFT_OP( T_StringBuilder , T_ModInfo const& )
-{
-	obj << value.identifier << '.' << value.revision;
-	return obj;
-}
-
-
-}
-#endif // _H_LW_LIB_INLINE_MODS
diff --git a/include/ebcl/inline/SRDBinary.hh b/include/ebcl/inline/SRDBinary.hh
index cf25bad..a5e218f 100644
--- a/include/ebcl/inline/SRDBinary.hh
+++ b/include/ebcl/inline/SRDBinary.hh
@@ -2,10 +2,10 @@
 /* SRD - BINARY STORAGE - INLINE CODE *****************************************/
 /******************************************************************************/
 
-#ifndef _H_LW_LIB_INLINE_SRDBINARY
-#define _H_LW_LIB_INLINE_SRDBINARY
-#include <lw/lib/SRDBinary.hh>
-namespace lw {
+#ifndef _H_EBCL_INLINE_SRDBINARY
+#define _H_EBCL_INLINE_SRDBINARY
+#include <ebcl/SRDBinary.hh>
+namespace ebcl {
 
 
 inline void SRDBinaryWriteTo( A_OutputStream& output , T_SRDList const& data )
@@ -30,4 +30,4 @@ inline T_SRDList SRDBinaryReadFrom( T_String const& name , A_InputStream& input
 
 
 } // namespace
-#endif // _H_LW_LIB_INLINE_SRDBINARY
+#endif // _H_EBCL_INLINE_SRDBINARY
diff --git a/include/ebcl/inline/SRDData.hh b/include/ebcl/inline/SRDData.hh
index 6bf0150..b5eadab 100644
--- a/include/ebcl/inline/SRDData.hh
+++ b/include/ebcl/inline/SRDData.hh
@@ -2,10 +2,10 @@
 /* SRD - DATA - INLINE CODE ***************************************************/
 /******************************************************************************/
 
-#ifndef _H_LW_LIB_INLINE_SRDDATA
-#define _H_LW_LIB_INLINE_SRDDATA
-#include <lw/lib/SRDData.hh>
-namespace lw {
+#ifndef _H_EBCL_INLINE_SRDDATA
+#define _H_EBCL_INLINE_SRDDATA
+#include <ebcl/SRDData.hh>
+namespace ebcl {
 
 
 /*= T_SRDLocationChaining ====================================================*/
@@ -435,4 +435,4 @@ inline T_SRDLocation const& T_SRDToken::location( ) const noexcept
 
 
 } // namespace
-#endif // _H_LW_LIB_INLINE_SRDDATA
+#endif // _H_EBCL_INLINE_SRDDATA
diff --git a/include/ebcl/inline/SRDDefinitions.hh b/include/ebcl/inline/SRDDefinitions.hh
index 0c94d56..e8dc3d9 100644
--- a/include/ebcl/inline/SRDDefinitions.hh
+++ b/include/ebcl/inline/SRDDefinitions.hh
@@ -2,10 +2,10 @@
 /* SRD - PARSER DEFINITIONS - INLINE CODE *************************************/
 /******************************************************************************/
 
-#ifndef _H_LW_LIB_INLINE_SRDDEFINITIONS
-#define _H_LW_LIB_INLINE_SRDDEFINITIONS
-#include <lw/lib/SRDDefinitions.hh>
-namespace lw {
+#ifndef _H_EBCL_INLINE_SRDDEFINITIONS
+#define _H_EBCL_INLINE_SRDDEFINITIONS
+#include <ebcl/SRDDefinitions.hh>
+namespace ebcl {
 
 
 /*= T_SRDEnum ================================================================*/
@@ -522,4 +522,4 @@ inline T_SRDInputRule::T_SetContextExecutor OnExit( F_SRDHandler f )
 
 
 } // namespace
-#endif // _H_LW_LIB_INLINE_SRDDEFINITIONS
+#endif // _H_EBCL_INLINE_SRDDEFINITIONS
diff --git a/include/ebcl/inline/SRDIO.hh b/include/ebcl/inline/SRDIO.hh
index 55a1c69..933317a 100644
--- a/include/ebcl/inline/SRDIO.hh
+++ b/include/ebcl/inline/SRDIO.hh
@@ -2,10 +2,10 @@
 /* SRD - INPUT AND OUTPUT - INLINE CODE ***************************************/
 /******************************************************************************/
 
-#ifndef _H_LW_LIB_INLINE_SRDIO
-#define _H_LW_LIB_INLINE_SRDIO
-#include <lw/lib/SRDIO.hh>
-namespace lw {
+#ifndef _H_EBCL_INLINE_SRDIO
+#define _H_EBCL_INLINE_SRDIO
+#include <ebcl/SRDIO.hh>
+namespace ebcl {
 
 /*= A_SRDWriter ==============================================================*/
 
@@ -77,4 +77,4 @@ inline bool T_SRDMemoryTarget::complete( ) const
 } // namespace
 
 
-#endif // _H_LW_LIB_INLINE_SRDIO
+#endif // _H_EBCL_INLINE_SRDIO
diff --git a/include/ebcl/inline/SRDParserConfig.hh b/include/ebcl/inline/SRDParserConfig.hh
index 58710ce..da11d5c 100644
--- a/include/ebcl/inline/SRDParserConfig.hh
+++ b/include/ebcl/inline/SRDParserConfig.hh
@@ -2,10 +2,10 @@
 /* SRD - PARSER CONFIGURATION - INLINE CODE ***********************************/
 /******************************************************************************/
 
-#ifndef _H_LW_LIB_INLINE_SRDPARSERCONFIG
-#define _H_LW_LIB_INLINE_SRDPARSERCONFIG
-#include <lw/lib/SRDParserConfig.hh>
-namespace lw {
+#ifndef _H_EBCL_INLINE_SRDPARSERCONFIG
+#define _H_EBCL_INLINE_SRDPARSERCONFIG
+#include <ebcl/SRDParserConfig.hh>
+namespace ebcl {
 
 
 /*= T_SRDTransition ==========================================================*/
@@ -30,4 +30,4 @@ inline T_Optional< uint32_t > T_SRDParserConfig::enumValue(
 
 
 } // namespace
-#endif // _H_LW_LIB_INLINE_SRDPARSERCONFIG
+#endif // _H_EBCL_INLINE_SRDPARSERCONFIG
diff --git a/include/ebcl/inline/SRDText.hh b/include/ebcl/inline/SRDText.hh
index 2ba0bfb..fb5b85d 100644
--- a/include/ebcl/inline/SRDText.hh
+++ b/include/ebcl/inline/SRDText.hh
@@ -2,10 +2,10 @@
 /* SRD - TEXT STORAGE - INLINE CODE *******************************************/
 /******************************************************************************/
 
-#ifndef _H_LW_LIB_INLINE_SRDTEXT
-#define _H_LW_LIB_INLINE_SRDTEXT
-#include <lw/lib/SRDText.hh>
-namespace lw {
+#ifndef _H_EBCL_INLINE_SRDTEXT
+#define _H_EBCL_INLINE_SRDTEXT
+#include <ebcl/SRDText.hh>
+namespace ebcl {
 
 
 inline void SRDWriteAsText( A_OutputStream& output , T_SRDList const& data )
@@ -22,4 +22,4 @@ inline T_SRDTextReader::T_SRDTextReader( A_SRDReaderTarget& target )
 
 
 } // namespace
-#endif // _H_LW_LIB_INLINE_SRDTEXT
+#endif // _H_EBCL_INLINE_SRDTEXT
diff --git a/src/Console-Unix.hh b/src/Console-Unix.hh
deleted file mode 100644
index db05496..0000000
--- a/src/Console-Unix.hh
+++ /dev/null
@@ -1,667 +0,0 @@
-/******************************************************************************/
-/* CONSOLE SUPPORT - UNIX IMPLEMENTATION **************************************/
-/******************************************************************************/
-
-#include <lw/lib/Console.hh>
-#include <unistd.h>
-#include <termios.h>
-#include <pty.h>
-
-
-namespace {
-
-// List of unsupported terminals
-char const* const BadTerminals_[] = {
-	"dumb" , "cons25" , "emacs" ,
-	nullptr
-};
-
-// Extended input sequences
-char const* const InputSequences_[] = {
-	"A" ,		// Up
-	"B" ,		// Down
-	"C" ,		// Right
-	"D" ,		// Left
-	"H" ,		// Home
-	"F" ,		// End
-	"3~" ,		// Delete
-	"1;5C" ,	// C-Right
-	"1;5D" ,	// C-Left
-	"15~" ,		// F5
-	"17~" ,		// F6
-	"18~" ,		// F7
-	"19~" ,		// F8
-	"20~" ,		// F9
-	"21~" ,		// F10
-	"23~" ,		// F11
-	"24~" ,		// F12
-	"1;2P" ,	// S-F1
-	"1;2Q" ,	// S-F2
-	"1;2R" ,	// S-F3
-	"1;2S" ,	// S-F4
-	"15;2~" ,	// S-F5
-	"17;2~" ,	// S-F6
-	"18;2~" ,	// S-F7
-	"19;2~" ,	// S-F8
-	"20;2~" ,	// S-F9
-	"21;2~" ,	// S-F10
-	"23;2~" ,	// S-F11
-	"24;2~" ,	// S-F12
-	"1;5P" ,	// C-F1
-	"1;5Q" ,	// C-F2
-	"1;5R" ,	// C-F3
-	"1;5S" ,	// C-F4
-	"15;5~" ,	// C-F5
-	"17;5~" ,	// C-F6
-	"18;5~" ,	// C-F7
-	"19;5~" ,	// C-F8
-	"20;5~" ,	// C-F9
-	"21;5~" ,	// C-F10
-	"23;5~" ,	// C-F11
-	"24;5~" ,	// C-F12
-	"1;6P" ,	// C-S-F1
-	"1;6Q" ,	// C-S-F2
-	"1;6R" ,	// C-S-F3
-	"1;6S" ,	// C-S-F4
-	"15;6~" ,	// C-S-F5
-	"17;6~" ,	// C-S-F6
-	"18;6~" ,	// C-S-F7
-	"19;6~" ,	// C-S-F8
-	"20;6~" ,	// C-S-F9
-	"21;6~" ,	// C-S-F10
-	"23;6~" ,	// C-S-F11
-	"24;6~" ,	// C-S-F12
-	nullptr
-};
-const lw::E_ConsoleKey InputKeys_[] = {
-	lw::E_ConsoleKey::UP ,
-	lw::E_ConsoleKey::DOWN ,
-	lw::E_ConsoleKey::RIGHT ,
-	lw::E_ConsoleKey::LEFT ,
-	lw::E_ConsoleKey::HOME ,
-	lw::E_ConsoleKey::END ,
-	lw::E_ConsoleKey::DELETE ,
-	lw::E_ConsoleKey::WNEXT ,
-	lw::E_ConsoleKey::WPREV ,
-	lw::E_ConsoleKey::F5 ,
-	lw::E_ConsoleKey::F6 ,
-	lw::E_ConsoleKey::F7 ,
-	lw::E_ConsoleKey::F8 ,
-	lw::E_ConsoleKey::F9 ,
-	lw::E_ConsoleKey::F10 ,
-	lw::E_ConsoleKey::F11 ,
-	lw::E_ConsoleKey::F12 ,
-	lw::E_ConsoleKey::S_F1 ,
-	lw::E_ConsoleKey::S_F2 ,
-	lw::E_ConsoleKey::S_F3 ,
-	lw::E_ConsoleKey::S_F4 ,
-	lw::E_ConsoleKey::S_F5 ,
-	lw::E_ConsoleKey::S_F6 ,
-	lw::E_ConsoleKey::S_F7 ,
-	lw::E_ConsoleKey::S_F8 ,
-	lw::E_ConsoleKey::S_F9 ,
-	lw::E_ConsoleKey::S_F10 ,
-	lw::E_ConsoleKey::S_F11 ,
-	lw::E_ConsoleKey::S_F12 ,
-	lw::E_ConsoleKey::C_F1 ,
-	lw::E_ConsoleKey::C_F2 ,
-	lw::E_ConsoleKey::C_F3 ,
-	lw::E_ConsoleKey::C_F4 ,
-	lw::E_ConsoleKey::C_F5 ,
-	lw::E_ConsoleKey::C_F6 ,
-	lw::E_ConsoleKey::C_F7 ,
-	lw::E_ConsoleKey::C_F8 ,
-	lw::E_ConsoleKey::C_F9 ,
-	lw::E_ConsoleKey::C_F10 ,
-	lw::E_ConsoleKey::C_F11 ,
-	lw::E_ConsoleKey::C_F12 ,
-	lw::E_ConsoleKey::CS_F1 ,
-	lw::E_ConsoleKey::CS_F2 ,
-	lw::E_ConsoleKey::CS_F3 ,
-	lw::E_ConsoleKey::CS_F4 ,
-	lw::E_ConsoleKey::CS_F5 ,
-	lw::E_ConsoleKey::CS_F6 ,
-	lw::E_ConsoleKey::CS_F7 ,
-	lw::E_ConsoleKey::CS_F8 ,
-	lw::E_ConsoleKey::CS_F9 ,
-	lw::E_ConsoleKey::CS_F10 ,
-	lw::E_ConsoleKey::CS_F11 ,
-	lw::E_ConsoleKey::CS_F12 ,
-};
-
-// Various control codes
-const char CCGetTermSizeStart_[] = "\033[s\033[99999C\033[99999A";
-const char CCGetTermSizeEnd_[] = "\033[u";
-const char CCGetCursorPos_[] = "\033[6n";
-const char CCClearScreen_[] = "\033[H\033[2J";
-const char CCNextLine_[] = "\n\033[99999D\033[K";
-const char CCClearLine_[] = "\033[99999D\033[K";
-const char CCClearLineUp_[] = "\033[99999D\033[K\033[A";
-
-// Are we running in an unsupported terminal?
-inline bool IsBadTerminal_( )
-{
-	char const* const t( getenv( "TERM" ) );
-	if ( t == nullptr ) {
-		return true;
-	}
-	for ( auto i = 0 ; BadTerminals_[ i ] ; i ++ ) {
-		if ( !strcasecmp( t , BadTerminals_[ i ] ) ) {
-			return true;
-		}
-	}
-	return false;
-}
-
-/*----------------------------------------------------------------------------*/
-
-class T_ConsoleImpl_
-{
-    private:
-	bool ok_;
-	termios initialTerm_;
-	lw::E_ConsoleInteractionMode mode_;
-	bool failed_;
-	bool interrupted_;
-
-	int sizePolling_;
-	uint32_t rows_ , cols_;
-
-	lw::T_StringBuilder styleSeq_;
-	uint8_t keyBuf_[ 16 ];
-	uint32_t kbPos_;
-
-    public:
-	T_ConsoleImpl_( );
-	~T_ConsoleImpl_( );
-
-	bool initConsole( );
-	void shutdownConsole( );
-	bool failed( ) const;
-
-	bool resized( uint32_t& rows , uint32_t& cols ) const;
-	bool getTerminalSize( uint32_t& rows , uint32_t& cols );
-	bool getCursorPosition( uint32_t& column , uint32_t& row );
-
-	bool readKey( lw::E_ConsoleKey& key , uint32_t& character );
-
-	bool clearScreen( );
-	void setTextStyle( uint8_t style , lw::T_TextColor color );
-	void printCharacter( lw::T_Character c );
-	void nextLine( );
-	void clearLine( );
-	void clearLines( uint32_t count );
-	void moveCursor( int32_t x , int32_t y );
-
-    private:
-	bool initTTY( );
-	bool checkInput( lw::E_ConsoleKey& key , uint32_t& character );
-
-	bool getTerminalSize( );
-	bool writeSequence( char const* sequence );
-	bool writeSequence( char const* sequence , uint32_t size );
-};
-
-/*----------------------------------------------------------------------------*/
-
-T_ConsoleImpl_::T_ConsoleImpl_( )
-{
-	// Buffer size:
-	// * "ESC[0m" always => 4
-	// * 2 per enabled style => 6
-	// * color: "38;2;" + 3 unsigned 8-bit numbers + 2 ";" separators => 16
-	// That would be 26, but let's go for 32 instead
-	styleSeq_.ensureCapacity( 32 );
-}
-
-T_ConsoleImpl_::~T_ConsoleImpl_( )
-{
-	shutdownConsole( );
-}
-
-bool T_ConsoleImpl_::initConsole( )
-{
-	failed_ = false;
-	kbPos_ = 0;
-	ok_ = isatty( STDIN_FILENO ) && !IsBadTerminal_( ) && initTTY( );
-	if ( ok_ && getTerminalSize( ) ) {
-		sizePolling_ = 0;
-	}
-	return ok_ && !failed_;
-}
-
-void T_ConsoleImpl_::shutdownConsole( )
-{
-	if ( ok_ ) {
-		setTextStyle( 0 , lw::E_TextColor::WHITE );
-		tcsetattr( STDIN_FILENO , TCSAFLUSH , &initialTerm_ );
-	}
-}
-
-inline bool T_ConsoleImpl_::failed( ) const
-{
-	return failed_;
-}
-
-bool T_ConsoleImpl_::resized( uint32_t& rows , uint32_t& cols ) const
-{
-	if ( cols_ != cols || rows_ != rows ) {
-		cols = cols_;
-		rows = rows_;
-		return true;
-	}
-	return false;
-}
-
-bool T_ConsoleImpl_::getTerminalSize( uint32_t& rows , uint32_t& cols )
-{
-	if ( !getTerminalSize( ) ) {
-		return false;
-	}
-	rows = rows_;
-	cols = cols_;
-	return true;
-}
-
-/*----------------------------------------------------------------------------*/
-
-bool T_ConsoleImpl_::readKey( lw::E_ConsoleKey& key , uint32_t& character )
-{
-	if ( failed_ ) {
-		return false;
-	}
-
-	do {
-		assert( kbPos_ < sizeof( keyBuf_ ) );
-		const auto n( read( STDIN_FILENO , &keyBuf_[ kbPos_ ] , 1 ) );
-		if ( n != 1 ) {
-			failed_ = failed_ || ( n == -1 );
-			if ( n == 0 && kbPos_ == 0 ) {
-				sizePolling_ = ( sizePolling_ + 1 ) % 20;
-				if ( sizePolling_ == 0 ) {
-					getTerminalSize( );
-				}
-			}
-			return false;
-		}
-		kbPos_ ++;
-	} while ( !checkInput( key , character ) );
-	kbPos_ = 0;
-	return true;
-}
-
-bool T_ConsoleImpl_::checkInput( lw::E_ConsoleKey& key , uint32_t& character )
-{
-	assert( kbPos_ > 0 );
-
-	const uint8_t first( keyBuf_[ 0 ] );
-	if ( kbPos_ == 1 ) {
-		// Escape or UTF-8 input
-		if ( first == 0x1b || first > 0x7f ) {
-			return false;
-		}
-
-		switch ( first ) {
-		    case 0x01:	// Ctrl+A
-			key = lw::E_ConsoleKey::HOME;
-			return true;
-
-		    case 0x02:	// Ctrl+B
-			key = lw::E_ConsoleKey::LEFT;
-			return true;
-
-		    case 0x03:	// Ctrl+C
-			key = lw::E_ConsoleKey::INTERRUPT;
-			return true;
-
-		    case 0x04:	// Ctrl+D
-			key = lw::E_ConsoleKey::EXIT;
-			return true;
-
-		    case 0x05:	// Ctrl+E
-			key = lw::E_ConsoleKey::END;
-			return true;
-
-		    case 0x06:	// Ctrl+F
-			key = lw::E_ConsoleKey::RIGHT;
-			return true;
-
-		    case 0x08:	// Ctrl+H
-		    case 0x7f:
-			key = lw::E_ConsoleKey::BACKSPACE;
-			return true;
-
-		    case 0x09:	// Ctrl+I/Tab
-			key = lw::E_ConsoleKey::CHARACTER;
-			character = ' ';
-			return true;
-
-		    case 0x0b:	// Ctrl+K
-			key = lw::E_ConsoleKey::KILL_REST;
-			return true;
-
-		    case 0x0c:	// Ctrl+L
-			key = lw::E_ConsoleKey::CLEAR;
-			return true;
-
-		    case 0x0d:	// Ctrl+M/Enter
-			key = lw::E_ConsoleKey::ENTER;
-			return true;
-
-		    case 0x0e:	// Ctrl+N
-			key = lw::E_ConsoleKey::DOWN;
-			return true;
-
-		    case 0x10:	// Ctrl+P
-			key = lw::E_ConsoleKey::UP;
-			return true;
-
-		    case 0x15:	// Ctrl+U
-			key = lw::E_ConsoleKey::KILL_LINE;
-			return true;
-
-		    case 0x17:	// Ctrl+W
-			key = lw::E_ConsoleKey::KILL_WORD;
-			return true;
-
-		    case 0x19:	// Ctrl+Y
-			key = lw::E_ConsoleKey::PASTE;
-			return true;
-		}
-
-		// Skip other control characters
-		if ( first < 32 ) {
-			kbPos_ = 0;
-			return false;
-		}
-
-		key = lw::E_ConsoleKey::CHARACTER;
-		character = first;
-		return true;
-	}
-
-	// Check for UTF-8 input
-	if ( first != 0x1b ) {
-		uint32_t l( 0 );
-		if ( !lw::UTF8BufferInfo( (char const*) keyBuf_ , kbPos_ , l ) ) {
-			if ( kbPos_ > 4 ) {
-				kbPos_ = 0;
-			}
-			return false;
-		}
-		if ( l != 1 ) {
-			kbPos_ = 0;
-			return false;
-		} else {
-			key = lw::E_ConsoleKey::CHARACTER;
-			character = lw::UTF8GetCodepoint( (char const*) keyBuf_ );
-			return true;
-		}
-	}
-
-	// Escape sequences
-	const uint8_t second( keyBuf_[ 1 ] );
-	if ( kbPos_ == 2 ) {
-		switch ( second ) {
-		    case 0x7f:
-			key = lw::E_ConsoleKey::KILL_WORD;
-			return true;
-
-		    case 'f':
-		    case 'F':
-			key = lw::E_ConsoleKey::WNEXT;
-			return true;
-
-		    case 'b':
-		    case 'B':
-			key = lw::E_ConsoleKey::WPREV;
-			return true;
-
-		    default:
-			kbPos_ = 0;
-		    case 'O':
-		    case '[':
-			return false;
-		}
-	}
-
-	// ESC-O-x sequences
-	if ( second == 'O' ) {
-		switch ( keyBuf_[ 2 ] ) {
-		    case 'F':
-			key = lw::E_ConsoleKey::END;
-			return true;
-		    case 'H':
-			key = lw::E_ConsoleKey::HOME;
-			return true;
-		    case 'P':
-			key = lw::E_ConsoleKey::F1;
-			return true;
-		    case 'Q':
-			key = lw::E_ConsoleKey::F2;
-			return true;
-		    case 'R':
-			key = lw::E_ConsoleKey::F3;
-			return true;
-		    case 'S':
-			key = lw::E_ConsoleKey::F4;
-			return true;
-		}
-		kbPos_ = 0;
-		return false;
-	}
-
-	// Extended sequences - ESC-[, ends with ~ or uppercase letter
-	const uint8_t last( keyBuf_[ kbPos_ - 1 ] );
-	if ( last != '~' && ( last < 'A' || last > 'Z' ) ) {
-		if ( kbPos_ == sizeof( keyBuf_ ) - 1 ) {
-			kbPos_ = 0;
-		}
-		return false;
-	}
-
-	// Check the list
-	uint32_t idx( 0 );
-	keyBuf_[ kbPos_ ] = 0;
-	while ( InputSequences_[ idx ] != nullptr ) {
-		if ( !strcmp( (char const*) keyBuf_ + 2 , InputSequences_[ idx ] ) ) {
-			key = InputKeys_[ idx ];
-			return true;
-		}
-		idx ++;
-	}
-	kbPos_ = 0;
-	return false;
-}
-
-/*----------------------------------------------------------------------------*/
-
-bool T_ConsoleImpl_::clearScreen( )
-{
-	return writeSequence( CCClearScreen_ , sizeof( CCClearScreen_ ) - 1 );
-}
-
-void T_ConsoleImpl_::setTextStyle( uint8_t style , lw::T_TextColor color )
-{
-	styleSeq_.clear( );
-	styleSeq_ << "\033[0";
-	if ( ( style & uint8_t( lw::E_TextStyle::BOLD ) ) != 0 ) {
-		styleSeq_ << ";1";
-	}
-	if ( ( style & uint8_t( lw::E_TextStyle::ITALIC ) ) != 0 ) {
-		styleSeq_ << ";3";
-	}
-	if ( ( style & uint8_t( lw::E_TextStyle::UNDERLINE ) ) != 0 ) {
-		styleSeq_ << ";4";
-	}
-	if ( color.type == lw::E_TextColor::CUSTOM ) {
-		styleSeq_ << ";38;2;" << color.r
-			<< ';' << color.g
-			<< ';' << color.b;
-	} else {
-		styleSeq_ << ';' << ( 30 + uint8_t( color.type ) );
-	}
-	styleSeq_ << 'm';
-	writeSequence( styleSeq_.data( ) , styleSeq_.size( ) );
-}
-
-void T_ConsoleImpl_::printCharacter( lw::T_Character c )
-{
-	char buf[ 8 ];
-	uint32_t l( UTF8PutCodepoint( buf , 7 , c ) );
-	if ( l == 0 ) {
-		return;
-	}
-	writeSequence( buf , l );
-}
-
-void T_ConsoleImpl_::nextLine( )
-{
-	writeSequence( CCNextLine_ , sizeof( CCNextLine_ ) - 1 );
-}
-
-void T_ConsoleImpl_::clearLine( )
-{
-	writeSequence( CCClearLine_ , sizeof( CCClearLine_ ) - 1 );
-}
-
-void T_ConsoleImpl_::clearLines( uint32_t count )
-{
-	assert( count > 0 );
-	while ( --count ) {
-		writeSequence( CCClearLineUp_ , sizeof( CCClearLineUp_ ) - 1 );
-	}
-	clearLine( );
-}
-
-void T_ConsoleImpl_::moveCursor( int32_t x , int32_t y )
-{
-	styleSeq_.clear( );
-	if ( x ) {
-		styleSeq_ << "\033["
-			<< ( x > 0 ? x : -x )
-			<< ( x > 0 ? 'C' : 'D' );
-	}
-	if ( y ) {
-		styleSeq_ << "\033["
-			<< ( y > 0 ? y : -y )
-			<< ( y > 0 ? 'B' : 'A' );
-	}
-	if ( styleSeq_.size( ) ) {
-		writeSequence( styleSeq_.data( ) , styleSeq_.size( ) );
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-bool T_ConsoleImpl_::initTTY( )
-{
-	if ( tcgetattr( STDIN_FILENO , &initialTerm_ ) == -1 ) {
-		failed_ = true;
-		return false;
-	}
-
-	termios rawTerm( initialTerm_ );
-	rawTerm.c_iflag &= ~( BRKINT | ICRNL | INPCK | ISTRIP | IXON );
-	rawTerm.c_oflag &= ~OPOST;
-	rawTerm.c_cflag |= CS8;
-	rawTerm.c_lflag &= ~( ECHO | ICANON | IEXTEN | ISIG );
-	rawTerm.c_cc[ VMIN ] = 0;
-	rawTerm.c_cc[ VTIME ] = 0;
-
-	if ( tcsetattr( STDIN_FILENO , TCSAFLUSH , &rawTerm ) >= 0 ) {
-		return getTerminalSize( );
-	} else {
-		failed_ = true;
-		return false;
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-bool T_ConsoleImpl_::getTerminalSize( )
-{
-	// Try obtaining the size using ioctl
-	winsize ws;
-	if ( ioctl( STDIN_FILENO , TIOCGWINSZ , &ws ) != -1 && ws.ws_col != 0 ) {
-		rows_ = ws.ws_row;
-		cols_ = ws.ws_col;
-		return true;
-	}
-
-	// Otherwise, we need to move the cursor to the bottom/right corner, then
-	// get its position.
-	return writeSequence( CCGetTermSizeStart_ , sizeof( CCGetTermSizeStart_ ) - 1 )
-		&& getCursorPosition( cols_ , rows_ )
-		&& writeSequence( CCGetTermSizeEnd_ , sizeof( CCGetTermSizeEnd_ ) - 1 );
-}
-
-bool T_ConsoleImpl_::getCursorPosition( uint32_t& column , uint32_t& row )
-{
-	if ( failed_ || tcflush( STDIN_FILENO , TCIFLUSH ) != 0 ) {
-		failed_ = true;
-		return false;
-	}
-	if ( !writeSequence( CCGetCursorPos_ , sizeof( CCGetCursorPos_ ) - 1 ) ) {
-		return false;
-	}
-
-	char buf[ 32 ];
-	size_t i( 0 );
-	while ( i < sizeof( buf ) ) {
-		if ( read( STDIN_FILENO , buf + i , 1 ) != 1 ) {
-			i = sizeof( buf );
-			break;
-		}
-		if ( buf[ i ] == 'R' ) {
-			break;
-		}
-		i ++;
-	}
-
-	if ( i == sizeof( buf ) || i < 6 || buf[ 0 ] != 27 || buf[ 1 ] != '[' ) {
-		failed_ = true;
-		return false;
-	}
-
-	buf[ i ] = 0;
-	if ( sscanf( buf + 2 , "%d;%d" , &row , &column ) != 2 ) {
-		failed_ = true;
-		return false;
-	}
-	return true;
-}
-
-#if 0
-bool T_ConsoleImpl_::writeSequence( char const* sequence )
-{
-	if ( failed_ ) {
-		return false;
-	}
-
-	const int n( strlen( sequence ) );
-	if ( write( STDOUT_FILENO , sequence , n ) != n ) {
-		failed_ = true;
-		return false;
-	}
-
-	return true;
-}
-#endif
-
-bool T_ConsoleImpl_::writeSequence( char const* sequence , uint32_t size )
-{
-	if ( failed_ ) {
-		return false;
-	}
-
-	if ( write( STDOUT_FILENO , sequence , size ) != size ) {
-		failed_ = true;
-		return false;
-	}
-
-	return true;
-}
-
-
-}
diff --git a/src/Console.cc b/src/Console.cc
deleted file mode 100644
index 2c217b5..0000000
--- a/src/Console.cc
+++ /dev/null
@@ -1,1346 +0,0 @@
-/******************************************************************************/
-/* CONSOLE SUPPORT ************************************************************/
-/******************************************************************************/
-
-#include <lw/lib/Console.hh>
-#include <lw/lib/Types.hh>
-using namespace lw;
-
-
-/*= T_TextBuilder ============================================================*/
-
-T_TextBuilder::T_TextBuilder( ) noexcept
-	: sb_( ) , chunks_( 16 ) , flushedLength_( 0 ) ,
-		cStyle_( 0 ) , cColor_( E_TextColor::WHITE )
-{ }
-
-/*----------------------------------------------------------------------------*/
-
-T_TextBuilder::T_TextBuilder( T_TextBuilder&& other ) noexcept
-	: T_TextBuilder( )
-{
-	swap( *this , other );
-}
-
-T_TextBuilder& T_TextBuilder::operator =( T_TextBuilder&& other ) noexcept
-{
-	sb_ = std::move( other.sb_ );
-	chunks_ = std::move( other.chunks_ );
-	flushedLength_ = other.flushedLength_;
-	cStyle_ = other.cStyle_;
-	cColor_ = other.cColor_;
-	other.flushedLength_ = other.cStyle_ = 0;
-	other.cColor_ = E_TextColor::WHITE;
-	return *this;
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_DEFINE_SWAP( T_TextBuilder )
-{
-	using std::swap;
-	swap( lhs.sb_ ,			rhs.sb_ );
-	swap( lhs.chunks_ ,		rhs.chunks_ );
-	swap( lhs.flushedLength_ ,	rhs.flushedLength_ );
-	swap( lhs.cStyle_ ,		rhs.cStyle_ );
-	swap( lhs.cColor_ ,		rhs.cColor_ );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void T_TextBuilder::clear( )
-{
-	chunks_.clear( );
-	sb_.clear( );
-	flushedLength_ = 0;
-	cStyle_ = 0;
-	cColor_ = E_TextColor::WHITE;
-}
-
-void T_TextBuilder::reset( bool style , bool color )
-{
-	if ( style ) {
-		setStyle( 0 );
-	}
-	if ( color ) {
-		setColor( E_TextColor::WHITE );
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-void T_TextBuilder::setStyle( uint8_t style )
-{
-	if ( style == cStyle_ ) {
-		return;
-	}
-	flush( );
-	cStyle_ = style;
-}
-
-void T_TextBuilder::setColor( T_TextColor color )
-{
-	if ( color == cColor_ ) {
-		return;
-	}
-	flush( );
-	cColor_ = color;
-}
-
-/*----------------------------------------------------------------------------*/
-
-T_TextBuilder& T_TextBuilder::append(
-		T_Text const& text ) noexcept
-{
-	flush( );
-	const uint32_t nChunks( text.chunks( ) );
-	for ( uint32_t i = 0 ; i < nChunks ; i ++ ) {
-		chunks_.add( text.chunk( i ) );
-	}
-	sb_ << text.string( );
-	flushedLength_ = sb_.size( );
-	return *this;
-}
-
-T_TextBuilder& T_TextBuilder::append(
-		T_TextBuilder const& text ) noexcept
-{
-	flush( );
-	chunks_.addAll( text.chunks_ );
-	sb_ << text.sb_;
-	flushedLength_ += text.flushedLength_;
-	return *this;
-}
-
-/*----------------------------------------------------------------------------*/
-
-void T_TextBuilder::flush( )
-{
-	const auto len( sb_.length( ) );
-	if ( flushedLength_ == len ) {
-		return;
-	}
-
-	T_TextChunk& chunk( chunks_.addNew( ) );
-	chunk.length = len - flushedLength_;
-	chunk.style = cStyle_;
-	chunk.color = cColor_;
-	flushedLength_ = len;
-}
-
-
-/*= T_Text ===================================================================*/
-
-T_Text::T_Text( )
-	: string_( ) , chunks_( 1 )
-{ }
-
-T_Text::T_Text( T_TextBuilder const& builder )
-	: string_( builder.sb_ ) , chunks_( std::max( 1u , builder.chunksCount( ) ) )
-{
-	initChunks( builder );
-}
-
-T_Text::T_Text( T_TextBuilder&& builder )
-	: string_( std::move( builder.sb_ ) ) ,
-		chunks_( std::max( 1u , builder.chunksCount( ) ) )
-{
-	initChunks( builder );
-	builder.clear( );
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_DEFINE_SWAP( T_Text )
-{
-	using std::swap;
-	swap( lhs.string_ , rhs.string_ );
-	swap( lhs.chunks_ , rhs.chunks_ );
-}
-
-/*----------------------------------------------------------------------------*/
-
-T_TextChunk const& T_Text::chunkAt( uint32_t pos ) const
-{
-	uint32_t sz( 0 );
-	int idx( -1 );
-	while ( pos >= sz ) {
-		idx ++;
-		sz += chunks_[ idx ].length;
-	}
-	return chunks_[ idx ];
-}
-
-/*----------------------------------------------------------------------------*/
-
-void T_Text::initChunks( T_TextBuilder const& builder )
-{
-	chunks_.addAll( builder.chunks_ );
-	if ( chunks_.size( ) < chunks_.growth( ) ) {
-		const auto len( string_.length( ) );
-		T_TextChunk& chunk( chunks_.addNew( ) );
-		chunk.length = len - builder.flushedLength_;
-		chunk.style = builder.cStyle_;
-		chunk.color = builder.cColor_;
-	}
-}
-
-
-/*= T_ConsoleLineState =======================================================*/
-
-T_ConsoleLineState::T_ConsoleLineState( )
-	: characters_( GROWTH )
-{
-	reset( );
-}
-
-void T_ConsoleLineState::reset( )
-{
-	size_ = 0;
-	pos_ = 0;
-	historyIndex_ = 0;
-}
-
-void T_ConsoleLineState::setContents( T_String const& contents , uint32_t index )
-{
-	const uint32_t len( contents.length( ) );
-	ensureCapacity( len );
-
-	T_StringIterator it( contents );
-	while ( !it.atEnd( ) ) {
-		characters_[ it.index( ) ] = T_Character( it );
-		it.next( );
-	}
-
-	historyIndex_ = index;
-	size_ = pos_ = len;
-}
-
-/*----------------------------------------------------------------------------*/
-
-T_String T_ConsoleLineState::getContents( ) const
-{
-	T_StringBuilder sb;
-	for ( uint32_t i = 0 ; i < size_ ; i ++ ) {
-		sb << T_Character( characters_[ i ] );
-	}
-	return T_String( std::move( sb ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void T_ConsoleLineState::prevWord( )
-{
-	while ( pos_ > 0 && characters_[ pos_ - 1 ] == ' ' ) {
-		pos_ --;
-	}
-	while ( pos_ > 0 && characters_[ pos_ - 1 ] != ' ' ) {
-		pos_ --;
-	}
-}
-
-void T_ConsoleLineState::nextWord( )
-{
-	while ( pos_ < size_ && characters_[ pos_ ] == ' ' ) {
-		pos_ ++;
-	}
-	while ( pos_ < size_ && characters_[ pos_ ] != ' ' ) {
-		pos_ ++;
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-void T_ConsoleLineState::removeCharacter( )
-{
-	if ( pos_ == size_ ) {
-		return;
-	}
-	size_--;
-	if ( pos_ < size_ ) {
-		memmove( &characters_[ pos_ ] , &characters_[ pos_ + 1 ] ,
-				( size_ - pos_ ) * sizeof( uint32_t ) );
-	}
-}
-
-void T_ConsoleLineState::removeWord( T_Buffer< uint32_t >& cpBuf , uint32_t& cpLength )
-{
-	const uint32_t end( pos_ );
-	prevWord( );
-	if ( pos_ == end ) {
-		return;
-	}
-
-	const uint32_t rmCount( end - pos_ );
-	cpLength = rmCount;
-	if ( cpBuf.size( ) < rmCount ) {
-		cpBuf.resize( rmCount );
-	}
-	memcpy( &cpBuf[ 0 ] , &characters_[ pos_ ] , rmCount * sizeof( uint32_t ) );
-
-	size_ -= rmCount;
-	if ( pos_ < size_ ) {
-		memmove( &characters_[ pos_ ] , &characters_[ end ] ,
-				( size_ - pos_ ) * sizeof( uint32_t ) );
-	}
-}
-
-void T_ConsoleLineState::removeRestOfLine( T_Buffer< uint32_t >& cpBuf , uint32_t& cpLength )
-{
-	if ( pos_ == size_ ) {
-		return;
-	}
-
-	const uint32_t rmCount( size_ - pos_ );
-	cpLength = rmCount;
-	if ( cpBuf.size( ) < rmCount ) {
-		cpBuf.resize( rmCount );
-	}
-	memcpy( &cpBuf[ 0 ] , &characters_[ pos_ ] , rmCount * sizeof( uint32_t ) );
-
-	size_ = pos_;
-}
-
-/*----------------------------------------------------------------------------*/
-
-void T_ConsoleLineState::insert( T_Character c )
-{
-	ensureCapacity( size_ + 1 );
-	if ( pos_ < size_ ) {
-		memmove( &characters_[ pos_ + 1 ] , &characters_[ pos_ ] ,
-				( size_ - pos_ ) * sizeof( uint32_t ) );
-	}
-	size_ ++;
-	characters_[ pos_ ++ ] = c;
-}
-
-void T_ConsoleLineState::insert( T_String const& s )
-{
-	const uint32_t length( s.length( ) );
-
-	ensureCapacity( size_ + length );
-	if ( pos_ < size_ ) {
-		memmove( &characters_[ pos_ + length ] , &characters_[ pos_ ] ,
-				( size_ - pos_ ) * sizeof( uint32_t ) );
-	}
-
-	T_StringIterator it( s );
-	while ( !it.atEnd( ) ) {
-		const T_Character c( it );
-		const uint32_t value( c.isControl( ) ? 32 : uint32_t( c ) );
-		characters_[ pos_ + it.index( ) ] = value;
-		it.next( );
-	}
-
-	size_ += length;
-	pos_ += length;
-}
-
-void T_ConsoleLineState::insert( T_Buffer< uint32_t > const& buffer , uint32_t length )
-{
-	if ( length == 0 ) {
-		return;
-	}
-
-	ensureCapacity( size_ + length );
-	if ( pos_ < size_ ) {
-		memmove( &characters_[ pos_ + length ] , &characters_[ pos_ ] ,
-				( size_ - pos_ ) * sizeof( uint32_t ) );
-	}
-	size_ += length;
-	memcpy( &characters_[ pos_ ] , &buffer[ 0 ] , length * sizeof( uint32_t ) );
-	pos_ += length;
-}
-
-/*----------------------------------------------------------------------------*/
-
-void T_ConsoleLineState::ensureCapacity( uint32_t needed )
-{
-	const uint32_t extra( needed + GROWTH - 1 );
-	const uint32_t actual( extra - extra % GROWTH );
-	if ( actual > characters_.size( ) ) {
-		characters_.resize( actual );
-	}
-}
-
-
-/*= T_ConsoleControl_ =========================================================*/
-
-// Information sent to the console
-namespace {
-struct T_ConsoleControl_
-{
-	enum {
-		C_TERMINATE ,		// End thread
-		C_SETMODE ,		// Set interaction mode
-		C_SETPROMPT ,		// Set prompt text
-		C_SETEXIT ,		// Set text for Ctrl+D
-		C_SETPROGRESS ,		// Set progress information
-		C_SETSHORTCUT ,		// Set a keyboard shortcut
-		C_SETHISTSIZE ,		// Set maximal history size
-		C_SETHISTORY ,		// Replace history contents
-		C_PRINT ,		// Print text
-	} type;
-	T_Variant data;
-};
-} // namespace
-
-
-/*= T_ConsolePrivate_ ========================================================*/
-
-// Load the implementation
-#ifdef _WIN32
-# error "Not implemented!"
-#else
-# include "Console-Unix.hh"
-#endif
-
-namespace {
-struct T_ConsolePrivate_
-{
-	enum {
-		C_TERMINATED ,		// Thread stopped
-		C_OUTPUT ,		// Output mode
-		C_INPUT ,		// Input mode
-		C_INPUT_READY ,		// Input finished
-		C_PROGRESS ,		// Progress display
-		C_INTERRUPTED		// Progress display, interrupted
-	} state_;
-
-	T_Text progress_;
-
-	T_Text prompt_;
-	T_String exitLine_;
-	T_String line_;
-
-	T_ConsoleLineState input_;
-	uint32_t ilLines_ , ilLastPromptLine_;
-	uint32_t ilCursorX_ , ilCursorY_;
-
-	T_Buffer< uint32_t > cpBuffer_;
-	uint32_t cpLength_;
-
-	T_String shortcuts_[ T_Console::NbShortcuts ];
-
-	T_Array< T_String > history_;
-	uint32_t maxHistory_;
-	uint32_t historyPos_;
-
-	OP_Thread thread_;
-
-	T_Mutex controlMutex_;
-	T_Condition controlCond_;
-	T_RingBuffer< T_ConsoleControl_ > control_;
-
-	T_ConsoleImpl_ impl_;
-	uint32_t width_ , height_;
-
-	// --------------------------------------------------------------------
-
-	T_ConsolePrivate_( );
-	~T_ConsolePrivate_( );
-
-	E_ConsoleInteractionMode interactionMode( ) const;
-
-	// --------------------------------------------------------------------
-
-	bool start( );
-	void terminate( );
-	void resetData( );
-
-	void mainLoop( );
-	bool handleControlMessage( T_ConsoleControl_& o );
-
-	// --------------------------------------------------------------------
-
-	void printText( T_Text const& text , bool line );
-	void printProgress( );
-
-	// --------------------------------------------------------------------
-
-	void inputKey( E_ConsoleKey key , T_Character character );
-	void clearInputLine( );
-	void printInputLine( );
-	void moveInputCursor( );
-
-	// --------------------------------------------------------------------
-
-	void setHistorySize( uint32_t newMax );
-	void setHistory( T_Array< T_String >& newData );
-
-	void getTextSize( T_String const& text , uint32_t& lines , uint32_t& lastLineLength );
-
-	void updateHistory( T_String const& string );
-	void newHistoryEntry( );
-
-	// --------------------------------------------------------------------
-
-	void sendToThread( T_ConsoleControl_&& o );
-	bool receiveFromMain( T_ConsoleControl_& output );
-};
-} // namespace
-
-/*----------------------------------------------------------------------------*/
-
-inline T_ConsolePrivate_::T_ConsolePrivate_( )
-	: maxHistory_( T_Console::DefaultHistory ) ,
-		historyPos_( 0 )
-{
-	history_.addNew( );
-}
-
-inline T_ConsolePrivate_::~T_ConsolePrivate_( )
-{
-	terminate( );
-}
-
-inline E_ConsoleInteractionMode T_ConsolePrivate_::interactionMode( ) const
-{
-	switch ( state_ ) {
-	    case C_INPUT:
-	    case C_INPUT_READY:
-		return E_ConsoleInteractionMode::INPUT;
-	    case C_PROGRESS:
-	    case C_INTERRUPTED:
-		return E_ConsoleInteractionMode::PROGRESS;
-	    default:
-		return E_ConsoleInteractionMode::OUTPUT;
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-bool T_ConsolePrivate_::start( )
-{
-	if ( impl_.initConsole( ) ) {
-		resetData( );
-		state_ = C_OUTPUT;
-		thread_ = NewOwned< T_Thread >( [this]() { mainLoop( ); } );
-		return true;
-	} else {
-		return false;
-	}
-}
-
-void T_ConsolePrivate_::terminate( )
-{
-	if ( thread_ ) {
-		T_ConsoleControl_ out;
-		out.type = T_ConsoleControl_::C_TERMINATE;
-		sendToThread( std::move( out ) );
-		thread_->join( );
-		thread_.clear( );
-		resetData( );
-	}
-}
-
-void T_ConsolePrivate_::resetData( )
-{
-	control_.free( );
-	line_ = T_String( );
-	prompt_ = T_Text( );
-	exitLine_ = T_String( );
-	progress_ = T_Text( );
-	input_.reset( );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void T_ConsolePrivate_::mainLoop( )
-{
-	E_ConsoleKey key( E_ConsoleKey::CHARACTER );
-	uint32_t character( 0 );
-	T_ConsoleControl_ o;
-	bool keepRunning( true );
-
-	impl_.getTerminalSize( height_ , width_ );
-	while ( keepRunning && !impl_.failed( ) ) {
-		if ( impl_.readKey( key , character ) ) {
-			if ( key == E_ConsoleKey::CLEAR ) {
-				impl_.clearScreen( );
-				if ( interactionMode( ) == E_ConsoleInteractionMode::PROGRESS ) {
-					printProgress( );
-				} else if ( state_ == C_INPUT ) {
-					printInputLine( );
-				}
-
-			} else if ( state_ == C_PROGRESS && key == E_ConsoleKey::INTERRUPT ) {
-				state_ = C_INTERRUPTED;
-
-			} else if ( state_ == C_INPUT ) {
-				inputKey( key , character );
-			}
-
-		} else if ( receiveFromMain( o ) ) {
-			keepRunning = handleControlMessage( o );
-		} else if ( impl_.resized( height_ , width_ ) ) {
-			if ( state_ == C_PROGRESS || state_ == C_INTERRUPTED ) {
-				printProgress( );
-			}
-		}
-	}
-
-	impl_.shutdownConsole( );
-}
-
-bool T_ConsolePrivate_::handleControlMessage( T_ConsoleControl_& o )
-{
-	switch ( o.type ) {
-
-	    case T_ConsoleControl_::C_TERMINATE:
-		if ( state_ == C_INPUT ) {
-			clearInputLine( );
-		} else if ( state_ == C_PROGRESS || state_ == C_INTERRUPTED ) {
-			impl_.clearLine( );
-		}
-		state_ = C_TERMINATED;
-		return false;
-
-	    case T_ConsoleControl_::C_SETMODE:
-		{
-			const auto m( o.data.value< E_ConsoleInteractionMode >( ) );
-			if ( m == E_ConsoleInteractionMode::OUTPUT ) {
-				if ( state_ == C_PROGRESS || state_ == C_INTERRUPTED ) {
-					impl_.clearLine( );
-				} else if ( state_ == C_INPUT ) {
-					clearInputLine( );
-				}
-				state_ = C_OUTPUT;
-			} else if ( m == E_ConsoleInteractionMode::INPUT ) {
-				if ( state_ != C_INPUT_READY ) {
-					if ( state_ == C_PROGRESS || state_ == C_INTERRUPTED ) {
-						impl_.clearLine( );
-					}
-					input_.reset( );
-					printInputLine( );
-					state_ = C_INPUT;
-				}
-			} else {
-				assert( m == E_ConsoleInteractionMode::PROGRESS );
-				if ( state_ == C_INPUT ) {
-					clearInputLine( );
-				}
-				state_ = C_PROGRESS;
-				printProgress( );
-			}
-		}
-		break;
-
-	    case T_ConsoleControl_::C_SETPROMPT:
-		if ( state_ == C_INPUT ) {
-			clearInputLine( );
-		}
-		prompt_ = o.data.value< T_Text >( );
-		if ( state_ == C_INPUT ) {
-			printInputLine( );
-		}
-		break;
-
-	    case T_ConsoleControl_::C_SETEXIT:
-		exitLine_ = o.data.value< T_String >( );
-		break;
-
-	    case T_ConsoleControl_::C_SETPROGRESS:
-		progress_ = o.data.value< T_Text >( );
-		if ( interactionMode( ) == E_ConsoleInteractionMode::PROGRESS ) {
-			printProgress( );
-		}
-		break;
-
-	    case T_ConsoleControl_::C_SETSHORTCUT:
-		{
-			auto const& p( o.data.value< std::pair< int , T_String > >( ) );
-			shortcuts_[ p.first ] = p.second;
-		}
-		break;
-
-	    case T_ConsoleControl_::C_SETHISTSIZE:
-		setHistorySize( o.data.value< uint32_t >( ) );
-		break;
-
-	    case T_ConsoleControl_::C_SETHISTORY:
-		setHistory( o.data.value< T_Array< T_String > >( ) );
-		break;
-
-	    case T_ConsoleControl_::C_PRINT:
-		if ( state_ == C_PROGRESS || state_ == C_INTERRUPTED ) {
-			impl_.clearLine( );
-		} else if ( state_ == C_INPUT ) {
-			clearInputLine( );
-		}
-		printText( o.data.value< T_Text >( ) , true );
-		if ( state_ == C_PROGRESS || state_ == C_INTERRUPTED ) {
-			printProgress( );
-		} else if ( state_ == C_INPUT ) {
-			printInputLine( );
-		}
-		break;
-	}
-
-	return true;
-}
-
-/*----------------------------------------------------------------------------*/
-
-void T_ConsolePrivate_::printText( T_Text const& text , bool line )
-{
-	T_StringIterator it( text.string( ) );
-	uint32_t chunkLeft( 0 );
-	uint32_t chunkIndex( 0 );
-	bool lastWasNL( false );
-	uint32_t cols( 0 );
-	while ( !( it.atEnd( ) || impl_.failed( ) ) ) {
-		if ( chunkLeft == 0 ) {
-			T_TextChunk const& chunk( text.chunk( chunkIndex ++ ) );
-			chunkLeft = chunk.length;
-			impl_.setTextStyle( chunk.style , chunk.color );
-		}
-
-		T_Character c( it );
-		lastWasNL = ( c == '\n' );
-		if ( !c.isControl( ) ) {
-			impl_.printCharacter( c );
-			cols ++;
-		} else if ( c == '\t' ) {
-			do {
-				impl_.printCharacter( ' ' );
-				cols ++;
-			} while ( cols % 8 != 0 );
-		} else if ( c == '\n' ) {
-			impl_.nextLine( );
-			cols = 0;
-		}
-		it.next( );
-		chunkLeft --;
-	}
-	if ( !lastWasNL && line ) {
-		impl_.nextLine( );
-	}
-}
-
-void T_ConsolePrivate_::printProgress( )
-{
-	impl_.getTerminalSize( height_ , width_ );
-	impl_.clearLine( );
-
-	T_StringIterator it( progress_.string( ) );
-	uint32_t chunkLeft( 0 );
-	uint32_t chunkIndex( 0 );
-	uint32_t cols( 0 );
-	while ( !( it.atEnd( ) || impl_.failed( ) || cols == width_ ) ) {
-		if ( chunkLeft == 0 ) {
-			T_TextChunk const& chunk( progress_.chunk( chunkIndex ++ ) );
-			chunkLeft = chunk.length;
-			impl_.setTextStyle( chunk.style , chunk.color );
-		}
-
-		T_Character c( it );
-		if ( !c.isControl( ) ) {
-			impl_.printCharacter( c );
-			cols ++;
-		} else if ( c == '\t' ) {
-			do {
-				impl_.printCharacter( ' ' );
-				cols ++;
-			} while ( cols % 8 != 0 && cols < width_ );
-		} else if ( c == '\n' ) {
-			break;
-		}
-		it.next( );
-		chunkLeft --;
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-void T_ConsolePrivate_::inputKey( E_ConsoleKey key , T_Character character )
-{
-	bool cursorMoved( true ) , stringChanged( false );
-	switch ( key ) {
-
-	    case E_ConsoleKey::CLEAR:
-		// This should never happen, but better safe than sorry
-		return;
-
-	    case E_ConsoleKey::ENTER:
-		input_.toEnd( );
-		moveInputCursor( );
-		line_ = input_.getContents( );
-		{
-			const uint32_t hs( history_.size( ) );
-			if ( line_ && ( hs == 1 || history_[ ( historyPos_ - 1 + hs ) % hs ] != line_ ) ) {
-				history_[ historyPos_ ] = line_;
-				newHistoryEntry( );
-			} else {
-				history_[ historyPos_ ] = T_String( );
-			}
-		}
-		input_.reset( );
-		impl_.nextLine( );
-		state_ = C_INPUT_READY;
-		return;
-
-	    case E_ConsoleKey::INTERRUPT:
-		if ( input_.size( ) != 0 ) {
-			input_.reset( );
-			impl_.nextLine( );
-			printInputLine( );
-		}
-		return;
-
-	    case E_ConsoleKey::CHARACTER:
-		input_.insert( character );
-		stringChanged = true;
-		break;
-
-	    case E_ConsoleKey::UP:
-		{
-			const auto hs( history_.size( ) ) , hi( input_.historyIndex( ) );
-			if ( hi == hs - 1 ) {
-				cursorMoved = false;
-			} else {
-				if ( input_.size( ) ) {
-					updateHistory( input_.getContents( ) );
-				}
-				input_.setContents( history_[ ( historyPos_ - hi - 1 + hs ) % hs ] , hi + 1 );
-				stringChanged = true;
-			}
-		}
-		break;
-
-	    case E_ConsoleKey::DOWN:
-		{
-			const auto hs( history_.size( ) ) , hi( input_.historyIndex( ) );
-			if ( hi == 0 ) {
-				cursorMoved = false;
-			} else {
-				if ( input_.size( ) ) {
-					updateHistory( input_.getContents( ) );
-				}
-				input_.setContents( history_[ ( historyPos_ - hi + 1 + hs ) % hs ] , hi - 1 );
-				stringChanged = true;
-			}
-		}
-		break;
-
-	    case E_ConsoleKey::LEFT:
-		if ( input_.pos( ) == 0 ) {
-			cursorMoved = false;
-		} else {
-			input_.left( );
-		}
-		break;
-
-	    case E_ConsoleKey::RIGHT:
-		if ( input_.pos( ) == input_.size( ) ) {
-			cursorMoved = false;
-		} else {
-			input_.right( );
-		}
-		break;
-
-	    case E_ConsoleKey::WPREV:
-		if ( input_.pos( ) == 0 ) {
-			cursorMoved = false;
-		} else {
-			input_.prevWord( );
-		}
-		break;
-
-	    case E_ConsoleKey::WNEXT:
-		if ( input_.pos( ) == input_.size( ) ) {
-			cursorMoved = false;
-		} else {
-			input_.nextWord( );
-		}
-		break;
-
-	    case E_ConsoleKey::HOME:
-		if ( input_.pos( ) == 0 ) {
-			cursorMoved = false;
-		} else {
-			input_.toStart( );
-		}
-		break;
-
-	    case E_ConsoleKey::END:
-		if ( input_.pos( ) == input_.size( ) ) {
-			cursorMoved = false;
-		} else {
-			input_.toEnd( );
-		}
-		break;
-
-	    case E_ConsoleKey::EXIT:
-		if ( input_.size( ) == 0 && exitLine_ ) {
-			input_.setContents( exitLine_ , 0 );
-			clearInputLine( );
-			printInputLine( );
-			impl_.nextLine( );
-			line_ = exitLine_;
-			state_ = C_INPUT_READY;
-			return;
-		}
-	    case E_ConsoleKey::DELETE:
-		if ( input_.pos( ) == input_.size( ) ) {
-			cursorMoved = false;
-		} else {
-			input_.removeCharacter( );
-			stringChanged = true;
-		}
-		break;
-
-	    case E_ConsoleKey::BACKSPACE:
-		if ( input_.pos( ) == 0 ) {
-			cursorMoved = false;
-		} else {
-			input_.left( );
-			input_.removeCharacter( );
-			stringChanged = true;
-		}
-		break;
-
-	    case E_ConsoleKey::KILL_WORD:
-		if ( input_.pos( ) == 0 ) {
-			cursorMoved = false;
-		} else {
-			input_.removeWord( cpBuffer_ , cpLength_ );
-			stringChanged = true;
-		}
-		break;
-
-	    case E_ConsoleKey::KILL_REST:
-		if ( input_.pos( ) == input_.size( ) ) {
-			cursorMoved = false;
-		} else {
-			input_.removeRestOfLine( cpBuffer_ , cpLength_ );
-			stringChanged = true;
-		}
-		break;
-
-	    case E_ConsoleKey::KILL_LINE:
-		if ( 0 == input_.size( ) ) {
-			cursorMoved = false;
-		} else {
-			input_.toStart( );
-			input_.removeRestOfLine( cpBuffer_ , cpLength_ );
-			stringChanged = true;
-		}
-		break;
-
-	    case E_ConsoleKey::PASTE:
-		if ( 0 == cpLength_ ) {
-			cursorMoved = false;
-		} else {
-			input_.insert( cpBuffer_ , cpLength_ );
-			stringChanged = true;
-		}
-		break;
-
-	    default:
-		{
-			assert( key >= E_ConsoleKey::F1 );
-			const T_String shortcut( shortcuts_[ int( key ) - int( E_ConsoleKey::F1 ) ] );
-			if ( shortcut ) {
-				input_.insert( shortcut );
-				stringChanged = true;
-			} else {
-				cursorMoved = false;
-			}
-		}
-		break;
-	}
-
-	if ( stringChanged ) {
-		clearInputLine( );
-		printInputLine( );
-	} else if ( cursorMoved ) {
-		moveInputCursor( );
-	}
-}
-
-void T_ConsolePrivate_::clearInputLine( )
-{
-	if ( ilLines_ != 0 ) {
-		impl_.moveCursor( 0 , ilLines_ - ilCursorY_ - 1 );
-		impl_.clearLines( ilLines_ );
-		ilLines_ = 0;
-	}
-}
-
-void T_ConsolePrivate_::printInputLine( )
-{
-	uint32_t promptLines;
-	getTextSize( prompt_.string( ) , promptLines , ilLastPromptLine_ );
-
-	const uint32_t iSize( input_.size( ) );
-	const uint32_t inputFull( ilLastPromptLine_ + iSize + 1 );
-	const uint32_t inputLines( inputFull / width_
-			+ ( inputFull % width_ != 0 ? 1 : 0 ) );
-	const uint32_t totalLines( inputLines + promptLines - 1 );
-	ilLines_ = totalLines;
-
-	if ( prompt_.string( ) ) {
-		printText( prompt_ , false );
-	} else {
-		impl_.setTextStyle( 0 , E_TextColor::WHITE );
-	}
-	for ( uint32_t i = 0 ; i < iSize ; i ++ ) {
-		impl_.printCharacter( input_[ i ] );
-	}
-	impl_.printCharacter( ' ' );
-
-	ilCursorY_ = totalLines - 1;
-	ilCursorX_ = inputFull % width_;
-	if ( ilCursorX_ == 0 ) {
-		ilCursorX_ = width_ - 1;
-	}
-	moveInputCursor( );
-}
-
-void T_ConsolePrivate_::moveInputCursor( )
-{
-	if ( ilLines_ == 0 ) {
-		return;
-	}
-	const uint32_t iPos( input_.pos( ) );
-	const int32_t line( ( iPos + ilLastPromptLine_ ) / width_ );
-	const int32_t column( ( iPos + ilLastPromptLine_ ) % width_ );
-	impl_.moveCursor( column - ilCursorX_ , line - ilCursorY_ );
-	ilCursorX_ = column;
-	ilCursorY_ = line;
-}
-
-/*----------------------------------------------------------------------------*/
-
-void T_ConsolePrivate_::setHistorySize( uint32_t newMax )
-{
-	assert( state_ != C_INPUT );
-	assert( newMax > 0 );
-
-	if ( newMax == maxHistory_ ) {
-		return;
-	}
-	maxHistory_ = newMax;
-
-	const uint32_t hs( history_.size( ) );
-	if ( hs > maxHistory_ || historyPos_ != hs - 1 ) {
-		const uint32_t cs( std::min( hs , maxHistory_ ) );
-		const uint32_t start( historyPos_ + hs - cs + 1 );
-		T_Array< T_String > nh;
-		for ( uint32_t i = 0 ; i < cs ; i ++ ) {
-			nh.add( std::move( history_[ ( start + i ) % hs ] ) );
-		}
-		swap( history_ , nh );
-		historyPos_ = cs - 1;
-	}
-}
-
-void T_ConsolePrivate_::setHistory( T_Array< T_String >& newData )
-{
-	assert( state_ != C_INPUT );
-	const auto sz( newData.size( ) );
-	if ( sz > maxHistory_ ) {
-		history_ = newData.moveRange( sz - maxHistory_ , sz - 1 );
-	} else {
-		swap( history_ , newData );
-		if ( sz == 0 ) {
-			history_.addNew( );
-			historyPos_ = 0;
-		} else {
-			historyPos_ = sz - 1;
-		}
-	}
-	if ( history_[ historyPos_ ] ) {
-		newHistoryEntry( );
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-void T_ConsolePrivate_::getTextSize( T_String const& text , uint32_t& lines , uint32_t& lastLineLength )
-{
-	T_StringIterator it( text );
-	lines = 1;
-	lastLineLength = 0;
-	while ( !it.atEnd( ) ) {
-		T_Character c( it );
-		it.next( );
-
-		if ( c == '\n' ) {
-			lines ++;
-			lastLineLength = 0;
-		} else if ( c == '\t' ) {
-			lastLineLength += 8 - ( lastLineLength % 8 );
-		} else if ( !c.isControl( ) ) {
-			lastLineLength ++;
-		}
-
-		while ( lastLineLength >= width_ ) {
-			lines ++;
-			lastLineLength -= width_;
-		}
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-inline void T_ConsolePrivate_::updateHistory( T_String const& string )
-{
-	const uint32_t hs( history_.size( ) );
-	assert( hs > 0 );
-	history_[ ( historyPos_ - input_.historyIndex( ) + hs ) % hs ] = string;
-}
-
-void T_ConsolePrivate_::newHistoryEntry( )
-{
-	if ( history_.size( ) < maxHistory_ ) {
-		assert( historyPos_ == history_.size( ) - 1 );
-		historyPos_ ++;
-		history_.addNew( );
-	} else {
-		historyPos_ = ( historyPos_ + 1 ) % maxHistory_;
-		history_[ historyPos_ ] = T_String( );
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-void T_ConsolePrivate_::sendToThread( T_ConsoleControl_&& o )
-{
-	assert( thread_ );
-	T_ScopeLock lock( controlMutex_ );
-	control_.put( std::move( o ) );
-	controlCond_.notify_one( );
-}
-
-bool T_ConsolePrivate_::receiveFromMain( T_ConsoleControl_& output )
-{
-	using namespace std::chrono_literals;
-	T_ExclusiveLock lock( controlMutex_ );
-	controlCond_.wait_for( lock , 20ms , [this]() {
-				return control_.size( ) != 0;
-			} );
-	return control_.readNext( output );
-}
-
-
-/*= T_Console ================================================================*/
-
-T_Console::T_Console( )
-	: A_PrivateImplementation( new T_ConsolePrivate_( ) )
-{ }
-
-/*----------------------------------------------------------------------------*/
-
-bool T_Console::mode( E_ConsoleMode mode )
-{
-	auto& pi( p< T_ConsolePrivate_ >( ) );
-	if ( mode == E_ConsoleMode::DISABLED ) {
-		pi.terminate( );
-		return true;
-	}
-	return isActive( ) || pi.start( ) || mode == E_ConsoleMode::OPTIONAL;
-}
-
-bool T_Console::isActive( ) const
-{
-	auto& pi( p< T_ConsolePrivate_ >( ) );
-	return pi.thread_ && pi.state_ != pi.C_TERMINATED;
-}
-
-/*----------------------------------------------------------------------------*/
-
-void T_Console::interactionMode( E_ConsoleInteractionMode mode )
-{
-	auto& pi( p< T_ConsolePrivate_ >( ) );
-	if ( pi.thread_ ) {
-		T_ConsoleControl_ o;
-		o.type = T_ConsoleControl_::C_SETMODE;
-		o.data = mode;
-		pi.sendToThread( std::move( o ) );
-	}
-}
-
-E_ConsoleInteractionMode T_Console::interactionMode( ) const
-{
-	return p< T_ConsolePrivate_ >( ).interactionMode( );
-}
-
-void T_Console::wait( )
-{
-	auto& pi( p< T_ConsolePrivate_ >( ) );
-	bool hasMessages( true );
-	while ( isActive( ) && hasMessages ) {
-		{
-			T_ScopeLock lock( pi.controlMutex_ );
-			hasMessages = pi.control_.size( ) != 0;
-		}
-		if ( hasMessages ) {
-			std::this_thread::yield( );
-		}
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-void T_Console::putLine( T_Text text )
-{
-	auto& pi( p< T_ConsolePrivate_ >( ) );
-	if ( pi.thread_ ) {
-		T_ConsoleControl_ o;
-		o.type = T_ConsoleControl_::C_PRINT;
-		o.data = std::move( text );
-		pi.sendToThread( std::move( o ) );
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-void T_Console::setPrompt( T_Text prompt )
-{
-	auto& pi( p< T_ConsolePrivate_ >( ) );
-	if ( pi.thread_ ) {
-		T_ConsoleControl_ o;
-		o.type = T_ConsoleControl_::C_SETPROMPT;
-		o.data = std::move( prompt );
-		pi.sendToThread( std::move( o ) );
-	}
-}
-
-void T_Console::setExitLine( T_String const& line )
-{
-	auto& pi( p< T_ConsolePrivate_ >( ) );
-	if ( pi.thread_ ) {
-		T_ConsoleControl_ o;
-		o.type = T_ConsoleControl_::C_SETEXIT;
-		o.data = line;
-		pi.sendToThread( std::move( o ) );
-	}
-}
-
-bool T_Console::getLine( T_String& line )
-{
-	auto& pi( p< T_ConsolePrivate_ >( ) );
-	if ( pi.state_ == pi.C_INPUT_READY && pi.line_ != "\001" ) {
-		line = pi.line_;
-		pi.line_ = T_String::Pooled( "\001" );
-
-		T_ConsoleControl_ o;
-		o.type = T_ConsoleControl_::C_SETMODE;
-		o.data = E_ConsoleInteractionMode::OUTPUT;
-		pi.sendToThread( std::move( o ) );
-		return true;
-	}
-	return false;
-}
-
-/*----------------------------------------------------------------------------*/
-
-void T_Console::setShortcut( E_ConsoleKey key , T_String const& value )
-{
-	assert( key >= E_ConsoleKey::F1 );
-	auto& pi( p< T_ConsolePrivate_ >( ) );
-	const int index( int( key ) - int( E_ConsoleKey::F1 ) );
-	if ( pi.thread_ ) {
-		T_ConsoleControl_ o;
-		o.type = T_ConsoleControl_::C_SETSHORTCUT;
-		o.data = std::make_pair< int , T_String >( int( index ) , T_String( value ) );
-		pi.sendToThread( std::move( o ) );
-	} else {
-		pi.shortcuts_[ index ] = value;
-	}
-}
-
-T_Array< T_String > T_Console::getShortcuts( )
-{
-	wait( );
-	auto& pi( p< T_ConsolePrivate_ >( ) );
-	T_Array< T_String > shortcuts( NbShortcuts );
-	for ( auto i = 0 ; i < NbShortcuts ; i ++ ) {
-		shortcuts.add( pi.shortcuts_[ i ] );
-	}
-	return shortcuts;
-}
-
-/*----------------------------------------------------------------------------*/
-
-uint32_t T_Console::maxHistorySize( ) const
-{
-	return p< T_ConsolePrivate_ >( ).maxHistory_;
-}
-
-T_Array< T_String > T_Console::history( )
-{
-	wait( );
-	auto& pi( p< T_ConsolePrivate_ >( ) );
-	if ( pi.state_ == pi.C_INPUT ) {
-		throw X_InvalidConsoleState( );
-	}
-	
-	const uint32_t hs( pi.history_.size( ) );
-	if ( hs == pi.historyPos_ + 1 ) {
-		return pi.history_;
-	}
-	
-	T_Array< T_String > copy( hs );
-	for ( uint32_t i = 0 ; i < hs ; i ++ ) {
-		copy.add( pi.history_[ ( pi.historyPos_ + i ) % hs ] );
-	}
-	return copy;
-}
-
-
-void T_Console::maxHistorySize( uint32_t mhs )
-{
-	assert( mhs > 0 );
-	wait( );
-	auto& pi( p< T_ConsolePrivate_ >( ) );
-	if ( pi.state_ == pi.C_INPUT ) {
-		throw X_InvalidConsoleState( );
-	}
-	if ( isActive( ) ) {
-		T_ConsoleControl_ c;
-		c.type = T_ConsoleControl_::C_SETHISTSIZE;
-		c.data = mhs;
-		pi.sendToThread( std::move( c ) );
-	} else {
-		pi.setHistorySize( mhs );
-	}
-}
-
-void T_Console::history( T_Array< T_String > const& lines )
-{
-	wait( );
-	auto& pi( p< T_ConsolePrivate_ >( ) );
-	if ( pi.state_ == pi.C_INPUT ) {
-		throw X_InvalidConsoleState( );
-	}
-	if ( isActive( ) ) {
-		T_ConsoleControl_ c;
-		c.type = T_ConsoleControl_::C_SETHISTORY;
-		c.data = lines;
-		pi.sendToThread( std::move( c ) );
-	} else {
-		T_Array< T_String > lcopy( lines );
-		pi.setHistory( lcopy );
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-void T_Console::setProgressInfo( T_Text info )
-{
-	auto& pi( p< T_ConsolePrivate_ >( ) );
-	if ( pi.thread_ ) {
-		T_ConsoleControl_ o;
-		o.type = T_ConsoleControl_::C_SETPROGRESS;
-		o.data = std::move( info );
-		pi.sendToThread( std::move( o ) );
-	}
-}
-
-bool T_Console::wasInterrupted( ) const
-{
-	return p< T_ConsolePrivate_ >( ).state_ == T_ConsolePrivate_::C_INTERRUPTED;
-}
diff --git a/src/ConsoleLogWriter.cc b/src/ConsoleLogWriter.cc
deleted file mode 100644
index e59d979..0000000
--- a/src/ConsoleLogWriter.cc
+++ /dev/null
@@ -1,83 +0,0 @@
-#include <lw/lib/BuiltinLoggers.hh>
-using namespace lw;
-
-
-namespace {
-
-char const* const V_Name_ = "console";
-inline T_String Name_( ) { return T_String::Pooled( V_Name_ ); }
-
-}
-
-
-/*= T_ConsoleLogWriterFactory ================================================*/
-
-T_ConsoleLogWriterFactory::T_ConsoleLogWriterFactory( T_Console& console )
-	: A_LogWriterFactory( Name_( ) ) , console_( console )
-{ }
-
-RP_LogWriterConfiguration T_ConsoleLogWriterFactory::createConfiguration( T_String const& name ) const
-{
-	RP_LogWriterConfiguration p( new T_LogWriterConfiguration( Name_( ) ) );
-	p->setName( name );
-	return p;
-}
-
-OP_LogWriter T_ConsoleLogWriterFactory::createLogWriter( OP_LogWriterConfiguration&& configuration ) const
-{
-	T_ConsoleLogWriter* p( new T_ConsoleLogWriter( std::move( configuration ) , console_ ) );
-	return OwnRawPointer( p );
-}
-
-
-/*= T_ConsoleLogWriter =======================================================*/
-
-T_ConsoleLogWriter::T_ConsoleLogWriter( OP_LogWriterConfiguration&& configuration , T_Console& console )
-	: A_LogWriter( std::move( configuration ) ) , console_( console )
-{ }
-
-void T_ConsoleLogWriter::log( T_LogTimestamp const& timestamp ,
-		E_LogLevel level , T_LogPath const& path ,
-		T_LogStringData const& data , uint32_t size )
-{
-	using namespace std::chrono;
-
-	char timeBuffer[ 128 ];
-	std::time_t tst( T_LogTimestamp::clock::to_time_t( timestamp ) );
-	std::strftime( timeBuffer , 128 , "%Y-%m-%d %H:%M:%S" , std::gmtime( &tst ) );
-	const auto ms( ( duration_cast< milliseconds >( timestamp - T_LogTimestamp( ) ) ).count( ) % 1000 );
-
-	T_TextBuilder sb;
-
-	sb << timeBuffer << '.';
-	if ( ms < 100 ) {
-		sb << '0';
-		if ( ms < 10 ) {
-			sb << '0';
-		}
-	}
-	sb << ms << ' ' << path.toString( ) << " - "
-		<< E_TextStyle::UNDERLINE;
-	switch ( level ) {
-	    case E_LogLevel::TRACE:
-	    case E_LogLevel::DEBUG:
-	    case E_LogLevel::INFO:
-		sb << E_TextColor::CYAN;
-		break;
-	    case E_LogLevel::NOTICE:
-		break;
-	    case E_LogLevel::WARNING:
-		sb << E_TextColor::YELLOW;
-		break;
-	    case E_LogLevel::CRITICAL:
-		sb << E_TextStyle::BOLD;
-	    case E_LogLevel::ERROR:
-		sb << E_TextColor::RED;
-		break;
-	}
-	sb << level;
-	sb.reset( );
-	sb << " - " << T_String( &( (*data) [ 0 ] ) , size );
-
-	console_.putLine( std::move( sb ) );
-}
diff --git a/src/CwdFileLogger.cc b/src/CwdFileLogger.cc
deleted file mode 100644
index 452fbeb..0000000
--- a/src/CwdFileLogger.cc
+++ /dev/null
@@ -1,153 +0,0 @@
-/******************************************************************************/
-/* LOGGING SYSTEM - BUILT-IN LOGGERS - NON-VFS FILE LOG WRITER ****************/
-/******************************************************************************/
-
-#include <lw/lib/BuiltinLoggers.hh>
-#include <lw/lib/SRDParser.hh>
-using namespace lw;
-
-
-namespace {
-
-
-char const* const V_Name_ = "preinit-file";
-inline T_String Name_( ) { return T_String::Pooled( V_Name_ ); }
-
-bool CFLCPath_( T_SRDParserData const& data )
-{
-	auto const& ptok( (*data.input)[ 1 ] );
-	auto lconf( data.targetData->value< RP_LogWriterConfiguration >( ) );
-	( dynamic_cast< T_CWDFileLogWriterCfg* >( lconf ) )->setPath( ptok.stringValue( ) );
-	return true;
-}
-
-bool CFLCAppend_( T_SRDParserData const& data )
-{
-	auto lconf( data.targetData->value< RP_LogWriterConfiguration >( ) );
-	( dynamic_cast< T_CWDFileLogWriterCfg* >( lconf ) )->setAppend( true );
-	return true;
-}
-
-bool CFLCTruncate_( T_SRDParserData const& data )
-{
-	auto lconf( data.targetData->value< RP_LogWriterConfiguration >( ) );
-	( dynamic_cast< T_CWDFileLogWriterCfg* >( lconf ) )->setAppend( false );
-	return true;
-}
-
-}
-
-
-/*= T_CWDFileLogWriterFactory ==================================================*/
-
-T_CWDFileLogWriterFactory::T_CWDFileLogWriterFactory( )
-	: A_LogWriterFactory( Name_( ) )
-{ }
-
-RP_LogWriterConfiguration T_CWDFileLogWriterFactory::createConfiguration( T_String const& name ) const
-{
-	RP_LogWriterConfiguration p( new T_CWDFileLogWriterCfg( ) );
-	p->setName( name );
-	return p;
-}
-
-OP_LogWriter T_CWDFileLogWriterFactory::createLogWriter( OP_LogWriterConfiguration&& configuration ) const
-{
-	T_CWDFileLogWriter* p( new T_CWDFileLogWriter( std::move( configuration ) ) );
-	return OwnRawPointer( p );
-}
-
-void T_CWDFileLogWriterFactory::initializeSyntax( T_SRDParserDefs& , T_SRDContext& main ) const
-{
-	using namespace lw::SRD;
-	main << ( Rule( ) << "file" << Text( ) << CFLCPath_ );
-	main << ( Rule( ) << "append" << CFLCAppend_ );
-	main << ( Rule( ) << "truncate" << CFLCTruncate_ );
-}
-
-
-/*= T_CWDFileLogWriterCfg ======================================================*/
-
-T_CWDFileLogWriterCfg::T_CWDFileLogWriterCfg( )
-	: T_LogWriterConfiguration( Name_( ) )
-{ }
-
-T_CWDFileLogWriterCfg::T_CWDFileLogWriterCfg( T_CWDFileLogWriterCfg const& source )
-	: T_LogWriterConfiguration( source ) , path_( source.path_ ) ,
-		append_( source.append_ )
-{ }
-
-OP_LogWriterConfiguration T_CWDFileLogWriterCfg::clone( )
-{
-	T_CWDFileLogWriterCfg* ptr( new T_CWDFileLogWriterCfg( *this ) );
-	return OwnRawPointer( ptr );
-}
-
-void T_CWDFileLogWriterCfg::check( T_SRDErrors& errors , T_SRDList const& input )
-{
-	T_LogWriterConfiguration::check( errors , input );
-	if ( !path_ ) {
-		errors.add( "no file selected" , input[ 0 ] );
-	}
-}
-
-
-/*= T_CWDFileLogWriter =========================================================*/
-
-T_CWDFileLogWriter::T_CWDFileLogWriter( OP_LogWriterConfiguration&& configuration )
-	: A_LogWriter( std::move( configuration ) )
-{ }
-
-void T_CWDFileLogWriter::log( T_LogTimestamp const& timestamp ,
-		E_LogLevel level , T_LogPath const& path ,
-		T_LogStringData const& data , uint32_t size )
-{
-	using namespace std::chrono;
-
-	char timeBuffer[ 128 ];
-	std::time_t tst( T_LogTimestamp::clock::to_time_t( timestamp ) );
-	std::strftime( timeBuffer , 128 , "%Y-%m-%d %H:%M:%S" , std::gmtime( &tst ) );
-	const auto ms( ( duration_cast< milliseconds >( timestamp - T_LogTimestamp( ) ) ).count( ) % 1000 );
-
-	T_StringBuilder sb;
-
-	sb << timeBuffer << '.';
-	if ( ms < 100 ) {
-		sb << '0';
-		if ( ms < 10 ) {
-			sb << '0';
-		}
-	}
-	sb << ms << ' ' << path.toString( ) << " - " << level << ": ";
-	sb.append( &( (*data) [ 0 ] ) , size );
-	sb << '\n';
-
-	auto const& cfg( configuration< T_CWDFileLogWriterCfg >( ) );
-	auto const& p( cfg.path( ) );
-	if ( !file_ ) {
-		file_ = NewOwned< T_File >( p , cfg.append( ) ? E_FileMode::READ_WRITE : E_FileMode::OVERWRITE );
-		if ( !file_ ) {
-			disable( );
-			return;
-		}
-
-		try {
-			file_->open( );
-		} catch ( X_StreamError const& ) {
-			disable( );
-			file_.clear( );
-			return;
-		}
-	}
-
-	try {
-		file_->position( 0 , true );
-		file_->write( sb.data( ) , sb.size( ) );
-		file_->flush( );
-	} catch ( X_StreamError ) {
-		disable( );
-		file_.clear( );
-		return;
-	}
-}
-
diff --git a/src/DynLib.cc b/src/DynLib.cc
index 8a255ee..c0de76b 100644
--- a/src/DynLib.cc
+++ b/src/DynLib.cc
@@ -2,9 +2,9 @@
 /* DYNAMIC LIBRARIES **********************************************************/
 /******************************************************************************/
 
-#include <lw/lib/DynLib.hh>
-#include <lw/lib/Threading.hh>
-using namespace lw;
+#include <ebcl/DynLib.hh>
+#include <ebcl/Threading.hh>
+using namespace ebcl;
 
 #ifdef _WIN32
 # error "Not implemented"
diff --git a/src/GameLoop.cc b/src/GameLoop.cc
deleted file mode 100644
index 5a3930c..0000000
--- a/src/GameLoop.cc
+++ /dev/null
@@ -1,140 +0,0 @@
-/******************************************************************************/
-/* GAME'S MAIN LOOP ***********************************************************/
-/******************************************************************************/
-
-#include <lw/lib/GameLoop.hh>
-#include <lw/lib/Threading.hh>
-#include <lw/lib/Log.hh>
-#include <lw/lib/LW.hh>
-using namespace lw;
-
-
-/*= T_GameLoopPrivate_ =======================================================*/
-
-namespace {
-struct T_GameLoopPrivate_
-{
-	T_Logger logger{ "/core/loop" };
-
-	OP_Thread thread;
-	bool active = false;
-	bool forceShutdown = false;
-
-	T_Mutex mutex;
-	T_Condition cond;
-	T_RingBuffer< T_UIMessage > messages{ 64 };
-
-	/* Game loop */
-	void run( ) noexcept;
-
-	/* Wait for the next message, no timeout */
-	bool nextMessage(
-			T_UIMessage& message ) noexcept;
-};
-} // namespace
-
-/*----------------------------------------------------------------------------*/
-
-inline void T_GameLoopPrivate_::run( ) noexcept
-{
-	const bool trace( logger.hasLevel( E_LogLevel::TRACE ) );
-	logger.debug( ) << "Game loop thread starting";
-
-	while ( !forceShutdown ) {
-		T_UIMessage message;
-		if ( !nextMessage( message ) ) {
-			continue;
-		}
-
-		const auto mt( message.type( ) );
-		if ( trace ) {
-			logger.trace( ) << "Got message " << mt;
-		}
-
-		switch ( mt ) {
-
-		    case lw::E_GameUIMessage::QUIT:
-			// FIXME quit properly
-			LW::ui( ).putMessage( E_GameLoopMessage::TERMINATED );
-			forceShutdown = true;
-			break;
-
-		    default:
-			logger.debug( ) << "Unhandled message " << mt;
-			break;
-
-		}
-	}
-
-	active = false;
-	logger.debug( ) << "Game loop thread exiting";
-}
-
-inline bool T_GameLoopPrivate_::nextMessage(
-		T_UIMessage& message ) noexcept
-{
-	T_ExclusiveLock lock( mutex );
-	cond.wait( lock , [this]() {
-			return messages.size( ) != 0 || forceShutdown;
-		} );
-	return messages.readNext( message )
-		&& message.hasMessage( );
-}
-
-
-/*= T_GameLoop ===============================================================*/
-
-#define M_PRIVATE_ \
-	auto& pi( p< T_GameLoopPrivate_ >( ) );
-
-T_GameLoop::T_GameLoop( ) noexcept
-	: A_PrivateImplementation( new T_GameLoopPrivate_( ) )
-{ }
-
-bool T_GameLoop::active( ) const noexcept
-{
-	M_PRIVATE_;
-	return bool( pi.thread ) && !pi.active;
-}
-
-void T_GameLoop::start( ) noexcept
-{
-	M_PRIVATE_;
-	pi.logger.trace( ) << "Starting main loop thread";
-	if ( pi.thread ) {
-		pi.logger.warning( )
-			<< "The main loop thread is already active?!";
-	}
-	pi.active = true;
-	pi.thread = NewOwned< T_Thread >( [&]{
-			pi.run( );
-		} );
-}
-
-void T_GameLoop::shutdown( ) noexcept
-{
-	M_PRIVATE_;
-	if ( !pi.thread ) {
-		pi.logger.trace( )
-			<< "The main loop thread is not present";
-		return;
-	}
-
-	if ( pi.active ) {
-		pi.logger.notice( ) << "Main loop is still active at shutdown!";
-		pi.forceShutdown = true;
-
-		T_ExclusiveLock lock( pi.mutex );
-		pi.cond.notify_one( );
-	}
-	pi.thread->join( );
-	pi.thread.clear( );
-}
-
-void T_GameLoop::putMessage( T_UIMessage&& message ) noexcept
-{
-	M_PRIVATE_;
-	T_ExclusiveLock lock( pi.mutex );
-	pi.messages.put( std::move( message ) );
-	pi.cond.notify_one( );
-}
diff --git a/src/LW.cc b/src/LW.cc
deleted file mode 100644
index 2e0db32..0000000
--- a/src/LW.cc
+++ /dev/null
@@ -1,603 +0,0 @@
-/******************************************************************************/
-/* MAIN CLASS *****************************************************************/
-/******************************************************************************/
-
-#include <lw/lib/LW.hh>
-#include <lw/lib/BuiltinLoggers.hh>
-#include <lw/lib/SRDBinary.hh>
-#include <lw/lib/SRDParser.hh>
-#include <lw/lib/SRDText.hh>
-#include <lw/lib/MemoryStreams.hh>
-#include <lw/lib/VFSDrivers.hh>
-using namespace lw;
-
-
-/*= LIBRARY DATA =============================================================*/
-
-namespace {
-#ifdef LW_BUILD
-# include "lib-rom.hh"
-#else
-const uint8_t lw_library_rom[] = { 0 };
-#endif
-} // namespace
-
-
-/*= INTERNALS ================================================================*/
-
-namespace {
-
-/* Command line arguments */
-struct T_CommandLine_
-{
-	T_String homePath;
-	T_Array< T_String > extraPaths;
-	T_String ui;
-};
-
-struct T_LWInternals_
-{
-	T_LWComponents& components;
-
-	const T_String executablePath_;
-	T_CommandLine_ arguments_;
-
-	OP_LoggingSystem loggingSystem;
-	T_Logger lPreinit;
-	T_Logger logger;
-	T_Logger lShutdown;
-
-	bool uiInitialised;
-
-	// ---------------------------------------------------------------------
-
-	T_LWInternals_( T_String const& executablePath ,
-			T_LWComponents& components ) noexcept;
-
-	// ---------------------------------------------------------------------
-
-	[[noreturn]] void fatalError( T_Logger& logger , char const* text );
-
-	/* Load a logging configuration file */
-	OP_LoggingConfiguration loadLoggingConfigFile(
-			T_Logger& logger ,
-			char const* path ) noexcept;
-
-	// ---------------------------------------------------------------------
-
-	/* Pre-initialisation - console, logging, VFS, mods manager */
-	void preInit( T_String const& commandLine );
-
-	OP_LoggingConfiguration getInitialLoggingConfig( );
-	void parseCommandLine(
-			T_String const& commandLine );
-	OP_LoggingConfiguration loadPreinitLoggingConfig( );
-	OP_LoggingConfiguration getDefaultPreinitLoggingConfig( );
-	T_ModsManagerConfiguration getModsManagerConfiguration( );
-
-	// ---------------------------------------------------------------------
-
-	void init( );
-	void run( );
-
-	// ---------------------------------------------------------------------
-
-	void shutdown( );
-	OP_LoggingConfiguration loadShutdownLoggingConfig( );
-	OP_LoggingConfiguration getDefaultShutdownLoggingConfig( );
-};
-
-} // namespace
-
-/*----------------------------------------------------------------------------*/
-
-inline T_LWInternals_::T_LWInternals_(
-		T_String const& executablePath ,
-		T_LWComponents& components ) noexcept
-	: components( components ) ,
-		executablePath_( executablePath ) ,
-		lPreinit( "/core/preinit" ) ,
-		logger( "/core/init" ) ,
-		lShutdown( "/core/shutdown" )
-{ }
-
-/*----------------------------------------------------------------------------*/
-
-void T_LWInternals_::fatalError( T_Logger& logger , char const* message )
-{
-	logger.critical( ) << message;
-	// XXX UI-specific error display if possible
-	throw X_FatalError( );
-}
-
-OP_LoggingConfiguration T_LWInternals_::loadLoggingConfigFile(
-		T_Logger& logger ,
-		char const* const path ) noexcept
-{
-	T_StringBuilder sb;
-	sb << path << ".srd";
-	const T_String srd( std::move( sb ) );
-	sb << path << ".srb";
-	const T_String srb( std::move( sb ) );
-
-	auto& vfs( LW::vfs( ) );
-	const bool useSRD( vfs.typeOf( srd ) == E_VFSEntryType::FILE );
-	if ( !useSRD && vfs.typeOf( srb ) != E_VFSEntryType::FILE ) {
-		return {};
-	}
-	T_String const& pstr( useSRD ? srd : srb );
-
-	auto cfg( LW::logWriters( ).getParserConfiguration( ) );
-	T_SRDParser parser( cfg );
-	OP_SRDReader reader( ([&]() -> OP_SRDReader {
-			if ( useSRD ) {
-				return NewOwned< T_SRDTextReader >( parser );
-			} else {
-				return NewOwned< T_SRDBinaryReader >( parser );
-			}
-		})( ) );
-	try {
-		OP_InputStream input( vfs.read( pstr ) );
-		if ( !input ) {
-			throw X_StreamError( E_StreamError::UNAVAILABLE );
-		}
-		reader->read( pstr , *input );
-		return NewOwned< T_LoggingConfiguration >(
-				std::move( *parser.getData< SP_LoggingConfiguration >( ) ) );
-
-	} catch ( X_StreamError const& e ) {
-		logger.warning( ) << "could not load '"
-			<< pstr << "': " << e.what( );
-	} catch ( X_SRDErrors const& errors ) {
-		errors.log( lPreinit );
-	}
-
-	return {};
-}
-
-
-/*= PRE-INITIALISATION =======================================================*/
-
-void T_LWInternals_::preInit(
-		T_String const& commandLine )
-{
-	// Initialise the console, if we can
-	components.console = NewOwned< T_Console >( );
-	components.console->mode( E_ConsoleMode::OPTIONAL );
-
-	// Register basic log writers
-	components.logWriters = NewOwned< T_LogWriterRegistry >( );
-	LW::logWriters( ).add< T_CWDFileLogWriterFactory >( ).automatic( false );
-	LW::logWriters( ).add< T_ConsoleLogWriterFactory >( LW::console( ) ).automatic( false );
-
-	// Initialise the logging system with a temporary configuration
-	loggingSystem = NewOwned< T_LoggingSystem >(
-			LW::logWriters( ) ,
-			getInitialLoggingConfig( ) );
-
-	// Parse command line arguments
-	if ( commandLine ) {
-		parseCommandLine( commandLine );
-	}
-
-	// Initialise the VFS
-	try {
-		if ( arguments_.homePath ) {
-			components.vfs = NewOwned< T_VFS >( arguments_.homePath );
-		} else {
-			components.vfs = NewOwned< T_VFS >( );
-		}
-	} catch ( X_VFSInitialisationFailure const& ) {
-		fatalError( lPreinit , "Could not initialise the VFS." );
-	}
-
-	// Add the VFS-based log writer, then try reconfiguring
-	LW::logWriters( ).add< T_TextFileLogWriterFactory >( LW::vfs( ) ).automatic( false );
-	loggingSystem->reconfigure( loadPreinitLoggingConfig( ) );
-
-	// Finish configuring the VFS
-	lPreinit.debug( ) << "Adding install path '" << executablePath_
-		<< "' to the VFS";
-	{
-		auto ipvfsd( LW::vfs( ).addDriver< T_VFSFilesystemDriver >(
-				executablePath_ ) );
-		if ( !ipvfsd ) {
-			fatalError( lPreinit , "Could not initialise the VFS." );
-		} else {
-			ipvfsd.automatic( false );
-		}
-	}
-	const uint32_t nExtraPaths( arguments_.extraPaths.size( ) );
-	for ( uint32_t i = 0 ; i < nExtraPaths ; i ++ ) {
-		auto const& path( arguments_.extraPaths[ i ] );
-		lPreinit.trace( ) << "Adding extra path '" << path << "' to the VFS";
-		auto vfsd( LW::vfs( ).addDriver< T_VFSFilesystemDriver >( path ) );
-		if ( vfsd ) {
-			vfsd.automatic( false );
-		} else {
-			lPreinit.warning( ) << "unable to add directory '"
-				<< path << "' to the VFS";
-		}
-	}
-	lPreinit.debug( ) << "Adding library data to the VFS";
-	LW::vfs( ).addDriver( LW::getLibData( ) ).automatic( false );
-
-	// Create the global preprocessor configuration
-	lPreinit.trace( ) << "Creating SRD preprocessor configuration";
-	components.ppConfig = NewOwned< T_SRDPreprocessorConfig >( );
-	components.ppConfig->addBuiltinCommands( );
-	components.ppConfig->addVFSCommands( *components.vfs );
-
-	// Initialise the mods manager
-	lPreinit.trace( ) << "Initialising mods manager";
-	components.mods = NewOwned< T_ModsManager >(
-			getModsManagerConfiguration( ) );
-	auto& mods( LW::mods( ) );
-	if ( !mods.scanForMods( ) ) {
-		// TODO later - switch to installer
-		fatalError( lPreinit , "No mods found" );
-	}
-	if ( !mods.resolveDependencies( ) ) {
-		// TODO later - switch to installer
-		fatalError( lPreinit ,
-				"Could not find a valid set of mods "
-				"matching the current configuration" );
-	}
-
-	// Pre-initialise mods
-	mods.preinitCommon( );
-	components.ui = arguments_.ui
-			? mods.preinitUIMods( arguments_.ui )
-			: mods.preinitUIMods( );
-	if ( !components.ui ) {
-		fatalError( lPreinit , "Unable to start the user interface." );
-	}
-	uiInitialised = false;
-
-	// Create the main loop object
-	components.gameLoop = NewOwned< T_GameLoop >( );
-	lPreinit.trace( ) << "UI & game loop created";
-
-	// Load main logging configuration
-	auto lc( loadLoggingConfigFile( lPreinit , "/logging" ) );
-	if ( lc ) {
-		loggingSystem->reconfigure( std::move( lc ) );
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-OP_LoggingConfiguration T_LWInternals_::getInitialLoggingConfig( )
-{
-	auto logCfg( NewOwned< T_LoggingConfiguration >( ) );
-	logCfg->setMinLevelFor( T_LogPath( ) , E_LogLevel::NOTICE );
-	{
-		const T_String console( T_String::Pooled( "console" ) );
-		logCfg->addLogWriter( T_LogPath( ) , console );
-		auto writerConfig( LW::logWriters( )
-				.get( console )
-				->createConfiguration( console ) );
-		logCfg->putLogWriter( OwnRawPointer( writerConfig ) );
-	}
-	{
-		const T_String tfw( "preinit-file" );
-		T_CWDFileLogWriterCfg* writerConfig(
-				dynamic_cast< T_CWDFileLogWriterCfg *>(
-					LW::logWriters( )
-						.get( tfw )
-						->createConfiguration( tfw ) ) );
-		writerConfig->setPath( T_String::Pooled( "legacyworlds-preinit.log" ) );
-		writerConfig->setAppend( false );
-		logCfg->putLogWriter( OwnRawPointer( writerConfig ) );
-		logCfg->addLogWriter( T_LogPath( ) , tfw );
-	}
-	return logCfg;
-}
-
-/*----------------------------------------------------------------------------*/
-
-void T_LWInternals_::parseCommandLine(
-		T_String const& commandLine )
-{
-	const T_SRDParserConfig clpConfig( ([]( T_CommandLine_* cl ) {
-		using namespace lw::SRD;
-		T_SRDParserDefs defs( "default" );
-
-		defs << OnStart( [cl]( T_SRDParserData const& d ) -> bool {
-			*( d.currentData ) = cl;
-			return true;
-		} );
-
-		defs.context( "default" )
-			<< ( Rule( ) << "ui" << Text( )
-				<< []( T_SRDParserData const& d ) -> bool {
-					auto cl( d.currentData->value< T_CommandLine_* >( ) );
-					if ( cl->ui ) {
-						d.errors.add( "duplicate UI identifier" , (*d.input)[ 0 ] );
-					} else {
-						cl->ui = (*d.input)[ 1 ].stringValue( );
-					}
-					return true;
-				} )
-			<< ( Rule( ) << "home" << Text( )
-				<< []( T_SRDParserData const& d ) -> bool {
-					auto cl( d.currentData->value< T_CommandLine_* >( ) );
-					if ( cl->homePath ) {
-						d.errors.add( "duplicate home directory" , (*d.input)[ 0 ] );
-					} else {
-						cl->homePath = (*d.input)[ 1 ].stringValue( );
-					}
-					return true;
-				} )
-			<< ( Rule( ) << "extra-paths" << ( AtLeast( 1 ) << Text( ) )
-				<< []( T_SRDParserData const& d ) -> bool {
-					auto cl( d.currentData->value< T_CommandLine_* >( ) );
-					auto const& input( *d.input );
-					const auto nPaths( input.size( ) );
-					for ( uint32_t i = 1 ; i < nPaths ; i ++ ) {
-						auto const& tok( input[ i ] );
-						if ( cl->extraPaths.contains( tok.stringValue( ) ) ) {
-							d.errors.add( "duplicate data path" , tok );
-						} else {
-							cl->extraPaths.add( tok.stringValue( ) );
-						}
-					}
-					return true;
-				} );
-
-		return T_SRDParserConfig( defs );
-	})( &arguments_ ) );
-
-	T_SRDParser parser( clpConfig );
-	T_SRDTextReader reader( parser );
-	T_MemoryInputStream input( commandLine.data( ) , commandLine.size( ) );
-	try {
-		reader.read( T_String( "command line" ) , input );
-	} catch ( X_SRDErrors const& errors ) {
-		errors.log( lPreinit );
-		fatalError( lPreinit , "Invalid command line arguments" );
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-OP_LoggingConfiguration T_LWInternals_::loadPreinitLoggingConfig( )
-{
-	auto rv( loadLoggingConfigFile( lPreinit , "/logging-pre" ) );
-	if ( !rv ) {
-		return getDefaultPreinitLoggingConfig( );
-	}
-	return rv;
-}
-
-OP_LoggingConfiguration T_LWInternals_::getDefaultPreinitLoggingConfig( )
-{
-	auto logCfg( NewOwned< T_LoggingConfiguration >( ) );
-	{
-		const T_String console( T_String::Pooled( "console" ) );
-		auto writerConfig( LW::logWriters( )
-				.get( console )
-				->createConfiguration( console ) );
-		writerConfig->setMinLevel( E_LogLevel::NOTICE );
-		logCfg->putLogWriter( OwnRawPointer( writerConfig ) );
-		logCfg->addLogWriter( T_LogPath( ) , console );
-	}
-	{
-		const T_String tfw( "text-file" );
-		T_TextFileLogWriterCfg* writerConfig(
-				dynamic_cast< T_TextFileLogWriterCfg *>(
-					LW::logWriters( )
-					.get( tfw )
-					->createConfiguration( tfw ) ) );
-		writerConfig->setMinLevel( E_LogLevel::INFO );
-		writerConfig->setPath( "/preinit.log" );
-		writerConfig->setAppend( false );
-		logCfg->putLogWriter( OwnRawPointer( writerConfig ) );
-		logCfg->addLogWriter( T_LogPath( ) , tfw );
-	}
-	return logCfg;
-}
-
-/*----------------------------------------------------------------------------*/
-
-T_ModsManagerConfiguration T_LWInternals_::getModsManagerConfiguration( )
-{
-	using T_MMC = T_ModsManagerConfiguration;
-	using SP_MMC = SP_ModsManagerConfiguration;
-
-	const T_String mmcfgf( "/mods.srd" );
-	auto& vfs( LW::vfs( ) );
-	if ( vfs.typeOf( mmcfgf ) == E_VFSEntryType::FILE ) {
-		auto pconf( T_MMC::GetParserConfig( ) );
-		T_SRDParser parser( pconf );
-		T_SRDTextReader reader( parser );
-		try {
-			OP_InputStream input( vfs.read( mmcfgf ) );
-			if ( !input ) {
-				throw X_StreamError( E_StreamError::UNAVAILABLE );
-			}
-			reader.read( mmcfgf , *input );
-			return std::move( *parser.getData< SP_MMC >( ) );
-
-		} catch ( X_StreamError const& e ) {
-			lPreinit.warning( ) << "could not load '" << mmcfgf << "': "
-				<< e.what( );
-		} catch ( X_SRDErrors const& errors ) {
-			errors.log( lPreinit );
-		}
-	}
-	lPreinit.debug( ) << "Using default mods configuration";
-	return T_MMC::DefaultConfiguration( );
-}
-
-
-/*= INITIALISATION ===========================================================*/
-
-void T_LWInternals_::init( )
-{
-	// Initialise all the mods
-	const uint32_t nLoaded( components.mods->modsCount( ) );
-	uint32_t initialised = 0;
-	components.mods->initialise(
-		[&]( RPC_ModInfo mi ) -> F_UpdateInitProgress {
-			const T_ProgressInfoPart main{
-				([&](){
-					T_StringBuilder sb( "Initializing mod " );
-					sb << mi->identifier.name;
-					return T_String{ std::move( sb ) };
-				})( ) , initialised + 1 , nLoaded + 2
-			};
-			initialised ++;
-			components.ui->setInitProgress(
-					T_ProgressInfo{ main } );
-
-			return [&]( T_ProgressInfoPart part ) {
-				components.ui->setInitProgress(
-						T_ProgressInfo{ main , part } );
-			};
-		} );
-
-	// Initialise UI
-	const T_ProgressInfoPart uiInitMain{
-		T_String( "Initializing user interface" ) ,
-		initialised + 1 , nLoaded + 2
-	};
-	components.ui->setInitProgress( T_ProgressInfo{ uiInitMain } );
-	if ( ! components.ui->init( [&]( T_ProgressInfoPart part ) {
-				components.ui->setInitProgress(
-					T_ProgressInfo{ uiInitMain , part } );
-			}) ) {
-		fatalError( logger , "Failed to initialize user interface" );
-	}
-	uiInitialised = true;
-	
-	// Start game loop
-	components.gameLoop->start( );
-}
-
-/*FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME*/
-
-void T_LWInternals_::run( )
-{
-	components.ui->run( );
-}
-
-
-/*= SHUTDOWN =================================================================*/
-
-void T_LWInternals_::shutdown( )
-{
-	lShutdown.trace( ) << "Starting shutdown";
-
-	// Shutdown game loop if it's still active
-	if ( components.gameLoop ) {
-		components.gameLoop->shutdown( );
-	}
-
-	// If the UI is present and initialised, shut it down
-	if ( components.ui && uiInitialised ) {
-		components.ui->shutdown( );
-		uiInitialised = false;
-	}
-
-	// Shut down mods
-	if ( components.mods ) {
-		components.mods->shutdown( );
-	}
-
-	// Reset logging configuration
-	lShutdown.trace( ) << "Resetting logger configuration";
-	loggingSystem->reconfigure( loadShutdownLoggingConfig( ) );
-
-	// Terminate the UI
-	if ( components.ui ) {
-		components.ui->postshutdown( );
-		components.ui.clear( );
-		components.gameLoop.clear( );
-		lShutdown.trace( ) << "UI and game loop terminated";
-	}
-
-	// Clear mods
-	if ( components.mods ) {
-		components.mods->unload( );
-		components.mods.clear( );
-		lShutdown.trace( ) << "Mods unloaded";
-	}
-
-	// Clear remaining components
-	lShutdown.trace( ) << "Terminating core components";
-	components.ppConfig.clear( );
-	loggingSystem.clear( );
-	components.logWriters.clear( );
-	components.console.clear( );
-	components.vfs.clear( );
-}
-
-/*----------------------------------------------------------------------------*/
-
-OP_LoggingConfiguration T_LWInternals_::loadShutdownLoggingConfig( )
-{
-	auto rv( loadLoggingConfigFile( lShutdown , "/logging-post" ) );
-	if ( !rv ) {
-		return getDefaultShutdownLoggingConfig( );
-	}
-	return rv;
-}
-
-OP_LoggingConfiguration T_LWInternals_::getDefaultShutdownLoggingConfig( )
-{
-	auto logCfg( NewOwned< T_LoggingConfiguration >( ) );
-	{
-		const T_String console( T_String::Pooled( "console" ) );
-		auto writerConfig( LW::logWriters( )
-				.get( console )
-				->createConfiguration( console ) );
-		writerConfig->setMinLevel( E_LogLevel::NOTICE );
-		logCfg->putLogWriter( OwnRawPointer( writerConfig ) );
-		logCfg->addLogWriter( T_LogPath( ) , console );
-	}
-	{
-		const T_String tfw( "text-file" );
-		T_TextFileLogWriterCfg* writerConfig(
-				dynamic_cast< T_TextFileLogWriterCfg *>(
-					LW::logWriters( )
-					.get( tfw )
-					->createConfiguration( tfw ) ) );
-		writerConfig->setMinLevel( E_LogLevel::INFO );
-		writerConfig->setPath( "/shutdown.log" );
-		writerConfig->setAppend( false );
-		logCfg->putLogWriter( OwnRawPointer( writerConfig ) );
-		logCfg->addLogWriter( T_LogPath( ) , tfw );
-	}
-	return logCfg;
-}
-
-
-/*= MAIN CLASS ===============================================================*/
-
-LW* LW::instance_ = nullptr;
-
-LW::LW( T_String const& commandLine , T_String const& executablePath )
-{
-	assert( instance_ == nullptr );
-	instance_ = this;
-	T_LWInternals_ pi( executablePath , components );
-	try {
-		pi.preInit( commandLine );
-		pi.init( );
-		pi.run( );
-	} catch ( X_FatalError const& ) {
-		pi.shutdown( );
-		components.~T_LWComponents( );
-		instance_ = nullptr;
-		throw;
-	}
-	pi.shutdown( );
-	instance_ = nullptr;
-}
-
-OP_VFSDriver LW::getLibData( ) noexcept
-{
-	return NewOwned< T_VFSRomDriver >(
-			lw_library_rom , sizeof( lw_library_rom ) );
-}
diff --git a/src/Log.cc b/src/Log.cc
deleted file mode 100644
index 20c65d5..0000000
--- a/src/Log.cc
+++ /dev/null
@@ -1,1041 +0,0 @@
-/******************************************************************************/
-/* LOGGING SYSTEM *************************************************************/
-/******************************************************************************/
-
-
-#include <lw/lib/Log.hh>
-#include <lw/lib/SRDParser.hh>
-using namespace lw;
-
-
-/*= IMPLEMENTATION CLASSES ===================================================*/
-
-namespace {
-
-struct T_LoggerPrivate_
-{
-	T_LogPath path_;
-	bool connected_;
-	uint32_t pathIndex_;
-	E_LogLevel minLevel_;
-	E_LogLevel maxLevel_;
-
-	T_LoggerPrivate_( T_LogPath&& path );
-	T_LoggerPrivate_( T_LoggerPrivate_ const& other );
-	~T_LoggerPrivate_( );
-
-	void connect( );
-};
-
-struct T_LoggingSystemPrivate_
-{
-	struct T_LogEntry
-	{
-		T_LogTimestamp time;
-		E_LogLevel level;
-		uint32_t path;
-		T_LogStringData string;
-		uint32_t size;
-
-		T_LogEntry( ) = default;
-
-		T_LogEntry( E_LogLevel level , uint32_t path ,
-				T_LogStringData&& string , uint32_t size );
-		
-		T_LogEntry( T_LogEntry const& ) = delete;
-		T_LogEntry( T_LogEntry&& ) noexcept = default;
-
-		T_LogEntry& operator =( T_LogEntry const& ) = delete;
-		T_LogEntry& operator =( T_LogEntry&& ) noexcept = default;
-	};
-
-	static constexpr uint32_t C_MAX_REUSE_SIZE = 256;
-	static constexpr uint32_t C_MAX_REUSE_QUANTITY = 64;
-
-	static T_LoggingSystemPrivate_ * instance_;
-	static T_Mutex loggersMutex_;
-	static T_Array< T_LoggerPrivate_ * > loggers_;
-
-	RP_LoggingSystem main_;
-
-	T_LogWriterRegistry const& registry_;
-	OP_LoggingConfiguration config_;
-	T_Array< OP_LogWriter > writers_;
-
-	OP_Thread thread_;
-
-	T_Mutex queueMutex_;
-	T_Condition queueCond_;
-	bool exit_;
-	T_RingBuffer< T_LogEntry > queue_;
-	T_Array< T_LogStringData > freeList_;
-	T_Array< T_LogPath > paths_;
-	T_Array< uint32_t > pathRefCount_;
-
-	// ---------------------------------------------------------------------
-
-	T_LoggingSystemPrivate_(
-			RP_LoggingSystem main ,
-			T_LogWriterRegistry const& registry ,
-			OP_LoggingConfiguration&& config );
-	~T_LoggingSystemPrivate_( );
-
-	// ---------------------------------------------------------------------
-
-	void log( E_LogLevel level , uint32_t pathIndex , char const* data , uint32_t size );
-
-	void initLogWriters( );
-
-	// ---------------------------------------------------------------------
-
-	void startLoggingThread( );
-	void stopLoggingThread( );
-	void expandQueue( );
-
-	// ---------------------------------------------------------------------
-
-	void loggingThread( );
-	void writeEntry( T_LogEntry const& entry );
-};
-}
-
-
-/*= E_LogLevel ===============================================================*/
-
-T_StringBuilder& lw::operator<< ( T_StringBuilder& sb , E_LogLevel level )
-{
-	switch ( level ) {
-		case E_LogLevel::TRACE: sb << "trace"; break;
-		case E_LogLevel::DEBUG: sb << "debug"; break;
-		case E_LogLevel::INFO: sb << "info"; break;
-		case E_LogLevel::NOTICE: sb << "notice"; break;
-		case E_LogLevel::WARNING: sb << "warning"; break;
-		case E_LogLevel::ERROR: sb << "error"; break;
-		case E_LogLevel::CRITICAL: sb << "critical"; break;
-	}
-	return sb;
-}
-
-
-/*= T_LogPath ================================================================*/
-
-T_LogPath::T_LogPath( )
-	: path_( 1 ) , valid_( true )
-{ }
-
-T_LogPath::T_LogPath( T_Array< T_String > const& path )
-	: path_( path ) , valid_( checkValid( ) )
-{ }
-
-T_LogPath::T_LogPath( T_Array< T_String >&& path )
-	: path_( std::move( path ) ) , valid_( checkValid( ) )
-{ }
-
-T_LogPath::T_LogPath( std::initializer_list< char const* > arguments )
-	: path_( arguments.size( ) )
-{
-	for ( char const* arg : arguments ) {
-		path_.addNew( T_String::Pooled( arg ) );
-	}
-	valid_ = checkValid( );
-}
-
-/*----------------------------------------------------------------------------*/
-
-T_LogPath T_LogPath::FromString( T_String const& string )
-{
-	T_StringIterator it( string );
-	T_Array< T_String > pieces;
-	uint32_t pieceStart( 0 );
-	bool atStart( true );
-	bool afterSlash( false );
-	bool valid( true );
-
-	while ( !it.atEnd( ) ) {
-		const T_Character c( it );
-
-		if ( c == '/' ) {
-			if ( !( atStart || afterSlash ) ) {
-				pieces.add( string.range( pieceStart , it.index( ) - 1 ) );
-				afterSlash = true;
-			}
-		} else {
-			if ( atStart ) {
-				atStart = false;
-				afterSlash = true;
-			}
-			if ( afterSlash ) {
-				afterSlash = false;
-				pieceStart = it.index( );
-			}
-			valid = valid && !c.isControl( );
-		}
-
-		it.next( );
-	}
-	if ( !( atStart || afterSlash ) ) {
-		pieces.add( string.range( pieceStart , it.index( ) ) );
-	}
-
-	if ( pieces.size( ) == 0 ) {
-		return T_LogPath( );
-	}
-
-	T_LogPath lp( pieces.size( ) , valid );
-	lp.path_.addAll( std::move( pieces ) );
-	return lp;
-}
-
-/*----------------------------------------------------------------------------*/
-
-T_LogPath T_LogPath::parent( ) const
-{
-	const auto sz( size( ) );
-	if ( sz > 1 ) {
-		if ( valid_ ) {
-			T_LogPath lp( sz - 1 , true );
-			for ( uint32_t i = 0 ; i < sz - 1 ; i ++ ) {
-				lp.path_.add( path_[ i ] );
-			}
-			return lp;
-		} else {
-			return T_LogPath( path_.copyRange( 0 , sz - 2 ) );
-		}
-	} else {
-		return T_LogPath( );
-	}
-}
-
-T_LogPath T_LogPath::child( T_String const& name ) const
-{
-	const auto sz( size( ) );
-	T_LogPath lp( sz + 1 , valid_ && checkName( name ) );
-	lp.path_.addAll( path_ );
-	lp.path_.add( name );
-	return lp;
-}
-
-/*----------------------------------------------------------------------------*/
-
-T_String T_LogPath::toString( ) const
-{
-	const auto sz( size( ) );
-	if ( sz ) {
-		T_StringBuilder sb;
-		for ( uint32_t i = 0 ; i < sz ; i ++ ) {
-			sb << '/' << path_[ i ];
-		}
-		return T_String( std::move( sb ) );
-	} else {
-		return T_String::Pooled( "/" );
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-bool T_LogPath::isChildOf( T_LogPath const& other ) const
-{
-	const auto os( other.size( ) );
-	if ( size( ) <= os ) {
-		return false;
-	}
-	for ( uint32_t i = 0 ; i < os ; i ++ ) {
-		if ( path_[ i ] != other.path_[ i ] ) {
-			return false;
-		}
-	}
-	return true;
-}
-
-bool T_LogPath::operator ==( T_LogPath const& other ) const
-{
-	if ( this == &other ) {
-		return true;
-	}
-
-	const auto ms( size( ) );
-	if ( ms != other.size( ) ) {
-		return false;
-	}
-	for ( uint32_t i = 0 ; i < ms ; i ++ ) {
-		if ( path_[ i ] != other.path_[ i ] ) {
-			return false;
-		}
-	}
-	return true;
-}
-
-/*----------------------------------------------------------------------------*/
-
-T_LogPath::T_LogPath( uint32_t size , bool valid )
-	: path_( size ) , valid_( valid )
-{ }
-
-bool T_LogPath::checkValid( ) const
-{
-	const auto s( path_.size( ) );
-	for ( uint32_t i = 0 ; i < s ; i ++ ) {
-		if ( !checkName( path_[ i ] ) ) {
-			return false;
-		}
-	}
-	return true;
-}
-
-bool T_LogPath::checkName( T_String const& name )
-{
-	if ( !name ) {
-		return false;
-	}
-
-	T_StringIterator it( name );
-	while ( !it.atEnd( ) ) {
-		const T_Character c( it );
-		it.next( );
-		if ( c.isControl( ) || c == '/' ) {
-			return false;
-		}
-	}
-	return true;
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_DEFINE_HASH( T_LogPath )
-{
-	const auto sz( item.size( ) );
-	uint32_t hash = 1;
-	for ( uint32_t i = 0 ; i < sz ; i ++ ) {
-		hash = hash * 47 + ComputeHash( item[ i ] );
-	}
-	return hash;
-}
-
-
-/*= T_LogWriterConfiguration ================================================*/
-
-T_LogWriterConfiguration::T_LogWriterConfiguration( T_String const& type )
-	: writerType_( type )
-{ }
-
-T_LogWriterConfiguration::~T_LogWriterConfiguration( )
-{ }
-
-OP_LogWriterConfiguration T_LogWriterConfiguration::clone( )
-{
-	RP_LogWriterConfiguration p( new T_LogWriterConfiguration( *this ) );
-	return OwnRawPointer( p );
-}
-
-void T_LogWriterConfiguration::check( T_SRDErrors& errors , T_SRDList const& input )
-{
-	if ( minLevel_ > maxLevel_ ) {
-		errors.add( "minimal level is higher than maximal level" , input[ 1 ] );
-	}
-}
-
-
-/*= A_LogWriterFactory ==========================================================*/
-
-void A_LogWriterFactory::initializeSyntax( T_SRDParserDefs& , T_SRDContext& ) const
-{ }
-
-
-/*= T_LogWriterRegistryPrivate_ =================================================*/
-
-namespace {
-struct T_LogWriterRegistryPrivate_
-{
-	T_ObjectTable< T_String , OP_LogWriterFactory > factories_{
-		[]( OP_LogWriterFactory const& f ) -> T_String const& {
-			return f->name( );
-		} , 128 , 128
-	};
-
-	T_RegisteredItem::SP_Unregister uf_{
-		NewShared< T_RegisteredItem::F_Unregister >(
-			[this]( void* data ) {
-				factories_.remove( *reinterpret_cast< T_String* >( data ) );
-			}
-		)
-	};
-
-};
-} // namespace
-
-
-/*= T_LogWriterRegistry =========================================================*/
-
-T_LogWriterRegistry::T_LogWriterRegistry( ) noexcept
-	: A_PrivateImplementation( new T_LogWriterRegistryPrivate_( ) )
-{ }
-
-T_RegisteredItem T_LogWriterRegistry::add( OP_LogWriterFactory&& factory ) noexcept
-{
-	auto& pi( p< T_LogWriterRegistryPrivate_ >( ) );
-	if ( !factory || pi.factories_.contains( factory->name( ) ) ) {
-		return T_RegisteredItem( );
-	}
-
-	auto const& fn( factory->name( ) );
-	pi.factories_.add( std::move( factory ) );
-	return T_RegisteredItem( pi.uf_ , new T_String( fn ) );
-}
-
-RPC_LogWriterFactory T_LogWriterRegistry::get( T_String const& name ) const noexcept
-{
-	auto& pi(  );
-	OP_LogWriterFactory const* ptr(
-			p< T_LogWriterRegistryPrivate_ >( ).factories_.get( name ) );
-	return ptr ? ptr->get( ) : nullptr;
-}
-
-/*----------------------------------------------------------------------------*/
-
-namespace {
-
-using T_PathCfg_ = std::pair< SP_LoggingConfiguration , T_LogPath >;
-
-// Start the parser
-bool PCStart_( T_SRDParserData const& data )
-{
-	*( data.currentData ) = NewShared< T_LoggingConfiguration >( );
-	return true;
-}
-
-// Entering a path configuration
-bool PCEnterPath_( T_SRDParserData const& data )
-{
-	auto const& tok( (*data.input)[ 0 ] );
-	const T_LogPath lp( tok.type( ) == E_SRDTokenType::WORD
-			? T_LogPath( )
-			: T_LogPath::FromString( tok.stringValue( ) ) );
-	auto cfg( data.currentData->value< SP_LoggingConfiguration >( ) );
-	if ( !lp.isValid( ) ) {
-		data.errors.add( "invalid logging path" , tok );
-	} else {
-		if ( lp.size( ) && cfg->isPathConfigured( lp ) ) {
-			data.errors.add( "duplicate path entry" , tok );
-		}
-	}
-
-	if ( !cfg->isPathConfigured( lp ) ) {
-		cfg->addPathConfiguration( lp );
-	}
-	*( data.targetData ) = std::make_pair< SP_LoggingConfiguration , T_LogPath >(
-			SP_LoggingConfiguration( std::move( cfg ) ) ,
-			T_LogPath( std::move( lp ) ) );
-	return true;
-}
-
-// End of path configuration - make sure it's valid
-bool PCCheckPath_( T_SRDParserData const& data )
-{
-	auto const& input( *data.input );
-	T_PathCfg_& pcfg( data.currentData->value< T_PathCfg_ >( ) );
-	if ( pcfg.first->logWritersFor( pcfg.second ).size( ) == 0 ) {
-		data.errors.add( "no loggers for this path" , input[ 1 ] );
-	}
-	const auto min( pcfg.first->minLevelFor( pcfg.second ) );
-	const auto max( pcfg.first->maxLevelFor( pcfg.second ) );
-	if ( min > max ) {
-		data.errors.add( "minimal level is higher than maximal level" , input[ 1 ] );
-	}
-	return true;
-}
-
-// Set the minimal or maximal log level for a path
-bool PCPathLevel_( T_SRDParserData const& data )
-{
-	auto const& input( *data.input );
-	T_SRDEnum const& levels( *data.config.enums.get( T_String::Pooled( "log-level" ) ) );
-	const E_LogLevel level( (E_LogLevel) levels[ input[ 1 ].stringValue( ) ] );
-
-	T_PathCfg_& pcfg( data.targetData->value< T_PathCfg_ >( ) );
-	if ( input[ 0 ].stringValue( ) == "min-level" ) {
-		pcfg.first->setMinLevelFor( pcfg.second , level );
-	} else {
-		pcfg.first->setMaxLevelFor( pcfg.second , level );
-	}
-
-	return true;
-}
-
-// Add a logger to a path
-bool PCPathLogger_( T_SRDParserData const& data )
-{
-	auto const& input( *data.input );
-	T_String const& logger( input[ 1 ].stringValue( ) );
-	T_PathCfg_& pcfg( data.targetData->value< T_PathCfg_ >( ) );
-	if ( pcfg.first->hasLogWriter( pcfg.second , logger ) ) {
-		data.errors.add( "duplicate logger for this path" , input[ 1 ] );
-	} else {
-		pcfg.first->addLogWriter( pcfg.second , logger );
-	}
-	return true;
-}
-
-// Prepare for a logger's configuration
-bool PCEnterLogger_( T_SRDParserData const& data , OP_LogWriterFactory const& factory )
-{
-	auto const& input( *data.input );
-	auto cfg( data.currentData->value< SP_LoggingConfiguration >( ) );
-
-	auto lconf( factory->createConfiguration( input[ 1 ].stringValue( ) ) );
-	if ( cfg->hasLogWriter( input[ 1 ].stringValue( ) ) ) {
-		data.errors.add( "duplicate logger" , input[ 1 ] );
-	}
-	*( data.targetData ) = lconf;
-	return true;
-}
-
-// Check a logger's configuration and add it to the list
-bool PCCheckLogger_( T_SRDParserData const& data )
-{
-	auto lconf( data.currentData->value< RP_LogWriterConfiguration >( ) );
-	auto cfg( data.targetData->value< SP_LoggingConfiguration >( ) );
-	lconf->check( data.errors , *data.input );
-	if ( cfg->hasLogWriter( lconf->name( ) ) ) {
-		delete lconf;
-	} else {
-		cfg->putLogWriter( OwnRawPointer( lconf ) );
-	}
-	return true;
-}
-
-// Set the minimal or maximal log level for a logger
-bool PCLoggerLevel_( T_SRDParserData const& data )
-{
-	auto const& input( *data.input );
-	T_SRDEnum const& levels( *data.config.enums.get( T_String::Pooled( "log-level" ) ) );
-	const E_LogLevel level( (E_LogLevel) levels[ input[ 1 ].stringValue( ) ] );
-
-	auto lconf( data.targetData->value< RP_LogWriterConfiguration >( ) );
-	if ( input[ 0 ].stringValue( ) == "min-level" ) {
-		lconf->setMinLevel( level );
-	} else {
-		lconf->setMaxLevel( level );
-	}
-
-	return true;
-}
-
-};
-
-T_SRDParserConfig T_LogWriterRegistry::getParserConfiguration( ) noexcept
-{
-	auto& pi( p< T_LogWriterRegistryPrivate_ >( ) );
-	assert( pi.factories_.size( ) != 0 && "no registered factories" );
-
-	using namespace lw::SRD;
-
-	T_SRDParserDefs defs( "default" );
-	defs << OnStart( PCStart_ );
-
-	defs.enumeration( "log-level" )
-		<< "trace" << "debug" << "info" << "notice"
-		<< "warning" << "error" << "critical";
-
-	defs.context( "default" )
-		<< ( Rule( ) << "paths" << EnterContext( "paths" ) )
-		<< ( Rule( ) << "loggers" << EnterContext( "loggers" ) );
-
-	defs.context( "paths" )
-		<< ( Rule( ) << ( Alt( ) << String( ) << Word( "root" ) )
-			<< EnterContext( "path" )
-			<< OnEnter( PCEnterPath_ ) << OnExit( PCCheckPath_ ) );
-	defs.context( "path" )
-		<< ( Rule( ) << "min-level" << Enum( "log-level" ) << PCPathLevel_ )
-		<< ( Rule( ) << "max-level" << Enum( "log-level" ) << PCPathLevel_ )
-		<< ( Rule( ) << "logger" << Word( ) << PCPathLogger_ );
-
-	T_Array< OP_LogWriterFactory > const& factories( pi.factories_.values( ) );
-	const auto nf( factories.size( ) );
-	for ( uint32_t i = 0 ; i < nf ; i ++ ) {
-		OP_LogWriterFactory const& f( factories[ i ] );
-
-		T_StringBuilder sb( "logger-" );
-		sb << f->name( );
-		const T_String ctxName( std::move( sb ) );
-
-		defs.context( "loggers" )
-			<< ( Rule( ) << Word( f->name( ) ) << Word( )
-					<< EnterContext( ctxName )
-					<< OnEnter( [&f]( auto const& data ) {
-							return PCEnterLogger_( data , f );
-						} )
-					<< OnExit( PCCheckLogger_ ) );
-
-		auto& ctx( defs.context( ctxName ) );
-		ctx << ( Rule( ) << "min-level" << Enum( "log-level" ) << PCLoggerLevel_ );
-		ctx << ( Rule( ) << "max-level" << Enum( "log-level" ) << PCLoggerLevel_ );
-		f->initializeSyntax( defs , ctx );
-	}
-
-	return T_SRDParserConfig( defs );
-}
-
-
-/*= T_LoggingConfiguration ===================================================*/
-
-T_LoggingConfiguration::T_PathInfo_::T_PathInfo_( T_LogPath const& path )
-	: path( path ) , writers( 8 )
-{ }
-
-/*----------------------------------------------------------------------------*/
-
-T_LoggingConfiguration::T_LoggingConfiguration( )
-	: writers_(
-		[]( OP_LogWriterConfiguration const& cfg ) -> T_String const& {
-			return cfg->name( );
-		} , 128 , 128 ) ,
-	paths_(
-		[]( T_PathInfo_ const& pi ) -> T_LogPath const& {
-			return pi.path;
-		} , 128 , 128 )
-{
-	paths_.add( T_PathInfo_( T_LogPath( ) ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-bool T_LoggingConfiguration::hasLogWriter( T_String const& name ) const
-{
-	return writers_.contains( name );
-}
-
-void T_LoggingConfiguration::putLogWriter( OP_LogWriterConfiguration&& configuration )
-{
-	const bool ok( writers_.add( std::move( configuration ) ) );
-	assert( ok );
-}
-
-T_Array< OP_LogWriterConfiguration > const& T_LoggingConfiguration::logWriters( ) const
-{
-	return writers_.values( );
-}
-
-/*----------------------------------------------------------------------------*/
-
-bool T_LoggingConfiguration::isPathConfigured( T_LogPath const& path ) const
-{
-	return paths_.contains( path );
-}
-
-void T_LoggingConfiguration::addPathConfiguration( T_LogPath const& path )
-{
-	const bool ok( paths_.add( T_PathInfo_( path ) ) );
-	assert( ok );
-}
-
-void T_LoggingConfiguration::setMinLevelFor( T_LogPath const& path , E_LogLevel minLevel )
-{
-	T_PathInfo_* const pi( paths_.get( path ) );
-	assert( pi != nullptr );
-	pi->minLevel = minLevel;
-}
-
-void T_LoggingConfiguration::setMaxLevelFor( T_LogPath const& path , E_LogLevel maxLevel )
-{
-	T_PathInfo_* const pi( paths_.get( path ) );
-	assert( pi != nullptr );
-	pi->maxLevel = maxLevel;
-}
-
-bool T_LoggingConfiguration::hasLogWriter( T_LogPath const& path , T_String const& name ) const
-{
-	T_PathInfo_ const* const pi( paths_.get( path ) );
-	assert( pi != nullptr );
-	return pi->writers.contains( name );
-}
-
-void T_LoggingConfiguration::addLogWriter( T_LogPath const& path , T_String const& name )
-{
-	T_PathInfo_ * const pi( paths_.get( path ) );
-	assert( pi != nullptr );
-	assert( !pi->writers.contains( name ) );
-	pi->writers.add( name );
-}
-
-/*----------------------------------------------------------------------------*/
-
-T_LoggingConfiguration::T_PathInfo_ const& T_LoggingConfiguration::getPathInfo(
-		T_LogPath const& path ) const
-{
-	T_PathInfo_ const* const pi( paths_.get( path ) );
-	if ( pi ) {
-		return *pi;
-	}
-
-	T_Array< T_PathInfo_ > const& all( paths_.values( ) );
-	const auto sz( all.size( ) );
-	uint32_t bestMatch( 0 );
-	uint32_t bmLength( 0 );
-	for ( uint32_t i = 0 ; i < sz ; i ++ ) {
-		auto const& p( all[ i ] );
-		if ( p.path.isParentOf( path ) && p.path.size( ) > bmLength ) {
-			bmLength = p.path.size( );
-			bestMatch = i;
-		}
-	}
-
-	return paths_[ bestMatch ];
-}
-
-
-/*= T_LoggingSystemPrivate_ ==================================================*/
-
-constexpr uint32_t T_LoggingSystemPrivate_::C_MAX_REUSE_SIZE;
-constexpr uint32_t T_LoggingSystemPrivate_::C_MAX_REUSE_QUANTITY;
-T_LoggingSystemPrivate_ * T_LoggingSystemPrivate_::instance_ = nullptr;
-T_Mutex T_LoggingSystemPrivate_::loggersMutex_;
-T_Array< T_LoggerPrivate_ * > T_LoggingSystemPrivate_::loggers_( 32 );
-
-/*----------------------------------------------------------------------------*/
-
-T_LoggingSystemPrivate_::T_LogEntry::T_LogEntry( E_LogLevel level ,
-		uint32_t path , T_LogStringData&& string , uint32_t size )
-	: time( std::chrono::high_resolution_clock::now( ) ) ,
-		level( level ) , path( path ) , string( std::move( string ) ) ,
-		size( size )
-{ }
-
-/*----------------------------------------------------------------------------*/
-
-inline T_LoggingSystemPrivate_::T_LoggingSystemPrivate_(
-		RP_LoggingSystem main ,
-		T_LogWriterRegistry const& registry ,
-		OP_LoggingConfiguration&& config )
-	: main_( main ) , registry_( registry ) ,
-		config_( std::move( config ) ) , writers_( 16 ) ,
-		thread_( ) , queueMutex_( ) , queueCond_( ) , exit_( false ) ,
-		queue_( 16 ) , freeList_( C_MAX_REUSE_QUANTITY ) ,
-		paths_( 8 ) , pathRefCount_( 8 )
-{
-	assert( config_ );
-	assert( instance_ == nullptr );
-	initLogWriters( );
-	{
-		T_ScopeLock lk( loggersMutex_ );
-		instance_ = this;
-		const auto nLoggers( loggers_.size( ) );
-		for ( uint32_t i = 0 ; i < nLoggers ; i ++ ) {
-			loggers_[ i ]->connect( );
-		}
-	}
-	startLoggingThread( );
-}
-
-inline T_LoggingSystemPrivate_::~T_LoggingSystemPrivate_( )
-{
-	assert( instance_ == this );
-	{
-		T_ScopeLock lk( loggersMutex_ );
-		instance_ = nullptr;
-		const auto nLoggers( loggers_.size( ) );
-		for ( uint32_t i = 0 ; i < nLoggers ; i ++ ) {
-			loggers_[ i ]->connected_ = false;
-		}
-	}
-	stopLoggingThread( );
-	writers_.clear( );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void T_LoggingSystemPrivate_::log( E_LogLevel level , uint32_t pathIndex ,
-		char const* data , uint32_t size )
-{
-	assert( size );
-	assert( pathIndex < paths_.size( ) );
-	assert( pathRefCount_[ pathIndex ] > 0 );
-
-	T_LogStringData lsd;
-	if ( size > C_MAX_REUSE_SIZE ) {
-		lsd = NewOwned< T_Buffer< char > >( data , size );
-	}
-
-	T_ScopeLock lk( queueMutex_ );
-	if ( !lsd ) {
-		const auto fls( freeList_.size( ) );
-		if ( fls == 0 ) {
-			lsd = NewOwned< T_Buffer< char > >( C_MAX_REUSE_SIZE );
-		} else {
-			lsd = std::move( freeList_[ fls - 1 ] );
-			freeList_.remove( fls - 1 );
-		}
-		memcpy( lsd->data( ) , data , size );
-	}
-
-	assert( lsd );
-	pathRefCount_[ pathIndex ] ++;
-	queue_.putNew( level , pathIndex , std::move( lsd ) , size );
-	queueCond_.notify_one( );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void T_LoggingSystemPrivate_::initLogWriters( )
-{
-	auto const& lws( config_->logWriters( ) );
-	const auto lwc( lws.size( ) );
-	writers_.ensureCapacity( lwc );
-	for ( uint32_t i = 0 ; i < lwc ; i ++ ) {
-		const RPC_LogWriterFactory factory( registry_.get( lws[ i ]->writerType( ) ) );
-		writers_.add( factory->createLogWriter( lws[ i ]->clone( ) ) );
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-void T_LoggingSystemPrivate_::startLoggingThread( )
-{
-	assert( !thread_ );
-	exit_ = false;
-	thread_ = NewOwned< T_Thread >( [this]() { loggingThread( ); } );
-}
-
-void T_LoggingSystemPrivate_::stopLoggingThread( )
-{
-	assert( thread_ );
-
-	{
-		T_ScopeLock lk( queueMutex_ );
-		exit_ = true;
-	}
-	queueCond_.notify_one( );
-	thread_->join( );
-	thread_ = T_OwnPtr< T_Thread >( );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void T_LoggingSystemPrivate_::loggingThread( )
-{
-	T_Array< T_LogEntry > entries( queue_.growth( ) );
-	T_ExclusiveLock lock( queueMutex_ );
-	do {
-		T_LogEntry entry;
-
-		queueCond_.wait( lock , [this]( ) {
-					return exit_ || queue_.size( );
-				} );
-		if ( queue_.readAll( entries ) ) {
-			lock.unlock( );
-		}
-
-		uint32_t nEntries( 0 );
-		while ( nEntries < entries.size( ) ) {
-			const auto nne( entries.size( ) );
-			for ( uint32_t i = nEntries ; i < nne ; i ++ ) {
-				writeEntry( entries[ i ] );
-			}
-
-			// Try to read new entries
-			nEntries = nne;
-			lock.lock( );
-			if ( queue_.readAll( entries ) ) {
-				lock.unlock( );
-			}
-		}
-
-		// Decrease path reference counters
-		for ( uint32_t i = 0 ; i < nEntries ; i ++ ) {
-			pathRefCount_[ entries[ i ].path ] --;
-		}
-
-		// Return string data buffers to the free list
-		for ( uint32_t i = 0 ; i < nEntries
-				&& freeList_.size( ) < C_MAX_REUSE_QUANTITY ; i ++ ) {
-			auto& entry( entries[ i ] );
-			if ( entry.string->size( ) == C_MAX_REUSE_SIZE ) {
-				freeList_.add( std::move( entry.string ) );
-			}
-		}
-
-		entries.clear( );
-	} while ( !exit_ );
-	lock.unlock( );
-}
-
-void T_LoggingSystemPrivate_::writeEntry( T_LogEntry const& entry )
-{
-	T_LogPath const& path( paths_[ entry.path ] );
-
-	const E_LogLevel min( config_->minLevelFor( path ) );
-	const E_LogLevel max( config_->maxLevelFor( path ) );
-	if ( min > entry.level || max < entry.level ) {
-		return;
-	}
-
-	const T_Array< T_String > writers( config_->logWritersFor( path ) );
-	const auto nw( writers.size( ) );
-	const auto nwi( writers_.size( ) );
-	for ( uint32_t i = 0 ; i < nw ; i ++ ) {
-		auto const& name( writers[ i ] );
-		for ( uint32_t j = 0 ; j < nwi ; j ++ ) {
-			auto& writer( writers_[ j ] );
-			auto const& cfg( writer->configuration< T_LogWriterConfiguration >( ) );
-			if ( cfg.name( ) != name ) {
-				continue;
-			}
-			if ( cfg.maxLevel( ) >= entry.level
-					&& cfg.minLevel( ) <= entry.level ) {
-				writer->log( entry.time , entry.level , path ,
-						entry.string , entry.size );
-			}
-			break;
-		}
-	}
-}
-
-
-/*= T_LoggerPrivate_ =========================================================*/
-
-inline T_LoggerPrivate_::T_LoggerPrivate_( T_LogPath&& path )
-	: path_( std::move( path ) ) , connected_( false ) ,
-		pathIndex_( 0 ) , minLevel_( E_LogLevel::TRACE ) ,
-		maxLevel_( E_LogLevel::CRITICAL )
-{
-	T_ScopeLock lk( T_LoggingSystemPrivate_::loggersMutex_ );
-	T_LoggingSystemPrivate_::loggers_.add( this );
-	if ( T_LoggingSystemPrivate_::instance_ ) {
-		connect( );
-	}
-}
-
-inline T_LoggerPrivate_::T_LoggerPrivate_( T_LoggerPrivate_ const& other )
-	: path_( other.path_ ) , connected_( other.connected_ ) ,
-		pathIndex_( other.pathIndex_ ) , minLevel_( other.minLevel_ ) ,
-		maxLevel_( other.maxLevel_ )
-{
-	T_ScopeLock lk( T_LoggingSystemPrivate_::loggersMutex_ );
-	T_LoggingSystemPrivate_::loggers_.add( this );
-	assert( connected_ == bool( T_LoggingSystemPrivate_::instance_ ) );
-	if ( T_LoggingSystemPrivate_::instance_ ) {
-		T_ScopeLock lk2( T_LoggingSystemPrivate_::instance_->queueMutex_ );
-		T_LoggingSystemPrivate_::instance_->pathRefCount_[ pathIndex_ ] ++;
-	}
-}
-
-inline T_LoggerPrivate_::~T_LoggerPrivate_( )
-{
-	T_ScopeLock lk( T_LoggingSystemPrivate_::loggersMutex_ );
-	assert( connected_ == bool( T_LoggingSystemPrivate_::instance_ ) );
-	if ( T_LoggingSystemPrivate_::instance_ ) {
-		T_ScopeLock lk2( T_LoggingSystemPrivate_::instance_->queueMutex_ );
-		T_LoggingSystemPrivate_::instance_->pathRefCount_[ pathIndex_ ] --;
-	}
-	T_LoggingSystemPrivate_::loggers_.removeSwap(
-			T_LoggingSystemPrivate_::loggers_.indexOf( this ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void T_LoggerPrivate_::connect( )
-{
-	T_LoggingSystemPrivate_ * ins( T_LoggingSystemPrivate_::instance_ );
-	connected_ = true;
-	minLevel_ = ins->config_->minLevelFor( path_ );
-	maxLevel_ = ins->config_->maxLevelFor( path_ );
-
-	T_ScopeLock lk2( ins->queueMutex_ );
-	const auto found( ins->paths_.indexOf( path_ ) );
-	if ( found != -1 ) {
-		pathIndex_ = found;
-		ins->pathRefCount_[ found ] ++;
-	} else {
-		const auto empty( ins->pathRefCount_.indexOf( 0 ) );
-		if ( empty == -1 ) {
-			pathIndex_ = ins->paths_.add( path_ );
-			ins->pathRefCount_.add( 1 );
-		} else {
-			ins->paths_[ empty ] = path_;
-			ins->pathRefCount_[ empty ] = 1;
-		}
-	}
-}
-
-
-/*= T_Logger =================================================================*/
-
-T_Logger::T_Logger( T_LogPath path )
-	: A_PrivateImplementation( new T_LoggerPrivate_( std::move( path ) ) )
-{ }
-
-T_Logger::T_Logger( T_Logger const& other )
-	: A_PrivateImplementation( new T_LoggerPrivate_(
-				other.p< T_LoggerPrivate_ >( ) ) )
-{ }
-
-/*----------------------------------------------------------------------------*/
-
-bool T_Logger::hasLevel( E_LogLevel level ) const
-{
-	auto const& pi( p< T_LoggerPrivate_ >( ) );
-	return pi.connected_ && level >= pi.minLevel_ && level <= pi.maxLevel_;
-}
-
-/*----------------------------------------------------------------------------*/
-
-void T_Logger::log( E_LogLevel level , T_String const& string )
-{
-	auto const& pi( p< T_LoggerPrivate_ >( ) );
-	if ( T_LoggingSystemPrivate_::instance_ && pi.connected_ && string ) {
-		T_LoggingSystemPrivate_::instance_->log( level , pi.pathIndex_ ,
-				string.data( ) , string.size( ) );
-	}
-}
-
-void T_Logger::log( E_LogLevel level , T_StringBuilder const& string )
-{
-	auto const& pi( p< T_LoggerPrivate_ >( ) );
-	if ( T_LoggingSystemPrivate_::instance_ && pi.connected_ && string ) {
-		T_LoggingSystemPrivate_::instance_->log( level , pi.pathIndex_ ,
-				string.data( ) , string.size( ) );
-	}
-}
-
-void T_Logger::log( E_LogLevel level , char const* string )
-{
-	assert( string );
-	const auto size( strlen( string ) );
-
-	auto const& pi( p< T_LoggerPrivate_ >( ) );
-	if ( T_LoggingSystemPrivate_::instance_ && pi.connected_ && size ) {
-		T_LoggingSystemPrivate_::instance_->log(
-				level , pi.pathIndex_ , string , size );
-	}
-}
-
-
-/*= T_LoggingSystem ==========================================================*/
-
-T_LoggingSystem::T_LoggingSystem(
-		T_LogWriterRegistry const& registry ,
-		OP_LoggingConfiguration&& config )
-	: A_PrivateImplementation( new T_LoggingSystemPrivate_(
-				this , registry , std::move( config ) ) )
-{ }
-
-void T_LoggingSystem::reconfigure( OP_LoggingConfiguration&& configuration )
-{
-	assert( configuration );
-	auto& pi( p< T_LoggingSystemPrivate_>( ) );
-	pi.stopLoggingThread( );
-	{
-		T_ScopeLock lk( pi.loggersMutex_ );
-		pi.config_ = std::move( configuration );
-
-		pi.paths_.clear( );
-		pi.pathRefCount_.clear( );
-		pi.writers_.clear( );
-
-		pi.initLogWriters( );
-		const auto nLoggers( pi.loggers_.size( ) );
-		for ( uint32_t i = 0 ; i < nLoggers ; i ++ ) {
-			pi.loggers_[ i ]->connect( );
-		}
-	}
-	pi.startLoggingThread( );
-}
diff --git a/src/Messages.cc b/src/Messages.cc
deleted file mode 100644
index 8012c72..0000000
--- a/src/Messages.cc
+++ /dev/null
@@ -1,86 +0,0 @@
-/******************************************************************************/
-/* UI<=>GAME MESSAGES *********************************************************/
-/******************************************************************************/
-
-#include <lw/lib/Messages.hh>
-
-using namespace lw;
-
-#define M_ENUM_OUT_( Type , Value ) \
-	case Type::Value: obj << #Value; break
-
-
-/*= A_GameView ===============================================================*/
-
-A_GameView::~A_GameView( )
-{ }
-
-
-/*= A_ViewBuilder ============================================================*/
-
-A_ViewBuilder::~A_ViewBuilder( )
-{ }
-
-
-/*= E_GameState ==============================================================*/
-
-namespace lw {
-M_LSHIFT_OP( T_StringBuilder , E_GameState )
-{
-	switch ( value ) {
-		M_ENUM_OUT_( E_GameState , NO_GAME );
-		M_ENUM_OUT_( E_GameState , GAME_PAUSED );
-		M_ENUM_OUT_( E_GameState , GAME_SLOW );
-		M_ENUM_OUT_( E_GameState , GAME_NORMAL );
-		M_ENUM_OUT_( E_GameState , GAME_FAST );
-	}
-	return obj;
-}
-} // namespace lw
-
-
-/*= E_GameUIMessage ==========================================================*/
-
-namespace lw {
-M_LSHIFT_OP( T_StringBuilder , E_GameUIMessage )
-{
-	switch ( value ) {
-		M_ENUM_OUT_( E_GameUIMessage , NEW );
-		M_ENUM_OUT_( E_GameUIMessage , LOAD );
-		M_ENUM_OUT_( E_GameUIMessage , SAVE );
-		M_ENUM_OUT_( E_GameUIMessage , STOP );
-		M_ENUM_OUT_( E_GameUIMessage , QUIT );
-		M_ENUM_OUT_( E_GameUIMessage , ABORT );
-		M_ENUM_OUT_( E_GameUIMessage , DELETE );
-		M_ENUM_OUT_( E_GameUIMessage , COPY_OR_RENAME );
-		M_ENUM_OUT_( E_GameUIMessage , SET_SPEED );
-		M_ENUM_OUT_( E_GameUIMessage , STEPS );
-		M_ENUM_OUT_( E_GameUIMessage , SET_VIEW );
-		M_ENUM_OUT_( E_GameUIMessage , VIEW_DISPLAYED );
-		M_ENUM_OUT_( E_GameUIMessage , QUERY );
-		M_ENUM_OUT_( E_GameUIMessage , COMMAND );
-	}
-	return obj;
-}
-} // namespace lw
-
-
-/*= E_GameLoopMessage ========================================================*/
-
-namespace lw {
-M_LSHIFT_OP( T_StringBuilder , E_GameLoopMessage )
-{
-	switch ( value ) {
-		M_ENUM_OUT_( E_GameLoopMessage , TERMINATED );
-		M_ENUM_OUT_( E_GameLoopMessage , PROGRESS );
-		M_ENUM_OUT_( E_GameLoopMessage , DONE );
-		M_ENUM_OUT_( E_GameLoopMessage , STATE_CHANGED );
-		M_ENUM_OUT_( E_GameLoopMessage , VIEW_AVAILABLE );
-		M_ENUM_OUT_( E_GameLoopMessage , QUERY_RESPONSE );
-		M_ENUM_OUT_( E_GameLoopMessage , COMMAND_OK );
-		M_ENUM_OUT_( E_GameLoopMessage , COMMAND_SYNTAX );
-		M_ENUM_OUT_( E_GameLoopMessage , COMMAND_ERROR );
-	}
-	return obj;
-}
-} // namespace lw
diff --git a/src/ModInterface.cc b/src/ModInterface.cc
deleted file mode 100644
index 8404c9b..0000000
--- a/src/ModInterface.cc
+++ /dev/null
@@ -1,20 +0,0 @@
-/******************************************************************************/
-/* MODDING SYSTEM INTERFACES **************************************************/
-/******************************************************************************/
-
-#include <lw/lib/ModInterface.hh>
-using namespace lw;
-
-
-/*= A_ModBase ===============================================================*/
-
-A_ModBase::~A_ModBase( ) noexcept
-{ }
-
-
-/*= A_NativeMod ==============================================================*/
-
-OP_UserInterface A_NativeMod::getUserInterface( ) const noexcept
-{
-	return {};
-}
diff --git a/src/Mods.cc b/src/Mods.cc
deleted file mode 100644
index b24f927..0000000
--- a/src/Mods.cc
+++ /dev/null
@@ -1,2646 +0,0 @@
-/******************************************************************************/
-/* MODDING SYSTEM *************************************************************/
-/******************************************************************************/
-
-#include <lw/lib/Mods.hh>
-#include <lw/lib/VFSDrivers.hh>
-#include <lw/lib/DynLib.hh>
-#include <lw/lib/SRDParser.hh>
-#include <lw/lib/SRDText.hh>
-#include <lw/lib/Version.hh>
-#include <lw/lib/LW.hh>
-
-using namespace lw;
-
-
-/*= T_ModIdentifier ==========================================================*/
-
-int T_ModIdentifier::compare(
-		T_ModIdentifier const& other ) const noexcept
-{
-	const int nc( name.compare( other.name ) );
-	if ( nc != 0 ) {
-		return nc;
-	}
-	return T_Comparator< uint32_t >::compare( version , other.version );
-}
-
-
-/*= MODULE CONFIGURATION DATA ================================================*/
-
-namespace {
-
-struct T_ModConfig_
-{
-	T_String name;
-	E_ModMode mode;
-	uint32_t version;
-	T_Optional< uint32_t > revision;
-
-	explicit T_ModConfig_(
-			T_String name ,
-			bool exclude ) noexcept;
-	T_ModConfig_(
-			T_String name ,
-			uint32_t version ) noexcept;
-	T_ModConfig_(
-			T_String name ,
-			uint32_t version ,
-			uint32_t revision ) noexcept;
-};
-
-struct T_MMConfig_
-{
-	T_ObjectTable< T_String , T_ModConfig_ > mods{
-		[]( T_ModConfig_ const& m ) -> T_String const& {
-			return m.name;
-		} , 64
-	};
-	T_KeyValueTable< T_String , int32_t > ui{ 64 };
-};
-
-} // namespace
-
-/*----------------------------------------------------------------------------*/
-
-T_ModConfig_::T_ModConfig_(
-		T_String name ,
-		const bool exclude ) noexcept
-	: name( std::move( name ) ) ,
-		mode( exclude ? E_ModMode::EXCLUDE : E_ModMode::REQUIRE )
-{ }
-
-T_ModConfig_::T_ModConfig_(
-		T_String name ,
-		const uint32_t version ) noexcept
-	: name( std::move( name ) ) ,
-		mode( E_ModMode::VERSION ) ,
-		version( version )
-{ }
-
-T_ModConfig_::T_ModConfig_(
-		T_String name ,
-		const uint32_t version ,
-		const uint32_t revision ) noexcept
-	: name( std::move( name ) ) ,
-		mode( E_ModMode::VERSION ) ,
-		version( version ) ,
-		revision( revision )
-{ }
-
-
-/*= MAIN CONFIGURATION PARSER ================================================*/
-
-namespace {
-
-bool MMCModAuto_(
-		T_SRDParserData const& data ) noexcept
-{
-	auto const& input( *( data.input ) );
-	auto& cfg( *data.currentData->value< SP_ModsManagerConfiguration >( ) );
-	cfg.setAuto( input[ 1 ].stringValue( ) );
-	return true;
-}
-
-bool MMCModRequire_(
-		T_SRDParserData const& data ) noexcept
-{
-	auto const& input( *( data.input ) );
-	auto& cfg( *data.currentData->value< SP_ModsManagerConfiguration >( ) );
-	cfg.setRequired( input[ 1 ].stringValue( ) );
-	return true;
-}
-
-bool MMCModExclude_(
-		T_SRDParserData const& data ) noexcept
-{
-	auto const& input( *( data.input ) );
-	auto& cfg( *data.currentData->value< SP_ModsManagerConfiguration >( ) );
-	cfg.setExcluded( input[ 1 ].stringValue( ) );
-	return true;
-}
-
-bool MMCModVersion_(
-		T_SRDParserData const& data ) noexcept
-{
-	auto const& input( *( data.input ) );
-	auto& cfg( *data.currentData->value< SP_ModsManagerConfiguration >( ) );
-	const bool hasRevision( input.size( ) == 4 );
-
-	const uint32_t version( ([&](){
-		const auto v( input[ 2 ].longValue( ) );
-		if ( v < 0 || v > int64_t( UINT32_MAX ) ) {
-			data.errors.add( "invalid version number" , input[ 2 ] );
-			return 0u;
-		}
-		return uint32_t( v );
-	})( ) );
-
-	const uint32_t revision( ([&](){
-		if ( !hasRevision ) {
-			return 0u;
-		}
-		const auto v( input[ 3 ].longValue( ) );
-		if ( v < 0 || v > int64_t( UINT32_MAX ) ) {
-			data.errors.add( "invalid revision number" , input[ 2 ] );
-			return 0u;
-		}
-		return uint32_t( v );
-	})( ) );
-
-	if ( hasRevision ) {
-		cfg.setVersion( input[ 1 ].stringValue( ) , version , revision );
-	} else {
-		cfg.setVersion( input[ 1 ].stringValue( ) , version );
-	}
-
-	return true;
-}
-
-bool MMCSetUIPreference_(
-		T_SRDParserData const& data ) noexcept
-{
-	auto const& input( *( data.input ) );
-	auto& cfg( *data.currentData->value< SP_ModsManagerConfiguration >( ) );
-	const int32_t pref( input.size( ) == 3 ? input[ 2 ].longValue( ) : 0 );
-	cfg.setUIPreference( input[ 1 ].stringValue( ) , pref );
-	return true;
-}
-
-bool MMCClearUIPreference_(
-		T_SRDParserData const& data ) noexcept
-{
-	auto& cfg( *data.currentData->value< SP_ModsManagerConfiguration >( ) );
-	cfg.clearUIPreference( (*data.input)[ 1 ].stringValue( ) );
-	return true;
-}
-
-} // namespace
-
-
-/*= T_ModsManagerConfiguration ===============================================*/
-
-T_ModsManagerConfiguration::T_ModsManagerConfiguration( ) noexcept
-	: A_PrivateImplementation( new T_MMConfig_( ) )
-{ }
-
-T_ModsManagerConfiguration::T_ModsManagerConfiguration(
-		T_ModsManagerConfiguration&& other ) noexcept
-	: A_PrivateImplementation( std::move( other ) )
-{ }
-
-T_ModsManagerConfiguration& T_ModsManagerConfiguration::operator =(
-		T_ModsManagerConfiguration&& other ) noexcept
-{
-	A_PrivateImplementation::operator =( std::move( other ) );
-	return *this;
-}
-
-/*----------------------------------------------------------------------------*/
-
-void T_ModsManagerConfiguration::setAuto(
-		T_String const& name ) noexcept
-{
-	p< T_MMConfig_ >( ).mods.remove( name );
-}
-
-void T_ModsManagerConfiguration::setRequired(
-		T_String const& name ) noexcept
-{
-	p< T_MMConfig_ >( ).mods.set( T_ModConfig_{ name , false } );
-}
-
-void T_ModsManagerConfiguration::setExcluded(
-		T_String const& name ) noexcept
-{
-	p< T_MMConfig_ >( ).mods.set( T_ModConfig_{ name , true } );
-}
-
-void T_ModsManagerConfiguration::setVersion(
-		T_String const& name ,
-		const uint32_t version ) noexcept
-{
-	p< T_MMConfig_ >( ).mods.set( T_ModConfig_{ name , version } );
-}
-
-void T_ModsManagerConfiguration::setVersion(
-		T_String const& name ,
-		const uint32_t version ,
-		const uint32_t revision ) noexcept
-{
-	p< T_MMConfig_ >( ).mods.set(
-		T_ModConfig_{ name , version , revision } );
-}
-
-/*----------------------------------------------------------------------------*/
-
-T_Array< T_String > T_ModsManagerConfiguration::configured( ) const noexcept
-{
-	return p< T_MMConfig_ >( ).mods.keys( );
-}
-
-E_ModMode T_ModsManagerConfiguration::modeFor(
-		T_String const& name ) const noexcept
-{
-	auto const* const mc( p< T_MMConfig_ >( ).mods.get( name ) );
-	return mc ? mc->mode : E_ModMode::AUTO;
-}
-
-uint32_t T_ModsManagerConfiguration::requiredVersion(
-		T_String const& name ) const noexcept
-{
-	auto const* const mc( p< T_MMConfig_ >( ).mods.get( name ) );
-	assert( mc != nullptr && mc->mode == E_ModMode::VERSION );
-	return mc->version;
-}
-
-T_Optional< uint32_t > T_ModsManagerConfiguration::requiredRevision(
-		T_String const& name ) const noexcept
-{
-	auto const* const mc( p< T_MMConfig_ >( ).mods.get( name ) );
-	assert( mc != nullptr && mc->mode == E_ModMode::VERSION );
-	return mc->revision;
-}
-
-/*----------------------------------------------------------------------------*/
-
-void T_ModsManagerConfiguration::setUIPreference(
-		T_String const& name ,
-		const int32_t weight ) noexcept
-{
-	p< T_MMConfig_ >( ).ui.set( name , weight );
-}
-
-void T_ModsManagerConfiguration::clearUIPreference(
-		T_String const& name ) noexcept
-{
-	p< T_MMConfig_ >( ).ui.remove( name );
-}
-
-T_Array< T_String > T_ModsManagerConfiguration::uiPreferences( ) const noexcept
-{
-	auto const& ui( p< T_MMConfig_ >( ).ui );
-	T_Array< T_String > names( ui.keys( ) );
-	names.sort( [&]( T_String const& a , T_String const& b ) {
-			return T_Comparator< int32_t >::compare( ui[ a ] , ui[ b ] );
-		} );
-	return names;
-}
-
-int32_t T_ModsManagerConfiguration::uiPreference(
-		T_String const& name ) const noexcept
-{
-	int32_t const* const pref( p< T_MMConfig_ >( ).ui.get( name ) );
-	if ( pref == nullptr ) {
-		return 0;
-	}
-	return *pref;
-}
-
-
-/*----------------------------------------------------------------------------*/
-
-namespace {
-/* Add a mod to the list if the specific name/version is not present.
- * If it is present, replace the entry if the new record's revision
- * number is higher than the one in the list.
- */
-void addOrReplaceMod_(
-		T_Array< RPC_ModInfo >& list ,
-		RPC_ModInfo const& mod )
-{
-	auto const nMods( list.size( ) );
-	for ( uint32_t i = 0 ; i < nMods ; i ++ ) {
-		auto const& record( *list[ i ] );
-		if ( record.identifier != mod->identifier ) {
-			continue;
-		}
-		if ( record.revision < mod->revision ) {
-			list[ i ] = mod;
-		}
-		return;
-	}
-	list.add( mod );
-}
-} // namespace
-
-T_Array< RPC_ModInfo > T_ModsManagerConfiguration::filterMods(
-		T_Array< RPC_ModInfo > const& mods ) const noexcept
-{
-	const auto nMods( mods.size( ) );
-	T_Array< RPC_ModInfo > output{ std::max( 1u , nMods ) };
-	for ( uint32_t i = 0 ; i < nMods ; i ++ ) {
-		auto const& mod( mods[ i ] );
-		auto const& mn( mod->identifier.name );
-		auto const m( modeFor( mn ) );
-
-		if ( m != E_ModMode::VERSION ) {
-			if ( m != E_ModMode::EXCLUDE ) {
-				addOrReplaceMod_( output , mod );
-			}
-			continue;
-		}
-
-		// Right version?
-		if ( mod->identifier.version != requiredVersion( mn ) ) {
-			continue;
-		}
-		auto const rv( requiredRevision( mn ) );
-		if ( rv.present( ) && mod->revision != rv ) {
-			continue;
-		}
-		addOrReplaceMod_( output , mod );
-	}
-	return output;
-}
-
-T_Array< T_String > T_ModsManagerConfiguration::requiredMods( ) const noexcept
-{
-	auto const& pi( p< T_MMConfig_ >( ) );
-	auto const nConfig( pi.mods.size( ) );
-	uint32_t nRequired( 0 );
-	for ( uint32_t i = 0 ; i < nConfig ; i ++ ) {
-		auto const m( pi.mods[ i ].mode );
-		if ( m == E_ModMode::VERSION || m == E_ModMode::REQUIRE ) {
-			nRequired ++;
-		}
-	}
-
-	T_Array< T_String > output{ std::max( 1u , nRequired ) };
-	for ( uint32_t i = 0 ; i < nConfig ; i ++ ) {
-		auto const m( pi.mods[ i ].mode );
-		if ( m == E_ModMode::VERSION || m == E_ModMode::REQUIRE ) {
-			output.add( pi.mods[ i ].name );
-			if ( output.size( ) == nRequired ) {
-				break;
-			}
-		}
-	}
-	return output;
-}
-
-/*----------------------------------------------------------------------------*/
-
-T_ModsManagerConfiguration T_ModsManagerConfiguration::DefaultConfiguration( ) noexcept
-{
-	const T_String mGame( T_String::Pooled( "lw-game" ) );
-	const T_String mConsoleUI( T_String::Pooled( "lw-ui-console" ) );
-	const T_String mGLUI( T_String::Pooled( "lw-ui-gl" ) );
-
-	T_ModsManagerConfiguration config;
-	config.setRequired( mGame );
-	config.setUIPreference( mConsoleUI , 100 );
-	config.setUIPreference( mGLUI , 1000 );
-	return config;
-}
-
-/*----------------------------------------------------------------------------*/
-
-T_SRDParserConfig T_ModsManagerConfiguration::GetParserConfig( )
-{
-	using namespace lw::SRD;
-	T_SRDParserDefs defs( "default" );
-	defs << OnStart( []( T_SRDParserData const& data ) -> bool {
-		*( data.currentData ) = NewShared< T_ModsManagerConfiguration >( );
-		return true;
-	} );
-
-	defs.context( "default" )
-		<< ( Rule( ) << "auto" << Word( )
-				<< MMCModAuto_ )
-		<< ( Rule( ) << "require" << Word( )
-				<< MMCModRequire_ )
-		<< ( Rule( ) << "exclude" << Word( )
-				<< MMCModExclude_ )
-		<< ( Rule( ) << "version" << Word( ) << Int32( ) << Opt( Int32( ) )
-				<< MMCModVersion_ )
-		<< ( Rule( ) << "ui" << Word( ) << Opt( Int32( ) )
-				<< MMCSetUIPreference_ )
-		<< ( Rule( ) << "clear-ui" << Word( )
-				<< MMCClearUIPreference_ )
-	;
-
-	return defs;
-}
-
-
-/*= T_MDData_ - Private data for T_ModsDependencies ==========================*/
-
-using T_ModsList_ = T_Array< RPC_ModInfo >;
-
-namespace {
-
-struct T_UIMods_
-{
-	T_String name;
-	T_ModsList_ mods{ 1 };
-};
-
-struct T_MDData_
-{
-	bool success = false;
-	bool ambiguous = false;
-	T_ModsList_ commonMods{ 1 };
-	T_Array< T_UIMods_ > uiMods{ 1 };
-};
-
-} // namespace
-
-
-/*= MODS DEPENDENCIES RESOLUTION =============================================*/
-
-namespace {
-
-using T_ModsTable_ = T_ObjectTable< T_ModIdentifier , RPC_ModInfo >;
-
-T_ModsTable_ makeModsTable_(
-		T_Array< RPC_ModInfo > const& mods ) noexcept
-{
-	const uint32_t nMods{ mods.size( ) };
-	T_ModsTable_ mt{
-		[]( RPC_ModInfo mi ) -> T_ModIdentifier const& {
-			return mi->identifier;
-		} , nMods , 128
-	};
-	for ( uint32_t i = 0 ; i < nMods ; i ++ ) {
-		mt.add( mods[ i ] );
-	}
-	return mt;
-}
-
-/*----------------------------------------------------------------------------*/
-
-using T_MinMaxVersions_ = std::pair< uint32_t , uint32_t >;
-using T_ModVersions_ = T_KeyValueTable< T_String , T_MinMaxVersions_ >;
-
-T_ModVersions_ makeModVersions_(
-		T_Array< RPC_ModInfo > const& mods ) noexcept
-{
-	const uint32_t nMods( mods.size( ) );
-	T_ModVersions_ versions{ nMods , 128 };
-	for ( uint32_t i = 0 ; i < nMods ; i ++ ) {
-		auto const& mi( mods[ i ]->identifier );
-		auto* previous( versions.get( mi.name ) );
-		const auto v( mi.version );
-		if ( previous == nullptr ) {
-			versions.add( mi.name , T_MinMaxVersions_( v , v ) );
-		} else {
-			versions.update( mi.name , T_MinMaxVersions_(
-					std::min( previous->first , v ) ,
-					std::max( previous->second , v ) ) );
-		}
-	}
-	return versions;
-}
-
-/*----------------------------------------------------------------------------*/
-
-/* Structure used to represent graph nodes while building the
- * dependency graph.
- */
-struct T_MDRNode_
-{
-	RPC_ModInfo mod;
-	bool valid;
-	T_Array< RPC_ModIdentifier > deps{ 16 };
-	T_Array< T_String > uiDeps{ 4 };
-	T_Optional< T_Array< RPC_ModIdentifier > > fullDeps;
-	T_Array< RPC_ModIdentifier > revDeps{ 16 };
-	T_Optional< uint32_t > sgId;
-
-	struct T_Dup {};
-
-	T_MDRNode_(
-			RPC_ModInfo mod ,
-			bool valid ,
-			T_Array< RPC_ModIdentifier >&& deps ,
-			T_Array< T_String >&& uiDeps ) noexcept;
-
-	T_MDRNode_( T_Dup ,
-			T_MDRNode_ const& node ) noexcept;
-};
-
-/*----------------------------------------------------------------------------*/
-
-T_MDRNode_::T_MDRNode_(
-		const RPC_ModInfo mod ,
-		const bool valid ,
-		T_Array< RPC_ModIdentifier >&& deps ,
-		T_Array< T_String >&& uiDeps ) noexcept
-	: mod( mod ) , valid( valid ) ,
-		deps( std::move( deps ) ) , uiDeps( std::move( uiDeps ) ) ,
-		fullDeps( ) , revDeps( 16 ) , sgId( )
-{ }
-
-
-T_MDRNode_::T_MDRNode_(
-		T_Dup ,
-		T_MDRNode_ const& node ) noexcept
-	: mod( node.mod ) , valid( true ) ,
-		deps( node.deps ) , fullDeps( node.fullDeps ) ,
-		revDeps( 16 ) , sgId( )
-{ }
-
-/*----------------------------------------------------------------------------*/
-
-struct T_MDRGraph_
-{
-	T_Array< T_MDRNode_ > nodes;
-	T_String key;
-	float score;
-	uint32_t weight;
-
-	explicit T_MDRGraph_(
-			const uint32_t nodesGrowth = 64 ) noexcept;
-
-	/* Find a node based on a mod identifier. Returns INVALID_INDEX
-	 * if no such node exists.
-	 */
-	uint32_t findNode(
-			T_ModIdentifier const& id ) const noexcept;
-	/* Remove invalid nodes from the graph */
-	void removeBadNodes( ) noexcept;
-	/* Checks whether the graph is final (i.e. only has one
-	 * version for each mod name).
-	 */
-	bool isFinal( ) const noexcept;
-	/* Generates the graph's "key", a sorted string of mod names. */
-	void genKey( ) noexcept;
-	/* Compute the graph's score and weight */
-	void computeScore(
-			T_ModVersions_ const& versions ) noexcept;
-};
-
-/*----------------------------------------------------------------------------*/
-
-T_MDRGraph_::T_MDRGraph_(
-		const uint32_t nodesGrowth ) noexcept
-	: nodes( std::max( 1u , nodesGrowth ) )
-{ }
-
-uint32_t T_MDRGraph_::findNode(
-		T_ModIdentifier const& id ) const noexcept
-{
-	const uint32_t nn( nodes.size( ) );
-	for ( uint32_t i = 0 ; i < nn ; i ++ ) {
-		if ( nodes[ i ].mod->identifier == id ) {
-			return i;
-		}
-	}
-	return T_HashIndex::INVALID_INDEX;
-}
-
-void T_MDRGraph_::removeBadNodes( ) noexcept
-{
-	uint32_t i = 0;
-	while ( i < nodes.size( ) ) {
-		if ( nodes[ i ].valid ) {
-			i ++;
-		} else {
-			nodes.removeSwap( i );
-		}
-	}
-}
-
-bool T_MDRGraph_::isFinal( ) const noexcept
-{
-	const uint32_t nn( nodes.size( ) );
-	assert( nn > 0 );
-	for ( uint32_t i = 0 ; i < nn - 1 ; i ++ ) {
-		T_String const& tnn( nodes[ i ].mod->identifier.name );
-		for ( uint32_t j = i + 1 ; j < nn ; j ++ ) {
-			if ( tnn == nodes[ j ].mod->identifier.name ) {
-				return false;
-			}
-		}
-	}
-	return true;
-}
-
-void T_MDRGraph_::genKey( ) noexcept
-{
-	const uint32_t nn( nodes.size( ) );
-	assert( nn > 0 );
-
-	RPC_ModIdentifier ids[ nn ];
-	for ( uint32_t i = 0 ; i < nn ; i ++ ) {
-		ids[ i ] = &( nodes[ i ].mod->identifier );
-	}
-	Sort< RPC_ModIdentifier >( ids , nn ,
-		[]( RPC_ModIdentifier a , RPC_ModIdentifier b ) -> int {
-			return a->compare( *b );
-		} );
-
-	T_StringBuilder sb;
-	for ( uint32_t i = 0 ; i < nn ; i ++ ) {
-		if ( i != 0 ) {
-			sb << ' ';
-		}
-		sb << *ids[ i ];
-	}
-	key = std::move( sb );
-}
-
-void T_MDRGraph_::computeScore(
-		T_ModVersions_ const& versions ) noexcept
-{
-	const uint32_t nn( nodes.size( ) );
-	assert( nn > 0 );
-
-	float sum = 0;
-	weight = 0;
-
-	for ( uint32_t i = 0 ; i < nn ; i ++ ) {
-		auto const& mi( nodes[ i ].mod->identifier );
-		auto const& mmv( *( versions.get( mi.name ) ) );
-		const uint32_t nWeight( 1 + nodes[ i ].revDeps.size( ) );
-		if ( mmv.first == mmv.second ) {
-			sum += nWeight;
-		} else {
-			sum += ( mi.version - mmv.first ) * nWeight
-				/ float( mmv.second - mmv.first );
-		}
-		weight += nWeight;
-	}
-	score = sum / float( weight );
-}
-
-/*----------------------------------------------------------------------------*/
-
-int LoadOrderCmp_( RPC_ModInfo a , RPC_ModInfo b )
-{
-	if ( a->modDeps.contains( b->identifier ) ) {
-		return 1;
-	} else if ( b->modDeps.contains( a->identifier ) ) {
-		return -1;
-	}
-	return a->identifier.compare( b->identifier );
-}
-
-/*----------------------------------------------------------------------------*/
-
-struct T_MDResolver_
-{
-	T_Logger& logger;
-	T_Array< T_String > const& required;
-	const T_ModsTable_ mods;
-	const T_ModVersions_ versions;
-	T_MDData_& output;
-
-	T_MDResolver_(
-			T_Logger& logger ,
-			T_Array< RPC_ModInfo > const& mods ,
-			T_Array< T_String > const& required ,
-			T_MDData_& output ) noexcept;
-
-	/* Add a mod to the initial graph of mods and dependencies.
-	 * All dependencies for the mod will be added. Will return
-	 * true on success, or false if there is a cyclic dependency
-	 * OR a dependency is missing OR a mod depends on more than
-	 * one UI mod (this also prevents UI mods dependending on
-	 * other UI mods).
-	 */
-	bool addModToInitialGraph(
-			T_MDRGraph_& graph ,
-			T_ModIdentifier const& mod ,
-			T_Array< T_ModIdentifier >& stack ) noexcept;
-
-	/* Generate the list of transitive dependencies for a node */
-	void generateFullDependencies(
-			T_MDRGraph_& graph ,
-			const uint32_t nid ) noexcept;
-	/* Generate the list of transitive reverse dependencies for a node */
-	void generateReverseDependencies(
-			T_MDRGraph_& graph ,
-			const uint32_t nid ) noexcept;
-	/* Generate all transitive dependencies for a graph */
-	void generateTransDepedencies(
-			T_MDRGraph_& graph ) noexcept;
-
-	/* Build the initial graph from tha table of mods */
-	T_MDRGraph_ buildInitialGraph( ) noexcept;
-
-	/* Gather subgraph identifiers for a set of mods */
-	void gatherSubgraphIds(
-			T_MDRGraph_& graph ,
-			T_Array< RPC_ModIdentifier > const& deps ,
-			T_Array< uint32_t >& ids ) noexcept;
-	/* Replace listed subgraph ids with another id */
-	void replaceSubgraphIds(
-			T_Array< T_MDRNode_ >& nodes ,
-			const uint32_t newId ,
-			T_Array< uint32_t > const& replace ) noexcept;
-	/* Set the subgraph id for a set of nodes */
-	void setSubgraphIds(
-			T_MDRGraph_& graph ,
-			T_Array< RPC_ModIdentifier > const& ids ,
-			const uint32_t sgId ) noexcept;
-	/* Find disjoint subgraphs in a graph, returning the array
-	 * of subgraph identifiers.
-	 */
-	T_Array< uint32_t > findSubgraphs(
-			T_MDRGraph_& graph ) noexcept;
-
-	/* Checks whether a subgraph contains all required mods
-	 * (and at least one UI mod)
-	 */
-	bool checkSubgraph(
-			T_MDRGraph_ const& graph ,
-			const uint32_t sgId ) noexcept;
-	/* Remove nodes that have the specified subgraph ID */
-	void removeSubgraphNodes(
-			T_MDRGraph_& graph ,
-			const uint32_t sgId ) noexcept;
-	/* Create a new graph based on a subgraph */
-	T_MDRGraph_ subgraphToGraph(
-			T_MDRGraph_ const& graph ,
-			const uint32_t sgId ) noexcept;
-	/* Create new graphs based on the specified subgraphs */
-	T_Array< T_MDRGraph_ > subgraphsToGraphs(
-			T_MDRGraph_ const& graph ,
-			T_Array< uint32_t> const& subgraphs ) noexcept;
-
-	/* Generate a graph that will contain only one version of a mod. Once
-	 * the graph is generated, it will be checked against the requirements
-	 * and eliminated if it doesn't match.
-	 */
-	T_Optional< T_MDRGraph_ > reduceGraph(
-			T_MDRGraph_ const& source ,
-			T_ModIdentifier const& wanted ) noexcept;
-	/* Generate reduced graphs from the first item in a list of graphs.
-	 * The resulting graphs will be added to the list. They may or may not
-	 * be final.
-	 */
-	void generateReducedGraphs(
-			T_Array< T_MDRGraph_ >& graphs ) noexcept;
-	/* Generate all final graphs from a list of graphs. */
-	void generateFinalGraphs(
-			T_Array< T_MDRGraph_ >& graphs ) noexcept;
-
-	/* Get the graph that will be used from the initial
-	 * graph and the list of subgraphs. */
-	T_Optional< T_MDRGraph_ > getGraph(
-			T_MDRGraph_ const& initialGraph ,
-			T_Array< uint32_t > const& subgraphs ) noexcept;
-
-	/* Copy a node and its dependencies from a graph to another. */
-	void copyNodes(
-			T_MDRGraph_ const& source ,
-			uint32_t node ,
-			T_MDRGraph_& dest ,
-			bool copyReverseDeps ) const noexcept;
-
-	/* Split the final graph into UI-specific graphs */
-	T_Array< T_MDRGraph_ > getUIGraphs(
-			T_MDRGraph_ const& graph ) noexcept;
-	/* Extract common mods from the various graphs */
-	T_Array< RPC_ModInfo > findCommonMods(
-			T_MDRGraph_ const& graph ,
-			T_Array< T_MDRGraph_ > const& uiGraphs ) noexcept;
-	/* Extract mods for a given UI */
-	T_UIMods_ extractUIMods(
-			T_MDRGraph_ const& uiGraph ,
-			T_ModsList_ const& commonMods ) noexcept;
-	/* Generate the list of UI mods */
-	T_Array< T_UIMods_ > generateUILists(
-			T_Array< T_MDRGraph_ > const& uiGraphs ,
-			T_ModsList_ const& commonMods ) noexcept;
-};
-
-/*----------------------------------------------------------------------------*/
-
-T_MDResolver_::T_MDResolver_(
-		T_Logger& logger ,
-		T_Array< RPC_ModInfo > const& mods ,
-		T_Array< T_String > const& required ,
-		T_MDData_& output ) noexcept
-	: logger( logger ) , required( required ) ,
-		mods( makeModsTable_( mods ) ) ,
-		versions( makeModVersions_( mods ) ) ,
-		output( output )
-{ }
-
-/*----------------------------------------------------------------------------*/
-
-bool T_MDResolver_::addModToInitialGraph(
-		T_MDRGraph_& graph ,
-		T_ModIdentifier const& mod ,
-		T_Array< T_ModIdentifier >& stack ) noexcept
-{
-	if ( stack.contains( mod ) ) {
-		logger.warning( ) << "Mod " << mod
-			<< " is part of a cycle.";
-		return false;
-	}
-
-	const uint32_t initialIndex( graph.findNode( mod ) );
-	if ( initialIndex != T_HashIndex::INVALID_INDEX ) {
-		return graph.nodes[ initialIndex ].valid;
-	}
-
-	RPC_ModInfo const* const miPtr( mods.get( mod ) );
-	if ( miPtr == nullptr ) {
-		logger.warning( ) << "Mod " << mod
-			<< " is missing.";
-		return false;
-	}
-	T_ModInfo const& mi( **miPtr );
-
-	bool valid( true );
-	T_Array< RPC_ModIdentifier > deps{ 16 };
-	T_Array< T_String > uiDeps{ 4 };
-	if ( mi.isUserInterface( ) ) {
-		uiDeps.add( mi.identifier.name );
-	}
-
-	// Push to stack
-	const uint32_t stackIndex( stack.size( ) );
-	stack.add( mod );
-
-	// Handle dependencies
-	const uint32_t nDeps( mi.modDeps.size( ) );
-	for ( uint32_t i = 0 ; i < nDeps ; i ++ ) {
-		T_ModIdentifier const& di( mi.modDeps[ i ] );
-		logger.trace( ) << "Checking "
-			<< mod << " -> " << di
-			<< " dependency";
-
-		const bool validDep( addModToInitialGraph(
-				graph , di , stack ) );
-		assert( stack.size( ) == stackIndex + 1 );
-		assert( stack[ stackIndex ] == mod );
-		if ( !validDep ) {
-			valid = false;
-			continue;
-		}
-
-		const uint32_t didx( graph.findNode( di ) );
-		assert( didx != T_HashIndex::INVALID_INDEX );
-		const RPC_ModIdentifier miPtr( &( graph.nodes[ didx ].mod->identifier ) );
-		assert( !deps.contains( miPtr ) );
-		deps.add( miPtr );
-
-		auto const& dr( graph.nodes[ didx ] );
-		auto const nuid( dr.uiDeps.size( ) );
-		for ( uint32_t j = 0 ; j < nuid ; j ++ ) {
-			if ( !uiDeps.contains( dr.uiDeps[ j ] ) ) {
-				uiDeps.add( dr.uiDeps[ j ] );
-			}
-		}
-	}
-	if ( uiDeps.size( ) > 1 ) {
-		valid = false;
-		T_StringBuilder sb( "Mod " );
-		sb << mod << " has more than 1 UI dependency:";
-		for ( uint32_t i = 0 ; i < uiDeps.size( ) ; i ++ ) {
-			sb << ' ' << uiDeps[ i ];
-		}
-		logger.warning( std::move( sb ) );
-	}
-
-	// Pop stack
-	stack.remove( stackIndex );
-
-	// Add the node
-	graph.nodes.addNew( *miPtr , valid , std::move( deps ) ,
-			std::move( uiDeps ) );
-	logger.trace( ) << "Added "
-		<< ( valid ? "valid" : "invalid" )
-		<< " mod " << mod << " to the graph";
-	return valid;
-}
-
-/*----------------------------------------------------------------------------*/
-
-void T_MDResolver_::generateFullDependencies(
-		T_MDRGraph_& graph ,
-		const uint32_t nid ) noexcept
-{
-	auto& node( graph.nodes[ nid ] );
-	if ( node.fullDeps.present( ) ) {
-		return;
-	}
-
-	const uint32_t nd( node.deps.size( ) );
-	T_Array< RPC_ModIdentifier > fd{ std::max( 1u , nd * 2 ) };
-	for ( uint32_t i = 0 ; i < nd ; i ++ ) {
-		const auto did( node.deps[ i ] );
-		if ( !fd.contains( did ) ) {
-			fd.add( did );
-		}
-
-		const auto didx( graph.findNode( *did ) );
-		generateFullDependencies( graph , didx );
-
-		const auto& dep( graph.nodes[ didx ] );
-		const auto& dfd( ( T_Array< RPC_ModIdentifier > const&) dep.fullDeps );
-		const uint32_t nfd( dfd.size( ) );
-		for ( uint32_t j = 0 ; j < nfd ; j ++ ) {
-			if ( !fd.contains( dfd[ j ] ) ) {
-				fd.add( dfd[ j ] );
-			}
-		}
-	}
-	node.fullDeps = fd;
-
-	if ( logger.hasLevel( E_LogLevel::TRACE ) ) {
-		if ( fd.size( ) == 0 ) {
-			logger.trace( ) << "No transitive dependencies for "
-				<< node.mod->identifier;
-		} else {
-			T_StringBuilder sb( "Transitive dependencies for " );
-			sb << node.mod->identifier << ':';
-			const auto nfd( fd.size( ) );
-			for ( uint32_t i = 0 ; i < nfd ; i ++ ) {
-				sb << ' ' << graph.nodes[
-						graph.findNode( *fd[ i ] )
-					].mod->identifier;
-			}
-			logger.trace( std::move( sb ) );
-		}
-	}
-}
-
-void T_MDResolver_::generateReverseDependencies(
-		T_MDRGraph_& graph ,
-		const uint32_t nid ) noexcept
-{
-	auto const& node( graph.nodes[ nid ] );
-	const auto identifier{ &( node.mod->identifier ) };
-
-	auto const& dfd( ( T_Array< RPC_ModIdentifier > const&) node.fullDeps );
-	const uint32_t nfd( dfd.size( ) );
-	for ( uint32_t i = 0 ; i < nfd ; i ++ ) {
-		auto& tgt( graph.nodes[ graph.findNode( *dfd[ i ] ) ] );
-		if ( !tgt.revDeps.contains( identifier ) ) {
-			tgt.revDeps.add( identifier );
-		}
-	}
-}
-
-void T_MDResolver_::generateTransDepedencies(
-		T_MDRGraph_& graph ) noexcept
-{
-	const uint32_t nn( graph.nodes.size( ) );
-	for ( uint32_t i = 0 ; i < nn ; i ++ ) {
-		generateFullDependencies( graph , i );
-	}
-	for ( uint32_t i = 0 ; i < nn ; i ++ ) {
-		generateReverseDependencies( graph , i );
-	}
-	if ( !logger.hasLevel( E_LogLevel::TRACE ) ) {
-		return;
-	}
-	for ( uint32_t i = 0 ; i < nn ; i ++ ) {
-		auto const& node( graph.nodes[ i ] );
-		const auto& rd( node.revDeps );
-		if ( rd.size( ) == 0 ) {
-			logger.trace( ) << "No transitive reverse dependencies for "
-				<< node.mod->identifier;
-		} else {
-			T_StringBuilder sb( "Transitive reverse dependencies for " );
-			sb << node.mod->identifier << ':';
-			const auto nrd( rd.size( ) );
-			for ( uint32_t i = 0 ; i < nrd ; i ++ ) {
-				sb << ' ' << *rd[ i ];
-			}
-			logger.trace( std::move( sb ) );
-		}
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-T_MDRGraph_ T_MDResolver_::buildInitialGraph( ) noexcept
-{
-	T_MDRGraph_ graph;
-	const uint32_t nMods( mods.size( ) );
-	T_Array< T_ModIdentifier > stack;
-	for ( uint32_t i = 0 ; i < nMods ; i ++ ) {
-		addModToInitialGraph( graph , mods[ i ]->identifier , stack );
-		assert( stack.size( ) == 0 );
-	}
-	graph.removeBadNodes( );
-	if ( graph.nodes.size( ) ) {
-		generateTransDepedencies( graph );
-	}
-	return graph;
-}
-
-/*----------------------------------------------------------------------------*/
-
-void T_MDResolver_::gatherSubgraphIds(
-		T_MDRGraph_& graph ,
-		T_Array< RPC_ModIdentifier > const& deps ,
-		T_Array< uint32_t >& ids ) noexcept
-{
-	const uint32_t nd{ deps.size( ) };
-	for ( uint32_t j = 0 ; j < nd ; j ++ ) {
-		auto const& dn( graph.nodes[ graph.findNode( *deps[ j ] ) ] );
-		if ( dn.sgId.present( ) ) {
-			const uint32_t v( dn.sgId );
-			if ( !ids.contains( v ) ) {
-				ids.add( v );
-			}
-		}
-	}
-}
-
-void T_MDResolver_::replaceSubgraphIds(
-		T_Array< T_MDRNode_ >& nodes ,
-		const uint32_t newId ,
-		T_Array< uint32_t > const& replace ) noexcept
-{
-	const uint32_t nn( nodes.size( ) );
-	for ( uint32_t i = 0 ; i < nn ; i ++ ) {
-		auto& node( nodes[ i ] );
-		if ( !node.sgId.present( ) ) {
-			continue;
-		}
-		const uint32_t oldId( node.sgId );
-		if ( replace.contains( oldId ) ) {
-			node.sgId = newId;
-		}
-	}
-}
-
-void T_MDResolver_::setSubgraphIds(
-		T_MDRGraph_& graph ,
-		T_Array< RPC_ModIdentifier > const& ids ,
-		const uint32_t sgId ) noexcept
-{
-	const auto ni( ids.size( ) );
-	for ( uint32_t i = 0 ; i < ni ; i ++ ) {
-		graph.nodes[ graph.findNode( *ids[ i ] ) ].sgId = sgId;
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-T_Array< uint32_t > T_MDResolver_::findSubgraphs(
-		T_MDRGraph_& graph ) noexcept
-{
-	uint32_t nextId( 0 );
-	T_Array< uint32_t > subgraphIds{ 16 };
-	T_Array< uint32_t > curIds{ 16 };
-	const auto nn( graph.nodes.size( ) );
-	for ( uint32_t i = 0 ; i < nn ; i ++ ) {
-		auto& node( graph.nodes[ i ] );
-		if ( node.sgId.present( ) ) {
-			continue;
-		}
-
-		// Find existing identifiers
-		curIds.clear( );
-		gatherSubgraphIds( graph , node.fullDeps , curIds );
-		gatherSubgraphIds( graph , node.revDeps , curIds );
-
-		// Get the nodes' new subgraph identifier
-		const uint32_t assign( ([&](){
-				if ( curIds.size( ) != 0 ) {
-					const uint32_t temp( curIds[ 0 ] );
-					curIds.removeSwap( 0 );
-					return temp;
-				} else {
-					subgraphIds.add( nextId );
-					return nextId ++;
-				}
-			})( ) );
-
-		// Replace other identifiers if there's more than 1
-		if ( curIds.size( ) != 0 ) {
-			replaceSubgraphIds( graph.nodes , assign , curIds );
-			for ( uint32_t j = 0 ; j < curIds.size( ) ; j ++ ) {
-				subgraphIds.removeSwap( subgraphIds.indexOf( curIds[ j ] ) );
-			}
-		}
-
-		// Assign new ID to node, deps and rdeps
-		node.sgId = assign;
-		setSubgraphIds( graph , node.fullDeps , assign );
-		setSubgraphIds( graph , node.revDeps , assign );
-	}
-
-	// XXX assert all nodes have a subgraph ID
-	logger.trace( ) << "Generated " << subgraphIds.size( ) << " subgraphs";
-	return subgraphIds;
-}
-
-/*----------------------------------------------------------------------------*/
-
-bool T_MDResolver_::checkSubgraph(
-		T_MDRGraph_ const& graph ,
-		const uint32_t sgId ) noexcept
-{
-	bool rFound[ required.size( ) ];
-	for ( uint32_t i = 0 ; i < required.size( ) ; i ++ ) {
-		rFound[ i ] = false;
-	}
-
-	const uint32_t nn( graph.nodes.size( ) );
-	bool hasUI( false );
-	for ( uint32_t i = 0 ; i < nn ; i ++ ) {
-		auto const& node( graph.nodes[ i ] );
-		if ( node.sgId != sgId ) {
-			continue;
-		}
-		hasUI = hasUI || node.mod->isUserInterface( );
-
-		const auto rIdx( required.indexOf( node.mod->identifier.name ) );
-		if ( rIdx != -1 ) {
-			rFound[ rIdx ] = true;
-		}
-	}
-	if ( !hasUI ) {
-		logger.trace( ) << "Subgraph #" << sgId
-			<< ": no user interface";
-	}
-
-	bool ok( hasUI );
-	for ( uint32_t i = 0 ; i < required.size( ) ; i ++ ) {
-		if ( !rFound[ i ] ) {
-			logger.trace( ) << "Subgraph #" << sgId
-				<< ": missing required mod " << required[ i ];
-			ok = false;
-		}
-	}
-	return ok;
-}
-
-void T_MDResolver_::removeSubgraphNodes(
-		T_MDRGraph_& graph ,
-		const uint32_t sgId ) noexcept
-{
-	uint32_t i = 0;
-	while ( i < graph.nodes.size( ) ) {
-		if ( graph.nodes[ i ].sgId == sgId ) {
-			graph.nodes.removeSwap( i );
-		} else {
-			i ++;
-		}
-	}
-}
-
-T_MDRGraph_ T_MDResolver_::subgraphToGraph(
-		T_MDRGraph_ const& graph ,
-		const uint32_t sgId ) noexcept
-{
-	const uint32_t nn( graph.nodes.size( ) );
-	const uint32_t ntn( ([&]() {
-			uint32_t ntn = 0;
-			for ( uint32_t i = 0 ; i < nn ; i ++ ) {
-				if ( graph.nodes[ i ].sgId == sgId ) {
-					ntn ++;
-				}
-			}
-			return ntn;
-		})( ) );
-	assert( ntn != 0 );
-
-	T_MDRGraph_ ng{ ntn };
-	for ( uint32_t i = 0 ; i < nn ; i ++ ) {
-		auto const& node( graph.nodes[ i ] );
-		if ( node.sgId == sgId ) {
-			const uint32_t idx( ng.nodes.add( node ) );
-			ng.nodes[ idx ].sgId.clear( );
-		}
-	}
-	return ng;
-}
-
-T_Array< T_MDRGraph_ > T_MDResolver_::subgraphsToGraphs(
-		T_MDRGraph_ const& graph ,
-		T_Array< uint32_t> const& subgraphs ) noexcept
-{
-	const uint32_t nsg( subgraphs.size( ) );
-	T_Array< T_MDRGraph_ > output{ std::max( 1u , 3 * nsg / 2 ) };
-	for ( uint32_t i = 0 ; i < nsg ; i ++ ) {
-		output.add( subgraphToGraph( graph , subgraphs[ i ] ) );
-	}
-	return output;
-}
-
-/*----------------------------------------------------------------------------*/
-
-T_Optional< T_MDRGraph_ > T_MDResolver_::reduceGraph(
-		T_MDRGraph_ const& source ,
-		T_ModIdentifier const& wanted ) noexcept
-{
-	T_MDRGraph_ output( source );
-	uint32_t i = 0;
-	while ( i < output.nodes.size( ) ) {
-		auto const& node( output.nodes[ i ] );
-		auto const& nid( node.mod->identifier );
-		if ( nid == wanted ) {
-			continue;
-		}
-
-		bool remove;
-		if ( nid.name == wanted.name ) {
-			remove = true;
-		} else {
-			T_Array< RPC_ModIdentifier > const& fd( node.fullDeps );
-			const uint32_t nfd( fd.size( ) );
-			remove = false;
-			for ( uint32_t i = 0 ; i < nfd && !remove ; i ++ ) {
-				auto const& mi( *fd[ i ] );
-				remove = mi.name == nid.name && mi.version != nid.version;
-			}
-		}
-
-		if ( remove ) {
-			output.nodes.removeSwap( i );
-		} else {
-			i ++;
-		}
-	}
-
-	// Clear full reverse deps and regenerate them
-	const uint32_t nn( output.nodes.size( ) );
-	for ( uint32_t i = 0 ; i < nn ; i ++ ) {
-		output.nodes[ i ].revDeps.clear( );
-	}
-	for ( uint32_t i = 0 ; i < nn ; i ++ ) {
-		generateReverseDependencies( output , i );
-	}
-
-	// Now extract subgraphs and find the one that contains our target
-	findSubgraphs( output );
-	auto const nid( output.findNode( wanted ) );
-	uint32_t const sg( output.nodes[ nid ].sgId );
-	if ( checkSubgraph( output , sg ) ) {
-		return subgraphToGraph( output , sg );
-	} else {
-		return {};
-	}
-}
-
-void T_MDResolver_::generateReducedGraphs(
-		T_Array< T_MDRGraph_ >& graphs ) noexcept
-{
-	T_MDRGraph_ const& initial( graphs[ 0 ] );
-	const uint32_t nn( initial.nodes.size( ) );
-
-	// Count the amount of different versions for each mod name
-	RPC_String names[ nn ];
-	uint32_t counters[ nn ];
-	uint32_t nNames = 0;
-	for ( uint32_t i = 0 ; i < nn ; i ++ ) {
-		auto const& nid( initial.nodes[ i ].mod->identifier );
-		bool found( false );
-		for ( uint32_t j = 0 ; j < nNames && !found ; j ++ ) {
-			if ( *names[ j ] == nid.name ) {
-				counters[ j ] ++;
-				found = true;
-			}
-		}
-		if ( !found ) {
-			names[ nNames ] = &nid.name;
-			counters[ nNames ] = 0;
-			nNames ++;
-		}
-	}
-
-	// Generate graphs
-	for ( uint32_t i = 0 ; i < nNames ; i ++ ) {
-		if ( counters[ i ] == 0 ) {
-			continue;
-		}
-		for ( uint32_t j = 0 ; j < nn ; j ++ ) {
-			auto const& nid( initial.nodes[ j ].mod->identifier );
-			if ( nid.name != *names[ i ] ) {
-				continue;
-			}
-
-			auto gen( reduceGraph( initial , nid ) );
-			if ( gen.present( ) ) {
-				logger.trace( )
-					<< "Generated new graph using "
-					<< nid;
-				graphs.add( std::move( gen ) );
-			}
-		}
-	}
-}
-
-void T_MDResolver_::generateFinalGraphs(
-		T_Array< T_MDRGraph_ >& graphs ) noexcept
-{
-	T_Array< T_MDRGraph_ > output{ graphs.growth( ) };
-	while ( graphs.size( ) != 0 ) {
-		T_MDRGraph_& initial( graphs[ 0 ] );
-		if ( initial.isFinal( ) ) {
-			initial.genKey( );
-			const uint32_t os( output.size( ) );
-			bool found( false );
-			for ( uint32_t i = 0 ; i < os ; i ++ ) {
-				if ( output[ i ].key == initial.key ) {
-					found = true;
-					break;
-				}
-			}
-			if ( !found ) {
-				logger.trace( )
-					<< "Adding final graph "
-					<< initial.key;
-				output.add( std::move( initial ) );
-			}
-		} else {
-			generateReducedGraphs( graphs );
-		}
-
-		graphs.removeSwap( 0 );
-	}
-	logger.trace( ) << output.size( ) << " final graphs";
-	graphs = output;
-}
-
-/*----------------------------------------------------------------------------*/
-
-T_Optional< T_MDRGraph_ > T_MDResolver_::getGraph(
-		T_MDRGraph_ const& initialGraph ,
-		T_Array< uint32_t > const& subgraphs ) noexcept
-{
-	T_Array< T_MDRGraph_ > graphs{ subgraphsToGraphs( initialGraph , subgraphs ) };
-	generateFinalGraphs( graphs );
-	const uint32_t nGraphs( graphs.size( ) );
-	if ( nGraphs == 0 ) {
-		logger.warning( ) << "No set of mods satisfies the configuration";
-		return {};
-	}
-
-	const bool trace( logger.hasLevel( E_LogLevel::TRACE ) );
-	uint32_t keepIndex = T_HashIndex::INVALID_INDEX ,
-		 maxWeight = 0 ,
-		 ambiguous = 0;
-	float maxScore = 0;
-	for ( uint32_t j = 0 ; j < nGraphs ; j ++ ) {
-		graphs[ j ].computeScore( versions );
-		if ( trace ) {
-			logger.trace( ) << "Score/Weight ( "
-				<< graphs[ j ].key << " ) = "
-				<< graphs[ j ].score << " / "
-				<< graphs[ j ].weight;
-		}
-		if ( graphs[ j ].score > maxScore ) {
-			keepIndex = j;
-			maxScore = graphs[ j ].score;
-			maxWeight = graphs[ j ].weight;
-			ambiguous = 0;
-		} else if ( graphs[ j ].score == maxScore
-				&& graphs[ j ].weight > maxWeight ) {
-			keepIndex = j;
-			maxWeight = graphs[ j ].weight;
-			ambiguous = 0;
-		} else if ( graphs[ j ].score == maxScore
-				&& graphs[ j ].weight == maxWeight ) {
-			ambiguous ++;
-		}
-	}
-	assert( keepIndex != T_HashIndex::INVALID_INDEX );
-	output.ambiguous = ( ambiguous != 0 );
-	if ( ambiguous ) {
-		logger.notice( ) << "Selected graph ("
-			<< graphs[ keepIndex ].key
-			<< ") but there were ambiguities.";
-	} else if ( trace ) {
-		logger.trace( ) << "Using graph ("
-			<< graphs[ keepIndex ].key << ')';
-	}
-	return std::move( graphs[ keepIndex ] );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void T_MDResolver_::copyNodes(
-		T_MDRGraph_ const& source ,
-		const uint32_t nid ,
-		T_MDRGraph_& dest ,
-		const bool copyReverseDeps ) const noexcept
-{
-	auto const& nsrc( source.nodes[ nid ] );
-	if ( dest.findNode( nsrc.mod->identifier ) != T_HashIndex::INVALID_INDEX ) {
-		return;
-	}
-
-	dest.nodes.addNew( T_MDRNode_::T_Dup( ) , nsrc );
-
-	T_Array< RPC_ModIdentifier > const& deps( nsrc.fullDeps );
-	const uint32_t nDeps( deps.size( ) );
-	for ( uint32_t i = 0 ; i < nDeps ; i ++ ) {
-		copyNodes( source , source.findNode( *deps[ i ] ) ,
-				dest , false );
-	}
-
-	if ( !copyReverseDeps ) {
-		return;
-	}
-
-	const uint32_t nRevDeps( nsrc.revDeps.size( ) );
-	for ( uint32_t i = 0 ; i < nRevDeps ; i ++ ) {
-		copyNodes( source , source.findNode( *nsrc.revDeps[ i ] ) ,
-				dest , false );
-	}
-}
-
-T_Array< T_MDRGraph_ > T_MDResolver_::getUIGraphs(
-		T_MDRGraph_ const& graph ) noexcept
-{
-	const uint32_t nn( graph.nodes.size( ) );
-	const uint32_t nui( ([&]() {
-			// How many UI mods?
-			uint32_t c = 0;
-			for ( uint32_t i = 0 ; i < nn ; i ++ ) {
-				if ( graph.nodes[ i ].mod->isUserInterface( ) ) {
-					c ++;
-				}
-			}
-			return c;
-		})( ) );
-	logger.trace( ) << "About to generate " << nui << " per-UI graphs";
-	T_Array< T_MDRGraph_ > output{ nui };
-	for ( uint32_t i = 0 ; output.size( ) < nui ; i ++ ) {
-		assert( i < nn );
-		auto const& node( graph.nodes[ i ] );
-		if ( !node.mod->isUserInterface( ) ) {
-			continue;
-		}
-
-		output.addNew( nn );
-		auto& ng( output[ output.size( ) - 1 ] );
-		copyNodes( graph , i , ng , true );
-
-		const uint32_t ngn( ng.nodes.size( ) );
-		logger.trace( )
-			<< "Generated graph for UI mod " << *node.mod << " ("
-			<< ngn << " nodes)";
-	}
-
-	return output;
-}
-
-/*----------------------------------------------------------------------------*/
-
-T_Array< RPC_ModInfo > T_MDResolver_::findCommonMods(
-		T_MDRGraph_ const& graph ,
-		T_Array< T_MDRGraph_ > const& uiGraphs ) noexcept
-{
-	const uint32_t nn( graph.nodes.size( ) );
-	const uint32_t nui( uiGraphs.size( ) );
-	const uint32_t minMods( ([&](){
-			uint32_t c = 0u;
-			for ( uint32_t i = 0 ; i < nui ; i ++ ) {
-				c = std::min( uiGraphs[ i ].nodes.size( ) , c );
-			}
-			return std::max( 1u , c );
-		})( ) );
-
-	RPC_ModIdentifier common[ minMods ];
-	uint32_t nc = 0;
-	for ( uint32_t i = 0 ; i < nn ; i ++ ) {
-		auto const& mgNode( graph.nodes[ i ] );
-		if ( mgNode.uiDeps.size( ) != 0 ) {
-			continue;
-		}
-
-		auto const& id( mgNode.mod->identifier );
-		bool ok( true );
-		for ( uint32_t j = 0 ; j < nui && ok ; j ++ ) {
-			ok = uiGraphs[ j ].findNode( id ) != T_HashIndex::INVALID_INDEX;
-		}
-		if ( ok ) {
-			common[ nc++ ] = &id;
-		}
-	}
-
-	T_ModsList_ cml{ std::max( 1u , nc ) };
-	for ( uint32_t i = 0 ; i < nc ; i ++ ) {
-		cml.add( *mods.get( *common[ i ] ) );
-	}
-	cml.sort( LoadOrderCmp_ );
-
-	if ( logger.hasLevel( E_LogLevel::TRACE ) ) {
-		if ( nc != 0 ) {
-			T_StringBuilder sb( "Common mods:" );
-			for ( uint32_t i = 0 ; i < nc ; i ++ ) {
-				sb << ' ' << *cml[ i ];
-			}
-			logger.trace( std::move( sb ) );
-		} else {
-			logger.trace( ) << "No common mods";
-		}
-	}
-
-	return cml;
-}
-
-T_UIMods_ T_MDResolver_::extractUIMods(
-		T_MDRGraph_ const& uiGraph ,
-		T_ModsList_ const& commonMods ) noexcept
-{
-	const uint32_t nn( uiGraph.nodes.size( ) );
-	RPC_ModIdentifier ui( nullptr );
-	RPC_ModInfo uiMods[ nn ];
-	uint32_t nm = 0;
-
-	for ( uint32_t i = 0 ; i < nn ; i ++ ) {
-		RPC_ModInfo nodeMod( uiGraph.nodes[ i ].mod );
-		if ( commonMods.contains( nodeMod ) ) {
-			continue;
-		}
-		uiMods[ nm ++ ] = nodeMod;
-		if ( nodeMod->isUserInterface( ) ) {
-			assert( ui == nullptr );
-			ui = &( nodeMod->identifier );
-		}
-	}
-	assert( ui != nullptr );
-	assert( nm > 0 );
-
-	T_ModsList_ uiml{ nm };
-	for ( uint32_t i = 0 ; i < nm ; i ++ ) {
-		uiml.add( uiMods[ i ] );
-	}
-	uiml.sort( LoadOrderCmp_ );
-
-	if ( logger.hasLevel( E_LogLevel::TRACE ) ) {
-		T_StringBuilder sb( "Mods for UI " );
-		sb << ui->name << ':';
-		for ( uint32_t i = 0 ; i < nm ; i ++ ) {
-			sb << ' ' << *uiml[ i ];
-		}
-		logger.trace( std::move( sb ) );
-	}
-
-	return T_UIMods_{ ui->name , std::move( uiml ) };
-}
-
-T_Array< T_UIMods_ > T_MDResolver_::generateUILists(
-		T_Array< T_MDRGraph_ > const& uiGraphs ,
-		T_ModsList_ const& commonMods ) noexcept
-{
-	const uint32_t nui( uiGraphs.size( ) );
-	T_Array< T_UIMods_ > result{ nui };
-	for ( uint32_t i = 0 ; i < nui ; i ++ ) {
-		result.add( extractUIMods( uiGraphs[ i ] , commonMods ) );
-	}
-	return result;
-}
-
-} // namespace
-
-
-/*= T_ModsDependencies =======================================================*/
-
-T_ModsDependencies::T_ModsDependencies( ) noexcept
-	: A_PrivateImplementation( new T_MDData_( ) )
-{ }
-
-T_ModsDependencies::T_ModsDependencies(
-		T_Logger& logger ,
-		T_Array< RPC_ModInfo > const& mods ,
-		T_ModsManagerConfiguration const& config ) noexcept
-	: A_PrivateImplementation( new T_MDData_( ) )
-{
-	const bool trace( logger.hasLevel( E_LogLevel::TRACE ) );
-	auto& pi( p< T_MDData_ >( ) );
-	pi.success = false;
-
-	const T_Array< RPC_ModInfo > matches{ config.filterMods( mods ) };
-	if ( matches.size( ) == 0 ) {
-		logger.warning( "No mods left after applying filters" );
-		return;
-	}
-	if ( trace ) {
-		T_StringBuilder sb( "Mods matching configuration:" );
-		auto const nMods( mods.size( ) );
-		for ( uint32_t i = 0 ; i < nMods ; i ++ ) {
-			sb << ' ' << *mods[ i ];
-		}
-		logger.trace( std::move( sb ) );
-	}
-
-	const T_Array< T_String > required( config.requiredMods( ) );
-	if ( trace ) {
-		if ( required.size( ) != 0 ) {
-			T_StringBuilder sb( "Required mods:" );
-			for ( uint32_t i = 0 ; i < required.size( ) ; i ++ ) {
-				sb << ' ' << required[ i ];
-			}
-			logger.trace( std::move( sb ) );
-		} else {
-			logger.trace( ) << "No mod requirements";
-		}
-	}
-
-	logger.debug( ) << "Resolving mod dependencies";
-	T_MDResolver_ resolver{ logger , matches , required , pi };
-	T_MDRGraph_ initialGraph{ resolver.buildInitialGraph( ) };
-	if ( initialGraph.nodes.size( ) == 0 ) {
-		logger.warning( ) << "No mods left after invalid dependencies removal";
-		return;
-	}
-	logger.trace( ) << "Full graph: " << initialGraph.nodes.size( ) << " valid nodes";
-
-	T_Array< uint32_t > subgraphs( resolver.findSubgraphs( initialGraph ) );
-	uint32_t i = 0;
-	while ( i < subgraphs.size( ) ) {
-		if ( resolver.checkSubgraph( initialGraph , subgraphs[ i ]  ) ) {
-			i ++;
-		} else {
-			resolver.removeSubgraphNodes( initialGraph , subgraphs[ i ] );
-			subgraphs.removeSwap( i );
-		}
-	}
-	if ( subgraphs.size( ) == 0 ) {
-		logger.warning( ) << "No set of mods satisfies the configuration";
-		return;
-	}
-
-	auto graph( resolver.getGraph( initialGraph , subgraphs ) );
-	if ( !graph.present( ) ) {
-		return;
-	}
-	auto uiGraphs( resolver.getUIGraphs( graph ) );
-	pi.commonMods = resolver.findCommonMods( graph , uiGraphs );
-	pi.uiMods = resolver.generateUILists( uiGraphs , pi.commonMods );
-	pi.uiMods.sort( [&]( T_UIMods_ const& a , T_UIMods_ const& b ) -> int {
-		const auto pa( config.uiPreference( a.name ) );
-		const auto pb( config.uiPreference( b.name ) );
-		if ( pa == pb ) {
-			return a.name.compare( b.name );
-		}
-		return -T_Comparator< int32_t >::compare( pa , pb );
-	} );
-	if ( trace ) {
-		T_StringBuilder sb( "User interfaces:" );
-		for ( uint32_t i = 0 ; i < pi.uiMods.size( ) ; i ++ ) {
-			sb << ' ' << pi.uiMods[ i ].name;
-		}
-		logger.trace( std::move( sb ) );
-	}
-	pi.success = true;
-}
-
-// ---------------------------------------------------------------------
-
-T_ModsDependencies::T_ModsDependencies(
-		T_ModsDependencies const& other ) noexcept
-	: A_PrivateImplementation( new T_MDData_( other.p< T_MDData_ >( ) ) )
-{ }
-
-T_ModsDependencies& T_ModsDependencies::operator =(
-		T_ModsDependencies const& other ) noexcept
-{
-	p< T_MDData_ >( ) = other.p< T_MDData_ >( );
-	return *this;
-}
-
-T_ModsDependencies::T_ModsDependencies(
-		T_ModsDependencies&& other ) noexcept
-	: A_PrivateImplementation( std::move( other ) )
-{ }
-
-T_ModsDependencies& T_ModsDependencies::operator =(
-		T_ModsDependencies&& other ) noexcept
-{
-	A_PrivateImplementation::operator =( std::move( other ) );
-	return *this;
-}
-
-M_DECLARE_SWAP( T_ModsDependencies )
-{
-	T_ModsDependencies temp( std::move( rhs ) );
-	rhs = std::move( lhs );
-	lhs = std::move( temp );
-}
-
-// ---------------------------------------------------------------------
-
-bool T_ModsDependencies::resolved( ) const
-{
-	return p< T_MDData_ >( ).success;
-}
-
-bool T_ModsDependencies::ambiguous( ) const
-{
-	return p< T_MDData_ >( ).ambiguous;
-}
-
-T_Array< T_String > T_ModsDependencies::userInterfaces( ) const
-{
-	auto const& pi( p< T_MDData_ >( ) );
-	const auto nui( pi.uiMods.size( ) );
-	T_Array< T_String > result{ nui };
-	for ( uint32_t i = 0 ; i < nui ; i ++ ) {
-		result.add( pi.uiMods[ i ].name );
-	}
-	return result;
-}
-
-T_Array< RPC_ModInfo > const& T_ModsDependencies::commonMods( ) const
-{
-	return p< T_MDData_ >( ).commonMods;
-}
-
-T_Array< RPC_ModInfo >::RPC T_ModsDependencies::forUserInterface(
-		T_String const& name ) const
-{
-	auto const& pi( p< T_MDData_ >( ) );
-	const auto nui( pi.uiMods.size( ) );
-	for ( uint32_t i = 0 ; i < nui ; i ++ ) {
-		auto const& uim( pi.uiMods[ i ] );
-		if ( uim.name == name ) {
-			return &uim.mods;
-		}
-	}
-	return nullptr;
-}
-
-
-/*= DATA MOD DESCRIPTION FILE ================================================*/
-
-namespace {
-struct T_ModInfoFromDescr_
-{
-	T_ModInfo modInfo;
-	bool hasVersion;
-	bool hasRevision;
-	bool hasLibVersion;
-};
-using SP_MIFD = T_SharedPtr< T_ModInfoFromDescr_ >;
-
-bool DMDFInitialise_( T_SRDParserData const& d )
-{
-	auto desc( NewShared< T_ModInfoFromDescr_ >( ) );
-	desc->hasVersion = desc->hasRevision = desc->hasLibVersion = false;
-	desc->modInfo.type = E_ModType::DATA;
-	*( d.currentData ) = desc;
-	return true;
-}
-
-bool DMDFSetName_( T_SRDParserData const& d )
-{
-	auto const& tok( (*d.input)[ 1 ] );
-	auto const& mi( d.currentData->value< SP_MIFD >( ) );
-	if ( mi->modInfo.identifier.name ) {
-		d.errors.add( "duplicate module name" , tok );
-	} else {
-		mi->modInfo.identifier.name = tok.stringValue( );
-	}
-	return true;
-}
-
-bool DMDFSetVersion_( T_SRDParserData const& d )
-{
-	auto const& tok( (*d.input)[ 1 ] );
-	auto const& mi( d.currentData->value< SP_MIFD >( ) );
-	if ( mi->hasVersion ) {
-		d.errors.add( "duplicate version number" , tok );
-	}
-
-	const auto v( tok.longValue( ) );
-	if ( v < 0 || v > UINT32_MAX ) {
-		d.errors.add( "invalid version number" , tok );
-	} else {
-		mi->modInfo.identifier.version = tok.longValue( );
-	}
-	mi->hasVersion = true;
-	return true;
-}
-
-bool DMDFSetRevision_( T_SRDParserData const& d )
-{
-	auto const& tok( (*d.input)[ 1 ] );
-	auto const& mi( d.currentData->value< SP_MIFD >( ) );
-	if ( mi->hasRevision ) {
-		d.errors.add( "duplicate revision number" , tok );
-	}
-
-	const auto v( tok.longValue( ) );
-	if ( v < 0 || v > UINT32_MAX ) {
-		d.errors.add( "invalid revision number" , tok );
-	} else {
-		mi->modInfo.revision = tok.longValue( );
-	}
-	mi->hasRevision = true;
-	return true;
-}
-
-bool DMDFSetLibVersion_( T_SRDParserData const& d )
-{
-	auto const& tok( (*d.input)[ 1 ] );
-	auto const& mi( d.currentData->value< SP_MIFD >( ) );
-	if ( mi->hasLibVersion ) {
-		d.errors.add( "duplicate library version number" , tok );
-	}
-
-	const auto v( tok.longValue( ) );
-	if ( v < 0 || v > UINT32_MAX ) {
-		d.errors.add( "invalid library version number" , tok );
-	} else {
-		mi->modInfo.libVersion = tok.longValue( );
-	}
-	mi->hasLibVersion = true;
-	return true;
-}
-
-bool DMDFAddDependency_( T_SRDParserData const& d )
-{
-	auto const& input( *d.input );
-	auto const& mi( d.currentData->value< SP_MIFD >( ) );
-
-	bool add( true );
-	auto const& name( input[ 1 ].stringValue( ) );
-	auto& deps( mi->modInfo.modDeps );
-	const auto nDeps( deps.size( ) );
-	for ( uint32_t i = 0 ; i < nDeps ; i ++ ) {
-		if ( deps[ i ].name == name ) {
-			d.errors.add( "duplicate dependency" , input[ 1 ] );
-			add = false;
-			break;
-		}
-	}
-
-	const auto v( input[ 2 ].longValue( ) );
-	if ( v < 0 || v > UINT32_MAX ) {
-		d.errors.add( "invalid version number" , input[ 2 ] );
-		add = false;
-	}
-
-	if ( add ) {
-		deps.add( T_ModIdentifier{ name , uint32_t( v ) } );
-	}
-	return true;
-}
-
-bool DMDFCheck_( T_SRDParserData const& d )
-{
-	auto const& mi( d.currentData->value< SP_MIFD >( ) );
-	if ( !mi->hasLibVersion ) {
-		d.errors.add( "no required library version" , T_SRDLocation( ) );
-	}
-	if ( !mi->modInfo.identifier.name ) {
-		d.errors.add( "no name" , T_SRDLocation( ) );
-	}
-	if ( !mi->hasVersion ) {
-		d.errors.add( "no version number" , T_SRDLocation( ) );
-	}
-	if ( !mi->hasRevision ) {
-		d.errors.add( "no revision number" , T_SRDLocation( ) );
-	}
-	*( d.currentData ) = NewShared< T_ModInfo >( std::move( mi->modInfo ) );
-	return true;
-}
-
-T_SRDParserConfig DMDFConfig_( )
-{
-	using namespace lw::SRD;
-
-	T_SRDParserDefs defs( "default" );
-	defs << OnStart( DMDFInitialise_ ) << OnFinish( DMDFCheck_ );
-	defs.context( "default" )
-		<< ( Rule( ) << "name" << Word( ) << DMDFSetName_ )
-		<< ( Rule( ) << "version" << Integer( ) << DMDFSetVersion_ )
-		<< ( Rule( ) << "revision" << Integer( ) << DMDFSetRevision_ )
-		<< ( Rule( ) << "library-version" << Integer( ) << DMDFSetLibVersion_ )
-		<< ( Rule( ) << "depends-on" << Word( ) << Integer( ) << DMDFAddDependency_ )
-	;
-	return T_SRDParserConfig( defs );
-}
-} // namespace
-
-
-/*= NATIVE MOD LOADING =======================================================*/
-
-namespace {
-class T_LoadedNativeMod_ : public A_NativeMod
-{
-    private:
-	T_Logger logger_;
-	T_String path_;
-	T_DynLib lib_;
-	OP_NativeMod mod_;
-	bool initialised_;
-
-    public:
-	explicit T_LoadedNativeMod_(
-			T_Logger& logger ,
-			T_String const& path ) noexcept;
-	~T_LoadedNativeMod_( ) noexcept override;
-
-	bool preinit( ) noexcept override;
-	bool init( F_UpdateInitProgress const& uip ) noexcept override;
-	void shutdown( ) noexcept override;
-	void postshutdown( ) noexcept override;
-	OP_UserInterface getUserInterface( ) const noexcept override;
-};
-} // namespace
-
-/*----------------------------------------------------------------------------*/
-
-T_LoadedNativeMod_::T_LoadedNativeMod_(
-		T_Logger& logger ,
-		T_String const& path ) noexcept
-	: logger_( logger ) , path_( path ) ,
-		lib_{ path } , mod_{}
-{}
-
-T_LoadedNativeMod_::~T_LoadedNativeMod_( ) noexcept
-{
-	shutdown( );
-	postshutdown( );
-}
-
-/*----------------------------------------------------------------------------*/
-
-bool T_LoadedNativeMod_::preinit( ) noexcept
-{
-	assert( !mod_ );
-	if ( !lib_.load( ) ) {
-		logger_.error( ) << "Native mod " << path_
-			<< " could not be loaded";
-		return false;
-	}
-
-	auto loader{ lib_.getFunction< void*( ) >( "LWMod_GetMod" ) };
-	if ( !loader ) {
-		lib_.unload( );
-		logger_.error( ) << "Cannot find mod entry point in " << path_;
-		return false;
-	}
-
-	auto mod{ reinterpret_cast< RP_NativeMod >( loader( ) ) };
-	if ( !mod ) {
-		lib_.unload( );
-		logger_.error( ) << "Mod entry point returned NULL in " << path_;
-		return false;
-	}
-
-	if ( !mod->preinit( ) ) {
-		delete mod;
-		lib_.unload( );
-		return false;
-	}
-
-	mod_ = OwnRawPointer( mod );
-	initialised_ = false;
-	return true;
-}
-
-/*----------------------------------------------------------------------------*/
-
-bool T_LoadedNativeMod_::init(
-		F_UpdateInitProgress const& uip ) noexcept
-{
-	assert( mod_ && !initialised_ );
-	initialised_ = mod_->init( uip );
-	return initialised_;
-}
-
-void T_LoadedNativeMod_::shutdown( ) noexcept
-{
-	if ( mod_ && initialised_ ) {
-		mod_->shutdown( );
-		initialised_ = false;
-	}
-}
-
-void T_LoadedNativeMod_::postshutdown( ) noexcept
-{
-	if ( mod_ && !initialised_ ) {
-		mod_->postshutdown( );
-		mod_.clear( );
-		lib_.unload( );
-	}
-}
-
-OP_UserInterface T_LoadedNativeMod_::getUserInterface( ) const noexcept
-{
-	assert( mod_ && !initialised_ );
-	return mod_->getUserInterface( );
-}
-
-
-/*= DATA MOD LOADING =========================================================*/
-
-namespace {
-class T_DataMod_ : public A_NativeMod
-{
-    private:
-	T_Logger logger_;
-	T_String path_;
-	T_RegisteredItem drv_;
-
-    public:
-	explicit T_DataMod_(
-			T_Logger& logger ,
-			T_String const& path ) noexcept;
-	~T_DataMod_( ) noexcept override;
-
-	bool preinit( ) noexcept override;
-	bool init( F_UpdateInitProgress const& ) noexcept override;
-	void shutdown( ) noexcept override;
-	void postshutdown( ) noexcept override;
-};
-} // namespace
-
-/*----------------------------------------------------------------------------*/
-
-T_DataMod_::T_DataMod_(
-		T_Logger& logger ,
-		T_String const& path ) noexcept
-	: logger_( logger ) , path_( path ) , drv_{}
-{ }
-
-T_DataMod_::~T_DataMod_( ) noexcept
-{
-	shutdown( );
-	postshutdown( );
-}
-
-bool T_DataMod_::preinit( ) noexcept
-{
-	assert( !drv_ );
-	drv_ = LW::vfs( ).addDriver( NewOwned< T_VFSDataFileDriver >(
-			NewOwned< T_File >( path_ , E_FileMode::READ_ONLY ) ) );
-	if ( !drv_ ) {
-		logger_.error( ) << "Failed to initialise VFS data file driver from "
-				<< T_String( path_ );
-		return false;
-	}
-	return true;
-}
-
-bool T_DataMod_::init(
-		F_UpdateInitProgress const& ) noexcept
-{
-	assert( drv_ );
-	return true;
-}
-
-void T_DataMod_::shutdown( ) noexcept
-{ }
-
-void T_DataMod_::postshutdown( ) noexcept
-{
-	if ( drv_ ) {
-		drv_ = T_RegisteredItem( );
-	}
-}
-
-
-/*= MODS MANAGER DATA ========================================================*/
-
-namespace {
-
-struct T_MMData_
-{
-	using T_ModIDs = T_Array< T_ModIdentifier >;
-
-	const T_SRDParserConfig dmdfConfig_{ DMDFConfig_( ) };
-
-	T_ModsManagerConfiguration config_;
-	T_Logger logger{ "/core/mods" };
-
-	T_Array< OP_ModInfo > modsList{ 128 };
-	T_ModsDependencies deps;
-
-	T_Array< OP_NativeMod > mods;
-	T_Array< bool > states;
-	T_Array< RPC_ModInfo > loadedMods;
-
-	// ---------------------------------------------------------------------
-
-	T_MMData_( T_ModsManagerConfiguration&& config ) noexcept;
-
-	// ---------------------------------------------------------------------
-
-	/* Find all available mods. */
-	bool scanForMods( );
-
-	/* Try to extract mod information from a file */
-	OP_ModInfo getModInfo(
-			T_VFSPath const& path ) noexcept;
-	/* Try to extract mod information from a data file mod */
-	OP_ModInfo getModInfoData(
-			T_VFSPath const& path ,
-			OP_File& modFile ) noexcept;
-	/* Try to extract mod information from a native mod */
-	OP_ModInfo getModInfoNative(
-			T_VFSPath const& path ,
-			T_String const& fsPath ) noexcept;
-
-	// ---------------------------------------------------------------------
-
-	/* Set up the arrays for the mods' instances */
-	void setupMods( ) noexcept;
-
-	/* Load and pre-initialise a mod */
-	bool loadMod( RPC_ModInfo mi ) noexcept;
-	/* "Rewind" the mod loader until only the specified amount of mods
-	 * are left. This is meant for mods that have only been preinitialised.
-	 */
-	void rewindMods( uint32_t target ) noexcept;
-
-	/* Load and preinitialise the UI mods, and try initialising the UI
-	 * itself.
-	 */
-	OP_UserInterface loadUserInterface(
-			T_ModsList_ const& ml ) noexcept;
-};
-} // namespace
-
-/*----------------------------------------------------------------------------*/
-
-T_MMData_::T_MMData_(
-		T_ModsManagerConfiguration&& config ) noexcept
-	: config_( std::move( config ) )
-{ }
-
-/*----------------------------------------------------------------------------*/
-
-inline bool T_MMData_::scanForMods( )
-{
-	const T_Array< T_VFSPath > paths( ([this]() {
-		T_Array< T_VFSPath > output;
-		LW::vfs( ).list( "/mods" , output );
-		output.sort( []( T_VFSPath const& a , T_VFSPath const& b ) {
-			return T_String( a ).compare( T_String( b ) );
-		} );
-		return output;
-	})( ) );
-
-	T_Array< T_String > remove( 8 );
-	const uint32_t nPaths( paths.size( ) );
-	modsList.clear( );
-	for ( uint32_t i = 0 ; i < nPaths ; i ++ ) {
-		const T_VFSPath path( "/mods" , paths[ i ] );
-		logger.trace( ) << "Checking " << T_String( path );
-
-		if ( LW::vfs( ).typeOf( path ) != E_VFSEntryType::FILE ) {
-			logger.trace( ) << T_String( path ) << " is not a file";
-			continue;
-		}
-
-		OP_ModInfo info( getModInfo( path ) );
-		if ( !info ) {
-			continue;
-		}
-		if ( remove.contains( info->identifier.name ) ) {
-			continue;
-		}
-
-		const auto nMods( modsList.size( ) );
-		bool badMod( false );
-		for ( uint32_t j = 0 ; j < nMods ; j ++ ) {
-			auto const& mod( *modsList[ j ] );
-			badMod = mod.identifier == info->identifier
-				&& mod.revision == info->revision;
-			if ( badMod ) {
-				logger.notice( ) << T_String( path ) << " and "
-					<< T_String( mod.path )
-					<< " contain the same mod ("
-					<< *info << ')';
-				break;
-			}
-
-			badMod = mod.identifier.name == info->identifier.name
-				&& mod.isUserInterface( ) != info->isUserInterface( );
-			if ( badMod ) {
-				remove.add( mod.identifier.name );
-				auto const& uiMod( mod.isUserInterface( ) ? mod : *info );
-				auto const& otherMod( mod.isUserInterface( ) ? *info : mod );
-				logger.notice( ) << "Mod " << uiMod
-					<< " is an UI mod, " << otherMod
-					<< " isn't; " << uiMod.identifier.name
-					<< " will be discarded.";
-				break;
-			}
-		}
-		if ( !badMod ) {
-			logger.info( ) << "Found mod " << *info
-				<< " in " << T_String( path );
-			modsList.add( std::move( info ) );
-		}
-	}
-
-	// Remove "bad" mods
-	auto const nRemove( remove.size( ) );
-	for ( uint32_t i = 0 ; i < nRemove ; i ++ ) {
-		auto const& name( remove[ i ] );
-		for ( uint32_t j = 0 ; j < modsList.size( ) ; j ++ ) {
-			if ( modsList[ i ]->identifier.name == name ) {
-				modsList.removeSwap( j );
-				j --;
-			}
-		}
-	}
-
-	return modsList.size( ) > 0;
-}
-
-/*----------------------------------------------------------------------------*/
-
-OP_ModInfo T_MMData_::getModInfo(
-		T_VFSPath const& path ) noexcept
-{
-	OP_File modFile( LW::vfs( ).file( path ) );
-	if ( !modFile ) {
-		logger.error( ) << "couldn't access " << T_String( path );
-		return OP_ModInfo( );
-	}
-	const T_String fsPath( modFile->path( ) );
-
-	OP_ModInfo result( getModInfoData( path , modFile ) );
-	if ( !result ) {
-		modFile.clear( );
-		result = getModInfoNative( path , fsPath );
-	}
-	if ( result ) {
-		result->path = fsPath;
-	}
-	return result;
-}
-
-OP_ModInfo T_MMData_::getModInfoData(
-		T_VFSPath const& path ,
-		OP_File& modFile ) noexcept
-{
-	const T_String p( path );
-	auto drv( NewOwned< T_VFSDataFileDriver >( std::move( modFile ) ) );
-	if ( !drv->init( ) ) {
-		logger.trace( ) << p << " is not a data file";
-		return OP_ModInfo( );
-	}
-
-	OP_ModInfo modInfo;
-	OP_InputStream stream( drv->read( "/mods/modinfo.srd" ) );
-	if ( stream ) {
-		T_SRDParser parser( dmdfConfig_ );
-		T_SRDTextReader reader( parser );
-		try {
-			reader.read( T_String( "modinfo.srd" ) , *stream );
-			modInfo = NewOwned< T_ModInfo >( std::move(
-						*parser.getData< SP_ModInfo >( ) ) );
-		} catch ( X_StreamError const& e ) {
-			logger.error( ) << "Error while reading modinfo.srd from "
-				<< p << ": " << e.what( );
-		} catch ( X_SRDErrors const& e ) {
-			logger.error( ) << "Couldn't read mod description from " << p;
-			e.log( logger );
-		}
-	} else {
-		logger.error( ) << "No module description in " << p;
-	}
-	drv->shutdown( );
-
-	if ( modInfo ) {
-		if ( modInfo->libVersion != LibVersion( ) ) {
-			logger.info( ) << p << " is incompatible with this version";
-			modInfo.clear( );
-		} else {
-			logger.trace( ) << p << " is a data mod";
-		}
-	}
-	return modInfo;
-}
-
-OP_ModInfo T_MMData_::getModInfoNative(
-		T_VFSPath const& path ,
-		T_String const& fsPath ) noexcept
-{
-	const T_String p( path );
-
-	T_DynLib lib( fsPath );
-	if ( !lib.load( ) ) {
-		logger.trace( ) << p << " is not a library; loader error: "
-			<< lib.lastError( );
-		return OP_ModInfo( );
-	}
-
-	uint32_t const* const pLibVersion( lib.getPointer< uint32_t >(
-				"LWMod_RequiredLibVersion" ) );
-	if ( pLibVersion == nullptr ) {
-		logger.trace( ) << p << " is not a LW mod";
-		return OP_ModInfo( );
-	}
-	if ( *pLibVersion != LibVersion( ) ) {
-		logger.info( ) << p << " is incompatible with this version";
-		return OP_ModInfo( );
-	}
-
-	char const* const pModName( lib.getPointer< char >( "LWMod_Name" ) );
-	auto const* const pModVersion( lib.getPointer< uint32_t >( "LWMod_Version" ) );
-	auto const* const pModRevision( lib.getPointer< uint32_t >( "LWMod_Revision" ) );
-	bool const* const pIsUI( lib.getPointer< bool >( "LWMod_IsUserInterface" ) );
-	if ( pModName == nullptr || pModVersion == nullptr
-			|| pModRevision == nullptr || pIsUI == nullptr ) {
-		logger.error( ) << p << " is missing some mod information";
-		return OP_ModInfo( );
-	}
-	if ( lib.getRawSymbol( "LWMod_GetMod" ) == nullptr ) {
-		logger.error( ) << p << " does not have an entry point";
-		return OP_ModInfo( );
-	}
-
-	auto mi( NewOwned< T_ModInfo >( ) );
-	mi->type = *pIsUI ? E_ModType::UI : E_ModType::NATIVE;
-	mi->identifier.name = T_String( pModName );
-	mi->identifier.version = *pModVersion;
-	mi->revision = *pModRevision;
-	mi->libVersion = *pLibVersion;
-
-	auto const* const pDepCount( lib.getPointer< uint32_t >( "LWMod_DepCount" ) );
-	if ( pDepCount && *pDepCount ) {
-		logger.trace( ) << p << " contains " << *pDepCount << " dependency record(s)";
-		char const* const* const pDepNames(
-				lib.getPointer< char const* const >( "LWMod_DepNames" ) );
-		auto const* const pDepVersions(
-				lib.getPointer< uint32_t >( "LWMod_DepVersions" ) );
-		if ( pDepNames == nullptr || pDepVersions == nullptr ) {
-			logger.notice( ) << p << " has missing dependency fields";
-			return OP_ModInfo( );
-		}
-		for ( uint32_t i = 0 ; i < *pDepCount ; i ++ ) {
-			T_String dName( pDepNames[ i ] );
-			for ( uint32_t j = 0 ; j < i ; j ++ ) {
-				if ( mi->modDeps[ j ].name == dName ) {
-					logger.notice( ) << p
-						<< " contains duplicate dependency on "
-						<< dName;
-					return {};
-				}
-			}
-			mi->modDeps.add( T_ModIdentifier{
-					std::move( dName ) ,
-					pDepVersions[ i ] } );
-		}
-	}
-	logger.trace( ) << p << " is a valid "
-		<< ( mi->type == E_ModType::NATIVE ? "native" : "user interface" )
-		<< " mod";
-	return mi;
-}
-
-/*----------------------------------------------------------------------------*/
-
-void T_MMData_::setupMods( ) noexcept
-{
-	assert( mods.size( ) == 0 );
-
-	const uint32_t nCommon( deps.commonMods( ).size( ) );
-	const auto uiSets( deps.userInterfaces( ) );
-	const auto nui( uiSets.size( ) );
-	uint32_t nUIMods = 0;
-	for ( uint32_t i = 0 ; i < nui ; i ++ ) {
-		auto mptr( deps.forUserInterface( uiSets[ i ] ) );
-		assert( mptr != nullptr );
-		nUIMods = std::max( nUIMods , mptr->size( ) );
-	}
-
-	const uint32_t nMods( nCommon + nUIMods );
-	assert( nMods > 0 );
-	mods = T_Array< OP_NativeMod >{ nMods };
-	states = T_Array< bool >{ nMods };
-	loadedMods = T_Array< RPC_ModInfo >{ nMods };
-}
-
-bool T_MMData_::loadMod(
-		const RPC_ModInfo mi ) noexcept
-{
-	logger.trace( ) << "Loading mod " << *mi;
-	OP_NativeMod mod( ([&]() -> OP_NativeMod {
-		if ( mi->type == E_ModType::DATA ) {
-			return NewOwned< T_DataMod_ >(
-					logger , mi->path );
-		}
-		return NewOwned< T_LoadedNativeMod_ >(
-				logger , mi->path );
-	})( ) );
-
-	if ( mod->preinit( ) ) {
-		mods.add( std::move( mod ) );
-		states.add( false );
-		loadedMods.add( mi );
-		logger.info( ) << "Loaded mod " << *mi;
-		return true;
-	} else {
-		return false;
-	}
-}
-
-void T_MMData_::rewindMods(
-		const uint32_t target ) noexcept
-{
-	assert( target <= mods.size( ) );
-	if ( target == mods.size( ) ) {
-		return;
-	}
-
-	if ( logger.hasLevel( E_LogLevel::DEBUG ) ) {
-		T_StringBuilder sb( "Unloading the previous " );
-		const uint32_t nUnload( mods.size( ) - target );
-		if ( nUnload > 1 ) {
-			sb << nUnload << " mods";
-		} else {
-			sb << "mod";
-		}
-		logger.debug( std::move( sb ) );
-	}
-
-	uint32_t left;
-	while ( ( left = mods.size( ) ) != target ) {
-		const uint32_t index( left - 1 );
-		auto& mod( mods[ index ] );
-		assert( !states[ index ] );
-		mod->postshutdown( );
-		mods.remove( index );
-		states.remove( index );
-		loadedMods.remove( index );
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-OP_UserInterface T_MMData_::loadUserInterface(
-		T_ModsList_ const& ml ) noexcept
-{
-	const uint32_t rewindTarget( mods.size( ) );
-	const uint32_t nMods( mods.size( ) );
-
-	T_Optional< uint32_t > uiModIndex{ };
-	for ( uint32_t i = 0 ; i < nMods ; i ++ ) {
-		if ( loadMod( ml[ i ] ) ) {
-			if ( ml[ i ]->isUserInterface( ) ) {
-				assert( !uiModIndex.present( ) );
-				uiModIndex = mods.size( ) - 1;
-			}
-			continue;
-		}
-		rewindMods( rewindTarget );
-		return {};
-	}
-	assert( uiModIndex.present( ) );
-
-	OP_UserInterface uiInst( mods[ uiModIndex ]->getUserInterface( ) );
-	if ( uiInst && uiInst->preinit( ) ) {
-		return std::move( uiInst );
-	}
-	uiInst.clear( );
-	rewindMods( rewindTarget );
-	return {};
-}
-
-
-/*= T_ModsManager ============================================================*/
-
-T_ModsManager::T_ModsManager(
-		T_ModsManagerConfiguration&& config ) noexcept
-	: A_PrivateImplementation( new T_MMData_( std::move( config ) ) )
-{ }
-
-/*----------------------------------------------------------------------------*/
-
-bool T_ModsManager::scanForMods( )
-{
-	return p< T_MMData_ >( ).scanForMods( );
-}
-
-T_Array< RPC_ModInfo > T_ModsManager::availableMods( ) const noexcept
-{
-	auto const& ml( p< T_MMData_ >( ).modsList );
-	const auto nm( ml.size( ) );
-	T_Array< RPC_ModInfo > result{ std::max( 1u , nm ) };
-	for ( uint32_t i = 0 ; i < nm ; i ++ ) {
-		result.add( ml[ i ].get( ) );
-	}
-	return result;
-}
-
-bool T_ModsManager::resolveDependencies( ) noexcept
-{
-	auto& pi( p< T_MMData_ >( ) );
-	pi.deps = T_ModsDependencies{ pi.logger , availableMods( ) , pi.config_ };
-	return pi.deps.resolved( );
-}
-
-/*----------------------------------------------------------------------------*/
-
-bool T_ModsManager::preinitCommon( ) noexcept
-{
-	auto& pi( p< T_MMData_ >( ) );
-	pi.setupMods( );
-
-	T_ModsList_ const& common( pi.deps.commonMods( ) );
-	const uint32_t ncm( common.size( ) );
-	for ( uint32_t i = 0 ; i < ncm ; i ++ ) {
-		if ( !pi.loadMod( common[ i ] ) ) {
-			pi.rewindMods( 0 );
-			return false;
-		}
-	}
-	return true;
-}
-
-OP_UserInterface T_ModsManager::preinitUIMods(
-		T_String const& ui ) noexcept
-{
-	auto& pi( p< T_MMData_ >( ) );
-	auto mods( pi.deps.forUserInterface( ui ) );
-	if ( mods == nullptr ) {
-		pi.logger.error( ) << "No mods for UI '" << ui << '\'';
-		return {};
-	}
-	return pi.loadUserInterface( *mods );
-}
-
-OP_UserInterface T_ModsManager::preinitUIMods( ) noexcept
-{
-	auto& pi( p< T_MMData_ >( ) );
-	auto uis( pi.deps.userInterfaces( ) );
-	const auto nui( uis.size( ) );
-	for ( uint32_t i = 0 ; i < nui ; i ++ ) {
-		pi.logger.debug( )
-			<< "Attempting to load & initialise UI "
-			<< uis[ i ];
-
-		auto mods( pi.deps.forUserInterface( uis[ i ] ) );
-		assert( mods != nullptr );
-
-		OP_UserInterface ui( pi.loadUserInterface( *mods ) );
-		if ( ui ) {
-			return ui;
-		}
-		pi.logger.notice( )
-			<< "Could not initialise UI " << uis[ i ];
-	}
-	pi.logger.error( ) << "All attempts at initialising an UI failed";
-	return {};
-}
-
-/*----------------------------------------------------------------------------*/
-
-uint32_t T_ModsManager::modsCount( ) const noexcept
-{
-	return p< T_MMData_ >( ).loadedMods.size( );
-}
-
-bool T_ModsManager::initialise(
-		F_CreateInitUpdater const& ciuf ) noexcept
-{
-	auto& pi( p< T_MMData_ >( ) );
-
-	const auto nMods( pi.loadedMods.size( ) );
-	pi.logger.trace( ) << "Initialising mods";
-	for ( uint32_t i = 0 ; i < nMods ; i ++ ) {
-		auto& mod( pi.mods[ i ] );
-		auto desc( pi.loadedMods[ i ] );
-		auto& state( pi.states[ i ] );
-		if ( state ) {
-			pi.logger.error( ) << "Mod " << *desc
-				<< " is already initialised";
-			shutdown( );
-			return false;
-		}
-		pi.logger.trace( ) << "Initialising mod " << *desc;
-		if ( !mod->init( ciuf( desc ) ) ) {
-			pi.logger.error( ) << "Mod " << *desc
-				<< " failed to initialise";
-			shutdown( );
-			return false;
-		}
-		state = true;
-	}
-	return true;
-}
-
-/*----------------------------------------------------------------------------*/
-
-void T_ModsManager::shutdown( ) noexcept
-{
-	auto& pi( p< T_MMData_ >( ) );
-
-	pi.logger.trace( ) << "Mods shutdown";
-	const uint32_t nMods( pi.mods.size( ) );
-	for ( uint32_t i = 0 ; i < nMods ; i ++ ) {
-		const uint32_t index( nMods - ( i + 1 ) );
-		auto& mod( pi.mods[ index ] );
-		auto& state( pi.states[ index ] );
-		if ( state ) {
-			pi.logger.trace( ) << "Shutting down mod "
-				<< *( pi.loadedMods[ index ] );
-			mod->shutdown( );
-			state = false;
-		} else {
-			pi.logger.debug( ) << "Mod "
-				<< *( pi.loadedMods[ index ] )
-				<< " is not initialised, skipping shutdown";
-		}
-	}
-}
-
-void T_ModsManager::unload( ) noexcept
-{
-	p< T_MMData_ >( ).rewindMods( 0 );
-}
diff --git a/src/SRDBinary.cc b/src/SRDBinary.cc
index 26d723c..f3fd4f1 100644
--- a/src/SRDBinary.cc
+++ b/src/SRDBinary.cc
@@ -2,8 +2,8 @@
 /* SRD PARSER AND PREPROCESSOR - BINARY FORM **********************************/
 /******************************************************************************/
 
-#include <lw/lib/SRDBinary.hh>
-using namespace lw;
+#include <ebcl/SRDBinary.hh>
+using namespace ebcl;
 
 
 /*= MAGIC NUMBERS, VERSIONS AND TAGS =========================================*/
@@ -36,7 +36,7 @@ enum class E_V1Tag_ : uint8_t {
 } // namespace
 
 
-namespace lw {
+namespace ebcl {
 
 // Writer for version numbers
 template< >
diff --git a/src/SRDData.cc b/src/SRDData.cc
index af665b0..bfbab1e 100644
--- a/src/SRDData.cc
+++ b/src/SRDData.cc
@@ -2,10 +2,9 @@
 /* SRD PARSER AND PREPROCESSOR - DATA REPRESENTATION **************************/
 /******************************************************************************/
 
-#include <lw/lib/SRDData.hh>
-#include <lw/lib/Alloc.hh>
-#include <lw/lib/Log.hh>
-using namespace lw;
+#include <ebcl/SRDData.hh>
+#include <ebcl/Alloc.hh>
+using namespace ebcl;
 
 
 /*= T_SRDLocation ============================================================*/
@@ -58,7 +57,7 @@ T_SRDLocation::T_SRDLocation(
 	swap( *this , other );
 }
 
-namespace lw {
+namespace ebcl {
 	M_DECLARE_SWAP( T_SRDLocation )
 	{
 		using std::swap;
@@ -149,34 +148,10 @@ char const* X_SRDErrors::what( ) const noexcept
 	return "SRD read/parse errors";
 }
 
-#ifndef LW_MINLIB
-void X_SRDErrors::log( T_Logger& logger ) const
-{
-	const auto nErrors( errors.size( ) );
-	for ( size_t i = 0 ; i < nErrors ; i ++ ) {
-		auto sb( logger.error( ) );
-		auto const& e( errors[ i ] );
-		auto const& l( e.location( ) );
-
-		if ( l.unknown( ) ) {
-			sb << "unknown location";
-		} else {
-			sb << l.source( );
-			if ( l.binary( ) ) {
-				sb << ", b" << l.byte( );
-			} else {
-				sb << ", l" << l.line( ) << ", c" << l.character( );
-			}
-		}
-		sb << ": " << e.error( );
-	}
-}
-#endif // LW_MINLIB
-
 
 /*= T_SRDToken =============================================================*/
 
-T_StringBuilder& lw::operator<< ( T_StringBuilder& sb , E_SRDTokenType tt )
+T_StringBuilder& ebcl::operator<< ( T_StringBuilder& sb , E_SRDTokenType tt )
 {
 	static char const* const C_TOKEN_TYPES_[] = {
 		"(...)" ,
@@ -425,7 +400,7 @@ T_SRDToken& T_SRDToken::operator= ( T_SRDToken const& other )
 
 /*----------------------------------------------------------------------------*/
 
-void lw::swap( T_SRDToken& lhs , T_SRDToken& rhs ) noexcept
+void ebcl::swap( T_SRDToken& lhs , T_SRDToken& rhs ) noexcept
 {
 	using std::swap;
 	swap( lhs.type_ , rhs.type_ );
diff --git a/src/SRDDefinitions.cc b/src/SRDDefinitions.cc
index 06c60cd..0fdf15d 100644
--- a/src/SRDDefinitions.cc
+++ b/src/SRDDefinitions.cc
@@ -3,8 +3,8 @@
 /******************************************************************************/
 
 
-#include <lw/lib/SRDDefinitions.hh>
-using namespace lw;
+#include <ebcl/SRDDefinitions.hh>
+using namespace ebcl;
 
 
 /*= T_SRDEnum ================================================================*/
@@ -52,7 +52,7 @@ uint32_t T_SRDEnum::operator[] ( char const* word ) const
 
 /*= T_SRDInputItem ===========================================================*/
 
-void lw::swap( T_SRDInputItem& lhs , T_SRDInputItem& rhs ) noexcept
+void ebcl::swap( T_SRDInputItem& lhs , T_SRDInputItem& rhs ) noexcept
 {
 	using std::swap;
 	swap( lhs.type_ , rhs.type_ );
@@ -80,7 +80,7 @@ T_SRDInputItem& T_SRDInputItem::operator<< ( T_SRDInputItem item )
 
 /*----------------------------------------------------------------------------*/
 
-T_StringBuilder& lw::operator<< ( T_StringBuilder& sb , T_SRDInputItem const& item )
+T_StringBuilder& ebcl::operator<< ( T_StringBuilder& sb , T_SRDInputItem const& item )
 {
 	switch ( item.type( ) ) {
 
@@ -166,7 +166,7 @@ T_SRDInputRule& T_SRDInputRule::operator<< ( T_SRDInputItem item )
 	return *this;
 }
 
-T_StringBuilder& lw::operator<< ( T_StringBuilder& sb , T_SRDInputRule const& item )
+T_StringBuilder& ebcl::operator<< ( T_StringBuilder& sb , T_SRDInputRule const& item )
 {
 	auto const& seq( item.rule( ) );
 	sb << '(';
diff --git a/src/SRDIO.cc b/src/SRDIO.cc
index 61460a4..e78c604 100644
--- a/src/SRDIO.cc
+++ b/src/SRDIO.cc
@@ -3,8 +3,8 @@
 /******************************************************************************/
 
 
-#include <lw/lib/SRDIO.hh>
-using namespace lw;
+#include <ebcl/SRDIO.hh>
+using namespace ebcl;
 
 
 /*= X_SRDWriterError =========================================================*/
@@ -36,7 +36,7 @@ A_SRDWriter& A_SRDWriter::putToken( T_SRDToken const& token )
 	    case E_SRDTokenType::LIST:
 		startList( );
 		putList( token.list( ) );
-
+		// fall through
 	    case E_SRDTokenType::END:
 		return endList( );
 
diff --git a/src/SRDPPCommands.cc b/src/SRDPPCommands.cc
deleted file mode 100644
index 827afd5..0000000
--- a/src/SRDPPCommands.cc
+++ /dev/null
@@ -1,2518 +0,0 @@
-/******************************************************************************/
-/* SRD - PREPROCESSOR COMMANDS ************************************************/
-/******************************************************************************/
-
-#include <lw/lib/MemoryStreams.hh>
-#include <lw/lib/SRDBinary.hh>
-#include <lw/lib/SRDPPCommands.hh>
-#include <lw/lib/SRDText.hh>
-#include <lw/lib/VFS.hh>
-#include <cmath>
-using namespace lw;
-
-
-/*= BUILTIN COMMANDS INITIALIZER =============================================*/
-
-#define M_ADDCMD_( NAME , ARGS... ) \
-	add< T_SRDPPCMD_ ## NAME >( ARGS )
-
-void T_SRDPreprocessorConfig::addBuiltinCommands( ) noexcept
-{
-	M_ADDCMD_( Add );
-	M_ADDCMD_( And );
-	M_ADDCMD_( Bless );
-	M_ADDCMD_( Break );
-	M_ADDCMD_( BwAnd );
-	M_ADDCMD_( BwNot );
-	M_ADDCMD_( BwOr );
-	M_ADDCMD_( BwXor );
-	M_ADDCMD_( Call );
-	M_ADDCMD_( CastString );
-	M_ADDCMD_( CastWord );
-	M_ADDCMD_( CastInt );
-	M_ADDCMD_( CastLong );
-	M_ADDCMD_( CastBestInt );
-	M_ADDCMD_( CastReal );
-	M_ADDCMD_( CastVar );
-	M_ADDCMD_( CastList );
-	M_ADDCMD_( ClearScope );
-	M_ADDCMD_( Cmp );
-	M_ADDCMD_( CmpEq );
-	M_ADDCMD_( CmpNe );
-	M_ADDCMD_( CmpLt );
-	M_ADDCMD_( CmpGt );
-	M_ADDCMD_( CmpLe );
-	M_ADDCMD_( CmpGe );
-	M_ADDCMD_( Concat );
-	M_ADDCMD_( Div );
-	M_ADDCMD_( EndsWith );
-	M_ADDCMD_( Eval );
-	M_ADDCMD_( Error );
-	M_ADDCMD_( FromSource );
-	M_ADDCMD_( FromSRB );
-	M_ADDCMD_( Get );
-	M_ADDCMD_( If );
-	M_ADDCMD_( Ignore );
-	M_ADDCMD_( IsBlessed );
-	M_ADDCMD_( IsMacro );
-	M_ADDCMD_( IsSet );
-	M_ADDCMD_( Length );
-	M_ADDCMD_( ListMacros );
-	M_ADDCMD_( ListVariables );
-	M_ADDCMD_( Mod );
-	M_ADDCMD_( Mul );
-	M_ADDCMD_( Neg );
-	M_ADDCMD_( Not );
-	M_ADDCMD_( Or );
-	M_ADDCMD_( Output );
-	M_ADDCMD_( Raw );
-	M_ADDCMD_( Rethrow );
-	M_ADDCMD_( Scope );
-	M_ADDCMD_( Set );
-	M_ADDCMD_( SetMacro );
-	M_ADDCMD_( StartsWith );
-	M_ADDCMD_( StrFind );
-	M_ADDCMD_( StrSplit );
-	M_ADDCMD_( Sub );
-	M_ADDCMD_( Substr );
-	M_ADDCMD_( ToSource );
-	M_ADDCMD_( Try );
-	M_ADDCMD_( TypeOf );
-	M_ADDCMD_( Unset );
-	M_ADDCMD_( UnsetMacro );
-	M_ADDCMD_( Unwrap );
-	M_ADDCMD_( Xor );
-}
-
-void T_SRDPreprocessorConfig::addVFSCommands(
-		T_VFS& vfs ) noexcept
-{
-	M_ADDCMD_( VFSList , vfs );
-	M_ADDCMD_( VFSLoad , vfs );
-	M_ADDCMD_( VFSType , vfs );
-}
-
-
-/*= HELPER FOR MATH COMMANDS =================================================*/
-
-typedef std::function< int64_t( int64_t , int64_t ) > F_LongOp_;
-typedef std::function< double ( double , double ) > F_RealOp_;
-
-namespace {
-
-void DoMathOp_( T_SRDPreprocessorState& state , F_LongOp_ longOp , F_RealOp_ realOp , bool nonZero = false )
-{
-	auto& input( state.output( ) );
-	auto& output( state.data( ).top( ).output( ) );
-	auto const& location( *state.initialLocation( ) );
-
-	const uint32_t nInputs( input.size( ) );
-	if ( nInputs < 2 ) {
-		state.data( ).addError( location , "not enough arguments" );
-		if ( nInputs == 0 ) {
-			T_SRDToken r( T_SRDToken::Integer( 0 ) );
-			r.location( location );
-			output.add( std::move( r ) );
-			return;
-		}
-	}
-
-	const E_SRDTokenType type( input[ 0 ].type( ) );
-	if ( type != E_SRDTokenType::INT && type != E_SRDTokenType::LONG && type != E_SRDTokenType::FLOAT ) {
-		state.data( ).addError( input[ 0 ] , "numeric argument expected" );
-	}
-
-	bool hadReal( type == E_SRDTokenType::FLOAT );
-	int64_t rl( input[ 0 ].longValue( ) );
-	double rr( input[ 0 ].floatValue( ) );
-	for ( uint32_t i = 1 ; i < nInputs ; i ++ ) {
-		auto& tok( input[ i ] );
-		const auto tt( tok.type( ) );
-		if ( tt != E_SRDTokenType::INT && tt != E_SRDTokenType::LONG &&
-		    tt != E_SRDTokenType::FLOAT ) {
-			state.data( ).addError( tok , "numeric argument expected" );
-			continue;
-		}
-		if ( tok.floatValue( ) == 0 && nonZero ) {
-			state.data( ).addError( tok , "non-zero argument expected" );
-			continue;
-		}
-		hadReal = hadReal || tt == E_SRDTokenType::FLOAT;
-		if ( !hadReal ) {
-			rl = longOp( rl , tok.longValue( ) );
-		}
-		rr = realOp( rr , tok.floatValue( ) );
-	}
-
-	T_SRDToken result( hadReal ? T_SRDToken::Float( rr ) : T_SRDToken::AutoInteger( rl ) );
-	result.location( location );
-	output.add( std::move( result ) );
-}
-
-void DoLogicOp_( T_SRDPreprocessorState& state , F_LongOp_ op )
-{
-	auto& input( state.output( ) );
-	auto& output( state.data( ).top( ).output( ) );
-	auto const& location( *state.initialLocation( ) );
-
-	const uint32_t nInputs( input.size( ) );
-	if ( nInputs < 2 ) {
-		state.data( ).addError( location , "not enough arguments" );
-		if ( nInputs == 0 ) {
-			T_SRDToken r( T_SRDToken::Integer( 0 ) );
-			r.location( location );
-			output.add( std::move( r ) );
-			return;
-		}
-	}
-	if ( !input[ 0 ].isInteger( ) ) {
-		state.data( ).addError( input[ 0 ] , "integer argument expected" );
-	}
-
-	int64_t rl( input[ 0 ].longValue( ) );
-	for ( uint32_t i = 1 ; i < nInputs ; i ++ ) {
-		auto& tok( input[ i ] );
-		if ( !tok.isInteger( ) ) {
-			state.data( ).addError( tok , "integer argument expected" );
-			continue;
-		}
-		rl = op( rl , tok.longValue( ) );
-	}
-
-	T_SRDToken result( T_SRDToken::AutoInteger( rl ) );
-	result.location( location );
-	output.add( std::move( result ) );
-}
-
-}
-
-
-/*= HELPER FOR COMPARISONS ===================================================*/
-
-namespace {
-
-bool CompareInput_( T_SRDPreprocessorState & state , int & result )
-{
-	auto& data( state.data( ) );
-	auto& input( state.output( ) );
-	auto& loc( *state.initialLocation( ) );
-
-	if ( input.size( ) < 2 ) {
-		data.addError( loc , "not enough arguments" );
-		return false;
-	}
-	if ( input.size( ) > 2 ) {
-		data.addError( loc , "too many arguments" );
-		return false;
-	}
-
-	result = input[ 0 ].compare( input[ 1 ] );
-	return true;
-}
-
-}
-
-
-/*= COMMANDS =================================================================*/
-
-M_SRDPP_COMMAND_EXEC( Add )
-{
-	DoMathOp_( state ,
-		  []( auto a , auto b ) {
-		return a + b;
-	} ,
-		  []( auto a , auto b ) {
-		return a + b;
-	} );
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( And )
-{
-	DoLogicOp_( state ,
-		  []( auto a , auto b ) {
-		return ( a && b ) ? 1 : 0;
-	} );
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( Bless )
-{
-	auto& input( state.output( ) );
-	auto& data( state.data( ) );
-	auto const& loc( *state.initialLocation( ) );
-
-	const auto n( input.size( ) );
-	if ( n == 0 ) {
-		data.addError( loc , "not enough arguments" );
-		return;
-	}
-
-	for ( uint32_t i = 0 ; i < n ; i ++ ) {
-		auto const& ntok( input[ i ] );
-		if ( ntok.type( ) != E_SRDTokenType::WORD ) {
-			data.addError( ntok , "word expected" );
-			continue;
-		}
-
-		auto const& vn( ntok.stringValue( ) );
-		auto& s( data.scopes( ) );
-		if ( s.isBlessed( vn ) ) {
-			continue;
-		}
-
-		RPC_SRDList var( s.get( false , vn ) );
-		if ( var == nullptr ) {
-			data.addError( ntok , "unknown variable" );
-			continue;
-		}
-
-		if ( T_SRDPreprocessor::isValidFunction( *var ) ) {
-			s.bless( vn );
-		} else {
-			data.addError( ntok , "variable does not contain a valid function" );
-		}
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( Break )
-{
-	if ( state.output( ).size( ) ) {
-		state.data().addError( *state.initialLocation( ) , "too many arguments" );
-	}
-	state.data( ).interrupt( T_SRDPreprocessorState::C_CALL );
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( BwAnd )
-{
-	DoLogicOp_( state ,
-		  []( auto a , auto b ) {
-		return a & b;
-	} );
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( BwNot )
-{
-	auto& input( state.output( ) );
-	auto& data( state.data( ) );
-	auto const& loc( *state.initialLocation( ) );
-
-	bool useLong( false );
-	int64_t iv( 0 );
-	if ( input.size( ) == 0 ) {
-		data.addError( loc , "not enough arguments" );
-	} else if ( input.size( ) != 1 ) {
-		data.addError( loc , "too many arguments" );
-	} else if ( !input[ 0 ].isInteger( ) ) {
-		data.addError( input[ 0 ] , "integer argument expected" );
-	} else {
-		iv = ~input[ 0 ].longValue( );
-		useLong = ( input[ 0 ].type( ) == E_SRDTokenType::LONG );
-		if ( !useLong ) {
-			iv = iv & 0xffffffff;
-		}
-	}
-
-	T_SRDToken output( useLong ? T_SRDToken::Long( iv ) : T_SRDToken::Integer( iv ) );
-	output.location( loc );
-	state.data( ).top( ).output( ).add( std::move( output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( BwOr )
-{
-	DoLogicOp_( state ,
-		  []( auto a , auto b ) {
-		return a | b;
-	} );
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( BwXor )
-{
-	DoLogicOp_( state ,
-		  []( auto a , auto b ) {
-		return a ^ b;
-	} );
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( Call )
-{
-	auto& data( state.data( ) );
-	auto& input( state.output( ) );
-	auto const& loc( *state.initialLocation( ) );
-
-	if ( input.size( ) < 1 ) {
-		data.addError( loc , "not enough arguments" );
-		return;
-	}
-
-	auto& func( input[ 0 ] );
-	if ( !T_SRDPreprocessor::isValidFunction( func ) ) {
-		data.addError( func , "invalid function" );
-		return;
-	}
-
-	auto const& argsTok( func.list( )[ 0 ] );
-	auto const& args( argsTok.list( ) );
-	const bool hasOptArgs( args.size( ) > 0
-			      && args[ args.size( ) - 1 ].type( ) == E_SRDTokenType::LIST );
-	const uint32_t reqArgs( args.size( ) - ( hasOptArgs ? 1 : 0 ) );
-	const auto nValues( input.size( ) - 1 );
-	if ( nValues < reqArgs ) {
-		data.addError( loc , "not enough function arguments" );
-		return;
-	}
-	if ( nValues > reqArgs && !hasOptArgs ) {
-		data.addError( loc , "too many function arguments" );
-		return;
-	}
-
-	data.scopes( ).setupCallScope( args , input , 1 );
-	data.push( T_SRDPreprocessorState::C_CALL ,
-			NewShared< T_SRDList >( func.list( ).moveRange( 1 ) ) ,
-			data.top( ).outputPointer( ) ,
-			[]( T_SRDPreprocessorState& ns ) {
-				ns.data( ).scopes( ).exit( );
-			} );
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( CastString )
-{
-	auto& input( state.output( ) );
-	auto& data( state.data( ) );
-	auto& output( data.top( ).output( ) );
-
-	const auto size( input.size( ) );
-	for ( uint32_t i = 0 ; i < size ; i ++ ) {
-		auto& token( input[ i ] );
-
-		T_String outString;
-		switch ( token.type( ) ) {
-
-			case E_SRDTokenType::STRING:
-				output.add( std::move( token ) );
-				continue;
-
-			case E_SRDTokenType::WORD:
-				outString = token.stringValue( );
-				break;
-
-			case E_SRDTokenType::INT:
-			case E_SRDTokenType::LONG:
-			{
-				T_StringBuilder sb;
-				sb << token.longValue( );
-				outString = std::move( sb );
-				break;
-			}
-
-			case E_SRDTokenType::FLOAT:
-			{
-				T_StringBuilder sb;
-				sb << token.floatValue( );
-				outString = std::move( sb );
-				break;
-			}
-
-			case E_SRDTokenType::VAR:
-			{
-				T_StringBuilder sb;
-				sb << '$' << token.stringValue( );
-				outString = std::move( sb );
-				break;
-			}
-
-			case E_SRDTokenType::BINARY:
-			{
-				auto const& buffer( token.binary( ) );
-				outString = T_String( (char const*) buffer.data( ) ,
-						buffer.bytes( ) );
-				if ( !outString.valid( ) ) {
-					outString = T_String( );
-					data.addError( token , "invalid UTF-8 data" );
-				}
-				break;
-			}
-
-			default:
-				data.addError( token , "unsupported type conversion" );
-				continue;
-				
-		}
-
-		T_SRDToken otok( T_SRDToken::String( std::move( outString ) ) );
-		otok.copyLocationOf( token );
-		output.add( std::move( otok ) );
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( CastWord )
-{
-	auto& input( state.output( ) );
-	auto& data( state.data( ) );
-	auto& output( data.top( ).output( ) );
-
-	const auto size( input.size( ) );
-	for ( uint32_t i = 0 ; i < size ; i ++ ) {
-		auto& token( input[ i ] );
-
-		T_String outString;
-		switch ( token.type( ) ) {
-
-			case E_SRDTokenType::STRING:
-				outString = token.stringValue( );
-				if ( !T_SRDToken::IsWord( outString ) ) {
-					data.addError( token , "invalid word" );
-					continue;
-				}
-				break;
-
-			case E_SRDTokenType::WORD:
-				output.add( std::move( token ) );
-				continue;
-
-			case E_SRDTokenType::VAR:
-				outString = token.stringValue( );
-				break;
-
-			default:
-				data.addError( token , "unsupported type conversion" );
-				continue;
-				
-		}
-
-		T_SRDToken otok( T_SRDToken::Word( std::move( outString ) ) );
-		otok.copyLocationOf( token );
-		output.add( std::move( otok ) );
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( CastInt )
-{
-	auto& input( state.output( ) );
-	auto& data( state.data( ) );
-	auto& output( data.top( ).output( ) );
-
-	const auto size( input.size( ) );
-	for ( uint32_t i = 0 ; i < size ; i ++ ) {
-		auto& token( input[ i ] );
-
-		int64_t value;
-		switch ( token.type( ) ) {
-
-			case E_SRDTokenType::INT:
-				output.add( std::move( token ) );
-				continue;
-
-			case E_SRDTokenType::STRING:
-			{
-				bool ok;
-				value = token.stringValue( ).toInteger( &ok );
-				if ( !ok ) {
-					data.addError( token , "invalid integer value" );
-					continue;
-				}
-				break;
-			}
-
-			case E_SRDTokenType::LONG:
-				value = token.longValue( );
-				break;
-
-			case E_SRDTokenType::FLOAT:
-				value = token.floatValue( );
-				break;
-
-			default:
-				data.addError( token , "unsupported type conversion" );
-				continue;
-				
-		}
-		if ( value < INT32_MIN || value > INT32_MAX ) {
-			data.addError( token , "value out of range" );
-			continue;
-		}
-
-		T_SRDToken otok( T_SRDToken::Integer( value ) );
-		otok.copyLocationOf( token );
-		output.add( std::move( otok ) );
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( CastLong )
-{
-	auto& input( state.output( ) );
-	auto& data( state.data( ) );
-	auto& output( data.top( ).output( ) );
-
-	const auto size( input.size( ) );
-	for ( uint32_t i = 0 ; i < size ; i ++ ) {
-		auto& token( input[ i ] );
-
-		int64_t value;
-		switch ( token.type( ) ) {
-
-			case E_SRDTokenType::LONG:
-				output.add( std::move( token ) );
-				continue;
-
-			case E_SRDTokenType::STRING:
-			{
-				bool ok;
-				value = token.stringValue( ).toInteger( &ok );
-				if ( !ok ) {
-					data.addError( token , "invalid integer value" );
-					continue;
-				}
-				break;
-			}
-
-			case E_SRDTokenType::INT:
-				value = token.longValue( );
-				break;
-
-			case E_SRDTokenType::FLOAT:
-				value = token.floatValue( );
-				break;
-
-			default:
-				data.addError( token , "unsupported type conversion" );
-				continue;
-				
-		}
-
-		T_SRDToken otok( T_SRDToken::Long( value ) );
-		otok.copyLocationOf( token );
-		output.add( std::move( otok ) );
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( CastBestInt )
-{
-	auto& input( state.output( ) );
-	auto& data( state.data( ) );
-	auto& output( data.top( ).output( ) );
-
-	const auto size( input.size( ) );
-	for ( uint32_t i = 0 ; i < size ; i ++ ) {
-		auto& token( input[ i ] );
-
-		int64_t value;
-		switch ( token.type( ) ) {
-
-			case E_SRDTokenType::INT:
-				output.add( std::move( token ) );
-				continue;
-
-			case E_SRDTokenType::STRING:
-			{
-				bool ok;
-				value = token.stringValue( ).toInteger( &ok );
-				if ( !ok ) {
-					data.addError( token , "invalid integer value" );
-					continue;
-				}
-				break;
-			}
-
-			case E_SRDTokenType::LONG:
-				value = token.longValue( );
-				break;
-
-			case E_SRDTokenType::FLOAT:
-				value = token.floatValue( );
-				break;
-
-			default:
-				data.addError( token , "unsupported type conversion" );
-				continue;
-				
-		}
-
-		T_SRDToken otok( T_SRDToken::AutoInteger( value ) );
-		otok.copyLocationOf( token );
-		output.add( std::move( otok ) );
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( CastReal )
-{
-	auto& input( state.output( ) );
-	auto& data( state.data( ) );
-	auto& output( data.top( ).output( ) );
-
-	const auto size( input.size( ) );
-	for ( uint32_t i = 0 ; i < size ; i ++ ) {
-		auto& token( input[ i ] );
-
-		double value;
-		switch ( token.type( ) ) {
-
-			case E_SRDTokenType::FLOAT:
-				output.add( std::move( token ) );
-				continue;
-
-			case E_SRDTokenType::STRING:
-			{
-				bool ok;
-				value = token.stringValue( ).toDouble( &ok );
-				if ( !ok ) {
-					data.addError( token , "invalid real value" );
-					continue;
-				}
-				break;
-			}
-
-			case E_SRDTokenType::INT:
-			case E_SRDTokenType::LONG:
-				value = token.longValue( );
-				break;
-
-			default:
-				data.addError( token , "unsupported type conversion" );
-				continue;
-				
-		}
-
-		T_SRDToken otok( T_SRDToken::Float( value ) );
-		otok.copyLocationOf( token );
-		output.add( std::move( otok ) );
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( CastVar )
-{
-	auto& input( state.output( ) );
-	auto& data( state.data( ) );
-	auto& output( data.top( ).output( ) );
-
-	const auto size( input.size( ) );
-	for ( uint32_t i = 0 ; i < size ; i ++ ) {
-		auto& token( input[ i ] );
-
-		T_String outString;
-		switch ( token.type( ) ) {
-
-			case E_SRDTokenType::STRING:
-				outString = token.stringValue( );
-				if ( outString[ 0 ] == '$' ) {
-					outString = outString.substr( 1 );
-				}
-				if ( !T_SRDToken::IsWord( outString ) || outString[ 0 ] == '-' ) {
-					data.addError( token , "invalid variable name" );
-					continue;
-				}
-				break;
-
-			case E_SRDTokenType::WORD:
-				outString = token.stringValue( );
-				if ( outString[ 0 ] == '-' ) {
-					data.addError( token , "invalid variable name" );
-					continue;
-				}
-				break;
-
-			case E_SRDTokenType::VAR:
-				output.add( std::move( token ) );
-				continue;
-
-			default:
-				data.addError( token , "unsupported type conversion" );
-				continue;
-				
-		}
-
-		T_SRDToken otok( T_SRDToken::Variable( std::move( outString ) ) );
-		otok.copyLocationOf( token );
-		output.add( std::move( otok ) );
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( CastList )
-{
-	auto& input( state.output( ) );
-	auto& data( state.data( ) );
-	auto& output( data.top( ).output( ) );
-
-	const auto size( input.size( ) );
-	for ( uint32_t i = 0 ; i < size ; i ++ ) {
-		auto& token( input[ i ] );
-		switch ( token.type( ) ) {
-
-			case E_SRDTokenType::STRING:
-			case E_SRDTokenType::WORD:
-			{
-				T_StringIterator it( token.stringValue( ) );
-				T_StringBuilder sb;
-				while ( !it.atEnd( ) ) {
-					T_Character c( it );
-					it.next( );
-					sb << c;
-					T_SRDToken ctok( T_SRDToken::String( sb ) );
-					ctok.copyLocationOf( token );
-					output.add( std::move( ctok ) );
-					sb.clear( );
-				}
-				break;
-			}
-
-			case E_SRDTokenType::BINARY:
-			{
-				auto const& buffer( token.binary( ) );
-				const auto bs( buffer.size( ) );
-				for ( auto i = 0u ; i < bs ; i ++ ) {
-					T_SRDToken vtok( T_SRDToken::Integer( buffer[ i ] ) );
-					vtok.copyLocationOf( token );
-					output.add( std::move( vtok ) );
-				}
-				break;
-			}
-
-			case E_SRDTokenType::LIST:
-			{
-				auto const& l( token.list( ) );
-				const auto ls( l.size( ) );
-				for ( auto i = 0u ; i < ls ; i ++ ) {
-					output.add( std::move( l[ i ] ) );
-				}
-				break;
-			}
-
-			default:
-				output.add( std::move( token ) );
-				continue;
-				
-		}
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( ClearScope )
-{
-	if ( state.output( ).size( ) != 0 ) {
-		auto& data( state.data( ) );
-		data.scopes( ).enter( );
-		data.scopes( ).clear( );
-		data.push( T_SRDPreprocessorState::C_INNER ,
-				state.outputPointer( ) , data.top( ).outputPointer( ) ,
-				[]( T_SRDPreprocessorState & ns ) {
-					ns.data( ).scopes( ).exit( );
-				} );
-	} else {
-		state.data( ).scopes( ).clear( );
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( Cmp )
-{
-	int result;
-	bool success( CompareInput_( state , result ) );
-	T_SRDToken token( T_SRDToken::Integer( success ? result : 0 ) );
-	token.location( *state.initialLocation( ) );
-	state.data( ).top( ).output( ).add( std::move( token ) );
-}
-
-M_SRDPP_COMMAND_EXEC( CmpEq )
-{
-	int result;
-	bool success( CompareInput_( state , result ) );
-	T_SRDToken token( T_SRDToken::Integer( ( success && result == 0 ) ? 1 : 0 ) );
-	token.location( *state.initialLocation( ) );
-	state.data( ).top( ).output( ).add( std::move( token ) );
-}
-
-M_SRDPP_COMMAND_EXEC( CmpNe )
-{
-	int result;
-	bool success( CompareInput_( state , result ) );
-	T_SRDToken token( T_SRDToken::Integer( ( success && result != 0 ) ? 1 : 0 ) );
-	token.location( *state.initialLocation( ) );
-	state.data( ).top( ).output( ).add( std::move( token ) );
-}
-
-M_SRDPP_COMMAND_EXEC( CmpLt )
-{
-	int result;
-	bool success( CompareInput_( state , result ) );
-	T_SRDToken token( T_SRDToken::Integer( ( success && result < 0 ) ? 1 : 0 ) );
-	token.location( *state.initialLocation( ) );
-	state.data( ).top( ).output( ).add( std::move( token ) );
-}
-
-M_SRDPP_COMMAND_EXEC( CmpGt )
-{
-	int result;
-	bool success( CompareInput_( state , result ) );
-	T_SRDToken token( T_SRDToken::Integer( ( success && result > 0 ) ? 1 : 0 ) );
-	token.location( *state.initialLocation( ) );
-	state.data( ).top( ).output( ).add( std::move( token ) );
-}
-
-M_SRDPP_COMMAND_EXEC( CmpLe )
-{
-	int result;
-	bool success( CompareInput_( state , result ) );
-	T_SRDToken token( T_SRDToken::Integer( ( success && result <= 0 ) ? 1 : 0 ) );
-	token.location( *state.initialLocation( ) );
-	state.data( ).top( ).output( ).add( std::move( token ) );
-}
-
-M_SRDPP_COMMAND_EXEC( CmpGe )
-{
-	int result;
-	bool success( CompareInput_( state , result ) );
-	T_SRDToken token( T_SRDToken::Integer( ( success && result >= 0 ) ? 1 : 0 ) );
-	token.location( *state.initialLocation( ) );
-	state.data( ).top( ).output( ).add( std::move( token ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( Concat )
-{
-	auto& input( state.output( ) );
-	auto& data( state.data( ) );
-	auto& output( data.top( ).output( ) );
-	auto const& loc( *state.initialLocation( ) );
-
-	const auto size( input.size( ) );
-	if ( size == 0 ) {
-		data.addError( loc , "not enough arguments" );
-		T_SRDToken otok( T_SRDToken::String( T_String( "" ) ) );
-		otok.location( loc );
-		output.add( std::move( otok ) );
-		return;
-	}
-
-	// Find out whether this is a string concatenation or a binary
-	// concatenation.
-	uint32_t binLength = 0;
-	bool isBinary = true;
-	for ( uint32_t i = 0 ; i < size ; i ++ ) {
-		auto const& token( input[ i ] );
-		if ( token.type( ) != E_SRDTokenType::BINARY ) {
-			isBinary = false;
-			break;
-		}
-		binLength += token.binary( ).size( );
-	}
-
-	// Binary concat
-	if ( isBinary ) {
-		auto ob( NewShared< T_Buffer< uint8_t > >( binLength ) );
-		binLength = 0;
-		for ( uint32_t i = 0 ; i < size ; i ++ ) {
-			auto const& bin( input[ i ].binary( ) );
-			memcpy( ob->data( ) + binLength ,
-					bin.data( ) , bin.size( ) );
-			binLength += bin.size( );
-		}
-		T_SRDToken otok( T_SRDToken::Binary( ob ) );
-		otok.location( loc );
-		output.add( std::move( otok ) );
-		return;
-	}
-
-	// String concat
-	T_StringBuilder sb;
-	for ( uint32_t i = 0 ; i < size ; i ++ ) {
-		auto const& token( input[ i ] );
-		if ( !( token.isText( ) || token.isNumeric( ) ) ) {
-			data.addError( token , "expected text or numeric argument" );
-			continue;
-		}
-
-		switch ( token.type( ) ) {
-
-			case E_SRDTokenType::STRING:
-			case E_SRDTokenType::WORD:
-				sb << token.stringValue( );
-				continue;
-
-			case E_SRDTokenType::INT:
-			case E_SRDTokenType::LONG:
-				sb << token.longValue( );
-				break;
-
-			case E_SRDTokenType::FLOAT:
-				sb << token.floatValue( );
-				break;
-
-			default:
-				assert( 0 && "we shouldn't be here" );
-				continue;
-				
-		}
-	}
-
-	T_SRDToken otok( T_SRDToken::String( std::move( sb ) ) );
-	otok.location( loc );
-	output.add( std::move( otok ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( Div )
-{
-	DoMathOp_( state ,
-		  []( auto a , auto b ) {
-		return a / b;
-	} ,
-		  []( auto a , auto b ) {
-		return a / b;
-	} , true );
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( EndsWith )
-{
-	auto& input( state.output( ) );
-	auto& data( state.data( ) );
-	auto const& loc( *state.initialLocation( ) );
-
-	uint32_t value = 0;
-	if ( input.size( ) < 2 ) {
-		data.addError( loc , "not enough arguments" );
-	} else if ( input.size( ) > 2 ) {
-		data.addError( loc , "too many arguments" );
-	} else {
-		if ( input[ 0 ].isText( ) && input[ 1 ].isText( ) ) {
-			value = input[ 1 ].stringValue( ).endsWith(
-					input[ 0 ].stringValue( ) );
-		} else if ( input[ 0 ].type( ) == E_SRDTokenType::BINARY
-				&& input[ 1 ].type( ) == E_SRDTokenType::BINARY ) {
-			auto const& needle( input[ 0 ].binary( ) );
-			auto const& haystack( input[ 1 ].binary( ) );
-			auto const nsz( needle.size( ) );
-			auto const hsz( haystack.size( ) );
-			value = ( nsz <= hsz
-				&& !( nsz && memcmp( needle.data( ) ,
-						haystack.data( ) + hsz - nsz ,
-						nsz ) ) );
-		} else {
-			data.addError( loc , "invalid arguments" );
-		}
-	}
-
-	auto tok( T_SRDToken::Integer( value ) );
-	tok.location( loc );
-	data.top( ).output( ).add( std::move( tok ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( Eval )
-{
-	if ( state.output( ).size( ) == 0 ) {
-		return;
-	}
-	auto& data( state.data( ) );
-//	data.push( T_SRDPreprocessorState::C_CALL , state.outputPointer( ) ,
-//			data.top( ).outputPointer( ) );
-	auto& input( state.output( ) );
-	const auto is( input.size( ) );
-	if ( is ) {
-		const SP_SRDLocation evalLocation( state.createChainedLocation( ) );
-		SP_SRDList updated( NewShared< T_SRDList >( is ) );
-		for ( size_t i = 0 ; i < is ; i ++ ) {
-			T_SRDToken token( std::move( input[ i ] ) );
-
-			auto& loc( token.location( ) );
-			SP_SRDLocation el( ( i == is - 1 )
-					? evalLocation
-					: NewShared< T_SRDLocation >( *evalLocation ) );
-			if ( loc.isChained( ) ) {
-				auto const& lc( loc.chaining( ) );
-				el->chain( lc.circumstances , lc.location );
-			}
-			loc.chain( E_SRDLocationChaining::EVALUATED , el );
-
-			updated->add( std::move( token ) );
-		}
-
-		data.push( T_SRDPreprocessorState::C_UNSPECIFIED , updated ,
-				data.top( ).outputPointer( ) );
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( Error )
-{
-	auto& data( state.data( ) );
-	auto const& loc( *state.initialLocation( ) );
-	auto& input( state.output( ) );
-	const auto nTokens( input.size( ) );
-	if ( nTokens == 0 ) {
-		data.addError( loc , "user error" );
-	} else {
-		T_StringBuilder sb;
-		for ( uint32_t i = 0 ; i < nTokens ; i ++ ) {
-			if ( i > 0 ) {
-				sb << ' ';
-			}
-			auto& tok( input[ i ] );
-			switch( tok.type( ) ) {
-
-				case E_SRDTokenType::VAR:
-					sb << '$';
-				case E_SRDTokenType::STRING:
-				case E_SRDTokenType::WORD:
-					sb << tok.stringValue( );
-					break;
-
-				case E_SRDTokenType::INT:
-				case E_SRDTokenType::LONG:
-					sb << tok.longValue( );
-					break;
-
-				case E_SRDTokenType::FLOAT:
-					sb << tok.floatValue( );
-					break;
-
-				case E_SRDTokenType::LIST:
-					tok.generateFullText( );
-					sb << tok.fullText( );
-					break;
-
-				default:
-					sb << "(INTERNAL ERROR)";
-					break;
-			}
-		}
-		data.addError( loc , sb );
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( FromSource )
-{
-	auto& data( state.data( ) );
-	auto const& loc( *state.initialLocation( ) );
-
-	auto& input( state.output( ) );
-	const auto is( input.size( ) );
-	if ( is == 0 ) {
-		data.addError( loc , "not enough arguments" );
-		return;
-	}
-	if ( is > 2 ) {
-		data.addError( loc , "too many arguments" );
-	}
-
-	if ( input[ 0 ].type( ) != E_SRDTokenType::STRING ) {
-		data.addError( input[ 0 ] , "string expected" );
-		return;
-	}
-	if ( is == 2 && !input[ 1 ].isText( ) ) {
-		data.addError( input[ 1 ] , "word or string expected" );
-	}
-
-	const T_String inputName( ( is == 2 && input[ 1 ].isText( ) )
-			? input[ 1 ].stringValue( )
-			: T_String::Pooled( "(-from-source)" ) );
-	T_SRDErrors& errors( data.errorContext( ) );
-
-	T_SRDMemoryTarget tgt( true );
-	T_SRDLexer lexer( inputName , errors , tgt );
-	tgt.start( errors );
-
-	T_StringIterator it( input[ 0 ].stringValue( ) );
-	while ( !it.atEnd( ) ) {
-		lexer.processCharacter( it );
-		it.next( );
-	}
-	lexer.processEnd( );
-
-	auto const& generated( tgt.list( ) );
-	auto& output( data.top( ).output( ) );
-	const auto gs( generated.size( ) );
-	const SP_SRDLocation gloc( state.createChainedLocation( ) );
-	for ( size_t i = 0 ; i < gs ; i ++ ) {
-		T_SRDToken t( generated[ i ] );
-		t.location( ).chain( E_SRDLocationChaining::GENERATED , gloc );
-		output.add( std::move( t ) );
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( FromSRB )
-{
-	auto& data( state.data( ) );
-	auto const& loc( *state.initialLocation( ) );
-
-	auto& input( state.output( ) );
-	const auto is( input.size( ) );
-	if ( is == 0 ) {
-		data.addError( loc , "not enough arguments" );
-		return;
-	}
-	if ( is > 2 ) {
-		data.addError( loc , "too many arguments" );
-	}
-
-	if ( input[ 0 ].type( ) != E_SRDTokenType::BINARY ) {
-		data.addError( input[ 0 ] , "binary array expected" );
-		return;
-	}
-	if ( is == 2 && !input[ 1 ].isText( ) ) {
-		data.addError( input[ 1 ] , "word or string expected" );
-	}
-
-	const T_String inputName( ( is == 2 && input[ 1 ].isText( ) )
-			? input[ 1 ].stringValue( )
-			: T_String::Pooled( "(-from-srb)" ) );
-	T_SRDErrors& errors( data.errorContext( ) );
-
-	T_SRDMemoryTarget tgt( true );
-	T_SRDBinaryReader reader( tgt );
-	T_MemoryInputStream istream( input[ 0 ].binary( ) );
-	try {
-		reader.read( inputName , istream );
-	} catch ( X_SRDErrors const& srbErrors ) {
-		errors.addAll( srbErrors.errors );
-	}
-	data.top( ).output( ).addAll( tgt.list( ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( Get )
-{
-	auto& data( state.data( ) );
-	auto& input( state.output( ) );
-	const auto sz( input.size( ) );
-	auto& output( state.data( ).top( ).output( ) );
-
-	for ( uint32_t i = 0 ; i < sz ; i ++ ) {
-		auto const& vtok( input[ i ] );
-		if ( vtok.type( ) != E_SRDTokenType::WORD ) {
-			data.addError( vtok , "word expected" );
-			continue;
-		}
-
-		auto var( data.scopes( ).get( false , vtok.stringValue( ) ) );
-		if ( var == nullptr ) {
-			data.addError( vtok , "unknown variable" );
-		} else {
-			output.addAll( *var );
-		}
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( If )
-{
-	auto& input( state.output( ) );
-	auto& data( state.data( ) );
-	auto const& loc( *state.initialLocation( ) );
-	const auto sz( input.size( ) );
-
-	if ( sz < 2 ) {
-		data.addError( loc , "not enough arguments" );
-		return;
-	}
-	if ( sz > 3 ) {
-		data.addError( loc , "too many arguments" );
-		return;
-	}
-
-	auto const& cdTok( input[ 0 ] );
-	if ( cdTok.type( ) != E_SRDTokenType::INT && cdTok.type( ) != E_SRDTokenType::LONG ) {
-		data.addError( cdTok , "integer expected" );
-		return;
-	}
-	if ( input[ 1 ].type( ) != E_SRDTokenType::LIST ) {
-		data.addError( input[ 1 ] , "list expected" );
-		return;
-	}
-	if ( sz == 3 && input[ 2 ].type( ) != E_SRDTokenType::LIST ) {
-		data.addError( input[ 2 ] , "list expected" );
-		return;
-	}
-
-	const bool cond( cdTok.longValue( ) != 0 );
-	if ( sz == 2 && !cond ) {
-		return;
-	}
-	data.push( T_SRDPreprocessorState::C_INNER ,
-			NewShared< T_SRDList >( input[ cond ? 1 : 2 ].list( ) ) ,
-			data.top( ).outputPointer( ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( Ignore )
-{
-	(void) state;
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( IsBlessed )
-{
-	auto& input( state.output( ) );
-	auto& data( state.data( ) );
-	auto const& loc( *state.initialLocation( ) );
-
-	bool blessed;
-	if ( input.size( ) == 0 ) {
-		data.addError( loc , "not enough arguments" );
-		blessed = false;
-	} else if ( input.size( ) > 1 ) {
-		data.addError( loc , "too many arguments" );
-		blessed = false;
-	} else if ( input[ 0 ].type( ) != E_SRDTokenType::WORD ) {
-		data.addError( input[ 0 ] , "word expected" );
-		blessed = false;
-	} else {
-		blessed = data.scopes( ).isBlessed( input[ 0 ].stringValue( ) );
-	}
-	T_SRDToken output( T_SRDToken::Integer( blessed ? 1 : 0 ) );
-	output.location( loc );
-	state.data( ).top( ).output( ).add( std::move( output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( IsMacro )
-{
-	auto& input( state.output( ) );
-	auto& data( state.data( ) );
-	auto const& loc( *state.initialLocation( ) );
-
-	bool set;
-	if ( input.size( ) == 0 ) {
-		data.addError( loc , "not enough arguments" );
-		set = false;
-	} else if ( input.size( ) > 1 ) {
-		data.addError( loc , "too many arguments" );
-		set = false;
-	} else if ( input[ 0 ].type( ) != E_SRDTokenType::WORD ) {
-		data.addError( input[ 0 ] , "word expected" );
-		set = false;
-	} else {
-		set = ( data.scopes( ).get( true , input[ 0 ].stringValue( ) ) != nullptr );
-	}
-	T_SRDToken output( T_SRDToken::Integer( set ? 1 : 0 ) );
-	output.location( loc );
-	state.data( ).top( ).output( ).add( std::move( output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( IsSet )
-{
-	auto& input( state.output( ) );
-	auto& data( state.data( ) );
-	auto const& loc( *state.initialLocation( ) );
-
-	bool set;
-	if ( input.size( ) == 0 ) {
-		data.addError( loc , "not enough arguments" );
-		set = false;
-	} else if ( input.size( ) > 1 ) {
-		data.addError( loc , "too many arguments" );
-		set = false;
-	} else if ( input[ 0 ].type( ) != E_SRDTokenType::WORD ) {
-		data.addError( input[ 0 ] , "word expected" );
-		set = false;
-	} else {
-		set = ( data.scopes( ).get( false , input[ 0 ].stringValue( ) ) != nullptr );
-	}
-	T_SRDToken output( T_SRDToken::Integer( set ? 1 : 0 ) );
-	output.location( loc );
-	state.data( ).top( ).output( ).add( std::move( output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( Length )
-{
-	auto& input( state.output( ) );
-	auto& data( state.data( ) );
-	auto const& loc( *state.initialLocation( ) );
-
-	int64_t length;
-	if ( input.size( ) == 0 ) {
-		data.addError( loc , "not enough arguments" );
-		length = -1;
-	} else if ( input.size( ) > 1 ) {
-		data.addError( loc , "too many arguments" );
-		length = -1;
-	} else if ( input[ 0 ].type( ) == E_SRDTokenType::LIST ) {
-		length = input[ 0 ].list( ).size( );
-	} else if ( input[ 0 ].type( ) == E_SRDTokenType::BINARY ) {
-		length = input[ 0 ].binary( ).size( );
-	} else if ( input[ 0 ].isText( ) ) {
-		length = input[ 0 ].stringValue( ).length( );
-	} else {
-		data.addError( input[ 0 ] , "list, word, string or binary array expected" );
-		length = -1;
-	}
-
-	T_SRDToken output( T_SRDToken::AutoInteger( length ) );
-	output.location( loc );
-	state.data( ).top( ).output( ).add( std::move( output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( ListMacros )
-{
-	auto& data( state.data( ) );
-	auto const& loc( *state.initialLocation( ) );
-	if ( state.output( ).size( ) != 0 ) {
-		data.addError( loc , "too many arguments" );
-	}
-
-	auto & output( data.top( ).output( ) );
-	T_Array< T_String > macroNames( data.scopes( ).list( true ) );
-	const auto nMacros( macroNames.size( ) );
-	for ( uint32_t i = 0 ; i < nMacros ; i ++ ) {
-		T_SRDToken tok( T_SRDToken::Word( macroNames[ i ] ) );
-		tok.location( loc );
-		output.add( std::move( tok ) );
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( ListVariables )
-{
-	auto& data( state.data( ) );
-	auto const& loc( *state.initialLocation( ) );
-	if ( state.output( ).size( ) != 0 ) {
-		data.addError( loc , "too many arguments" );
-	}
-
-	auto & output( data.top( ).output( ) );
-	T_Array< T_String > varNames( data.scopes( ).list( false ) );
-	const auto nVars( varNames.size( ) );
-	for ( uint32_t i = 0 ; i < nVars ; i ++ ) {
-		T_SRDToken tok( T_SRDToken::Word( varNames[ i ] ) );
-		tok.location( loc );
-		output.add( std::move( tok ) );
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( Mod )
-{
-	DoMathOp_( state ,
-		  []( auto a , auto b ) {
-		return a % b;
-	} ,
-		  []( auto a , auto b ) {
-		return std::fmod( a , b );
-	} , true );
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( Mul )
-{
-	DoMathOp_( state ,
-		  []( auto a , auto b ) {
-		return a * b;
-	} ,
-		  []( auto a , auto b ) {
-		return a * b;
-	} );
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( Neg )
-{
-	auto& input( state.output( ) );
-	auto& data( state.data( ) );
-	auto const& loc( *state.initialLocation( ) );
-
-	bool of( false );
-	int64_t iv( 0 );
-	double fv( 0 );
-	if ( input.size( ) == 0 ) {
-		data.addError( loc , "not enough arguments" );
-	} else if ( input.size( ) != 1 ) {
-		data.addError( loc , "too many arguments" );
-	} else if ( !input[ 0 ].isNumeric( ) ) {
-		data.addError( input[ 0 ] , "numeric argument expected" );
-	} else if ( input[ 0 ].isInteger( ) ) {
-		iv = -input[ 0 ].longValue( );
-	} else {
-		fv = -input[ 0 ].floatValue( );
-		of = true;
-	}
-
-	T_SRDToken output( of ? T_SRDToken::Float( fv ) : T_SRDToken::AutoInteger( iv ) );
-	output.location( loc );
-	state.data( ).top( ).output( ).add( std::move( output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( Not )
-{
-	auto& input( state.output( ) );
-	auto& data( state.data( ) );
-	auto const& loc( *state.initialLocation( ) );
-
-	int64_t iv( 0 );
-	if ( input.size( ) == 0 ) {
-		data.addError( loc , "not enough arguments" );
-	} else if ( input.size( ) != 1 ) {
-		data.addError( loc , "too many arguments" );
-	} else if ( !input[ 0 ].isInteger( ) ) {
-		data.addError( input[ 0 ] , "integer argument expected" );
-	} else {
-		iv = input[ 0 ].longValue( ) ? 0 : 1;
-	}
-
-	T_SRDToken output( T_SRDToken::Integer( iv ) );
-	output.location( loc );
-	state.data( ).top( ).output( ).add( std::move( output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( Or )
-{
-	DoLogicOp_( state ,
-		  []( auto a , auto b ) {
-		return ( a || b ) ? 1 : 0;
-	} );
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( Output )
-{
-	auto& out( state.output( ) );
-	const auto n( out.size( ) );
-
-	if ( n ) {
-		auto& data( state.data( ) );
-		auto& pp( data.preprocessor( ) );
-		auto& ec( data.errorContext( ) );
-		for ( uint32_t i = 0 ; i < n ; i ++ ) {
-			pp.sendOutput( ec , out[ i ] );
-		}
-		pp.target( ).push( ec , T_SRDToken::Flush( ) );
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( Raw )
-{
-	state.data( ).top( ).output( ).addAll( state.output( ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-namespace {
-
-void RethrowError_( T_SRDPreprocessorData& data , T_SRDList const& error )
-{
-	auto const& esTok( error[ 0 ] );
-	if ( esTok.type( ) != E_SRDTokenType::STRING ) {
-		data.addError( esTok , "string expected" );
-		return;
-	}
-
-	const auto elSize( error.size( ) );
-	SP_SRDLocation location;
-	for ( uint32_t i = elSize - 1 ; i > 0 ; i -- ) {
-		auto const& locEntry( error[ i ] );
-		if ( locEntry.type( ) != E_SRDTokenType::LIST ) {
-			data.addError( locEntry , "list expected" );
-			return;
-		}
-
-		auto const& locList( locEntry.list( ) );
-		const bool hasChaining( i != elSize - 1 );
-		const uint32_t expectedLength( hasChaining ? 4 : 3 );
-		if ( locList.size( ) != expectedLength ) {
-			data.addError( locEntry , "invalid location entry" );
-			return;
-		}
-
-		auto const& locName( locList[ 0 ] );
-		if ( locName.type( ) != E_SRDTokenType::STRING ) {
-			data.addError( locName , "string expected" );
-			return;
-		}
-		auto const& locLine( locList[ 1 ] );
-		if ( !locLine.isInteger( ) ) {
-			data.addError( locLine , "integer expected" );
-			return;
-		}
-		const int64_t line( locLine.longValue( ) );
-		if ( line < 0 || line > UINT32_MAX ) {
-			data.addError( locLine , "invalid line number" );
-			return;
-		}
-
-		auto const& locChar( locList[ 2 ] );
-		if ( !locChar.isInteger( ) ) {
-			data.addError( locChar , "integer expected" );
-			return;
-		}
-		const int64_t character( locChar.longValue( ) );
-		if ( character < 0 || character > UINT32_MAX ) {
-			data.addError( locChar , "invalid character/byte number" );
-			return;
-		}
-
-		E_SRDLocationChaining chaining;
-		if ( hasChaining ) {
-			if ( locList[ 3 ].type( ) != E_SRDTokenType::WORD ) {
-				data.addError( locList[ 3 ] , "word expected" );
-				return;
-			}
-			T_String const& chainWord( locList[ 3 ].stringValue( ) );
-			if ( chainWord == "generated" ) {
-				chaining = E_SRDLocationChaining::GENERATED;
-			} else if ( chainWord == "included" ) {
-				chaining = E_SRDLocationChaining::INCLUDED;
-			} else if ( chainWord == "loaded" ) {
-				chaining = E_SRDLocationChaining::LOADED;
-			} else if ( chainWord == "called" ) {
-				chaining = E_SRDLocationChaining::CALLED;
-			} else if ( chainWord == "evaluated" ) {
-				chaining = E_SRDLocationChaining::EVALUATED;
-			} else if ( chainWord == "expanded" ) {
-				chaining = E_SRDLocationChaining::EXPANDED;
-			} else if ( chainWord == "substituted" ) {
-				chaining = E_SRDLocationChaining::SUBSTITUTED;
-			} else {
-				data.addError( locList[ 3 ] , "invalid chaining" );
-				return;
-			}
-		} else {
-			// Compiler stfu
-			chaining = E_SRDLocationChaining( 0 );
-		}
-
-		T_String const& src( locName.stringValue( )  );
-		SP_SRDLocation nLocation( line > 0
-				? NewShared< T_SRDLocation >( src , line , character )
-				: NewShared< T_SRDLocation >( src , character ) );
-		if ( hasChaining ) {
-			nLocation->chain( chaining , location );
-		}
-		location = nLocation;
-	}
-
-	data.addError( *location , esTok.stringValue( ) );
-}
-
-void DoRethrow_( T_SRDPreprocessorData& data , T_SRDList const& errors )
-{
-	const auto nErrors( errors.size( ) );
-	for ( uint32_t i = 0 ; i < nErrors ; i ++ ) {
-		auto const& errTok( errors[ i ] );
-		if ( errTok.type( ) != E_SRDTokenType::LIST ) {
-			data.addError( errTok , "list expected" );
-			continue;
-		}
-		if ( errTok.list( ).size( ) < 2 ) {
-			data.addError( errTok , "invalid error record" );
-			continue;
-		}
-		RethrowError_( data , errTok.list( ) );
-	}
-}
-
-}
-
-M_SRDPP_COMMAND_EXEC( Rethrow )
-{
-	auto const& input( state.output( ) );
-	if ( input.size( ) == 0 ) {
-		return;
-	}
-	if ( input.size( ) == 1 && input[ 0 ].type( ) == E_SRDTokenType::LIST ) {
-		auto const& innerList( input[ 0 ].list( ) );
-		if ( innerList.size( ) == 0 ) {
-			return;
-		}
-		if ( innerList[ 0 ].type( ) == E_SRDTokenType::LIST ) {
-			DoRethrow_( state.data( ) , innerList );
-			return;
-		}
-	}
-	DoRethrow_( state.data( ) , input );
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( Scope )
-{
-	if ( state.output( ).size( ) == 0 ) {
-		return;
-	}
-	auto& data( state.data( ) );
-	data.scopes( ).enter( );
-	data.push( T_SRDPreprocessorState::C_INNER ,
-			state.outputPointer( ) , data.top( ).outputPointer( ) ,
-			[]( T_SRDPreprocessorState & ns ) {
-				ns.data( ).scopes( ).exit( );
-			} );
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( Set )
-{
-	auto& input( state.output( ) );
-	auto& data( state.data( ) );
-	auto const& loc( *state.initialLocation( ) );
-
-	if ( input.size( ) == 0 ) {
-		data.addError( loc , "not enough arguments" );
-		return;
-	}
-
-	auto const& names( input[ 0 ] );
-	auto& s( data.scopes( ) );
-	if ( names.type( ) == E_SRDTokenType::WORD ) {
-		auto const& vn( names.stringValue( ) );
-		if ( !s.canSet( false , vn ) ) {
-			data.addError( names , "duplicate variable name" );
-			return;
-		}
-		s.set( false , vn , input , 1 );
-
-	} else if ( names.type( ) == E_SRDTokenType::LIST ) {
-		auto const& list( names.list( ) );
-		const auto n( list.size( ) );
-		if ( n == 0 ) {
-			data.addError( names , "non-empty list expected" );
-			return;
-		}
-
-		bool ok( true );
-		for ( uint32_t i = 0 ; i < n ; i ++ ) {
-			auto const& name( list[ i ] );
-			if ( name.type( ) != E_SRDTokenType::WORD ) {
-				data.addError( name , "word expected" );
-				ok = false;
-				continue;
-			}
-
-			auto const& vn( name.stringValue( ) );
-			for ( uint32_t j = 0 ; j < i ; j ++ ) {
-				if ( list[ j ].type( ) != E_SRDTokenType::WORD ) {
-					continue;
-				}
-				if ( list[ j ].stringValue( ) == vn ) {
-					data.addError( name , "duplicate variable name" );
-					ok = false;
-					goto next;
-				}
-			}
-			if ( !s.canSet( false , vn ) ) {
-				data.addError( name , "duplicate variable name" );
-				ok = false;
-			}
-
-next:                   ;
-		}
-
-		if ( !ok ) {
-			return;
-		}
-		for ( uint32_t i = 0 ; i + 1 < n ; i ++ ) {
-			s.set( false , list[ i ].stringValue( ) , input , 1 + i , 1 + i );
-		}
-		s.set( false , list[ n - 1 ].stringValue( ) , input , n );
-
-	} else {
-		data.addError( names , "word or list expected" );
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( SetMacro )
-{
-	auto& input( state.output( ) );
-	auto& data( state.data( ) );
-	auto const& loc( *state.initialLocation( ) );
-
-	if ( input.size( ) < 2 ) {
-		data.addError( loc , "not enough arguments" );
-		return;
-	}
-	if ( input.size( ) > 2 ) {
-		data.addError( loc , "too many arguments" );
-		return;
-	}
-
-	auto const& name( input[ 0 ] );
-	if ( name.type( ) != E_SRDTokenType::WORD ) {
-		data.addError( name , "word expected" );
-		return;
-	}
-	auto const& mn( name.stringValue( ) );
-	auto& s( data.scopes( ) );
-	if ( !s.canSet( true , mn ) ) {
-		data.addError( name , "duplicate macro name" );
-		return;
-	}
-
-	auto const& value( input[ 1 ] );
-	if ( !T_SRDPreprocessor::isValidFunction( value ) ) {
-		data.addError( value , "invalid macro body" );
-		return;
-	}
-
-	s.set( true , mn , value.list( ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( StartsWith )
-{
-	auto& input( state.output( ) );
-	auto& data( state.data( ) );
-	auto const& loc( *state.initialLocation( ) );
-
-	uint32_t value = 0;
-	if ( input.size( ) < 2 ) {
-		data.addError( loc , "not enough arguments" );
-	} else if ( input.size( ) > 2 ) {
-		data.addError( loc , "too many arguments" );
-	} else {
-		if ( input[ 0 ].isText( ) && input[ 1 ].isText( ) ) {
-			value = input[ 1 ].stringValue( ).startsWith(
-					input[ 0 ].stringValue( ) );
-		} else if ( input[ 0 ].type( ) == E_SRDTokenType::BINARY
-				&& input[ 1 ].type( ) == E_SRDTokenType::BINARY ) {
-			auto const& needle( input[ 0 ].binary( ) );
-			auto const& haystack( input[ 1 ].binary( ) );
-			auto const nsz( needle.size( ) );
-			auto const hsz( haystack.size( ) );
-			value = ( nsz <= hsz
-				&& !( nsz && memcmp( needle.data( ) ,
-						haystack.data( ) , nsz ) ) );
-		} else {
-			data.addError( loc , "invalid arguments" );
-		}
-	}
-
-	auto tok( T_SRDToken::Integer( value ) );
-	tok.location( loc );
-	data.top( ).output( ).add( std::move( tok ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( StrFind )
-{
-	auto& input( state.output( ) );
-	auto& data( state.data( ) );
-	auto const& loc( *state.initialLocation( ) );
-
-	int32_t value = -1;
-	if ( input.size( ) < 2 ) {
-		data.addError( loc , "not enough arguments" );
-	} else if ( input.size( ) > 2 ) {
-		data.addError( loc , "too many arguments" );
-	} else {
-		if ( !input[ 0 ].isText( ) ) {
-			data.addError( input[ 0 ] , "text expected" );
-		}
-		if ( !input[ 1 ].isText( ) ) {
-			data.addError( input[ 1 ] , "text expected" );
-		}
-		if ( input[ 0 ].isText( ) && input[ 1 ].isText( ) ) {
-			value = input[ 1 ].stringValue( ).find(
-					input[ 0 ].stringValue( ) );
-		}
-	}
-
-	auto tok( T_SRDToken::Integer( value ) );
-	tok.location( loc );
-	data.top( ).output( ).add( std::move( tok ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( StrSplit )
-{
-	auto& input( state.output( ) );
-	auto& data( state.data( ) );
-	auto const& loc( *state.initialLocation( ) );
-	auto& output( data.top( ).output( ) );
-
-	if ( input.size( ) < 2 ) {
-		data.addError( loc , "not enough arguments" );
-		return;
-	}
-	if ( input.size( ) > 3 ) {
-		data.addError( loc , "too many arguments" );
-		return;
-	}
-
-	bool argsOk = true;
-	if ( !input[ 0 ].isText( ) ) {
-		data.addError( input[ 0 ] , "text expected" );
-		argsOk = false;
-	} else if ( !input[ 0 ].stringValue( ) ) {
-		data.addError( input[ 0 ] , "invalid argument value" );
-		argsOk = false;
-	}
-	if ( !input[ 1 ].isText( ) ) {
-		data.addError( input[ 1 ] , "text expected" );
-		argsOk = false;
-	}
-	if ( input.size( ) == 3
-			&& input[ 2 ].type( ) != E_SRDTokenType::INT
-			&& input[ 2 ].type( ) != E_SRDTokenType::LONG ) {
-		data.addError( input[ 2 ] , "integer expected" );
-		argsOk = false;
-	}
-	if ( !argsOk ) {
-		return;
-	}
-	uint32_t maxOutput;
-	if ( input.size( ) == 3 ) {
-		int64_t n( input[ 2 ].longValue( ) );
-		if ( n < 0 || n > UINT32_MAX ) {
-			data.addError( input[ 2 ] , "invalid argument value" );
-			maxOutput = UINT32_MAX;
-		} else {
-			maxOutput = n;
-		}
-	} else {
-		maxOutput = UINT32_MAX;
-	}
-
-	int32_t nextSearch( 0 );
-	auto const& needle( input[ 0 ].stringValue( ) );
-	auto const& haystack( input[ 1 ].stringValue( ) );
-	while ( nextSearch != -1 && maxOutput != 0 ) {
-		const int32_t sepIndex( haystack.find( needle , nextSearch ) );
-
-		const T_String os( sepIndex == -1
-				? haystack.substr( nextSearch )
-				: ( sepIndex == 0
-					? T_String( )
-					: haystack.range( nextSearch ,  sepIndex - 1 ) ) );
-		T_SRDToken otok( T_SRDToken::String( os ) );
-		otok.location( loc );
-		output.add( std::move( otok ) );
-
-		if ( sepIndex == -1 ) {
-			nextSearch = -1;
-		} else {
-			nextSearch = sepIndex + needle.length( );
-		}
-		maxOutput --;
-	}
-
-	if ( maxOutput == 0 && nextSearch != -1 ) {
-		T_SRDToken otok( T_SRDToken::String( haystack.substr( nextSearch ) ) );
-		otok.location( loc );
-		output.add( std::move( otok ) );
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( Sub )
-{
-	DoMathOp_( state ,
-		  []( auto a , auto b ) {
-		return a - b;
-	} ,
-		  []( auto a , auto b ) {
-		return a - b;
-	} );
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( Substr )
-{
-	auto& input( state.output( ) );
-	auto& data( state.data( ) );
-	auto const& loc( *state.initialLocation( ) );
-
-	const auto is( input.size( ) );
-	if ( is < 2 ) {
-		data.addError( loc , "not enough arguments" );
-	} else if ( is > 4 ) {
-		data.addError( loc , "too many arguments" );
-	}
-	if ( is == 0 ) {
-		T_SRDToken otok( T_SRDToken::String( T_String( ) ) );
-		otok.location( loc );
-		data.top( ).output( ).add( std::move( otok ) );
-		return;
-	}
-
-	const bool isBinary( input[ 0 ].type( ) == E_SRDTokenType::BINARY );
-	if ( is < 2 || is > 4 ) {
-		T_SRDToken otok( isBinary
-				? T_SRDToken::Binary( (uint8_t const*) nullptr , 0 )
-				: T_SRDToken::String( T_String( ) ) );
-		otok.location( loc );
-		data.top( ).output( ).add( std::move( otok ) );
-		return;
-	}
-
-	const bool isRange = ( is == 4 );
-	bool argsOk = true;
-	uint32_t start( 0 );
-	uint32_t end( UINT32_MAX );
-
-	if ( !( input[ 0 ].isText( ) || isBinary ) ) {
-		data.addError( input[ 0 ] , "binary or text expected" );
-		argsOk = false;
-	}
-
-	if ( isRange && ( input[ 2 ].type( ) != E_SRDTokenType::WORD
-				|| input[ 2 ].stringValue( ) != "to" ) ) {
-		data.addError( input[ 2 ] , "'to' expected" );
-		argsOk = false;
-	}
-
-	if ( !input[ 1 ].isNumeric( ) || input[ 1 ].type( ) == E_SRDTokenType::FLOAT ) {
-		data.addError( input[ 1 ] , "integer expected" );
-		argsOk = false;
-	} else {
-		const int64_t v( input[ 1 ].longValue( ) );
-		if ( v < 0 || v > UINT32_MAX ) {
-			data.addError( input[ 1 ] , "invalid argument value" );
-			argsOk = false;
-		} else {
-			start = v;
-		}
-	}
-
-	if ( is > 2 ) {
-		auto const& next( input[ isRange ? 3 : 2 ] );
-		if ( !next.isNumeric( ) || next.type( ) == E_SRDTokenType::FLOAT ) {
-			data.addError( next , "integer expected" );
-			argsOk = false;
-		} else {
-			const int64_t v( next.longValue( ) );
-			if ( v < 0 || v > UINT32_MAX ) {
-				data.addError( next , "invalid argument value" );
-				argsOk = false;
-			} else {
-				end = v;
-			}
-		}
-	}
-
-	if ( !argsOk ) {
-		T_SRDToken otok( isBinary
-				? T_SRDToken::Binary( (uint8_t const*) nullptr , 0 )
-				: T_SRDToken::String( T_String( ) ) );
-		otok.location( loc );
-		data.top( ).output( ).add( std::move( otok ) );
-		return;
-	}
-
-	if ( !isBinary ) {
-		auto const& str( input[ 0 ].stringValue( ) );
-		T_SRDToken otok( T_SRDToken::String( isRange
-				? str.range( start , end )
-				: str.substr( start , end ) ) );
-		otok.location( loc );
-		data.top( ).output( ).add( std::move( otok ) );
-		return;
-	}
-
-	const uint32_t oriLen( input[ 0 ].binary( ).size( ) );
-	const uint32_t realEnd( std::min( oriLen , end ) );
-	const uint32_t lengthMax( isRange
-			? ( realEnd < start ? 0 : realEnd - start + 1 )
-			: realEnd );
-	const uint32_t length( start >= oriLen
-			? 0 : ( std::min( oriLen , start + lengthMax ) - start ) );
-	auto buffer( NewShared< T_Buffer< uint8_t > >( length ) );
-	if ( length ) {
-		memcpy( buffer->data( ) , input[ 0 ].binary( ).data( ) , length );
-	}
-	T_SRDToken otok( T_SRDToken::Binary( buffer ) );
-	otok.location( loc );
-	data.top( ).output( ).add( std::move( otok ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( ToSource )
-{
-	auto& input( state.output( ) );
-	const auto n( input.size( ) );
-	T_StringBuilder sb;
-	for ( uint32_t i = 0 ; i < n ; i ++ ) {
-		if ( i > 0 ) {
-			sb << ' ';
-		}
-
-		auto& token( input[ i ] );
-		token.generateFullText( );
-		sb << token.fullText( );
-	}
-
-	T_SRDToken otok( T_SRDToken::String( std::move( sb ) ) );
-	otok.location( *state.initialLocation( ) );
-	state.data( ).top( ).output( ).add( std::move( otok ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-namespace {
-
-void ErrorsToList_( T_SRDLocation const& location , T_SRDErrors const& errors , T_SRDList & output )
-{
-	const auto nErrors( errors.size( ) );
-	for ( uint32_t i = 0 ; i < nErrors ; i ++ ) {
-		auto const& error( errors[ i ] );
-		auto& errToken( output[ output.add( T_SRDToken::List( ) ) ] );
-		auto& etl( errToken.list( ) );
-		errToken.location( location );
-
-		{
-			T_SRDToken msg( T_SRDToken::String( error.error( ) ) );
-			msg.location( location );
-			etl.add( std::move( msg ) );
-		}
-
-		RPC_SRDLocation errLoc( &error.location( ) );
-		RPC_SRDLocationChaining chaining( nullptr );
-		while ( errLoc != nullptr ) {
-			auto& locToken( etl[ etl.add( T_SRDToken::List( ) ) ] );
-			auto& ll( locToken.list( ) );
-			locToken.location( location );
-
-			{
-				T_SRDToken src( T_SRDToken::String( errLoc->source( ) ) );
-				src.location( location );
-				ll.add( std::move( src ) );
-			}{
-				T_SRDToken ln( T_SRDToken::Integer( errLoc->line( ) ) );
-				ln.location( location );
-				ll.add( std::move( ln ) );
-			}{
-				T_SRDToken cn( T_SRDToken::Integer( errLoc->character( ) ) );
-				cn.location( location );
-				ll.add( std::move( cn ) );
-			}
-			if ( chaining ) {
-				T_String chain( T_String::Pooled( ( []( RPC_SRDLocationChaining c ) -> char const* {
-					switch ( c->circumstances ) {
-					    case E_SRDLocationChaining::INCLUDED:
-						return "included";
-					    case E_SRDLocationChaining::LOADED:
-						return "loaded";
-					    case E_SRDLocationChaining::CALLED:
-						return "called";
-					    case E_SRDLocationChaining::GENERATED:
-						return "generated";
-					    case E_SRDLocationChaining::SUBSTITUTED:
-						return "substituted";
-					    case E_SRDLocationChaining::EVALUATED:
-						return "evaluated";
-					    case E_SRDLocationChaining::EXPANDED:
-						return "expanded";
-					}
-					return "unknown";
-				} )( chaining ) ) );
-
-				T_SRDToken ctok( T_SRDToken::Word( std::move( chain ) ) );
-				ctok.location( location );
-				ll.add( std::move( ctok ) );
-			}
-
-			if ( errLoc->isChained( ) ) {
-				chaining = &errLoc->chaining( );
-				errLoc = RPC_SRDLocation( chaining->location );
-			} else {
-				errLoc = nullptr;
-			}
-		}
-	}
-}
-
-}
-
-M_SRDPP_COMMAND_EXEC( Try )
-{
-	auto& data( state.data( ) );
-	auto& output( data.top( ).output( ) );
-
-	T_SRDToken otok( T_SRDToken::List( ) );
-	otok.location( *state.initialLocation( ) );
-	if ( state.output( ).size( ) == 0 ) {
-		// No input -> empty list
-		output.add( std::move( otok ) );
-		return;
-	}
-
-	const SP_SRDList fullOutput( NewShared< T_SRDList >( 16 ) );
-	fullOutput->add( std::move( otok ) );
-
-	data.pushErrorContext( );
-	data.push( T_SRDPreprocessorState::C_TRY , state.outputPointer( ) , fullOutput ,
-			[]( T_SRDPreprocessorState & ns ) {
-				const RP_SRDErrors errors( ns.data( ).popErrorContext( ) );
-				auto& errTok( ns.output( )[ 0 ] );
-				ErrorsToList_( errTok.location( ) , *errors , errTok.list( ) );
-				delete errors;
-				ns.data( ).top( ).output( ).addAll( std::move( ns.output( ) ) );
-			} );
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( TypeOf )
-{
-	auto& input( state.output( ) );
-	auto& data( state.data( ) );
-	auto const& loc( *state.initialLocation( ) );
-
-	char const* type;
-	if ( input.size( ) == 0 ) {
-		data.addError( loc , "not enough arguments" );
-		type = "none";
-	} else if ( input.size( ) > 1 ) {
-		data.addError( loc , "too many arguments" );
-		type = "none";
-	} else {
-		switch ( input[ 0 ].type( ) ) {
-		    case E_SRDTokenType::LIST:
-			type = "list";
-			break;
-
-		    case E_SRDTokenType::WORD:
-			type = "word";
-			break;
-
-		    case E_SRDTokenType::STRING:
-			type = "string";
-			break;
-
-		    case E_SRDTokenType::INT:
-			type = "int";
-			break;
-
-		    case E_SRDTokenType::LONG:
-			type = "long";
-			break;
-
-		    case E_SRDTokenType::FLOAT:
-			type = "real";
-			break;
-
-		    case E_SRDTokenType::VAR:
-			type = "var";
-			break;
-
-		    case E_SRDTokenType::BINARY:
-			type = "binary";
-			break;
-
-		    case E_SRDTokenType::COMMENT:
-			type = "comment";
-			break;
-
-		    default:
-			type = "none";
-			data.addError( input[ 0 ] , "internal error" );
-			break;
-		}
-	}
-
-	T_SRDToken output( T_SRDToken::Word( T_String::Pooled( type ) ) );
-	output.location( loc );
-	state.data( ).top( ).output( ).add( std::move( output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( Unset )
-{
-	auto& input( state.output( ) );
-	auto& data( state.data( ) );
-	auto const& loc( *state.initialLocation( ) );
-
-	if ( input.size( ) == 0 ) {
-		data.addError( loc , "not enough arguments" );
-		return;
-	}
-
-	const uint32_t n( input.size( ) );
-	for ( uint32_t i = 0 ; i < n ; i ++ ) {
-		auto const& name( input[ i ] );
-		if ( name.type( ) != E_SRDTokenType::WORD ) {
-			data.addError( name , "word expected" );
-		} else {
-			data.scopes( ).unset( false , name.stringValue( ) );
-		}
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( UnsetMacro )
-{
-	auto& input( state.output( ) );
-	auto& data( state.data( ) );
-	auto const& loc( *state.initialLocation( ) );
-
-	if ( input.size( ) == 0 ) {
-		data.addError( loc , "not enough arguments" );
-		return;
-	}
-
-	const uint32_t n( input.size( ) );
-	for ( uint32_t i = 0 ; i < n ; i ++ ) {
-		auto const& name( input[ i ] );
-		if ( name.type( ) != E_SRDTokenType::WORD ) {
-			data.addError( name , "word expected" );
-		} else {
-			data.scopes( ).unset( true , name.stringValue( ) );
-		}
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( Unwrap )
-{
-	auto& input( state.output( ) );
-	auto& data( state.data( ) );
-	auto const& loc( *state.initialLocation( ) );
-
-	if ( input.size( ) == 0 ) {
-		data.addError( loc , "not enough arguments" );
-	} else if ( input.size( ) > 1 ) {
-		data.addError( loc , "too many arguments" );
-	} else if ( input[ 0 ].type( ) != E_SRDTokenType::LIST ) {
-		data.addError( input[ 0 ] , "list expected" );
-	} else {
-		data.top( ).output( ).addAll( std::move( input[ 0 ].list( ) ) );
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( Xor )
-{
-	DoLogicOp_( state ,
-		  []( auto a , auto b ) {
-		return ( a || b ) && !( a && b );
-	} );
-}
-
-
-/*= VFS COMMANDS =============================================================*/
-
-M_SRDPP_COMMAND_EXEC( VFSList )
-{
-	auto& input( state.output( ) );
-	auto& data( state.data( ) );
-	auto const& loc( *state.initialLocation( ) );
-
-	if ( input.size( ) == 0 ) {
-		data.addError( loc , "not enough arguments" );
-		return;
-	}
-	if ( input.size( ) > 1 ) {
-		data.addError( loc , "too many arguments" );
-		return;
-	}
-	if ( input[ 0 ].type( ) != E_SRDTokenType::STRING ) {
-		data.addError( input[ 0 ] , "string expected" );
-		return;
-	}
-
-	const T_VFSPath path( input[ 0 ].stringValue( ) );
-	if ( path.type( ) != E_VFSPathType::ABSOLUTE ) {
-		data.addError( input[ 0 ] , "absolute VFS path expected" );
-		return;
-	}
-
-	T_Array< T_VFSPath > list( 32 );
-	if ( !vfs_.list( path , list ) ) {
-		return;
-	}
-
-	const uint32_t n( list.size( ) );
-	T_SRDList output( std::max( 1u , n ) );
-	output.ensureCapacity( n );
-	for ( uint32_t i = 0 ; i < n ; i ++ ) {
-		output.add( T_SRDToken::String( T_String( list[ i ] ) ) );
-	}
-
-	auto otok( T_SRDToken::List( std::move( output ) ) );
-	otok.location( loc );
-	data.top( ).output( ).add( std::move( otok ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( VFSLoad )
-{
-	auto& input( state.output( ) );
-	auto& data( state.data( ) );
-	auto const& loc( *state.initialLocation( ) );
-
-	if ( input.size( ) == 0 ) {
-		data.addError( loc , "not enough arguments" );
-		return;
-	}
-	if ( input.size( ) > 1 ) {
-		data.addError( loc , "too many arguments" );
-		return;
-	}
-	if ( input[ 0 ].type( ) != E_SRDTokenType::STRING ) {
-		data.addError( input[ 0 ] , "string expected" );
-		return;
-	}
-
-	const T_VFSPath path( input[ 0 ].stringValue( ) );
-	if ( path.type( ) != E_VFSPathType::ABSOLUTE ) {
-		data.addError( input[ 0 ] , "absolute VFS path expected" );
-		return;
-	}
-
-	const OP_InputStream istream( vfs_.read( path ) );
-	if ( !istream ) {
-		T_StringBuilder sb( "error while loading '" );
-		sb << T_String( path ) << "': file not found";
-		data.addError( input[ 0 ] , std::move( sb ) );
-		return;
-	}
-
-	T_SharedPtr< T_Buffer< uint8_t > > buffer;
-	try {
-		if ( istream->isSizeKnown( ) ) {
-			const auto sz( istream->size( ) );
-			buffer = NewShared< T_Buffer< uint8_t > >( sz );
-			if ( sz ) {
-				istream->read( buffer->data( ) , sz );
-			}
-		} else {
-			uint8_t temp[ 4096 ];
-			buffer = NewShared< T_Buffer< uint8_t > >( );
-			try {
-				while ( 1 ) {
-					const auto nRead( istream->read( temp , sizeof( temp ) ) );
-					const auto prevSize( buffer->size( ) );
-					assert( nRead > 0 );
-					buffer->resize( prevSize + nRead );
-					memcpy( buffer->data( ) + prevSize , temp , nRead );
-				}
-			} catch ( X_StreamError const& error ) {
-				if ( error.code( ) != E_StreamError::END ) {
-					throw;
-				}
-			}
-		}
-	} catch ( X_StreamError const& error ) {
-		T_StringBuilder sb( "error while loading '" );
-		sb << T_String( path ) << "': " << error.what( );
-		data.addError( input[ 0 ] , std::move( sb ) );
-	}
-
-	auto otok( T_SRDToken::Binary( buffer ) );
-	otok.location( loc );
-	data.top( ).output( ).add( std::move( otok ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_SRDPP_COMMAND_EXEC( VFSType )
-{
-	auto& input( state.output( ) );
-	auto& data( state.data( ) );
-
-	const auto is( input.size( ) );
-	if ( is == 0 ) {
-		return;
-	}
-
-	T_Array< T_VFSPath > paths( 4 );
-	paths.ensureCapacity( is );
-	for ( uint32_t i = 0 ; i < is ; i ++ ) {
-		if ( input[ i ].type( ) != E_SRDTokenType::STRING ) {
-			data.addError( input[ i ] , "string expected" );
-			return;
-		}
-
-		T_VFSPath const& path( paths.addNew( input[ i ].stringValue( ) ) );
-		if ( path.type( ) != E_VFSPathType::ABSOLUTE ) {
-			data.addError( input[ i ] , "absolute VFS path expected" );
-			return;
-		}
-	}
-
-	auto& out( data.top( ).output( ) );
-	for ( uint32_t i = 0 ; i < is ; i ++ ) {
-		const E_VFSEntryType et( vfs_.typeOf( paths[ i ] ) );
-		T_SRDToken token( ( []( E_VFSEntryType et ) {
-			switch ( et ) {
-			    case E_VFSEntryType::NONE:
-				return T_SRDToken::Word( T_String::Pooled( "none" ) );
-
-			    case E_VFSEntryType::FILE:
-				return T_SRDToken::Word( T_String::Pooled( "file" ) );
-
-			    case E_VFSEntryType::DIRECTORY:
-				return T_SRDToken::Word( T_String::Pooled( "directory" ) );
-
-			    case E_VFSEntryType::OTHER:
-				return T_SRDToken::Word( T_String::Pooled( "other" ) );
-			}
-			return T_SRDToken::Word( T_String::Pooled( "unknown" ) );
-		})( et ) );
-		token.copyLocationOf( input[ i ] );
-		out.add( std::move( token ) );
-	}
-}
diff --git a/src/SRDParser.cc b/src/SRDParser.cc
index 2858ba3..fe1eea4 100644
--- a/src/SRDParser.cc
+++ b/src/SRDParser.cc
@@ -3,8 +3,8 @@
 /******************************************************************************/
 
 
-#include <lw/lib/SRDParser.hh>
-using namespace lw;
+#include <ebcl/SRDParser.hh>
+using namespace ebcl;
 
 
 /*= T_SRDParserData ==========================================================*/
diff --git a/src/SRDParserConfig.cc b/src/SRDParserConfig.cc
index bb5b0c4..b8d8644 100644
--- a/src/SRDParserConfig.cc
+++ b/src/SRDParserConfig.cc
@@ -2,8 +2,8 @@
 /* SRD - PARSER CONFIGURATION *************************************************/
 /******************************************************************************/
 
-#include <lw/lib/SRDParserConfig.hh>
-using namespace lw;
+#include <ebcl/SRDParserConfig.hh>
+using namespace ebcl;
 
 namespace {
 
diff --git a/src/SRDPreproc.cc b/src/SRDPreproc.cc
deleted file mode 100644
index 1909be8..0000000
--- a/src/SRDPreproc.cc
+++ /dev/null
@@ -1,1416 +0,0 @@
-/******************************************************************************/
-/* SRD - PREPROCESSOR *********************************************************/
-/******************************************************************************/
-
-#include <lw/lib/SRDPreproc.hh>
-#include <lw/lib/Alloc.hh>
-#include <lw/lib/Config.hh>
-using namespace lw;
-
-
-/*= A_SRDPreprocessorCommand =================================================*/
-
-A_SRDPreprocessorCommand::~A_SRDPreprocessorCommand( )
-{ }
-
-
-/*= T_SRDPreprocessorConfig ==================================================*/
-
-T_SRDPreprocessorConfig::T_SRDPreprocessorConfig( )
-	: commands_( []( OP_SRDPreprocessorCommand const& cmd ) -> T_String const& {
-		return cmd->command( );
-	} )
-{ }
-
-T_SRDPreprocessorConfig& T_SRDPreprocessorConfig::add(
-		OP_SRDPreprocessorCommand&& command )
-{
-	commands_.add( std::move( command ) );
-	return *this;
-}
-
-RPC_SRDPreprocessorCommand T_SRDPreprocessorConfig::command(
-		T_String const& name ) const
-{
-	const auto cmd( commands_.get( name ) );
-	if ( cmd == nullptr ) {
-		return nullptr;
-	}
-	return cmd->get( );
-}
-
-
-/*= T_SRDPPStateImpl_ ========================================================*/
-
-namespace {
-struct T_SRDPPStateImpl_
-{
-	using E_Type = T_SRDPreprocessorState::E_Type;
-
-	// ---------------------------------------------------------------------
-
-	T_SRDPreprocessorData& data_;
-
-	SP_SRDList input_;
-	uint32_t pos_;
-
-	SP_SRDList output_;
-	SP_SRDLocation initialLocation_;
-
-	F_SRDPreprocessorHandler postExec_;
-
-	uint32_t processLimit_;
-	bool rawMode_;
-	T_Array< T_SRDToken > rawStack_;
-
-	T_SRDPreprocessorState::E_Type type_;
-	uint8_t exiting_;
-
-	// ---------------------------------------------------------------------
-
-	explicit T_SRDPPStateImpl_(
-			T_SRDPreprocessorData& data ) noexcept;
-
-	T_SRDPPStateImpl_(
-			T_SRDPreprocessorData& data ,
-			E_Type type ,
-			SP_SRDList&& input ) noexcept;
-
-	T_SRDPPStateImpl_(
-			T_SRDPreprocessorData& data ,
-			E_Type type ,
-			SP_SRDList&& input ,
-			SP_SRDList&& output ,
-			F_SRDPreprocessorHandler postExec ) noexcept;
-
-	// ---------------------------------------------------------------------
-};
-}
-
-/*----------------------------------------------------------------------------*/
-
-inline T_SRDPPStateImpl_::T_SRDPPStateImpl_(
-			T_SRDPreprocessorData& data ) noexcept
-	: T_SRDPPStateImpl_( data , T_SRDPreprocessorState::C_UNSPECIFIED , {} )
-{ }
-
-inline T_SRDPPStateImpl_::T_SRDPPStateImpl_(
-			T_SRDPreprocessorData& data ,
-			const E_Type type ,
-			SP_SRDList&& input ) noexcept
-	: T_SRDPPStateImpl_( data , type , std::move( input ) ,
-			NewShared< T_SRDList >( 32 ) , {} )
-{ }
-
-inline T_SRDPPStateImpl_::T_SRDPPStateImpl_(
-			T_SRDPreprocessorData& data ,
-			const E_Type type ,
-			SP_SRDList&& input ,
-			SP_SRDList&& output ,
-			F_SRDPreprocessorHandler postExec ) noexcept
-	: data_( data ) ,
-		//
-		input_( std::move( input ) ) ,
-		pos_( 0 ) ,
-		//
-		output_( std::move( output ) ) ,
-		initialLocation_( ) ,
-		//
-		postExec_( postExec ) ,
-		//
-		processLimit_( UINT32_MAX ) ,
-		rawMode_( false ) ,
-		rawStack_( 16 ) ,
-		//
-		type_( type ) ,
-		exiting_( 0 )
-{ }
-
-
-
-/*= T_SRDPreprocessorState ===================================================*/
-
-T_SRDPreprocessorState::T_SRDPreprocessorState(
-		T_SRDPreprocessorData& data )
-	: A_PrivateImplementation( new T_SRDPPStateImpl_( data ) )
-{ }
-
-T_SRDPreprocessorState::T_SRDPreprocessorState(
-		T_SRDPreprocessorData& data ,
-		const E_Type type ,
-		SP_SRDList input )
-	: A_PrivateImplementation( new T_SRDPPStateImpl_(
-				data , type , std::move( input ) ) )
-{ }
-
-T_SRDPreprocessorState::T_SRDPreprocessorState(
-		T_SRDPreprocessorData& data ,
-		const E_Type type ,
-		SP_SRDList input ,
-		SP_SRDList output ,
-		F_SRDPreprocessorHandler postExec )
-	: A_PrivateImplementation( new T_SRDPPStateImpl_(
-				data , type , std::move( input ) ,
-				std::move( output ) , postExec ) )
-{ }
-
-/*----------------------------------------------------------------------------*/
-
-T_SRDPreprocessorData& T_SRDPreprocessorState::data( ) const
-{
-	return p< T_SRDPPStateImpl_ >( ).data_;
-}
-
-bool T_SRDPreprocessorState::hasInput( ) const
-{
-	return bool( p< T_SRDPPStateImpl_ >( ).input_ );
-}
-
-bool T_SRDPreprocessorState::isFinished( ) const
-{
-	auto const& pi( p< T_SRDPPStateImpl_ >( ) );
-	return !pi.input_ || pi.pos_ >= pi.input_->size( );
-}
-
-T_SRDList& T_SRDPreprocessorState::output( ) const
-{
-	return *( p< T_SRDPPStateImpl_ >( ).output_ );
-}
-
-SP_SRDList const& T_SRDPreprocessorState::outputPointer( ) const
-{
-	return p< T_SRDPPStateImpl_ >( ).output_;
-}
-
-RPC_SRDLocation T_SRDPreprocessorState::initialLocation( ) const
-{
-	return RPC_SRDLocation( p< T_SRDPPStateImpl_ >( ).initialLocation_ );
-}
-
-T_SRDPreprocessorState::E_Type T_SRDPreprocessorState::type( ) const
-{
-	return p< T_SRDPPStateImpl_ >( ).type_;
-}
-
-void T_SRDPreprocessorState::setExiting( E_Type type )
-{
-	auto& e( p< T_SRDPPStateImpl_ >( ).exiting_ );
-	e = e | uint8_t( type );
-}
-
-uint8_t T_SRDPreprocessorState::isExiting( ) const
-{
-	return p< T_SRDPPStateImpl_ >( ).exiting_;
-}
-
-/*----------------------------------------------------------------------------*/
-
-SP_SRDLocation T_SRDPreprocessorState::createChainedLocation( ) const
-{
-	auto& pi( p< T_SRDPPStateImpl_ >( ) );
-	SP_SRDLocation cloc( pi.data_.callLocation( ) );
-	if ( pi.initialLocation_ && cloc ) {
-		SP_SRDLocation location( NewShared< T_SRDLocation >( *pi.initialLocation_ ) );
-		if ( location->isChained( ) ) {
-			auto& lc( location->chaining( ) );
-			SP_SRDLocation ptrInitial( cloc );
-			SP_SRDLocation ptrNew( NewShared< T_SRDLocation >( *cloc ) );
-			cloc = ptrNew;
-			while ( ptrInitial ) {
-				if ( ptrInitial->isChained( ) ) {
-					auto& chain( ptrInitial->chaining( ) );
-					SP_SRDLocation ptrNext( NewShared< T_SRDLocation >(
-								*( chain.location ) ) );
-					if ( chain.depth > 1 ) {
-						ptrNew->chain( chain.circumstances , chain.depth , ptrNext );
-					} else {
-						ptrNew->chain( chain.circumstances , ptrNext );
-					}
-					ptrNew = ptrNext;
-					ptrInitial = chain.location;
-				} else {
-					if ( lc.depth > 1 ) {
-						ptrNew->chain( lc.circumstances , lc.depth , lc.location );
-					} else {
-						ptrNew->chain( lc.circumstances , lc.location );
-					}
-					ptrInitial = SP_SRDLocation( );
-				}
-			}
-		}
-		location->chain( E_SRDLocationChaining::CALLED , pi.data_.callRecursionDepth( ) , cloc );
-		return location;
-	} else if ( pi.initialLocation_ ) {
-		return pi.initialLocation_;
-	} else {
-		return cloc;
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-void T_SRDPreprocessorState::processToken(
-		T_SRDToken& token )
-{
-	auto& pi( p< T_SRDPPStateImpl_ >( ) );
-	if ( token.type( ) != E_SRDTokenType::COMMENT
-			&& ( ( pi.rawMode_ && handleRaw( token ) )
-				|| ( !pi.rawMode_ && handleProcessed( token ) ) ) ) {
-		return;
-	}
-	pi.pos_ ++;
-	if ( pi.pos_ >= pi.processLimit_ ) {
-		pi.rawMode_ = true;
-	}
-}
-
-void T_SRDPreprocessorState::processNext( )
-{
-	auto& pi( p< T_SRDPPStateImpl_ >( ) );
-	assert( pi.input_ );
-	assert( pi.pos_ < pi.input_->size( ) );
-	processToken( (*pi.input_)[ pi.pos_ ] );
-}
-
-void T_SRDPreprocessorState::checkUnterminated(
-		T_SRDErrors& errors ) const
-{
-	auto& pi( p< T_SRDPPStateImpl_ >( ) );
-	if ( !pi.rawMode_ ) {
-		return;
-	}
-
-	auto const rss( pi.rawStack_.size( ) );
-	for ( uint32_t i = 0 ; i < rss ; i ++ ) {
-		auto const& item( pi.rawStack_[ i ] );
-		errors.add( "unterminated list" , item.location( ) );
-	}
-}
-
-void T_SRDPreprocessorState::terminate( )
-{
-	// We need to store this so the current instance lives on until we exit
-	// the method.
-	auto& pi( p< T_SRDPPStateImpl_ >( ) );
-	auto se( pi.data_.pop( ) );
-	assert( RP_SRDPreprocessorState( se ) == this );
-	if ( pi.postExec_ ) {
-		try {
-			pi.postExec_( *this );
-		} catch ( X_SRDErrors const& ) {
-			pi.data_.interrupt( C_TRY );
-		}
-	}
-}
-
-bool T_SRDPreprocessorState::handleRaw(
-		T_SRDToken& token )
-{
-	auto& pi( p< T_SRDPPStateImpl_ >( ) );
-	const auto tt( token.type( ) );
-
-	if ( tt == E_SRDTokenType::START ) {
-		T_SRDToken& top( pi.rawStack_[
-				pi.rawStack_.add( T_SRDToken::List( ) ) ] );
-		top.copyLocationOf( token );
-		return false;
-	}
-
-	const uint32_t ss( pi.rawStack_.size( ) );
-	if ( tt == E_SRDTokenType::END ) {
-		if ( ss == 0 ) {
-			terminate( );
-			return true;
-		}
-
-		const uint32_t last( ss - 1 );
-		T_SRDToken top( std::move( pi.rawStack_[ last ] ) );
-		pi.rawStack_.remove( last );
-		if ( last != 0 ) {
-			pi.rawStack_[ last - 1 ].list( ).add( std::move( top ) );
-		} else {
-			pi.output_->add( std::move( top ) );
-		}
-		return false;
-	}
-
-	if ( ss != 0 ) {
-		pi.rawStack_[ ss - 1 ].list( ).add( std::move( token ) );
-	} else {
-		pi.output_->add( std::move( token ) );
-	}
-	return false;
-}
-
-bool T_SRDPreprocessorState::handleProcessed(
-		T_SRDToken& token )
-{
-	auto& pi( p< T_SRDPPStateImpl_ >( ) );
-	const auto tt( token.type( ) );
-
-	// Lists that have already been processed
-	if ( tt == E_SRDTokenType::LIST ) {
-		T_SRDPreprocessorState& nState(
-				pi.data_.push( C_UNSPECIFIED ,
-					   NewShared< T_SRDList >( std::move( token.list( ) ) ) ,
-					   NewShared< T_SRDList >( ) ,
-					   &T_SRDPreprocessorState::handleEndOfList ) );
-		nState.p< T_SRDPPStateImpl_ >( ).initialLocation_ = NewShared< T_SRDLocation >( token.location( ) );
-		return false;
-	}
-
-	// Start of unprocessed list
-	if ( tt == E_SRDTokenType::START ) {
-		T_SRDPreprocessorState& nState( pi.data_.push( ) );
-		auto& npi( nState.p< T_SRDPPStateImpl_ >( ) );
-		npi.postExec_ = &T_SRDPreprocessorState::handleEndOfList;
-		npi.initialLocation_ = NewShared< T_SRDLocation >( token.location( ) );
-		return false;
-	}
-
-	// End of unprocessed list
-	if ( tt == E_SRDTokenType::END ) {
-		terminate( );
-		return true;
-	}
-
-	// Variables and calls
-	if ( tt == E_SRDTokenType::VAR ) {
-		handleVariable( token );
-		return false;
-	}
-
-	// Macros, commands and words at the start of a list
-	if ( tt == E_SRDTokenType::WORD && pi.pos_ == 0
-			&& !pi.data_.topLevel( ) && pi.type_ == C_UNSPECIFIED
-			&& checkCommandsAndMacros( token ) ) {
-		return false;
-	}
-
-	// Otherwise simply copy the token
-	pi.output_->addNew( std::move( token ) );
-	return false;
-}
-
-/*----------------------------------------------------------------------------*/
-
-void T_SRDPreprocessorState::handleVariable(
-		T_SRDToken& token )
-{
-	auto& pi( p< T_SRDPPStateImpl_ >( ) );
-	auto const& s( pi.data_.scopes( ) );
-	auto const& vn( token.stringValue( ) );
-	RPC_SRDList var( s.get( false , vn ) );
-	if ( var == nullptr ) {
-		try {
-			pi.data_.addError( token , "unknown variable" );
-		} catch ( X_SRDErrors const& ) {
-			pi.data_.interrupt( C_TRY );
-		}
-	} else if ( pi.type_ == C_UNSPECIFIED && pi.pos_ == 0
-			&& s.isBlessed( vn ) ) {
-		initFunctionCall( ( *var )[ 0 ].list( ) );
-	} else {
-		pi.output_->addAll( *var );
-	}
-}
-
-bool T_SRDPreprocessorState::checkCommandsAndMacros(
-		T_SRDToken& token )
-{
-	auto& pi( p< T_SRDPPStateImpl_ >( ) );
-	auto const& cfg( pi.data_.preprocessor( ).config( ) );
-	RPC_SRDPreprocessorCommand cmd( cfg.command( token.stringValue( ) ) );
-	if ( cmd != nullptr ) {
-		const auto pl( cmd->processArgs( ) );
-		if ( pl != UINT32_MAX ) {
-			pi.processLimit_ = 1 + pl;
-		}
-		pi.postExec_ = [cmd]( T_SRDPreprocessorState& state ) {
-				    cmd->execute( state );
-			    };
-		return true;
-	}
-
-	RPC_SRDList macro( pi.data_.scopes( ).get( true , token.stringValue( ) ) );
-	if ( macro != nullptr ) {
-		initMacro( *macro );
-		return true;
-	}
-
-	if ( token.stringValue( )[ 0 ] == '-' ) {
-		try {
-			pi.data_.addError( token , "unknown command" );
-		} catch ( X_SRDErrors const& ) {
-			pi.data_.interrupt( C_TRY );
-		}
-		return true;
-	}
-
-	return false;
-}
-
-/*----------------------------------------------------------------------------*/
-
-void T_SRDPreprocessorState::initFunctionCall(
-		T_SRDList const& function )
-{
-	assert( function.size( ) > 0 );
-	assert( function[ 0 ].type( ) == E_SRDTokenType::LIST );
-
-	p< T_SRDPPStateImpl_ >( ).postExec_ = [&]( T_SRDPreprocessorState& state ) {
-		const uint32_t fSize( function.size( ) );
-		T_SRDToken arguments( function[ 0 ] );
-		SP_SRDList body( NewShared< T_SRDList >( fSize > 1 ? ( fSize - 1 ) : 1 ) );
-		for ( uint32_t i = 1 ; i < fSize ; i ++ ) {
-			body->add( function[ i ] );
-		}
-
-		auto& sp( state.p< T_SRDPPStateImpl_ >( ) );
-		auto& data( sp.data_ );
-		auto const& args( arguments.list( ) );
-		if ( !state.checkCallArguments( args ) ) {
-			return;
-		}
-
-		data.pushCallLocation( sp.initialLocation_ );
-		data.scopes( ).setupCallScope( args , *sp.output_ );
-		data.push( C_CALL , body , NewShared< T_SRDList >( ) ,
-			[]( T_SRDPreprocessorState& ns ) {
-				auto& nsp( ns.p< T_SRDPPStateImpl_ >( ) );
-				auto& data( nsp.data_ );
-				data.scopes( ).exit( );
-
-				const auto callDepth( data.callRecursionDepth( ) );
-				SP_SRDLocation initialLocation( data.popCallLocation( ) );
-				auto& output( data.top( ).output( ) );
-				auto& input( ns.output( ) );
-				const auto is( input.size( ) );
-				for ( size_t i = 0 ; i < is ; i ++ ) {
-					T_SRDToken token( std::move( input[ i ] ) );
-					auto& loc( token.location( ) );
-					if ( !loc.isChained( ) ) {
-						SP_SRDLocation gLoc( NewShared< T_SRDLocation >( loc ) );
-						gLoc->chain( E_SRDLocationChaining::CALLED , callDepth ,
-								initialLocation );
-						loc.chain( E_SRDLocationChaining::GENERATED , gLoc );
-					}
-					output.add( std::move( token ) );
-				}
-			} );
-		};
-}
-
-void T_SRDPreprocessorState::initMacro(
-		T_SRDList const& macro )
-{
-	assert( macro.size( ) > 0 );
-	assert( macro[ 0 ].type( ) == E_SRDTokenType::LIST );
-
-	auto& pi( p< T_SRDPPStateImpl_ >( ) );
-	pi.rawMode_ = true;
-	pi.postExec_ = [&]( T_SRDPreprocessorState& state ) {
-		const uint32_t mSize( macro.size( ) );
-		T_SRDToken arguments( macro[ 0 ] );
-		SP_SRDList body( NewShared< T_SRDList >(
-				mSize > 1 ? ( mSize - 1 ) : 1 ) );
-		for ( uint32_t i = 1 ; i < mSize ; i ++ ) {
-			body->add( macro[ i ] );
-		}
-
-		auto& sp( state.p< T_SRDPPStateImpl_ >( ) );
-		auto& data( sp.data_ );
-		auto const& args( arguments.list( ) );
-		if ( !state.checkCallArguments( args ) ) {
-			return;
-		}
-
-		SP_SRDLocation evalLocation( sp.initialLocation_ );
-		data.pushCallLocation( sp.initialLocation_ );
-		data.scopes( ).setupCallScope( args , *sp.output_ );
-		data.push( C_CALL , body , NewShared< T_SRDList >( ) ,
-			[evalLocation]( T_SRDPreprocessorState& ns ) {
-				// Process the macro's output
-				auto& nsp( ns.p< T_SRDPPStateImpl_ >( ) );
-				auto& data( nsp.data_ );
-				data.scopes( ).exit( );
-
-				const uint32_t depth( data.callRecursionDepth( ) );
-				SP_SRDLocation callLocation( data.popCallLocation( ) );
-				SP_SRDList updated( NewShared< T_SRDList >( nsp.output_->size( )
-							? nsp.output_->size( ) : 1 ) );
-				auto& input( ns.output( ) );
-				const auto is( input.size( ) );
-				for ( size_t i = 0 ; i < is ; i ++ ) {
-					T_SRDToken token( std::move( input[ i ] ) );
-					auto& loc( token.location( ) );
-					SP_SRDLocation el( NewShared< T_SRDLocation >( *evalLocation ) );
-					if ( loc.isChained( ) ) {
-						auto const& lc( loc.chaining( ) );
-						el->chain( lc.circumstances , lc.location );
-					} else {
-						SP_SRDLocation gen( NewShared< T_SRDLocation >( loc ) );
-						gen->chain( E_SRDLocationChaining::CALLED ,
-								depth , callLocation );
-						el->chain( E_SRDLocationChaining::GENERATED , gen );
-					}
-					loc.chain( E_SRDLocationChaining::EVALUATED , el );
-					updated->add( std::move( token ) );
-				}
-
-				data.push( T_SRDPreprocessorState::C_UNSPECIFIED ,
-						updated , data.top( ).outputPointer( ) );
-			} );
-	};
-}
-
-bool T_SRDPreprocessorState::checkCallArguments(
-		T_SRDList const& spec ) const
-{
-	auto const& pi( p< T_SRDPPStateImpl_ >( ) );
-	const bool hasOptArgs( spec.size( ) > 0
-		&& spec[ spec.size( ) - 1 ].type( ) == E_SRDTokenType::LIST );
-	const uint32_t reqArgs( spec.size( ) - ( hasOptArgs ? 1 : 0 ) );
-	auto const& argVals( *pi.output_ );
-	if ( argVals.size( ) < reqArgs ) {
-		p< T_SRDPPStateImpl_ >( ).data_.addError(
-			*pi.initialLocation_ , "not enough arguments" );
-		return false;
-	}
-	if ( argVals.size( ) > reqArgs && !hasOptArgs ) {
-		p< T_SRDPPStateImpl_ >( ).data_.addError(
-			*pi.initialLocation_ , "too many arguments" );
-		return false;
-	}
-	return true;
-}
-
-/*----------------------------------------------------------------------------*/
-
-void T_SRDPreprocessorState::handleEndOfList(
-		T_SRDPreprocessorState& state )
-{
-	auto& spi( state.p< T_SRDPPStateImpl_ >( ) );
-	auto& output( *( spi.data_.top( ).p< T_SRDPPStateImpl_ >( ).output_ ) );
-	uint32_t const pos( output.add( T_SRDToken::List( std::move( *spi.output_ ) ) ) );
-	output[ pos ].location( std::move( *spi.initialLocation_ ) );
-}
-
-
-/*= T_SRDPreprocessorScopes ==================================================*/
-
-constexpr char T_SRDPreprocessorScopes::C_SET_;
-constexpr char T_SRDPreprocessorScopes::C_BLESSED_;
-
-T_SRDPreprocessorScopes::T_SRDPreprocessorScopes( )
-	: depth_( 0 )
-{ }
-
-/*----------------------------------------------------------------------------*/
-
-void T_SRDPreprocessorScopes::exit( )
-{
-	assert( depth_ > 0 );
-
-	// Find all items for the current depth
-	const uint32_t size( itemDepth_.size( ) );
-	const uint32_t nItems( ( [&]() {
-		uint32_t nItems( 0 );
-		while ( size - nItems > 0 && itemDepth_[ size - nItems - 1 ] == depth_ ) {
-			nItems ++;
-		}
-		return nItems;
-	} )( ) );
-
-	// Remove items
-	for ( uint32_t i = 0 ; i < nItems ; i ++ ) {
-		const uint32_t ii( size - i - 1 );
-		const uint32_t mainIndex( reverse_[ ii ] );
-		const uint32_t chain( chain_[ ii ] );
-
-		// We're always removing from the end of the array, so removeSwap
-		// isn't needed.
-		if ( chain == T_HashIndex::INVALID_INDEX ) {
-			index_.remove( mainIndex );
-			keys_.remove( mainIndex );
-			indices_.remove( mainIndex );
-		} else {
-			reverse_[ chain ] = mainIndex;
-			indices_[ mainIndex ] = chain;
-		}
-
-		itemDepth_.remove( ii );
-		chain_.remove( ii );
-		reverse_.remove( ii );
-		flags_.remove( ii );
-		contents_.remove( ii );
-	}
-
-	depth_ --;
-}
-
-void T_SRDPreprocessorScopes::clear( )
-{
-	if ( depth_ == 0 ) {
-		index_.clear( );
-		keys_.clear( );
-		indices_.clear( );
-		itemDepth_.clear( );
-		chain_.clear( );
-		reverse_.clear( );
-		flags_.clear( );
-		contents_.clear( );
-		return;
-	}
-
-	const uint32_t nEntries( keys_.size( ) );
-	for ( uint32_t i = 0 ; i < nEntries ; i ++ ) {
-		const uint32_t idx( indices_[ i ] );
-		if ( ( flags_[ idx ] & C_SET_ ) == 0 ) {
-			continue;
-		}
-
-		if ( itemDepth_[ idx ] == depth_ ) {
-			flags_[ idx ] = 0;
-			contents_[ idx ] = NewShared< T_SRDList >( );
-		} else {
-			addChained( i , idx , 0 , NewShared< T_SRDList >( ) );
-		}
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-void T_SRDPreprocessorScopes::setupCallScope(
-		T_SRDList const& spec ,
-		T_SRDList const& values ,
-		uint32_t start )
-{
-	const uint32_t nEntries( indices_.size( ) );
-	enter( );
-
-	// Add parameters
-	const auto nSpec( spec.size( ) );
-	for ( uint32_t i = 0 ; i < nSpec ; i ++ ) {
-		auto const& argSpec( spec[ i ] );
-
-		if ( argSpec.type( ) == E_SRDTokenType::WORD ) {
-			assert( i < values.size( ) );
-			bool ok( set( false , argSpec.stringValue( ) , values ,
-						i + start , i + start ) );
-			assert( ok );
-			continue;
-		}
-
-		assert( argSpec.type( ) == E_SRDTokenType::LIST
-				&& i == nSpec - 1 );
-
-		T_SRDList const& optArgs( argSpec.list( ) );
-		const auto nOpt( optArgs.size( ) );
-		for ( uint32_t j = 0 ; j < nOpt ; j ++ ) {
-			auto const& optArg( optArgs[ j ] );
-			assert( optArg.type( ) == E_SRDTokenType::WORD );
-
-			bool ok( set( false , optArg.stringValue( ) ,
-					values , i + j + start ,
-					j == nOpt - 1 ? UINT32_MAX : i + j + start ) );
-			assert( ok );
-		}
-	}
-
-	// Hide all variables from previous scopes
-	for ( uint32_t i = 0 ; i < nEntries ; i ++ ) {
-		if ( keys_[ i ].first ) {
-			continue;
-		}
-
-		const uint32_t index( indices_[ i ] );
-		if ( itemDepth_[ index ] == depth_ ) {
-			continue;
-		}
-
-		const char flags( flags_[ index ] );
-		if ( ( flags & C_SET_ ) == 0 || ( flags & C_BLESSED_ ) != 0 ) {
-			continue;
-		}
-		addChained( i , index , 0 , NewShared< T_SRDList >( ) );
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-RPC_SRDList T_SRDPreprocessorScopes::get(
-		const bool macro ,
-		T_String const& name ) const
-{
-	const uint32_t idx( find( macro , name ) );
-	if ( idx == T_HashIndex::INVALID_INDEX ) {
-		return nullptr;
-	}
-	const uint32_t vIndex( indices_[ idx ] );
-	if ( ( flags_[ vIndex ] & C_SET_ ) == 0 ) {
-		return nullptr;
-	}
-	return RPC_SRDList( contents_[ vIndex ] );
-}
-
-bool T_SRDPreprocessorScopes::canSet(
-		const bool macro ,
-		T_String const& name ) const
-{
-	const uint32_t idx( find( macro , name ) );
-	if ( idx == T_HashIndex::INVALID_INDEX ) {
-		return true;
-	}
-	const uint32_t vIndex( indices_[ idx ] );
-	return ( itemDepth_[ vIndex ] != depth_
-			|| ( flags_[ vIndex ] & C_SET_ ) == 0 );
-}
-
-/*----------------------------------------------------------------------------*/
-
-bool T_SRDPreprocessorScopes::set(
-		const bool macro ,
-		T_String const& name ,
-		T_SRDList const& value ,
-		const uint32_t from ,
-		const uint32_t to )
-{
-	const uint32_t hash( ComputeHash( name ) ^ ( macro ? 0x55555555 : 0 ) );
-	const uint32_t idx( find( hash , macro , name ) );
-
-	// If no entry exists, create a new one
-	if ( idx == T_HashIndex::INVALID_INDEX ) {
-		index_.add( hash );
-
-		const uint32_t mainIndex( keys_.size( ) );
-		keys_.add( std::pair< bool , T_String >( macro , name ) );
-		indices_.add( itemDepth_.size( ) );
-
-		itemDepth_.add( depth_ );
-		chain_.add( T_HashIndex::INVALID_INDEX );
-		reverse_.add( mainIndex );
-		flags_.add( C_SET_ );
-		contents_.add( NewShared< T_SRDList >(
-					value.copyRange( from , to ) ) );
-		return true;
-	}
-
-	const uint32_t previous( indices_[ idx ] );
-
-	// If there's an entry at the current depth, try to update it.
-	if ( itemDepth_[ previous ] == depth_ ) {
-		if ( ( flags_[ previous ] & C_SET_ ) != 0 ) {
-			return false;
-		}
-		flags_[ previous ] = C_SET_;
-		contents_[ previous ] = NewShared< T_SRDList >(
-				value.copyRange( from , to ) );
-		return true;
-	}
-
-	// Otherwise we need to chain it
-	addChained( idx , previous , C_SET_ , NewShared< T_SRDList >(
-				value.copyRange( from , to ) ) );
-	return true;
-}
-
-bool T_SRDPreprocessorScopes::unset(
-		const bool macro ,
-		T_String const& name )
-{
-	const uint32_t idx( find( macro , name ) );
-	if ( idx == T_HashIndex::INVALID_INDEX ) {
-		return false;
-	}
-	const uint32_t vIndex( indices_[ idx ] );
-	if ( ( flags_[ vIndex ] & C_SET_ ) == 0 ) {
-		return false;
-	}
-	if ( itemDepth_[ vIndex ] == depth_ ) {
-		if ( depth_ == 0 ) {
-			removeItem( idx );
-		} else {
-			contents_[ vIndex ] = NewShared< T_SRDList >( );
-			flags_[ vIndex ] = 0;
-		}
-		return true;
-	}
-	addChained( idx , vIndex , 0 , NewShared< T_SRDList >( ) );
-	return true;
-}
-
-/*----------------------------------------------------------------------------*/
-
-bool T_SRDPreprocessorScopes::isBlessed(
-		T_String const& name ) const
-{
-	const uint32_t idx( find( false , name ) );
-	if ( idx == T_HashIndex::INVALID_INDEX ) {
-		return false;
-	}
-	const uint32_t vIndex( indices_[ idx ] );
-	return ( ( flags_[ vIndex ] & C_BLESSED_ ) != 0 );
-}
-
-bool T_SRDPreprocessorScopes::bless(
-		T_String const& name )
-{
-	const uint32_t idx( find( false , name ) );
-	if ( idx == T_HashIndex::INVALID_INDEX ) {
-		return false;
-	}
-	
-	const uint32_t vIndex( indices_[ idx ] );
-	const char cFlags( flags_[ vIndex ] );
-	if ( ( cFlags & C_SET_ ) == 0 || ( cFlags & C_BLESSED_ ) != 0 ) {
-		return false;
-	}
-	
-	if ( itemDepth_[ vIndex ] == depth_ ) {
-		flags_[ vIndex ] = cFlags | C_BLESSED_;
-	} else {
-		addChained( idx , vIndex , cFlags | C_BLESSED_ , NewShared< T_SRDList >( contents_[ vIndex ] ) );
-	}
-	return true;
-}
-
-/*----------------------------------------------------------------------------*/
-
-T_Array< T_String > T_SRDPreprocessorScopes::list(
-		const bool macros ) const
-{
-	T_Array< T_String > result;
-	const uint32_t nEntries( keys_.size( ) );
-	for ( uint32_t i = 0 ; i < nEntries ; i ++ ) {
-		auto const& k( keys_[ i ] );
-		if ( k.first != macros ) {
-			continue;
-		}
-		if ( ( flags_[ indices_[ i ] ] & C_SET_ ) == 0 ) {
-			continue;
-		}
-		result.add( k.second );
-	}
-	return result;
-}
-
-/*----------------------------------------------------------------------------*/
-
-uint32_t T_SRDPreprocessorScopes::find(
-		const bool macro ,
-		T_String const& name ) const
-{
-	const uint32_t hash( ComputeHash( name ) ^ ( macro ? 0x55555555 : 0 ) );
-	uint32_t idx = index_.first( hash );
-	while ( idx != T_HashIndex::INVALID_INDEX ) {
-		auto const& key( keys_[ idx ] );
-		if ( key.first == macro && key.second == name ) {
-			break;
-		}
-		idx = index_.next( idx );
-	}
-	return idx;
-}
-
-uint32_t T_SRDPreprocessorScopes::find(
-		const uint32_t hash ,
-		const bool macro ,
-		T_String const& name ) const
-{
-	uint32_t idx = index_.first( hash );
-	while ( idx != T_HashIndex::INVALID_INDEX ) {
-		auto const& key( keys_[ idx ] );
-		if ( key.first == macro && key.second == name ) {
-			break;
-		}
-		idx = index_.next( idx );
-	}
-	return idx;
-}
-
-/*----------------------------------------------------------------------------*/
-
-void T_SRDPreprocessorScopes::addChained(
-		const uint32_t index ,
-		const uint32_t previous ,
-		const char flags ,
-		SP_SRDList&& contents )
-{
-	const uint32_t newIndex( itemDepth_.size( ) );
-	itemDepth_.add( depth_ );
-	chain_.add( previous );
-	reverse_.add( index );
-	flags_.add( flags );
-	contents_.add( std::move( contents ) );
-	indices_[ index ] = newIndex;
-	reverse_[ previous ] = newIndex;
-}
-
-void T_SRDPreprocessorScopes::removeItem(
-		const uint32_t index )
-{
-	// We only ever do that at depth 0, so we don't have to worry about
-	// chaining (we still need to update the index for the element that
-	// gets swapped, though).
-
-	assert( depth_ == 0 );
-	assert( keys_.size( ) == itemDepth_.size( ) );
-
-	itemDepth_.removeSwap( index );
-	flags_.removeSwap( index );
-	chain_.removeSwap( index );
-	reverse_.removeSwap( index );
-	contents_.removeSwap( index );
-
-	keys_.removeSwap( index );
-	indices_.removeSwap( index );
-	index_.remove( index );
-
-	if ( index != indices_.size( ) ) {
-		reverse_[ index ] = index;
-		indices_[ index ] = index;
-	}
-}
-
-
-/*= T_SRDPPDataImpl_ =========================================================*/
-
-namespace {
-struct T_SRDPPDataImpl_ {
-	T_SRDPreprocessor& preprocessor;
-
-	SP_SRDPreprocessorScopes scopes;
-	T_Array< RP_SRDErrors > errors;
-
-	T_Array< SP_SRDPreprocessorState > stack;
-	T_Array< SP_SRDLocation > callStack;
-	T_Array< uint32_t > recursionDepths;
-
-	T_SRDPPDataImpl_(
-			T_SRDPreprocessor& preprocessor ,
-			T_SRDErrors& errors ,
-			SP_SRDPreprocessorScopes scopes ) noexcept;
-	~T_SRDPPDataImpl_( );
-};
-} // namespace
-
-/*----------------------------------------------------------------------------*/
-
-inline T_SRDPPDataImpl_::T_SRDPPDataImpl_(
-		T_SRDPreprocessor& preprocessor ,
-		T_SRDErrors& errors ,
-		SP_SRDPreprocessorScopes scopes ) noexcept
-	: preprocessor( preprocessor ) ,
-		scopes( std::move( scopes ) ) ,
-		errors( 32 )
-{
-	this->errors.add( &errors );
-}
-
-T_SRDPPDataImpl_::~T_SRDPPDataImpl_( )
-{
-	const uint32_t nErrors( errors.size( ) );
-	for ( uint32_t i = 1 ; i < nErrors ; i ++ ) {
-		delete errors[ i ];
-	}
-
-	try {
-		T_SRDErrors& elst( *errors[ 0 ] );
-		const uint32_t ss( stack.size( ) );
-		for ( uint32_t i = 1 ; i < ss ; i ++ ) {
-			T_SRDPreprocessorState & state( *stack[ i ] );
-			if ( state.initialLocation( ) ) {
-				elst.add( "unterminated list" , *state.initialLocation( ) );
-			}
-			state.checkUnterminated( elst );
-		}
-	} catch ( X_SRDErrors const& ) {
-		// Just stop adding errors
-	}
-}
-
-
-/*= T_SRDPreprocessorData ====================================================*/
-
-T_SRDPreprocessorData::T_SRDPreprocessorData(
-		T_SRDPreprocessor& preprocessor ,
-		T_SRDErrors& errors ,
-		SP_SRDPreprocessorScopes scopes )
-	: A_PrivateImplementation( new T_SRDPPDataImpl_(
-				preprocessor , errors , std::move( scopes ) ) )
-{
-	push( );
-}
-
-/*----------------------------------------------------------------------------*/
-
-T_SRDPreprocessor& T_SRDPreprocessorData::preprocessor( ) const
-{
-	return p< T_SRDPPDataImpl_ >( ).preprocessor;
-}
-
-T_SRDList& T_SRDPreprocessorData::output( ) const
-{
-	return p< T_SRDPPDataImpl_ >( ).stack[ 0 ]->output( );
-}
-
-T_SRDPreprocessorScopes& T_SRDPreprocessorData::scopes( )
-{
-	return *( p< T_SRDPPDataImpl_ >( ).scopes );
-}
-
-T_SRDPreprocessorScopes const& T_SRDPreprocessorData::scopes( ) const
-{
-	return *( p< T_SRDPPDataImpl_ >( ).scopes );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void T_SRDPreprocessorData::push(
-		SP_SRDPreprocessorState&& state )
-{
-	p< T_SRDPPDataImpl_ >( ).stack.add( std::move( state ) );
-}
-
-T_SRDPreprocessorState& T_SRDPreprocessorData::top( ) const
-{
-	auto const& stack( p< T_SRDPPDataImpl_ >( ).stack );
-	return *( stack[ stack.size( ) - 1 ] );
-}
-
-bool T_SRDPreprocessorData::topLevel( ) const
-{
-	return p< T_SRDPPDataImpl_ >( ).stack.size( ) == 1;
-}
-
-inline SP_SRDLocation T_SRDPreprocessorData::callLocation( ) const noexcept
-{
-	auto const& cs( p< T_SRDPPDataImpl_ >( ).callStack );
-	if ( cs.size( ) ) {
-		return cs[ cs.size( ) - 1 ];
-	}
-	return SP_SRDLocation( );
-}
-
-SP_SRDPreprocessorState T_SRDPreprocessorData::pop( )
-{
-	auto& stack( p< T_SRDPPDataImpl_ >( ).stack );
-	const auto last( stack.size( ) - 1 );
-	SP_SRDPreprocessorState state( stack[ last ] );
-	stack.remove( last );
-	return state;
-}
-
-void T_SRDPreprocessorData::interrupt(
-		const T_SRDPreprocessorState::E_Type type )
-{
-	assert( type != T_SRDPreprocessorState::C_UNSPECIFIED
-			&& type != T_SRDPreprocessorState::C_INNER );
-
-	auto& stack( p< T_SRDPPDataImpl_ >( ).stack );
-	const uint32_t ss( stack.size( ) );
-	uint32_t i( 0 );
-	while ( i < ss ) {
-		auto& toRemove( *( stack[ ss - i - 1 ] ) );
-		i ++;
-		toRemove.setExiting( type );
-		if ( toRemove.type( ) == type ) {
-			break;
-		}
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-void T_SRDPreprocessorData::pushCallLocation(
-		SP_SRDLocation const& location ) noexcept
-{
-	auto& pi( p< T_SRDPPDataImpl_ >( ) );
-	const auto css( pi.callStack.size( ) );
-	if ( css ) {
-		auto& next( pi.callStack[ css - 1 ] );
-		auto depth( pi.recursionDepths[ css - 1 ] );
-		SP_SRDLocation append( NewShared< T_SRDLocation >( *location ) );
-		if ( next->line( ) == location->line( )
-				&& next->character( ) == location->character( )
-				&& next->source( ) == location->source( ) ) {
-			pi.recursionDepths.add( depth + 1 );
-			if ( next->isChained( ) ) {
-				auto& nc( next->chaining( ) );
-				append->chain( E_SRDLocationChaining::CALLED , nc.depth ,
-						nc.location );
-			}
-		} else {
-			append->chain( E_SRDLocationChaining::CALLED , depth , next );
-			pi.recursionDepths.add( 1 );
-		}
-		pi.callStack.add( std::move( append ) );
-	} else {
-		pi.callStack.add( location );
-		pi.recursionDepths.add( 1 );
-	}
-}
-
-SP_SRDLocation T_SRDPreprocessorData::popCallLocation( ) noexcept
-{
-	auto& pi( p< T_SRDPPDataImpl_ >( ) );
-	const auto css( pi.callStack.size( ) );
-	SP_SRDLocation location( pi.callStack[ css - 1 ] );
-	pi.callStack.remove( css - 1 );
-	pi.recursionDepths.remove( css - 1 );
-	return location;
-}
-
-uint32_t T_SRDPreprocessorData::callRecursionDepth( ) const noexcept
-{
-	auto& pi( p< T_SRDPPDataImpl_ >( ) );
-	const auto css( pi.callStack.size( ) );
-	assert( css > 0 );
-	return pi.recursionDepths[ css - 1 ];
-}
-
-/*----------------------------------------------------------------------------*/
-
-void T_SRDPreprocessorData::pushErrorContext( )
-{
-	p< T_SRDPPDataImpl_ >( ).errors.add( new T_SRDErrors( ) );
-}
-
-RP_SRDErrors T_SRDPreprocessorData::popErrorContext( )
-{
-	auto& errs( p< T_SRDPPDataImpl_ >( ).errors );
-	const auto sz( errs.size( ) );
-	assert( sz > 1 );
-
-	const RP_SRDErrors record( errs[ sz - 1 ] );
-	errs.remove( sz - 1 );
-	return record;
-}
-
-T_SRDErrors& T_SRDPreprocessorData::errorContext( ) const
-{
-	auto const& errs( p< T_SRDPPDataImpl_ >( ).errors );
-	return *( errs[ errs.size( ) - 1 ] );
-}
-
-void T_SRDPreprocessorData::addError(
-		T_SRDLocation const& location ,
-		T_String const& text )
-{
-	auto& pi( p< T_SRDPPDataImpl_ >( ) );
-	auto& errs( pi.errors );
-	const auto last( errs.size( ) - 1 );
-	RP_SRDErrors errData( errs[ last ] );
-
-	const auto css( pi.callStack.size( ) );
-	if ( css == 0 || location.isChained( ) ) {
-		errData->add( text , location );
-	} else {
-		T_SRDLocation l( location );
-		l.chain( E_SRDLocationChaining::CALLED , callRecursionDepth( ) ,
-				pi.callStack[ css - 1 ] );
-		errData->add( text , l );
-	}
-}
-
-
-/*= T_SRDPreprocessor ========================================================*/
-
-T_SRDPreprocessor::T_SRDPreprocessor(
-		T_SRDPreprocessorConfig const& config ,
-		A_SRDReaderTarget& target ,
-		SP_SRDPreprocessorScopes scopes )
-	: config_( config ) , target_( target ) , scopes_( scopes )
-{ }
-
-void T_SRDPreprocessor::start( T_SRDErrors& errors )
-{
-	if ( scopes_ ) {
-		data_ = NewOwned< T_SRDPreprocessorData >( *this , errors , scopes_ );
-	} else {
-		data_ = NewOwned< T_SRDPreprocessorData >( *this , errors );
-	}
-	outPos_ = 0;
-	outDepth_ = 0;
-	target_.start( errors );
-}
-
-void T_SRDPreprocessor::push(
-		T_SRDErrors& errors ,
-		T_SRDToken&& token )
-{
-	while ( !data_->topLevel( ) && data_->top( ).isExiting( ) ) {
-		data_->top( ).terminate( );
-	}
-
-	// Process the new token
-	if ( !data_->top( ).isExiting( ) ) {
-		data_->top( ).processToken( token );
-	}
-
-	// Try to process as much as possible from the stack
-	while ( 1 ) {
-		auto& top( data_->top( ) );
-		if ( top.isExiting( ) ) {
-			if ( data_->topLevel( ) ) {
-				break;
-			}
-			top.terminate( );
-			continue;
-		}
-
-		if ( !top.hasInput( ) ) {
-			break;
-		}
-		if ( top.isFinished( ) ) {
-			top.terminate( );
-		} else {
-			top.processNext( );
-		}
-	}
-
-	// Send output to the target
-	auto& outBuffer( data_->output( ) );
-	const uint32_t bufSize( outBuffer.size( ) );
-	assert( outPos_ <= bufSize );
-	uint32_t remove = 0;
-	for ( uint32_t i = outPos_ ; i < bufSize ; i ++ ) {
-		auto& token( outBuffer[ i ] );
-		const auto tt( token.type( ) );
-		if ( tt == E_SRDTokenType::START ) {
-			outDepth_ ++;
-
-		} else if ( tt == E_SRDTokenType::END ) {
-			assert( outDepth_ > 0 );
-			outDepth_ --;
-			if ( outDepth_ == 0 ) {
-				for ( uint32_t j = 0 ; j <= i ; j ++ ) {
-					sendOutput( errors , outBuffer[ j ] );
-				}
-				remove = i + 1;
-				outPos_ = i;
-			}
-
-		} else if ( outDepth_ == 0 ) {
-			sendOutput( errors , token );
-			remove ++;
-		}
-	}
-	outPos_ = bufSize;
-	if ( remove != 0 ) {
-		outBuffer = outBuffer.moveRange( remove , bufSize );
-		outPos_ -= remove;
-
-		target_.push( errors , T_SRDToken::Flush( ) );
-	}
-}
-
-void T_SRDPreprocessor::end(
-		T_SRDErrors& errors )
-{
-	data_ = T_OwnPtr< T_SRDPreprocessorData >( );
-	target_.end( errors );
-}
-
-void T_SRDPreprocessor::sendOutput(
-		T_SRDErrors& errors ,
-		T_SRDToken& token )
-{
-	if ( token.type( ) == E_SRDTokenType::LIST ) {
-		{
-			T_SRDToken lStart( T_SRDToken::ListStart( ) );
-			lStart.copyLocationOf( token );
-			target_.push( errors , std::move( lStart ) );
-		}
-		{
-			auto& list( token.list( ) );
-			const auto n( list.size( ) );
-			for ( uint32_t i = 0 ; i < n ; i ++ ) {
-				sendOutput( errors , list[ i ] );
-			}
-		}
-		{
-			T_SRDToken lEnd( T_SRDToken::ListEnd( ) );
-			lEnd.copyLocationOf( token );
-			target_.push( errors , std::move( lEnd ) );
-		}
-
-	} else {
-		target_.push( errors , std::move( token ) );
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-bool T_SRDPreprocessor::isValidFunction(
-		T_SRDToken const& token )
-{
-	if ( token.type( ) != E_SRDTokenType::LIST ) {
-		return false;
-	}
-
-	auto const& list( token.list( ) );
-	if ( list.size( ) == 0 ) {
-		return false;
-	}
-
-	auto const& ft( list[ 0 ] );
-	if ( ft.type( ) != E_SRDTokenType::LIST ) {
-		return false;
-	}
-
-	auto const& pl( ft.list( ) );
-	const auto n( pl.size( ) );
-	for ( uint32_t i = 0 ; i < n ; i ++ ) {
-		auto const& p( pl[ i ] );
-		const auto tt( p.type( ) );
-
-		if ( tt == E_SRDTokenType::WORD ) {
-			// Check for duplicate names
-			auto const& pn( p.stringValue( ) );
-			for ( uint32_t j = 0 ; j < i ; j ++ ) {
-				if ( pl[ j ].stringValue( ) == pn ) {
-					return false;
-				}
-			}
-			continue;
-
-		} else if ( tt != E_SRDTokenType::LIST ) {
-			return false;
-		}
-
-		// Must be the last entry
-		if ( i != n - 1 ) {
-			return false;
-		}
-
-		auto const& opl( p.list( ) );
-		const auto no( opl.size( ) );
-		if ( no == 0 ) {
-			return false;
-		}
-		for ( uint32_t j = 0 ; j < no ; j ++ ) {
-			auto const& op( opl[ j ] );
-			if ( op.type( ) != E_SRDTokenType::WORD ) {
-				return false;
-			}
-
-			auto const& opn( op.stringValue( ) );
-			// Check for duplicates in main list
-			for ( uint32_t k = 0 ; k < i ; k ++ ) {
-				if ( pl[ k ].stringValue( ) == opn ) {
-					return false;
-				}
-			}
-			// Check for duplicates in optional args
-			for ( uint32_t k = 0 ; k < j ; k ++ ) {
-				if ( opl[ k ].stringValue( ) == opn ) {
-					return false;
-				}
-			}
-		}
-	}
-
-	return true;
-}
diff --git a/src/SRDText.cc b/src/SRDText.cc
index d703ea4..e8ac8bb 100644
--- a/src/SRDText.cc
+++ b/src/SRDText.cc
@@ -3,8 +3,8 @@
 /******************************************************************************/
 
 
-#include <lw/lib/SRDText.hh>
-using namespace lw;
+#include <ebcl/SRDText.hh>
+using namespace ebcl;
 
 
 /*= T_SRDLexerPrivate_ =======================================================*/
@@ -787,7 +787,7 @@ inline void T_SRDLexerPrivate_::processEnd( )
 
 	    case E_State_::COMMENT_ML:
 		pushComment( );
-
+		// fall through
 	    case E_State_::COMMENT_ML_START:
 		error( "unterminated multi-line comment" );
 		break;
@@ -798,7 +798,7 @@ inline void T_SRDLexerPrivate_::processEnd( )
 
 	    case E_State_::NB_FRAC_PART_M:
 		error( "fractional part expected" );
-
+		// fall through
 	    case E_State_::NB_FRAC_PART:
 	    case E_State_::NB_EXP:
 		pushFloat( );
@@ -814,7 +814,7 @@ inline void T_SRDLexerPrivate_::processEnd( )
 		error( "incomplete word" );
 		stringBuffer_.clear( );
 		stringBuffer_ << "invalid";
-
+		// fall through
 	    case E_State_::WORD:
 		pushWord( );
 		break;
@@ -899,7 +899,7 @@ void T_SRDTextReader::read( T_String const& name , A_InputStream& input )
 
 /*= TEXT LEXING HELPERS ======================================================*/
 
-T_SRDList lw::SRDFromText( T_String const& name , T_String const& string , bool structured )
+T_SRDList ebcl::SRDFromText( T_String const& name , T_String const& string , bool structured )
 {
 	T_SRDMemoryTarget mt( structured );
 	T_SRDErrors errors;
@@ -919,7 +919,7 @@ T_SRDList lw::SRDFromText( T_String const& name , T_String const& string , bool
 	return mt.list( );
 }
 
-T_SRDList lw::SRDFromText( T_String const& name , char const* string , bool structured )
+T_SRDList ebcl::SRDFromText( T_String const& name , char const* string , bool structured )
 {
 	T_SRDMemoryTarget mt( structured );
 	T_SRDErrors errors;
diff --git a/src/TemplateInstantiation.cc b/src/TemplateInstantiation.cc
index 9a5622b..338bdaa 100644
--- a/src/TemplateInstantiation.cc
+++ b/src/TemplateInstantiation.cc
@@ -5,6 +5,8 @@
 #include <ebcl/Utilities.hh>
 #include <ebcl/Arrays.hh>
 #include <ebcl/Strings.hh>
+#include <ebcl/SRDData.hh>
+#include <ebcl/SRDDefinitions.hh>
 
 namespace ebcl {
 
@@ -17,6 +19,8 @@ template struct T_Comparator< uint32_t >;
 template class T_Array< uint32_t >;
 template class T_Array< bool >;
 template class T_Array< T_String >;
+template class T_Array< T_SRDInputItem >;
+template class T_Array< T_SRDToken >;
 
 /*----------------------------------------------------------------------------*/
 
diff --git a/src/TextFileLogger.cc b/src/TextFileLogger.cc
deleted file mode 100644
index ce7f509..0000000
--- a/src/TextFileLogger.cc
+++ /dev/null
@@ -1,159 +0,0 @@
-/******************************************************************************/
-/* LOGGING SYSTEM - BUILT-IN LOGGERS - TEXT FILE LOGGER ***********************/
-/******************************************************************************/
-
-#include <lw/lib/BuiltinLoggers.hh>
-#include <lw/lib/SRDParser.hh>
-using namespace lw;
-
-
-namespace {
-
-
-char const* const V_Name_ = "text-file";
-inline T_String Name_( ) { return T_String::Pooled( V_Name_ ); }
-
-bool TFLCPath_( T_SRDParserData const& data )
-{
-	auto const& ptok( (*data.input)[ 1 ] );
-	T_VFSPath path( ptok.stringValue( ) );
-	path = path.normalize( );
-	if ( path.type( ) != E_VFSPathType::ABSOLUTE ) {
-		data.errors.add( "invalid path" , ptok );
-	} else {
-		auto lconf( data.targetData->value< RP_LogWriterConfiguration >( ) );
-		( dynamic_cast< T_TextFileLogWriterCfg* >( lconf ) )->setPath( std::move( path ) );
-	}
-	return true;
-}
-
-bool TFLCAppend_( T_SRDParserData const& data )
-{
-	auto lconf( data.targetData->value< RP_LogWriterConfiguration >( ) );
-	( dynamic_cast< T_TextFileLogWriterCfg* >( lconf ) )->setAppend( true );
-	return true;
-}
-
-bool TFLCTruncate_( T_SRDParserData const& data )
-{
-	auto lconf( data.targetData->value< RP_LogWriterConfiguration >( ) );
-	( dynamic_cast< T_TextFileLogWriterCfg* >( lconf ) )->setAppend( false );
-	return true;
-}
-
-}
-
-
-/*= T_TextFileLogWriterFactory ==================================================*/
-
-T_TextFileLogWriterFactory::T_TextFileLogWriterFactory( T_VFS& vfs )
-	: A_LogWriterFactory( Name_( ) ) , vfs_( vfs )
-{ }
-
-RP_LogWriterConfiguration T_TextFileLogWriterFactory::createConfiguration( T_String const& name ) const
-{
-	RP_LogWriterConfiguration p( new T_TextFileLogWriterCfg( ) );
-	p->setName( name );
-	return p;
-}
-
-OP_LogWriter T_TextFileLogWriterFactory::createLogWriter( OP_LogWriterConfiguration&& configuration ) const
-{
-	T_TextFileLogWriter* p( new T_TextFileLogWriter( std::move( configuration ) , vfs_ ) );
-	return OwnRawPointer( p );
-}
-
-void T_TextFileLogWriterFactory::initializeSyntax( T_SRDParserDefs& , T_SRDContext& main ) const
-{
-	using namespace lw::SRD;
-	main << ( Rule( ) << "file" << Text( ) << TFLCPath_ );
-	main << ( Rule( ) << "append" << TFLCAppend_ );
-	main << ( Rule( ) << "truncate" << TFLCTruncate_ );
-}
-
-
-/*= T_TextFileLogWriterCfg ======================================================*/
-
-T_TextFileLogWriterCfg::T_TextFileLogWriterCfg( )
-	: T_LogWriterConfiguration( Name_( ) )
-{ }
-
-T_TextFileLogWriterCfg::T_TextFileLogWriterCfg( T_TextFileLogWriterCfg const& source )
-	: T_LogWriterConfiguration( source ) , path_( source.path_ ) ,
-		append_( source.append_ )
-{ }
-
-OP_LogWriterConfiguration T_TextFileLogWriterCfg::clone( )
-{
-	T_TextFileLogWriterCfg* ptr( new T_TextFileLogWriterCfg( *this ) );
-	return OwnRawPointer( ptr );
-}
-
-void T_TextFileLogWriterCfg::check( T_SRDErrors& errors , T_SRDList const& input )
-{
-	T_LogWriterConfiguration::check( errors , input );
-	if ( path_.type( ) == E_VFSPathType::UNKNOWN || path_.elements( ) == 0 ) {
-		errors.add( "no file selected" , input[ 0 ] );
-	}
-}
-
-
-/*= T_TextFileLogWriter =========================================================*/
-
-T_TextFileLogWriter::T_TextFileLogWriter( OP_LogWriterConfiguration&& configuration , T_VFS& vfs )
-	: A_LogWriter( std::move( configuration ) ) , vfs_( vfs )
-{ }
-
-void T_TextFileLogWriter::log( T_LogTimestamp const& timestamp ,
-		E_LogLevel level , T_LogPath const& path ,
-		T_LogStringData const& data , uint32_t size )
-{
-	using namespace std::chrono;
-
-	char timeBuffer[ 128 ];
-	std::time_t tst( T_LogTimestamp::clock::to_time_t( timestamp ) );
-	std::strftime( timeBuffer , 128 , "%Y-%m-%d %H:%M:%S" , std::gmtime( &tst ) );
-	const auto ms( ( duration_cast< milliseconds >( timestamp - T_LogTimestamp( ) ) ).count( ) % 1000 );
-
-	T_StringBuilder sb;
-
-	sb << timeBuffer << '.';
-	if ( ms < 100 ) {
-		sb << '0';
-		if ( ms < 10 ) {
-			sb << '0';
-		}
-	}
-	sb << ms << ' ' << path.toString( ) << " - " << level << ": ";
-	sb.append( &( (*data) [ 0 ] ) , size );
-	sb << '\n';
-
-	auto const& cfg( configuration< T_TextFileLogWriterCfg >( ) );
-	auto const& p( cfg.path( ) );
-	if ( !file_ ) {
-		vfs_.mkdir( p.parent( ) );
-		file_ = vfs_.file( p , cfg.append( ) ? E_FileMode::READ_WRITE : E_FileMode::OVERWRITE );
-		if ( !file_ ) {
-			disable( );
-			return;
-		}
-
-		try {
-			file_->open( );
-		} catch ( X_StreamError const& ) {
-			disable( );
-			file_.clear( );
-			return;
-		}
-	}
-
-	try {
-		file_->position( 0 , true );
-		file_->write( sb.data( ) , sb.size( ) );
-		file_->flush( );
-	} catch ( X_StreamError ) {
-		disable( );
-		file_.clear( );
-		return;
-	}
-}
diff --git a/src/VFS.cc b/src/VFS.cc
deleted file mode 100644
index 26619b2..0000000
--- a/src/VFS.cc
+++ /dev/null
@@ -1,930 +0,0 @@
-/******************************************************************************/
-/* VIRTUAL FILE SYSTEM ********************************************************/
-/******************************************************************************/
-
-#include <lw/lib/VFS.hh>
-#ifndef _WIN32
-# include <sys/stat.h>
-# include <dirent.h>
-# include <unistd.h>
-#endif
-using namespace lw;
-
-
-/*= VARIOUS INTERNALS ========================================================*/
-
-namespace {
-
-bool MkDir_( T_String const& path )
-{
-	const auto chars( path.toOSString( ) );
-#ifdef _WIN32
-	return CreateDirectoryW( ( wchar_t const* ) &chars[ 0 ] , nullptr );
-#else
-	return mkdir( ( char const* ) &chars[ 0 ] , 0755 ) == 0;
-#endif
-}
-
-E_VFSEntryType TypeOfPath_( T_String const& path )
-{
-	const auto chars( path.toOSString( ) );
-
-#ifdef _WIN32
-
-	uint32_t fa( GetFileAttributesW( (wchar_t const*) & chars[ 0 ] ) );
-	if ( fa == INVALID_FILE_ATTRIBUTES ) {
-		return E_VFSEntryType::NONE;
-	} else if ( ( fa & FILE_ATTRIBUTE_DIRECTORY ) != 0 ) {
-		return E_VFSEntryType::DIRECTORY;
-	} else if ( ( fa & FILE_ATTRIBUTE_NORMAL ) != 0 ) {
-		return E_VFSEntryType::FILE;
-	} else {
-		return E_VFSEntryType::OTHER;
-	}
-
-#else
-
-	struct stat fa;
-	if ( stat( ( char const* ) &chars[ 0 ] , &fa ) ) {
-		return E_VFSEntryType::NONE;
-	}
-
-	const auto masked( fa.st_mode & S_IFMT );
-	switch ( masked ) {
-	    case S_IFREG:
-		return E_VFSEntryType::FILE;
-
-	    case S_IFDIR:
-		return E_VFSEntryType::DIRECTORY;
-
-	    default:
-		return E_VFSEntryType::OTHER;
-	}
-
-#endif
-}
-
-} // namespace
-
-
-/*= T_DirLister_ =============================================================*/
-
-namespace {
-
-class T_DirLister_
-{
-   private:
-	T_Buffer< char > path_;
-#ifdef _WIN32
-	HANDLE handle_;
-	WIN32_FIND_DATAW output_;
-#else
-	DIR* dir_;
-	struct dirent* output_;
-#endif
-
-   public:
-	explicit T_DirLister_( T_Buffer< char > path );
-	~T_DirLister_( );
-
-	bool start( );
-	void next( );
-	bool hasValue( ) const;
-	T_String getName( ) const;
-};
-
-
-} // namespace
-
-/*----------------------------------------------------------------------------*/
-
-inline T_DirLister_::T_DirLister_( T_Buffer< char > path )
-	: path_( std::move( path ) )
-{
-#ifdef _WIN32
-# error "Not implemented"
-#else
-	dir_ = nullptr;
-	output_ = nullptr;
-#endif
-}
-
-T_DirLister_::~T_DirLister_( )
-{
-#ifdef _WIN32
-# error "Not implemented"
-#else
-	if ( dir_ != nullptr ) {
-		closedir( dir_ );
-	}
-#endif
-}
-
-inline bool T_DirLister_::start( )
-{
-#ifdef _WIN32
-# error "Not implemented"
-#else
-	dir_ = opendir( &path_[ 0 ] );
-	if ( dir_ == nullptr ) {
-		return false;
-	}
-	output_ = readdir( dir_ );
-	return true;
-#endif
-}
-
-inline void T_DirLister_::next( )
-{
-#ifdef _WIN32
-# error "Not implemented"
-#else
-	output_ = readdir( dir_ );
-#endif
-}
-
-inline bool T_DirLister_::hasValue( ) const
-{
-#ifdef _WIN32
-# error "Not implemented"
-#else
-	return output_ != nullptr;
-#endif
-}
-
-inline T_String T_DirLister_::getName( ) const
-{
-#ifdef _WIN32
-# error "Not implemented"
-#else
-	return T_String( output_->d_name , strlen( output_->d_name ) );
-#endif
-}
-
-
-/*= T_VFSPath ================================================================*/
-
-T_VFSPath::T_VFSPath( E_VFSPathType type )
-	: type_( type ) , elements_( 16 )
-{ }
-
-
-T_VFSPath::T_VFSPath( T_String const& path )
-	: T_VFSPath( )
-{
-	extractPath( path );
-}
-
-/*----------------------------------------------------------------------------*/
-
-T_VFSPath::T_VFSPath( T_VFSPath const& parent , T_VFSPath const& child )
-	: T_VFSPath( parent.type_ )
-{
-	if ( child.type( ) == E_VFSPathType::UNKNOWN ) {
-		type_ = E_VFSPathType::UNKNOWN;
-	}
-	if ( type_ == E_VFSPathType::UNKNOWN || child.type( ) == E_VFSPathType::UNKNOWN ) {
-		return;
-	}
-
-	if ( child.type_ == E_VFSPathType::INVALID ) {
-		type_ = E_VFSPathType::INVALID;
-	}
-	elements_.ensureCapacity( parent.elements( ) + child.elements( ) );
-	elements_.addAll( parent.elements_ );
-	elements_.addAll( child.elements_ );
-}
-
-/*----------------------------------------------------------------------------*/
-
-T_VFSPath::T_VFSPath( T_VFSPath const& other )
-	: type_( other.type_ ) , elements_( other.elements_ )
-{ }
-
-T_VFSPath::T_VFSPath( T_VFSPath&& other ) noexcept
-	: T_VFSPath( )
-{
-	swap( *this , other );
-}
-
-/*----------------------------------------------------------------------------*/
-
-T_VFSPath& T_VFSPath::operator= ( T_VFSPath const& other )
-{
-	type_ = other.type_;
-	elements_ = other.elements_;
-	return *this;
-}
-
-T_VFSPath& T_VFSPath::operator= ( T_VFSPath&& other ) noexcept
-{
-	swap( *this , other );
-	return *this;
-}
-
-/*----------------------------------------------------------------------------*/
-
-T_VFSPath::operator T_String ( ) const
-{
-	T_StringBuilder sb;
-	if ( type_ == E_VFSPathType::ABSOLUTE ) {
-		sb << '/';
-	}
-
-	const auto n( elements_.size( ) );
-	for ( uint32_t i = 0 ; i < n ; i ++ ) {
-		if ( i > 0 ) {
-			sb << '/';
-		}
-		sb << elements_[ i ];
-	}
-
-	return T_String( std::move( sb ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void lw::swap( T_VFSPath& lhs , T_VFSPath& rhs ) noexcept
-{
-	using std::swap;
-	swap( lhs.type_ , rhs.type_ );
-	swap( lhs.elements_ , rhs.elements_ );
-}
-
-/*----------------------------------------------------------------------------*/
-
-T_VFSPath T_VFSPath::normalize( ) const
-{
-	T_VFSPath normed;
-	if ( type_ == E_VFSPathType::UNKNOWN || type_ == E_VFSPathType::INVALID ) {
-		return normed;
-	}
-
-	normed.type_ = type_;
-	const auto absolute( type_ == E_VFSPathType::ABSOLUTE );
-	const auto n( elements_.size( ) );
-	for ( uint32_t i = 0 ; i < n ; i ++ ) {
-		auto const& e( elements_[ i ] );
-
-		// Simply remove .'s
-		if ( e == "." ) {
-			continue;
-		}
-
-		if ( e == ".." ) {
-			auto const te( normed.elements( ) );
-
-			// Remove ..'s at the start of an absolute path
-			if ( te == 0 && absolute ) {
-				continue;
-			}
-
-			// Use ..'s to remove stuff like "dir/../wat/../wut/.."
-			if ( te != 0 && normed.elements_[ te - 1 ] != ".." ) {
-				normed.elements_.remove( te - 1 );
-				continue;
-			}
-		}
-		normed.elements_.add( e );
-	}
-
-	if ( normed.elements( ) == 0 && normed.type( ) == E_VFSPathType::RELATIVE ) {
-		normed.elements_.add( T_String::Pooled( "." ) );
-	}
-
-	return normed;
-}
-
-/*----------------------------------------------------------------------------*/
-
-T_VFSPath T_VFSPath::parent( ) const
-{
-	if ( type_ == E_VFSPathType::UNKNOWN || type_ == E_VFSPathType::INVALID
-			|| elements_.size( ) == 0 ) {
-		return *this;
-	}
-
-	if ( type_ == E_VFSPathType::RELATIVE && elements_.size( ) == 1 ) {
-		T_VFSPath p( E_VFSPathType::RELATIVE );
-		p.elements_.add( T_String::Pooled( "." ) );
-		return p;
-	}
-
-	T_VFSPath p( *this );
-	p.elements_.remove( elements_.size( ) - 1 );
-	return p;
-}
-
-/*----------------------------------------------------------------------------*/
-
-bool T_VFSPath::operator== ( T_VFSPath const& other ) const
-{
-	if ( this == &other ) {
-		return true;
-	}
-
-	const auto n( elements( ) );
-	if ( type_ != other.type_ || n != other.elements( ) ) {
-		return false;
-	}
-
-	for ( uint32_t i = 0 ; i < n ; i ++ ) {
-		if ( elements_[ i ] != other[ i ] ) {
-			return false;
-		}
-	}
-
-	return true;
-}
-
-/*----------------------------------------------------------------------------*/
-
-void T_VFSPath::extractPath( T_String const& path )
-{
-	// Extract the path's elements
-	T_StringIterator it( path );
-	bool elementStarted( false ) , absolute( false ) , invalid( false );
-	uint32_t startIndex , index( 0 );
-	while ( !it.atEnd( ) ) {
-		T_Character c( it );
-
-		if ( c == '/' ) {
-			if ( elementStarted ) {
-				elements_.add( path.range( startIndex , it.index( ) - 1 ) );
-				elementStarted = false;
-			}
-			if ( it.index( ) == 0 ) {
-				absolute = true;
-			}
-		} else {
-			if ( !( c.isNumeric( ) || c.isLowercase( )
-			       || c == '-' || c == '_' || c == '.' ) ) {
-				invalid = true;
-			}
-			if ( !elementStarted ) {
-				elementStarted = true;
-				startIndex = it.index( );
-			}
-		}
-
-		it.next( );
-		index ++;
-	}
-
-	if ( elementStarted ) {
-		elements_.add( path.substr( startIndex ) );
-	}
-
-	// Only "." and ".." should start with a dot
-	if ( !invalid ) {
-		const auto n( elements_.size( ) );
-		for ( uint32_t i = 0 ; i < n && !invalid ; i ++ ) {
-			T_String const& s( elements_[ i ] );
-			if ( s[ 0 ] == '.' ) {
-				invalid = ( s != "." && s != ".." );
-			}
-		}
-	}
-
-	// Set the type
-	if ( invalid ) {
-		type_ = E_VFSPathType::INVALID;
-	} else if ( absolute ) {
-		type_ = E_VFSPathType::ABSOLUTE;
-	} else if ( elements_.size( ) == 0 ) {
-		type_ = E_VFSPathType::UNKNOWN;
-	} else {
-		type_ = E_VFSPathType::RELATIVE;
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-M_DEFINE_HASH( T_VFSPath )
-{
-	uint32_t hash( uint32_t( item.type( ) ) << 16 );
-	const auto n( item.elements( ) );
-	hash ^= n;
-	for ( uint32_t i = 0 ; i < n ; i ++ ) {
-		hash = ( hash << 11 ) | ( hash >> 21 );
-		hash ^= ComputeHash( item[ i ] );
-	}
-	return hash;
-}
-
-/*= A_VFSDriver ==============================================================*/
-
-bool A_VFSDriver::init( )
-{
-	return true;
-}
-
-void A_VFSDriver::shutdown( )
-{ }
-
-OP_File A_VFSDriver::file( T_VFSPath const& )
-{
-	return OP_File( );
-}
-
-
-/*= T_VFSFilesystemDriver ====================================================*/
-
-#ifdef _WIN32
-# define C_SEPARATOR_ '\\'
-#else
-# define C_SEPARATOR_ '/'
-#endif
-
-T_VFSFilesystemDriver::T_VFSFilesystemDriver( T_String root )
-	: root_( root )
-{ }
-
-/*----------------------------------------------------------------------------*/
-
-bool T_VFSFilesystemDriver::init( )
-{
-	const auto path( root_.toOSString( ) );
-
-#ifdef _WIN32
-
-	uint32_t fa( GetFileAttributesW( (wchar_t const*) & path[ 0 ] ) );
-	return fa != INVALID_FILE_ATTRIBUTES && ( fa & FILE_ATTRIBUTE_DIRECTORY ) != 0;
-
-#else
-
-	struct stat fa;
-	if ( stat( ( char const* ) &path[ 0 ] , &fa ) ) {
-		return false;
-	}
-	return ( fa.st_mode & S_IFMT ) == S_IFDIR;
-
-#endif
-}
-
-/*----------------------------------------------------------------------------*/
-
-E_VFSEntryType T_VFSFilesystemDriver::typeOf( T_VFSPath const& path )
-{
-	return TypeOfPath_( getFullPath( path ) );
-}
-
-bool T_VFSFilesystemDriver::list( T_VFSPath const& path , T_Array< T_VFSPath >& values , T_HashIndex& index )
-{
-	T_DirLister_ dl( getOSPath( path ) );
-	if ( !dl.start( ) ) {
-		return false;
-	}
-	while ( dl.hasValue( ) ) {
-		const auto v( dl.getName( ) );
-		dl.next( );
-		if ( v == "." || v == ".." ) {
-			continue;
-		}
-
-		const T_VFSPath entry( v );
-		if ( entry.type( ) == E_VFSPathType::INVALID ) {
-			continue;
-		}
-
-		const uint32_t hash( ComputeHash( entry ) );
-		uint32_t idx( index.first( hash ) );
-		while ( idx != T_HashIndex::INVALID_INDEX ) {
-			if ( values[ idx ] == entry ) {
-				break;
-			}
-			idx = index.next( idx );
-		}
-		if ( idx == T_HashIndex::INVALID_INDEX ) {
-			index.add( hash );
-			values.add( entry );
-		}
-	}
-	return true;
-}
-
-OP_InputStream T_VFSFilesystemDriver::read( T_VFSPath const& path )
-{
-	if ( typeOf( path ) != E_VFSEntryType::FILE ) {
-		return OP_InputStream( );
-	} else {
-		auto f( file( path ) );
-		if ( f ) {
-			return NewOwned< T_FileInputStream >( std::move( f ) );
-		} else {
-			return OP_InputStream( );
-		}
-	}
-}
-
-OP_File T_VFSFilesystemDriver::file( T_VFSPath const& path )
-{
-	if ( typeOf( path ) != E_VFSEntryType::FILE ) {
-		return OP_File( );
-	}
-	return NewOwned< T_File >( getFullPath( path ) , E_FileMode::READ_ONLY );
-}
-
-/*----------------------------------------------------------------------------*/
-
-T_String T_VFSFilesystemDriver::getFullPath( T_VFSPath const& path ) const
-{
-	T_StringBuilder sb( root_ );
-	const auto n( path.elements( ) );
-	for ( uint32_t i = 0 ; i < n ; i ++ ) {
-		sb << C_SEPARATOR_ << path[ i ];
-	}
-	return T_String( std::move( sb ) );
-}
-
-inline T_Buffer< char > T_VFSFilesystemDriver::getOSPath( T_VFSPath const& path ) const
-{
-	return getFullPath( path ).toOSString( );
-}
-
-
-/*= T_VFSUserDirectory_ ======================================================*/
-
-namespace {
-
-class T_VFSUserDirectory_ : public T_VFSFilesystemDriver
-{
-   public:
-	explicit T_VFSUserDirectory_( T_String const& base );
-
-	bool init( ) override;
-
-	OP_File file( T_VFSPath const& path ) override;
-	OP_File file( T_VFSPath const& path , E_FileMode mode );
-	OP_OutputStream write( T_VFSPath const& path );
-	bool mkdir( T_VFSPath const& path ) const;
-	bool rmdir( T_VFSPath const& path ) const;
-	bool rm( T_VFSPath const& path ) const;
-	bool move( T_VFSPath const& from , T_VFSPath const& to ) const;
-};
-
-
-} // namespace
-
-/*----------------------------------------------------------------------------*/
-
-T_VFSUserDirectory_::T_VFSUserDirectory_( T_String const& base )
-	: T_VFSFilesystemDriver( base )
-{ }
-
-bool T_VFSUserDirectory_::init( )
-{
-	if ( T_VFSFilesystemDriver::init( ) ) {
-		return true;
-	}
-
-	// Try creating the user directory
-	T_String const& r( root( ) );
-	int32_t nextSep( r.find( C_SEPARATOR_ ) );
-	while ( 1 ) {
-		const T_String p( nextSep == -1 ? r : r.substr( 0 , nextSep ) );
-		if ( p ) {
-			const auto t( TypeOfPath_( p ) );
-			if ( ( t != E_VFSEntryType::DIRECTORY && t != E_VFSEntryType::NONE )
-					|| ( t == E_VFSEntryType::NONE && !MkDir_( p ) ) ) {
-				return false;
-			}
-		}
-		if ( nextSep == -1 ) {
-			break;
-		} else {
-			nextSep = r.find( C_SEPARATOR_ , nextSep + 1 );
-		}
-	}
-
-	return true;
-}
-
-/*----------------------------------------------------------------------------*/
-
-OP_File T_VFSUserDirectory_::file( T_VFSPath const& path )
-{
-	return T_VFSFilesystemDriver::file( path );
-}
-
-OP_File T_VFSUserDirectory_::file( T_VFSPath const& path , E_FileMode mode )
-{
-	if ( mode == E_FileMode::READ_ONLY ) {
-		return file( path );
-	}
-
-	const auto fp( getFullPath( path ) );
-	const auto ft( TypeOfPath_( fp ) );
-	if ( ft != E_VFSEntryType::FILE && ft != E_VFSEntryType::NONE ) {
-		return OP_File( );
-	}
-	return NewOwned< T_File >( fp , mode );
-}
-
-/*----------------------------------------------------------------------------*/
-
-OP_OutputStream T_VFSUserDirectory_::write( T_VFSPath const& path )
-{
-	auto f( file( path , E_FileMode::OVERWRITE ) );
-	if ( f ) {
-		return NewOwned< T_FileOutputStream >( std::move( f ) );
-	} else {
-		return OP_OutputStream( );
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-bool T_VFSUserDirectory_::mkdir( T_VFSPath const& path ) const
-{
-	T_StringBuilder sb( root( ) );
-	const auto n( path.elements( ) );
-	for ( uint32_t i = 0 ; i < n ; i ++ ) {
-		sb << C_SEPARATOR_ << path[ i ];
-		if ( !MkDir_( sb ) ) {
-			return false;
-		}
-	}
-	return true;
-}
-
-bool T_VFSUserDirectory_::rmdir( T_VFSPath const& path ) const
-{
-	const auto chars( getOSPath( path ) );
-#ifdef _WIN32
-	return RemoveDirectoryW( ( wchar_t const* ) &chars[ 0 ] );
-#else
-	return ::rmdir( ( char const* ) &chars[ 0 ] ) == 0;
-#endif
-}
-
-bool T_VFSUserDirectory_::rm( T_VFSPath const& path ) const
-{
-	const auto chars( getOSPath( path ) );
-#ifdef _WIN32
-	return DeleteFileW( ( wchar_t const* ) &chars[ 0 ] );
-#else
-	return unlink( ( char const* ) &chars[ 0 ] ) == 0;
-#endif
-}
-
-bool T_VFSUserDirectory_::move( T_VFSPath const& from , T_VFSPath const& to ) const
-{
-	const auto charsFrom( getOSPath( from ) );
-	const auto charsTo( getOSPath( to ) );
-#ifdef _WIN32
-	return MoveFileW( ( wchar_t const* ) &charsFrom[ 0 ] ,
-			 ( wchar_t const* ) &charsTo[ 0 ] );
-#else
-	return rename( ( char const* ) &charsFrom[ 0 ] ,
-		      ( char const* ) &charsTo[ 0 ] ) == 0;
-#endif
-}
-
-
-/*= T_VFSPrivate_ ============================================================*/
-
-namespace {
-struct T_VFSPrivate_
-{
-	T_RegisteredItem::SP_Unregister unregisterFunction_{
-		NewShared< T_RegisteredItem::F_Unregister >(
-			[this]( void* data ) {
-				auto const n( drivers_.size( ) );
-				for ( uint32_t i = 0 ; i < n ; i ++ ) {
-					auto& p( drivers_[ i ] );
-					if ( p.get( ) == data ) {
-						p->shutdown( );
-						drivers_.removeSwap( i );
-						break;
-					}
-				}
-			}
-		) };
-	OP_VFSFilesystemDriver userDir_;
-	T_Array< OP_VFSDriver > drivers_{ 16 };
-
-	static T_String findUserDir( );
-	void initUserDir( T_String const& dir );
-};
-} // namespace
-
-/*----------------------------------------------------------------------------*/
-
-T_String T_VFSPrivate_::findUserDir( )
-{
-#ifdef _WIN32
-# error "Not implemented!"
-#else
-	T_String base;
-	char const* const lwHome( getenv( "LWHOME" ) );
-	if ( lwHome == nullptr ) {
-		char const* const userHome( getenv( "HOME" ) );
-		if ( userHome == nullptr ) {
-			throw X_VFSInitialisationFailure( );
-		} else {
-			T_StringBuilder sb( userHome );
-			sb << "/.local/share/LegacyWorlds";
-			base = std::move( sb );
-		}
-	} else {
-		base = T_String( lwHome , strlen( lwHome ) );
-	}
-	return base;
-#endif
-}
-
-void T_VFSPrivate_::initUserDir( T_String const& dir )
-{
-	assert( !userDir_ );
-	userDir_ = NewOwned< T_VFSUserDirectory_ >( dir );
-	if ( !userDir_->init( ) ) {
-		throw X_VFSInitialisationFailure( );
-	}
-}
-
-
-/*= T_VFS ====================================================================*/
-
-T_VFS::T_VFS( )
-	: A_PrivateImplementation( new T_VFSPrivate_( ) )
-{
-	p< T_VFSPrivate_ >( ).initUserDir( T_VFSPrivate_::findUserDir( ) );
-}
-
-T_VFS::T_VFS( T_String const& userDir )
-	: A_PrivateImplementation( new T_VFSPrivate_( ) )
-{
-	p< T_VFSPrivate_ >( ).initUserDir( userDir );
-}
-
-T_RegisteredItem T_VFS::addDriver( OP_VFSDriver&& driver )
-{
-	assert( driver );
-	const bool ok( driver->init( ) );
-	if ( ok ) {
-		auto& pi( p< T_VFSPrivate_ >( ) );
-		void* const ptr( driver.get( ) );
-		pi.drivers_.add( std::move( driver ) );
-		return T_RegisteredItem( pi.unregisterFunction_ , ptr );
-	}
-	return T_RegisteredItem( );
-}
-
-/*----------------------------------------------------------------------------*/
-
-E_VFSEntryType T_VFS::typeOf( T_VFSPath const& path ) const
-{
-	if ( path.type( ) != E_VFSPathType::ABSOLUTE ) {
-		return E_VFSEntryType::NONE;
-	}
-
-	auto& pi( p< T_VFSPrivate_ >( ) );
-	const auto np( path.normalize( ) );
-	E_VFSEntryType rv( pi.userDir_->typeOf( np ) );
-	const auto nd( pi.drivers_.size( ) );
-	for ( uint32_t i = nd ; i != 0 && rv == E_VFSEntryType::NONE ; i -- ) {
-		rv = pi.drivers_[ i - 1 ]->typeOf( np );
-	}
-
-	return rv;
-}
-
-bool T_VFS::list( T_VFSPath const& path , T_Array< T_VFSPath >& output ) const
-{
-	output.clear( );
-	if ( path.type( ) != E_VFSPathType::ABSOLUTE ) {
-		return false;
-	}
-
-	const auto np( path.normalize( ) );
-	auto& pi( p< T_VFSPrivate_ >( ) );
-	T_HashIndex index( 1024 , 256 , 256 );
-	bool rv( pi.userDir_->list( np , output , index ) );
-	const auto nd( pi.drivers_.size( ) );
-	for ( uint32_t i = nd ; i != 0 ; i -- ) {
-		rv = pi.drivers_[ i - 1 ]->list( np , output , index ) || rv;
-	}
-
-	return rv;
-}
-
-OP_InputStream T_VFS::read( T_VFSPath const& path ) const
-{
-	if ( path.type( ) != E_VFSPathType::ABSOLUTE ) {
-		return OP_InputStream( );
-	}
-
-	const auto np( path.normalize( ) );
-	auto& pi( p< T_VFSPrivate_ >( ) );
-	OP_InputStream rv( pi.userDir_->read( np ) );
-	const auto nd( pi.drivers_.size( ) );
-	for ( uint32_t i = nd ; i != 0 && !rv ; i -- ) {
-		rv = pi.drivers_[ i - 1 ]->read( np );
-	}
-	return rv;
-}
-
-OP_File T_VFS::file( T_VFSPath const& path ) const
-{
-	if ( path.type( ) != E_VFSPathType::ABSOLUTE ) {
-		return OP_File( );
-	}
-
-	const auto np( path.normalize( ) );
-	auto& pi( p< T_VFSPrivate_ >( ) );
-	OP_File rv( pi.userDir_->file( np ) );
-	const auto nd( pi.drivers_.size( ) );
-	for ( uint32_t i = nd ; i != 0 && !rv ; i -- ) {
-		rv = pi.drivers_[ i - 1 ]->file( np );
-	}
-
-	return rv;
-}
-
-/*----------------------------------------------------------------------------*/
-
-OP_File T_VFS::file( T_VFSPath const& path , E_FileMode mode ) const
-{
-	if ( mode == E_FileMode::READ_ONLY ) {
-		return file( path );
-	} else if ( path.type( ) != E_VFSPathType::ABSOLUTE ) {
-		return OP_File( );
-	} else {
-		return dynamic_cast< T_VFSUserDirectory_* >(
-				p< T_VFSPrivate_ >( ).userDir_.get( ) )
-				       ->file( path.normalize( ) , mode );
-	}
-}
-
-OP_OutputStream T_VFS::write( T_VFSPath const& path ) const
-{
-	if ( path.type( ) != E_VFSPathType::ABSOLUTE ) {
-		return OP_OutputStream( );
-	} else {
-		return dynamic_cast< T_VFSUserDirectory_* >(
-				p< T_VFSPrivate_ >( ).userDir_.get( ) )
-				       ->write( path.normalize( ) );
-	}
-}
-
-bool T_VFS::mkdir( T_VFSPath const& path ) const
-{
-	if ( path.type( ) != E_VFSPathType::ABSOLUTE ) {
-		return false;
-	} else {
-		return dynamic_cast< T_VFSUserDirectory_* >(
-				p< T_VFSPrivate_ >( ).userDir_.get( ) )
-				       ->mkdir( path.normalize( ) );
-	}
-}
-
-bool T_VFS::rmdir( T_VFSPath const& path ) const
-{
-	if ( path.type( ) != E_VFSPathType::ABSOLUTE ) {
-		return false;
-	} else {
-		return dynamic_cast< T_VFSUserDirectory_* >(
-				p< T_VFSPrivate_ >( ).userDir_.get( ) )
-				       ->rmdir( path.normalize( ) );
-	}
-}
-
-bool T_VFS::rm( T_VFSPath const& path ) const
-{
-	if ( path.type( ) != E_VFSPathType::ABSOLUTE ) {
-		return false;
-	} else {
-		return dynamic_cast< T_VFSUserDirectory_* >(
-				p< T_VFSPrivate_ >( ).userDir_.get( ) )
-				       ->rm( path.normalize( ) );
-	}
-}
-
-bool T_VFS::move( T_VFSPath const& from , T_VFSPath const& to ) const
-{
-	if ( from.type( ) != E_VFSPathType::ABSOLUTE ) {
-		return false;
-	}
-
-	const auto nFrom( from.normalize( ) );
-	if ( from.elements( ) == 0 ) {
-		return false;
-	}
-
-	T_VFSPath nTo;
-	if ( to.type( ) == E_VFSPathType::ABSOLUTE ) {
-		nTo = to.normalize( );
-	} else if ( to.type( ) == E_VFSPathType::RELATIVE ) {
-		nTo = T_VFSPath( nFrom , T_VFSPath( ".." , to ) ).normalize( );
-	} else {
-		return false;
-	}
-	if ( nTo.elements( ) == 0 ) {
-		return false;
-	}
-
-	return dynamic_cast< T_VFSUserDirectory_* >(
-			p< T_VFSPrivate_ >( ).userDir_.get( ) )
-			       ->move( nFrom , nTo );
-}
diff --git a/src/VFSDrivers.cc b/src/VFSDrivers.cc
deleted file mode 100644
index dc93d1e..0000000
--- a/src/VFSDrivers.cc
+++ /dev/null
@@ -1,614 +0,0 @@
-/******************************************************************************/
-/* VIRTUAL FILE SYSTEM - NON-ESSENTIAL DRIVERS ********************************/
-/******************************************************************************/
-
-#include <lw/lib/VFSDrivers.hh>
-#include <lw/lib/Threading.hh>
-#include <lw/lib/MemoryStreams.hh>
-#include <lw/lib/BinaryStreams.hh>
-using namespace lw;
-
-
-/*= T_VFSDataIndexPrivate_ ===================================================*/
-
-namespace {
-struct T_VFSDataIndexPrivate_
-{
-	// Information about an entry.
-	struct T_EntryInfo {
-		uint32_t index;
-		bool isFile;
-	};
-
-	const uint32_t magic_;
-	T_KeyValueTable< T_VFSPath , T_EntryInfo > entries_;
-	T_MultiArray< T_String > dirEntries_;
-	T_Array< T_VFSDataIndex::T_FileInfo > files_;
-
-	// ---------------------------------------------------------------------
-
-	explicit T_VFSDataIndexPrivate_(
-			uint32_t magic );
-
-	// ---------------------------------------------------------------------
-
-	// Read the index from a stream
-	bool readIndex(
-			T_BinaryReader& reader );
-	// Free the index
-	void free( );
-
-	// ---------------------------------------------------------------------
-
-	// Get the type of an entry
-	E_VFSEntryType typeOf( T_VFSPath const& path ) const;
-
-	// List a directory
-	bool list(
-			T_VFSPath const& path ,
-			T_Array< T_VFSPath >& values ,
-			T_HashIndex& index ) const;
-
-	// Returns the file information record for a given path
-	T_VFSDataIndex::T_FileInfo const* getFileInfo(
-			T_VFSPath const& path ) const;
-};
-} // namespace
-
-/*----------------------------------------------------------------------------*/
-
-inline T_VFSDataIndexPrivate_::T_VFSDataIndexPrivate_(
-		uint32_t magic )
-	: magic_( magic )
-{ }
-
-/*----------------------------------------------------------------------------*/
-
-inline bool T_VFSDataIndexPrivate_::readIndex(
-		T_BinaryReader& reader )
-{
-	/*
-	 * FIXME clean this up later
-	 *
-	 * Format:
-	 *
-	 * magic
-	 * version
-	 * root directory
-	 * other directories
-	 * file data
-	 *
-	 * a directory:
-	 *	number of entries
-	 *	list of entries
-	 *
-	 * a directory entry:
-	 * 	Entry's name (T_String)
-	 * 	is file? (0/1)
-	 * 	if it's a file:
-	 * 		size (uint32_t)
-	 * 		offset relative to start of data (uint32_t)
-	 *
-	 * size of a directory entry:
-	 *	size( name ) + 4 + isFile ? 8 : 0
-	 *
-	 * size of a directory list:
-	 * 	4 + sum( size( entry ) for all entries )
-	 *
-	 */
-	if ( reader.read< uint32_t >( ) != magic_ ) {
-		return false;
-	}
-	if ( reader.read< uint32_t >( ) != 0 ) {
-		return false;
-	}
-
-	const auto inSize( reader.stream( ).size( ) );
-	T_RingBuffer< T_VFSPath > directories;
-	directories.put( T_VFSPath( "/" ) );
-	entries_.add( T_VFSPath( "/" ) , T_EntryInfo{ 0 , false } );
-	uint32_t dirReserved( 1 );
-
-	T_VFSPath current;
-	while ( directories.size( ) ) {
-		directories.readNext( current );
-		dirEntries_.next( );
-
-		const auto nEntries( reader.read< uint32_t >( ) );
-		for ( uint32_t i = 0 ; i < nEntries ; i ++ ) {
-			T_String name( reader.read< T_String >( ) );
-			const T_VFSPath path( current , name );
-
-			const bool isFile( reader.read< uint8_t >( ) );
-			const uint32_t index( isFile ? files_.size( ) : dirReserved );
-			dirEntries_.add( name );
-			if ( !entries_.add( path , T_EntryInfo{ index , isFile } ) ) {
-				return false;
-			}
-
-			if ( isFile ) {
-				const auto size( reader.read< uint32_t >( ) );
-				const auto offset( reader.read< uint32_t >( ) );
-				if ( offset >= inSize || offset + size > inSize ) {
-					return false;
-				}
-				files_.add( T_VFSDataIndex::T_FileInfo{ size , offset } );
-			} else {
-				directories.put( path );
-				dirReserved ++;
-			}
-		}
-	}
-
-	return dirReserved == dirEntries_.size( );
-}
-
-inline void T_VFSDataIndexPrivate_::free( )
-{
-	entries_.free( );
-	dirEntries_.free( );
-	files_.free( );
-}
-
-/*----------------------------------------------------------------------------*/
-
-inline E_VFSEntryType T_VFSDataIndexPrivate_::typeOf(
-		T_VFSPath const& path ) const
-{
-	T_EntryInfo const* eptr( entries_.get( path ) );
-	if ( eptr == nullptr ) {
-		return E_VFSEntryType::NONE;
-	}
-	return eptr->isFile ? E_VFSEntryType::FILE : E_VFSEntryType::DIRECTORY;
-}
-
-inline bool T_VFSDataIndexPrivate_::list(
-		T_VFSPath const& path ,
-		T_Array< T_VFSPath >& values ,
-		T_HashIndex& index ) const
-{
-	T_EntryInfo const* eptr( entries_.get( path ) );
-	if ( eptr == nullptr || eptr->isFile ) {
-		return false;
-	}
-
-	const auto first( dirEntries_.firstOf( eptr->index ) );
-	const auto size( dirEntries_.sizeOf( eptr->index ) );
-	for ( uint32_t i = 0 ; i < size ; i ++ ) {
-		const T_VFSPath p( dirEntries_[ i + first ] );
-		const uint32_t hash( ComputeHash( p ) );
-		uint32_t idx( index.first( hash ) );
-		while ( idx != T_HashIndex::INVALID_INDEX ) {
-			if ( values[ idx ] == p ) {
-				break;
-			}
-			idx = index.next( idx );
-		}
-		if ( idx == T_HashIndex::INVALID_INDEX ) {
-			index.add( hash );
-			values.add( p );
-		}
-	}
-	return true;
-}
-
-inline T_VFSDataIndex::T_FileInfo const* T_VFSDataIndexPrivate_::getFileInfo(
-		T_VFSPath const& path ) const
-{
-	T_EntryInfo const* eptr( entries_.get( path ) );
-	if ( eptr == nullptr || !eptr->isFile ) {
-		return nullptr;
-	}
-	return &files_[ eptr->index ];
-}
-
-
-/*= T_VFSDataIndex ===========================================================*/
-
-T_VFSDataIndex::T_VFSDataIndex(
-		uint32_t magic )
-	: A_PrivateImplementation( new T_VFSDataIndexPrivate_( magic ) )
-{ }
-
-/*----------------------------------------------------------------------------*/
-
-bool T_VFSDataIndex::readIndex(
-		T_BinaryReader& reader )
-{
-	return p< T_VFSDataIndexPrivate_ >( ).readIndex( reader );
-}
-
-void T_VFSDataIndex::free( )
-{
-	return p< T_VFSDataIndexPrivate_ >( ).free( );
-}
-
-/*----------------------------------------------------------------------------*/
-
-E_VFSEntryType T_VFSDataIndex::typeOf(
-		T_VFSPath const& path ) const
-{
-	return p< T_VFSDataIndexPrivate_ >( ).typeOf( path );
-}
-
-bool T_VFSDataIndex::list(
-		T_VFSPath const& path ,
-		T_Array< T_VFSPath >& values ,
-		T_HashIndex& index ) const
-{
-	return p< T_VFSDataIndexPrivate_ >( ).list( path , values , index );
-}
-
-T_VFSDataIndex::T_FileInfo const* T_VFSDataIndex::getFileInfo(
-		T_VFSPath const& path ) const
-{
-	return p< T_VFSDataIndexPrivate_ >( ).getFileInfo( path );
-}
-
-
-/*= T_VFSRomDriverStream_ ====================================================*/
-
-namespace lw {
-
-M_CLASS_POINTERS( VFSRomDriverStream_ );
-class T_VFSRomDriverStream_ : public A_InputStream
-{
-    private:
-	RP_VFSRomDriverStream_& head_;
-	T_ReadWriteMutex& mutex_;
-
-	RP_VFSRomDriverStream_ prev_;
-	RP_VFSRomDriverStream_ next_;
-	OP_MemoryInputStream actual_;
-	
-    public:
-	T_VFSRomDriverStream_( ) = delete;
-	T_VFSRomDriverStream_( T_VFSRomDriverStream_ const& ) = delete;
-	T_VFSRomDriverStream_( T_VFSRomDriverStream_&& ) = delete;
-
-	T_VFSRomDriverStream_( RP_VFSRomDriverStream_& head ,
-			T_ReadWriteMutex& mutex ,
-			OP_MemoryInputStream&& stream );
-	~T_VFSRomDriverStream_( );
-
-	size_t read( void* data , size_t size ) override;
-
-	void disable( );
-};
-
-}
-
-/*----------------------------------------------------------------------------*/
-
-T_VFSRomDriverStream_::T_VFSRomDriverStream_( RP_VFSRomDriverStream_& head ,
-		T_ReadWriteMutex& mutex ,
-		OP_MemoryInputStream&& stream )
-	: A_InputStream( stream->position( ) , stream->size( ) ) ,
-		head_( head ) , mutex_( mutex ) ,
-		prev_( nullptr ) , next_( head ) ,
-		actual_( std::move( stream ) )
-{
-	head = this;
-	if ( next_ ) {
-		next_->prev_ = this;
-	}
-}
-
-T_VFSRomDriverStream_::~T_VFSRomDriverStream_( )
-{
-	T_WriteLock lock( mutex_ );
-	disable( );
-}
-
-size_t T_VFSRomDriverStream_::read( void* data , size_t size )
-{
-	T_ReadLock lock( mutex_ );
-	if ( actual_ ) {
-		return actual_->read( data , size );
-	} else {
-		throw X_StreamError( E_StreamError::UNAVAILABLE );
-	}
-}
-
-void T_VFSRomDriverStream_::disable( )
-{
-	actual_.clear( );
-	if ( prev_ == nullptr ) {
-		head_ = next_;
-	} else {
-		prev_->next_ = next_;
-	}
-	if ( next_ != nullptr ) {
-		next_->prev_ = prev_;
-	}
-}
-
-
-/*= T_VFSRomDriverPrivate_ ===================================================*/
-
-struct T_VFSRomDriverPrivate_
-{
-	uint8_t const* data_;
-	uint32_t size_;
-	T_VFSDataIndex index_;
-	T_ReadWriteMutex mutex_;
-	T_VFSRomDriverStream_* streams_;
-
-	T_VFSRomDriverPrivate_(
-			uint8_t const* const data ,
-			uint32_t const size );
-};
-
-/*----------------------------------------------------------------------------*/
-
-inline T_VFSRomDriverPrivate_::T_VFSRomDriverPrivate_(
-		uint8_t const* const data ,
-		uint32_t const size )
-	: data_( data ) , size_( size ) ,
-		index_( T_VFSRomDriver::C_MAGIC ) ,
-		streams_( nullptr )
-{
-	assert( data_ != nullptr );
-	assert( size_ > 0 );
-}
-
-
-/*= T_VFSRomDriver ===========================================================*/
-
-constexpr uint32_t T_VFSRomDriver::C_MAGIC;
-
-/*----------------------------------------------------------------------------*/
-
-T_VFSRomDriver::T_VFSRomDriver(
-		uint8_t const* const data ,
-		uint32_t const size )
-	: A_PrivateImplementation( new T_VFSRomDriverPrivate_( data , size ) )
-{ }
-
-/*----------------------------------------------------------------------------*/
-
-uint8_t const* T_VFSRomDriver::data( ) const
-{
-	return p< T_VFSRomDriverPrivate_ >( ).data_;
-}
-
-uint32_t T_VFSRomDriver::size( ) const
-{
-	return p< T_VFSRomDriverPrivate_ >( ).size_;
-}
-
-/*----------------------------------------------------------------------------*/
-
-bool T_VFSRomDriver::init( )
-{
-	auto& pi( p< T_VFSRomDriverPrivate_ >( ) );
-	T_MemoryInputStream input( pi.data_ , pi.size_ );
-	T_BinaryReader reader( input , E_Endian::NATIVE );
-	bool rv;
-	try {
-		rv = pi.index_.readIndex( reader );
-	} catch ( X_StreamError const& ) {
-		rv = false;
-	}
-	if ( !rv ) {
-		pi.index_.free( );
-	}
-	return rv;
-}
-
-void T_VFSRomDriver::shutdown( )
-{
-	auto& pi( p< T_VFSRomDriverPrivate_ >( ) );
-	T_WriteLock lock( pi.mutex_ );
-	while ( pi.streams_ != nullptr ) {
-		pi.streams_->disable( );
-	}
-	pi.index_.free( );
-}
-
-/*----------------------------------------------------------------------------*/
-
-E_VFSEntryType T_VFSRomDriver::typeOf( T_VFSPath const& path )
-{
-	auto& pi( p< T_VFSRomDriverPrivate_ >( ) );
-	T_ReadLock lock( pi.mutex_ );
-	return pi.index_.typeOf( path );
-}
-
-bool T_VFSRomDriver::list( T_VFSPath const& path , T_Array< T_VFSPath >& values , T_HashIndex& index )
-{
-	auto& pi( p< T_VFSRomDriverPrivate_ >( ) );
-	T_ReadLock lock( pi.mutex_ );
-	return pi.index_.list( path , values , index );
-}
-
-OP_InputStream T_VFSRomDriver::read( T_VFSPath const& path )
-{
-	auto& pi( p< T_VFSRomDriverPrivate_ >( ) );
-	T_ReadLock lock( pi.mutex_ );
-	T_VFSDataIndex::T_FileInfo const* p( pi.index_.getFileInfo( path ) );
-	if ( p == nullptr ) {
-		return OP_InputStream( );
-	}
-
-	T_WriteLock wLock( lock.upgrade( ) );
-	return NewOwned< T_VFSRomDriverStream_ >( pi.streams_ , pi.mutex_ ,
-			NewOwned< T_MemoryInputStream >( pi.data_ + p->offset , p->size ) );
-}
-
-
-/*= T_VFSDataFileDriverStream_ ===============================================*/
-
-namespace lw {
-
-M_CLASS_POINTERS( VFSDataFileDriverStream_ );
-class T_VFSDataFileDriverStream_ : public A_InputStream
-{
-    private:
-	RP_VFSDataFileDriverStream_& head_;
-	T_Mutex& mutex_;
-
-	RP_VFSDataFileDriverStream_ prev_;
-	RP_VFSDataFileDriverStream_ next_;
-	OP_FileInputStream actual_;
-	
-    public:
-	T_VFSDataFileDriverStream_( ) = delete;
-	T_VFSDataFileDriverStream_( T_VFSDataFileDriverStream_ const& ) = delete;
-	T_VFSDataFileDriverStream_( T_VFSDataFileDriverStream_&& ) = delete;
-
-	T_VFSDataFileDriverStream_( RP_VFSDataFileDriverStream_& head , T_Mutex& mutex ,
-			OP_FileInputStream&& stream );
-	~T_VFSDataFileDriverStream_( );
-
-	size_t read( void* data , size_t size ) override;
-
-	void disable( );
-};
-
-}
-
-/*----------------------------------------------------------------------------*/
-
-T_VFSDataFileDriverStream_::T_VFSDataFileDriverStream_(
-		RP_VFSDataFileDriverStream_& head , T_Mutex& mutex ,
-		OP_FileInputStream&& stream )
-	: A_InputStream( stream->position( ) , stream->size( ) ) ,
-		head_( head ) , mutex_( mutex ) ,
-		prev_( nullptr ) , next_( head ) ,
-		actual_( std::move( stream ) )
-{
-	head = this;
-	if ( next_ ) {
-		next_->prev_ = this;
-	}
-}
-
-T_VFSDataFileDriverStream_::~T_VFSDataFileDriverStream_( )
-{
-	T_ScopeLock lock( mutex_ );
-	disable( );
-}
-
-size_t T_VFSDataFileDriverStream_::read( void* data , size_t size )
-{
-	T_ScopeLock lock( mutex_ );
-	if ( actual_ ) {
-		return actual_->read( data , size );
-	} else {
-		throw X_StreamError( E_StreamError::UNAVAILABLE );
-	}
-}
-
-void T_VFSDataFileDriverStream_::disable( )
-{
-	actual_.clear( );
-	if ( prev_ == nullptr ) {
-		head_ = next_;
-	} else {
-		prev_->next_ = next_;
-	}
-	if ( next_ != nullptr ) {
-		next_->prev_ = prev_;
-	}
-}
-
-
-/*= T_VFSDataFileDriverPrivate_ ==============================================*/
-
-namespace {
-struct T_VFSDataFileDriverPrivate_
-{
-	T_Mutex mutex_;
-	OP_File file_;
-	T_VFSDataIndex index_;
-	T_VFSDataFileDriverStream_* streams_;
-
-	explicit T_VFSDataFileDriverPrivate_(
-			OP_File&& file );
-};
-} // namespace
-
-/*----------------------------------------------------------------------------*/
-
-T_VFSDataFileDriverPrivate_::T_VFSDataFileDriverPrivate_(
-		OP_File&& file )
-	: file_( std::move( file ) ) ,
-		index_( T_VFSDataFileDriver::C_MAGIC ) ,
-		streams_( nullptr )
-{
-	assert( file_ );
-}
-
-
-/*= T_VFSDataFileDriver ======================================================*/
-
-T_VFSDataFileDriver::T_VFSDataFileDriver( OP_File&& file )
-	: A_PrivateImplementation( new T_VFSDataFileDriverPrivate_( std::move( file ) ) )
-{ }
-
-/*----------------------------------------------------------------------------*/
-
-T_File const& T_VFSDataFileDriver::dataFile( ) const
-{
-	return *( p< T_VFSDataFileDriverPrivate_ >( ).file_ );
-}
-
-/*----------------------------------------------------------------------------*/
-
-bool T_VFSDataFileDriver::init( )
-{
-	auto& pi( p< T_VFSDataFileDriverPrivate_ >( ) );
-	bool rv;
-	try {
-		T_FileInputStream input( *pi.file_ , 0 );
-		T_BinaryReader reader( input , E_Endian::NATIVE );
-		rv = pi.index_.readIndex( reader );
-	} catch ( X_StreamError const& ) {
-		rv = false;
-	}
-	if ( !rv ) {
-		pi.index_.free( );
-	}
-	return rv;
-}
-
-void T_VFSDataFileDriver::shutdown( )
-{
-	auto& pi( p< T_VFSDataFileDriverPrivate_ >( ) );
-	T_ScopeLock lock( pi.mutex_ );
-	while ( pi.streams_ != nullptr ) {
-		pi.streams_->disable( );
-	}
-	pi.index_.free( );
-	pi.file_->close( );
-}
-
-/*----------------------------------------------------------------------------*/
-
-E_VFSEntryType T_VFSDataFileDriver::typeOf( T_VFSPath const& path )
-{
-	auto& pi( p< T_VFSDataFileDriverPrivate_ >( ) );
-	T_ScopeLock lock( pi.mutex_ );
-	return pi.index_.typeOf( path );
-}
-
-bool T_VFSDataFileDriver::list( T_VFSPath const& path , T_Array< T_VFSPath >& values , T_HashIndex& index )
-{
-	auto& pi( p< T_VFSDataFileDriverPrivate_ >( ) );
-	T_ScopeLock lock( pi.mutex_ );
-	return pi.index_.list( path , values , index );
-}
-
-OP_InputStream T_VFSDataFileDriver::read( T_VFSPath const& path )
-{
-	auto& pi( p< T_VFSDataFileDriverPrivate_ >( ) );
-	T_ScopeLock lock( pi.mutex_ );
-	T_VFSDataIndex::T_FileInfo const* p( pi.index_.getFileInfo( path ) );
-	if ( p == nullptr ) {
-		return OP_InputStream( );
-	}
-	pi.file_->position( p->offset );
-	return NewOwned< T_VFSDataFileDriverStream_ >( pi.streams_ , pi.mutex_ ,
-			NewOwned< T_FileInputStream >( *pi.file_ , 0 , p->size ) );
-}
diff --git a/src/files.mk b/src/files.mk
index 78bab9e..28885db 100644
--- a/src/files.mk
+++ b/src/files.mk
@@ -1,34 +1,18 @@
 LIB_SOURCES = \
+	src/DynLib.cc \
 	src/Files.cc \
 	src/HashIndex.cc \
 	src/MemoryStreams.cc \
 	src/Pointers.cc \
+	src/SRDBinary.cc \
+	src/SRDData.cc \
+	src/SRDDefinitions.cc \
+	src/SRDIO.cc \
+	src/SRDParser.cc \
+	src/SRDParserConfig.cc \
+	src/SRDText.cc \
 	src/Streams.cc \
 	src/Strings.cc \
 	src/TemplateInstantiation.cc \
 	src/Utilities.cc \
 # END
-
-#
-#	src/SRDBinary.cc \
-#	src/SRDData.cc \
-#	src/SRDDefinitions.cc \
-#	src/SRDIO.cc \
-#	src/SRDParser.cc \
-#	src/SRDParserConfig.cc \
-#	src/SRDPreproc.cc \
-#	src/SRDPPCommands.cc \
-#	src/SRDText.cc \
-#	src/VFS.cc \
-#	src/VFSDrivers.cc \
-#	src/Console.cc \
-#	src/ConsoleLogWriter.cc \
-#	src/CwdFileLogger.cc \
-#	src/DynLib.cc \
-#	src/GameLoop.cc \
-#	src/LW.cc \
-#	src/Log.cc \
-#	src/Messages.cc \
-#	src/ModInterface.cc \
-#	src/Mods.cc \
-#	src/TextFileLogger.cc
diff --git a/tests/alloc-pool.cc b/tests/alloc-pool.cc
index d82fa43..6f610d1 100644
--- a/tests/alloc-pool.cc
+++ b/tests/alloc-pool.cc
@@ -1,7 +1,7 @@
-#include <lw/lib/Alloc.hh>
-#include <lw/lib/Pointers.hh>
+#include <ebcl/Alloc.hh>
+#include <ebcl/Pointers.hh>
 #include <cppunit/extensions/HelperMacros.h>
-using namespace lw;
+using namespace ebcl;
 
 
 class AllocPoolTest : public CppUnit::TestFixture
diff --git a/tests/console-edit.cc b/tests/console-edit.cc
deleted file mode 100644
index 8338f5b..0000000
--- a/tests/console-edit.cc
+++ /dev/null
@@ -1,468 +0,0 @@
-#include <lw/lib/Console.hh>
-#include <cppunit/extensions/HelperMacros.h>
-using namespace lw;
-
-
-class ConsoleEditTest : public CppUnit::TestFixture
-{
-	CPPUNIT_TEST_SUITE( ConsoleEditTest );
-		CPPUNIT_TEST( testEmpty );
-		CPPUNIT_TEST( testSetContents );
-		CPPUNIT_TEST( testReset );
-
-		CPPUNIT_TEST( testCursorStart );
-		CPPUNIT_TEST( testCursorStartEmpty );
-		CPPUNIT_TEST( testCursorEnd );
-		CPPUNIT_TEST( testCursorEndEmpty );
-		CPPUNIT_TEST( testCursorLeft );
-		CPPUNIT_TEST( testCursorLeftStart );
-		CPPUNIT_TEST( testCursorRight );
-		CPPUNIT_TEST( testCursorRightEnd );
-
-		CPPUNIT_TEST( testAppendCharacter );
-		CPPUNIT_TEST( testInsertCharacter );
-		CPPUNIT_TEST( testAppendBuffer );
-		CPPUNIT_TEST( testInsertBuffer );
-
-		CPPUNIT_TEST( testPrevWordStart );
-		CPPUNIT_TEST( testPrevWordInWord );
-		CPPUNIT_TEST( testPrevWordSpaces );
-		CPPUNIT_TEST( testNextWordEnd );
-		CPPUNIT_TEST( testNextWordInWord );
-		CPPUNIT_TEST( testNextWordSpaces );
-
-		CPPUNIT_TEST( testRmCharAtEnd );
-		CPPUNIT_TEST( testRmCharLast );
-		CPPUNIT_TEST( testRmCharMiddle );
-
-		CPPUNIT_TEST( testRmWordAtEnd );
-		CPPUNIT_TEST( testRmWordMiddle );
-		CPPUNIT_TEST( testRmWordAtStart );
-
-		CPPUNIT_TEST( testRmRestAtStart );
-		CPPUNIT_TEST( testRmRestMiddle );
-		CPPUNIT_TEST( testRmRestAtEnd );
-	CPPUNIT_TEST_SUITE_END( );
-
-public:
-	void testEmpty( );
-	void testSetContents( );
-	void testReset( );
-
-	void testCursorStart( );
-	void testCursorStartEmpty( );
-	void testCursorEnd( );
-	void testCursorEndEmpty( );
-	void testCursorLeft( );
-	void testCursorLeftStart( );
-	void testCursorRight( );
-	void testCursorRightEnd( );
-
-	void testAppendCharacter( );
-	void testInsertCharacter( );
-	void testAppendBuffer( );
-	void testInsertBuffer( );
-
-	void testPrevWordStart( );
-	void testPrevWordInWord( );
-	void testPrevWordSpaces( );
-	void testNextWordEnd( );
-	void testNextWordInWord( );
-	void testNextWordSpaces( );
-
-	void testRmCharAtEnd( );
-	void testRmCharLast( );
-	void testRmCharMiddle( );
-
-	void testRmWordAtEnd( );
-	void testRmWordMiddle( );
-	void testRmWordAtStart( );
-
-	void testRmRestAtStart( );
-	void testRmRestMiddle( );
-	void testRmRestAtEnd( );
-};
-CPPUNIT_TEST_SUITE_REGISTRATION( ConsoleEditTest );
-
-/*----------------------------------------------------------------------------*/
-
-void ConsoleEditTest::testEmpty( )
-{
-	T_ConsoleLineState s;
-	CPPUNIT_ASSERT( s.getContents( ) == "" );
-	CPPUNIT_ASSERT_EQUAL( 0u , s.size( ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , s.pos( ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , s.historyIndex( ) );
-}
-
-void ConsoleEditTest::testSetContents( )
-{
-	const T_String str( "t\xe2\x82\xacst" );
-	T_ConsoleLineState s;
-	s.setContents( str , 1 );
-	CPPUNIT_ASSERT( s.getContents( ) == str );
-	CPPUNIT_ASSERT_EQUAL( 4u , s.size( ) );
-	CPPUNIT_ASSERT_EQUAL( 4u , s.pos( ) );
-	CPPUNIT_ASSERT_EQUAL( 1u , s.historyIndex( ) );
-}
-
-void ConsoleEditTest::testReset( )
-{
-	const T_String str( "t\xe2\x82\xacst" );
-	T_ConsoleLineState s;
-	s.setContents( str , 1 );
-	s.reset( );
-	CPPUNIT_ASSERT( s.getContents( ) == "" );
-	CPPUNIT_ASSERT_EQUAL( 0u , s.size( ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , s.pos( ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , s.historyIndex( ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void ConsoleEditTest::testCursorStart( )
-{
-	const T_String str( "t\xe2\x82\xacst" );
-	T_ConsoleLineState s;
-	s.setContents( str , 0 );
-	s.toStart( );
-	CPPUNIT_ASSERT_EQUAL( 4u , s.size( ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , s.pos( ) );
-}
-
-void ConsoleEditTest::testCursorStartEmpty( )
-{
-	T_ConsoleLineState s;
-	s.toStart( );
-	CPPUNIT_ASSERT_EQUAL( 0u , s.size( ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , s.pos( ) );
-}
-
-void ConsoleEditTest::testCursorEnd( )
-{
-	const T_String str( "t\xe2\x82\xacst" );
-	T_ConsoleLineState s;
-	s.setContents( str , 0 );
-	s.toStart( );
-	s.toEnd( );
-	CPPUNIT_ASSERT_EQUAL( 4u , s.size( ) );
-	CPPUNIT_ASSERT_EQUAL( 4u , s.pos( ) );
-}
-
-void ConsoleEditTest::testCursorEndEmpty( )
-{
-	T_ConsoleLineState s;
-	s.toEnd( );
-	CPPUNIT_ASSERT_EQUAL( 0u , s.size( ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , s.pos( ) );
-}
-
-void ConsoleEditTest::testCursorLeft( )
-{
-	const T_String str( "t\xe2\x82\xacst" );
-	T_ConsoleLineState s;
-	s.setContents( str , 0 );
-	s.left( );
-	CPPUNIT_ASSERT_EQUAL( 4u , s.size( ) );
-	CPPUNIT_ASSERT_EQUAL( 3u , s.pos( ) );
-}
-
-void ConsoleEditTest::testCursorLeftStart( )
-{
-	T_ConsoleLineState s;
-	s.left( );
-	CPPUNIT_ASSERT_EQUAL( 0u , s.size( ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , s.pos( ) );
-}
-
-void ConsoleEditTest::testCursorRight( )
-{
-	const T_String str( "t\xe2\x82\xacst" );
-	T_ConsoleLineState s;
-	s.setContents( str , 0 );
-	s.toStart( );
-	s.right( );
-	CPPUNIT_ASSERT_EQUAL( 4u , s.size( ) );
-	CPPUNIT_ASSERT_EQUAL( 1u , s.pos( ) );
-}
-
-void ConsoleEditTest::testCursorRightEnd( )
-{
-	T_ConsoleLineState s;
-	s.right( );
-	CPPUNIT_ASSERT_EQUAL( 0u , s.size( ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , s.pos( ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void ConsoleEditTest::testAppendCharacter( )
-{
-	const T_String str( "t\xe2\x82\xacst" );
-	T_ConsoleLineState s;
-	s.insert( 't' );
-	s.insert( 0x20ac );
-	s.insert( 's' );
-	s.insert( 't' );
-	CPPUNIT_ASSERT( s.getContents( ) == str );
-	CPPUNIT_ASSERT_EQUAL( 4u , s.size( ) );
-	CPPUNIT_ASSERT_EQUAL( 4u , s.pos( ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , s.historyIndex( ) );
-}
-
-void ConsoleEditTest::testInsertCharacter( )
-{
-	const T_String str( "t\xe2\x82\xacst" );
-	T_ConsoleLineState s;
-	s.insert( 0x20ac );
-	s.insert( 's' );
-	s.insert( 't' );
-	s.toStart( );
-	s.insert( 't' );
-	CPPUNIT_ASSERT( s.getContents( ) == str );
-	CPPUNIT_ASSERT_EQUAL( 4u , s.size( ) );
-	CPPUNIT_ASSERT_EQUAL( 1u , s.pos( ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , s.historyIndex( ) );
-}
-
-void ConsoleEditTest::testAppendBuffer( )
-{
-	const T_String str( "t\xe2\x82\xacst" );
-	T_Buffer< uint32_t > b( 4 );
-	b[ 0 ] = b[ 3 ] = 't';
-	b[ 1 ] = 0x20ac;
-	b[ 2 ] = 's';
-
-	T_ConsoleLineState s;
-	s.insert( b , 4 );
-	CPPUNIT_ASSERT( s.getContents( ) == str );
-	CPPUNIT_ASSERT_EQUAL( 4u , s.size( ) );
-	CPPUNIT_ASSERT_EQUAL( 4u , s.pos( ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , s.historyIndex( ) );
-}
-
-void ConsoleEditTest::testInsertBuffer( )
-{
-	const T_String str( "t\xe2\x82\xacst" );
-	T_Buffer< uint32_t > b( 3 );
-	b[ 0 ] = 't';
-	b[ 1 ] = 0x20ac;
-	b[ 2 ] = 's';
-
-	T_ConsoleLineState s;
-	s.insert( 't' );
-	s.toStart( );
-	s.insert( b , 3 );
-
-	CPPUNIT_ASSERT( s.getContents( ) == str );
-	CPPUNIT_ASSERT_EQUAL( 4u , s.size( ) );
-	CPPUNIT_ASSERT_EQUAL( 3u , s.pos( ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , s.historyIndex( ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void ConsoleEditTest::testPrevWordStart( )
-{
-	const T_String str( "t\xe2\x82\xacst  " );
-	T_ConsoleLineState s;
-	s.setContents( str , 0 );
-	s.toStart( );
-	s.prevWord( );
-	CPPUNIT_ASSERT_EQUAL( 0u , s.pos( ) );
-}
-
-void ConsoleEditTest::testPrevWordInWord( )
-{
-	const T_String str( " t\xe2\x82\xacst" );
-	T_ConsoleLineState s;
-	s.setContents( str , 0 );
-	s.prevWord( );
-	CPPUNIT_ASSERT_EQUAL( 1u , s.pos( ) );
-}
-
-void ConsoleEditTest::testPrevWordSpaces( )
-{
-	const T_String str( " t\xe2\x82\xacst  " );
-	T_ConsoleLineState s;
-	s.setContents( str , 0 );
-	s.prevWord( );
-	CPPUNIT_ASSERT_EQUAL( 1u , s.pos( ) );
-}
-
-void ConsoleEditTest::testNextWordEnd( )
-{
-	const T_String str( "t\xe2\x82\xacst  " );
-	T_ConsoleLineState s;
-	s.setContents( str , 0 );
-	s.nextWord( );
-	CPPUNIT_ASSERT_EQUAL( s.size( ) , s.pos( ) );
-}
-
-void ConsoleEditTest::testNextWordInWord( )
-{
-	const T_String str( "t\xe2\x82\xacst  " );
-	T_ConsoleLineState s;
-	s.setContents( str , 0 );
-	s.toStart( );
-	s.nextWord( );
-	CPPUNIT_ASSERT_EQUAL( 4u , s.pos( ) );
-}
-
-void ConsoleEditTest::testNextWordSpaces( )
-{
-	const T_String str( "  t\xe2\x82\xacst  " );
-	T_ConsoleLineState s;
-	s.setContents( str , 0 );
-	s.toStart( );
-	s.nextWord( );
-	CPPUNIT_ASSERT_EQUAL( 6u , s.pos( ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void ConsoleEditTest::testRmCharAtEnd( )
-{
-	const T_String str( "test" );
-	T_ConsoleLineState s;
-	s.setContents( str , 0 );
-	s.removeCharacter( );
-	CPPUNIT_ASSERT( s.getContents( ) == "test" );
-	CPPUNIT_ASSERT_EQUAL( 4u , s.pos( ) );
-	CPPUNIT_ASSERT_EQUAL( 4u , s.size( ) );
-}
-
-void ConsoleEditTest::testRmCharLast( )
-{
-	const T_String str( "test" );
-	T_ConsoleLineState s;
-	s.setContents( str , 0 );
-	s.left( );
-	s.removeCharacter( );
-	CPPUNIT_ASSERT( s.getContents( ) == "tes" );
-	CPPUNIT_ASSERT_EQUAL( 3u , s.pos( ) );
-	CPPUNIT_ASSERT_EQUAL( 3u , s.size( ) );
-}
-
-void ConsoleEditTest::testRmCharMiddle( )
-{
-	const T_String str( "test" );
-	T_ConsoleLineState s;
-	s.setContents( str , 0 );
-	s.toStart( );
-	s.removeCharacter( );
-	CPPUNIT_ASSERT( s.getContents( ) == "est" );
-	CPPUNIT_ASSERT_EQUAL( 0u , s.pos( ) );
-	CPPUNIT_ASSERT_EQUAL( 3u , s.size( ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void ConsoleEditTest::testRmWordAtEnd( )
-{
-	const T_String str( "test blah" );
-	T_ConsoleLineState s;
-	s.setContents( str , 0 );
-	T_Buffer< uint32_t > cpb;
-	uint32_t cpl( 572 );
-	s.removeWord( cpb , cpl );
-	CPPUNIT_ASSERT( s.getContents( ) == "test " );
-	CPPUNIT_ASSERT_EQUAL( 5u , s.pos( ) );
-	CPPUNIT_ASSERT_EQUAL( 5u , s.size( ) );
-	CPPUNIT_ASSERT_EQUAL( 4u , cpl );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 'b' ) , cpb[ 0 ] );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 'l' ) , cpb[ 1 ] );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 'a' ) , cpb[ 2 ] );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 'h' ) , cpb[ 3 ] );
-}
-
-void ConsoleEditTest::testRmWordMiddle( )
-{
-	const T_String str( "test blah" );
-	T_ConsoleLineState s;
-	s.setContents( str , 0 );
-	s.left( );
-	s.left( );
-	s.left( );
-	s.left( );
-	T_Buffer< uint32_t > cpb;
-	uint32_t cpl( 572 );
-	s.removeWord( cpb , cpl );
-	CPPUNIT_ASSERT( s.getContents( ) == "blah" );
-	CPPUNIT_ASSERT_EQUAL( 0u , s.pos( ) );
-	CPPUNIT_ASSERT_EQUAL( 4u , s.size( ) );
-	CPPUNIT_ASSERT_EQUAL( 5u , cpl );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 't' ) , cpb[ 0 ] );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 'e' ) , cpb[ 1 ] );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 's' ) , cpb[ 2 ] );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 't' ) , cpb[ 3 ] );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( ' ' ) , cpb[ 4 ] );
-}
-
-void ConsoleEditTest::testRmWordAtStart( )
-{
-	const T_String str( "test blah" );
-	T_ConsoleLineState s;
-	s.setContents( str , 0 );
-	s.toStart( );
-	T_Buffer< uint32_t > cpb;
-	uint32_t cpl( 572 );
-	s.removeWord( cpb , cpl );
-	CPPUNIT_ASSERT( s.getContents( ) == "test blah" );
-	CPPUNIT_ASSERT_EQUAL( 0u , s.pos( ) );
-	CPPUNIT_ASSERT_EQUAL( 9u , s.size( ) );
-	CPPUNIT_ASSERT_EQUAL( 572u , cpl );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void ConsoleEditTest::testRmRestAtStart( )
-{
-	const T_String str( "test" );
-	T_ConsoleLineState s;
-	s.setContents( str , 0 );
-	s.toStart( );
-	T_Buffer< uint32_t > cpb;
-	uint32_t cpl( 572 );
-	s.removeRestOfLine( cpb , cpl );
-	CPPUNIT_ASSERT( s.getContents( ) == "" );
-	CPPUNIT_ASSERT_EQUAL( 0u , s.pos( ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , s.size( ) );
-	CPPUNIT_ASSERT_EQUAL( 4u , cpl );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 't' ) , cpb[ 0 ] );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 'e' ) , cpb[ 1 ] );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 's' ) , cpb[ 2 ] );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 't' ) , cpb[ 3 ] );
-}
-
-void ConsoleEditTest::testRmRestMiddle( )
-{
-	const T_String str( "test" );
-	T_ConsoleLineState s;
-	s.setContents( str , 0 );
-	s.left( );
-	s.left( );
-	T_Buffer< uint32_t > cpb;
-	uint32_t cpl( 572 );
-	s.removeRestOfLine( cpb , cpl );
-	CPPUNIT_ASSERT( s.getContents( ) == "te" );
-	CPPUNIT_ASSERT_EQUAL( 2u , s.pos( ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , s.size( ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , cpl );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 's' ) , cpb[ 0 ] );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 't' ) , cpb[ 1 ] );
-}
-
-void ConsoleEditTest::testRmRestAtEnd( )
-{
-	const T_String str( "test" );
-	T_ConsoleLineState s;
-	s.setContents( str , 0 );
-	T_Buffer< uint32_t > cpb;
-	uint32_t cpl( 572 );
-	s.removeRestOfLine( cpb , cpl );
-	CPPUNIT_ASSERT( s.getContents( ) == "test" );
-	CPPUNIT_ASSERT_EQUAL( 4u , s.pos( ) );
-	CPPUNIT_ASSERT_EQUAL( 4u , s.size( ) );
-	CPPUNIT_ASSERT_EQUAL( 572u , cpl );
-}
diff --git a/tests/console-text.cc b/tests/console-text.cc
deleted file mode 100644
index 233aabf..0000000
--- a/tests/console-text.cc
+++ /dev/null
@@ -1,405 +0,0 @@
-#include <lw/lib/Console.hh>
-#include <cppunit/extensions/HelperMacros.h>
-using namespace lw;
-
-
-class ConsoleTextTest : public CppUnit::TestFixture
-{
-	CPPUNIT_TEST_SUITE( ConsoleTextTest );
-		CPPUNIT_TEST( testEmpty );
-		CPPUNIT_TEST( testSimpleString );
-
-		CPPUNIT_TEST( testChangeStyle );
-		CPPUNIT_TEST( testChangeStyleTwice );
-		CPPUNIT_TEST( testChangeStyleAtEnd );
-
-		CPPUNIT_TEST( testChangeColor );
-		CPPUNIT_TEST( testChangeColorTwice );
-		CPPUNIT_TEST( testChangeColorAtEnd );
-
-		CPPUNIT_TEST( testChangeColorAndStyle );
-
-		CPPUNIT_TEST( testTextCopyCons );
-		CPPUNIT_TEST( testTextCopyAss );
-		CPPUNIT_TEST( testTextMoveCons );
-		CPPUNIT_TEST( testTextMoveAss );
-		CPPUNIT_TEST( testTextSwap );
-
-		CPPUNIT_TEST( testBuilderCopyCons );
-		CPPUNIT_TEST( testBuilderCopyAss );
-		CPPUNIT_TEST( testBuilderMoveCons );
-		CPPUNIT_TEST( testBuilderMoveAss );
-		CPPUNIT_TEST( testBuilderSwap );
-	CPPUNIT_TEST_SUITE_END( );
-
-public:
-	void testEmpty( );
-	void testSimpleString( );
-
-	void testChangeStyle( );
-	void testChangeStyleTwice( );
-	void testChangeStyleAtEnd( );
-
-	void testChangeColor( );
-	void testChangeColorTwice( );
-	void testChangeColorAtEnd( );
-
-	void testChangeColorAndStyle( );
-
-	void testTextCopyCons( );
-	void testTextCopyAss( );
-	void testTextMoveCons( );
-	void testTextMoveAss( );
-	void testTextSwap( );
-
-	void testBuilderCopyCons( );
-	void testBuilderCopyAss( );
-	void testBuilderMoveCons( );
-	void testBuilderMoveAss( );
-	void testBuilderSwap( );
-};
-CPPUNIT_TEST_SUITE_REGISTRATION( ConsoleTextTest );
-
-/*----------------------------------------------------------------------------*/
-
-void ConsoleTextTest::testEmpty( )
-{
-	T_TextBuilder tb;
-	T_Text t( tb );
-	CPPUNIT_ASSERT( t.string( ) == "" );
-}
-
-void ConsoleTextTest::testSimpleString( )
-{
-	T_TextBuilder tb;
-	tb << "test";
-	T_Text t( tb );
-	CPPUNIT_ASSERT( t.string( ) == "test" );
-	for ( int i = 0 ; i < 4 ; i ++ ) {
-		CPPUNIT_ASSERT_EQUAL( uint8_t( 0 ) , t.styleAt( i ) );
-		CPPUNIT_ASSERT( E_TextColor::WHITE == t.colorAt( i ).type );
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-void ConsoleTextTest::testChangeStyle( )
-{
-	T_TextBuilder tb;
-	tb << "te";
-	tb.addStyle( E_TextStyle::BOLD );
-	tb << "st";
-
-	T_Text t( tb );
-	CPPUNIT_ASSERT( t.string( ) == "test" );
-	for ( int i = 0 ; i < 4 ; i ++ ) {
-		if ( i < 2 ) {
-			CPPUNIT_ASSERT_EQUAL( uint8_t( 0 ) , t.styleAt( i ) );
-		} else {
-			CPPUNIT_ASSERT_EQUAL( uint8_t( E_TextStyle::BOLD ) , t.styleAt( i ) );
-		}
-		CPPUNIT_ASSERT( E_TextColor::WHITE == t.colorAt( i ).type );
-	}
-}
-
-void ConsoleTextTest::testChangeStyleTwice( )
-{
-	T_TextBuilder tb;
-	tb << "te";
-	tb.addStyle( E_TextStyle::BOLD );
-	tb.addStyle( E_TextStyle::ITALIC );
-	tb << "st";
-
-	T_Text t( tb );
-	CPPUNIT_ASSERT( t.string( ) == "test" );
-	for ( int i = 0 ; i < 4 ; i ++ ) {
-		if ( i < 2 ) {
-			CPPUNIT_ASSERT_EQUAL( uint8_t( 0 ) , t.styleAt( i ) );
-		} else {
-			CPPUNIT_ASSERT_EQUAL(
-					uint8_t( uint8_t( E_TextStyle::BOLD ) | uint8_t( E_TextStyle::ITALIC ) ) ,
-					t.styleAt( i ) );
-		}
-		CPPUNIT_ASSERT( E_TextColor::WHITE == t.colorAt( i ).type );
-	}
-}
-
-void ConsoleTextTest::testChangeStyleAtEnd( )
-{
-	T_TextBuilder tb;
-	tb << "test";
-	tb.addStyle( E_TextStyle::BOLD );
-	T_Text t( tb );
-	CPPUNIT_ASSERT( t.string( ) == "test" );
-	for ( int i = 0 ; i < 4 ; i ++ ) {
-		CPPUNIT_ASSERT_EQUAL( uint8_t( 0 ) , t.styleAt( i ) );
-		CPPUNIT_ASSERT( E_TextColor::WHITE == t.colorAt( i ).type );
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-void ConsoleTextTest::testChangeColor( )
-{
-	T_TextBuilder tb;
-	tb << "te";
-	tb.setColor( E_TextColor::RED );
-	tb << "st";
-
-	T_Text t( tb );
-	CPPUNIT_ASSERT( t.string( ) == "test" );
-	for ( int i = 0 ; i < 4 ; i ++ ) {
-		CPPUNIT_ASSERT_EQUAL( uint8_t( 0 ) , t.styleAt( i ) );
-		if ( i < 2 ) {
-			CPPUNIT_ASSERT( E_TextColor::WHITE == t.colorAt( i ).type );
-		} else {
-			CPPUNIT_ASSERT( E_TextColor::RED == t.colorAt( i ).type );
-		}
-	}
-}
-
-void ConsoleTextTest::testChangeColorTwice( )
-{
-	T_TextBuilder tb;
-	tb << "te";
-	tb.setColor( E_TextColor::RED );
-	tb.setColor( E_TextColor::GREEN );
-	tb << "st";
-
-	T_Text t( tb );
-	CPPUNIT_ASSERT( t.string( ) == "test" );
-	for ( int i = 0 ; i < 4 ; i ++ ) {
-		CPPUNIT_ASSERT_EQUAL( uint8_t( 0 ) , t.styleAt( i ) );
-		if ( i < 2 ) {
-			CPPUNIT_ASSERT( E_TextColor::WHITE == t.colorAt( i ).type );
-		} else {
-			CPPUNIT_ASSERT( E_TextColor::GREEN == t.colorAt( i ).type );
-		}
-	}
-}
-
-void ConsoleTextTest::testChangeColorAtEnd( )
-{
-	T_TextBuilder tb;
-	tb << "test";
-	tb.setColor( E_TextColor::GREEN );
-
-	T_Text t( tb );
-	CPPUNIT_ASSERT( t.string( ) == "test" );
-	for ( int i = 0 ; i < 4 ; i ++ ) {
-		CPPUNIT_ASSERT_EQUAL( uint8_t( 0 ) , t.styleAt( i ) );
-		CPPUNIT_ASSERT( E_TextColor::WHITE == t.colorAt( i ).type );
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-void ConsoleTextTest::testChangeColorAndStyle( )
-{
-	T_TextBuilder tb;
-	tb.addStyle( E_TextStyle::BOLD );
-	tb << "te";
-	tb.removeStyle( E_TextStyle::BOLD );
-	tb.setColor( E_TextColor::GREEN );
-	tb << "st";
-
-	T_Text t( tb );
-	CPPUNIT_ASSERT( t.string( ) == "test" );
-	for ( int i = 0 ; i < 4 ; i ++ ) {
-		if ( i < 2 ) {
-			CPPUNIT_ASSERT_EQUAL( uint8_t( E_TextStyle::BOLD ) , t.styleAt( i ) );
-			CPPUNIT_ASSERT( E_TextColor::WHITE == t.colorAt( i ).type );
-		} else {
-			CPPUNIT_ASSERT_EQUAL( uint8_t( 0 ) , t.styleAt( i ) );
-			CPPUNIT_ASSERT( E_TextColor::GREEN == t.colorAt( i ).type );
-		}
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-void ConsoleTextTest::testTextCopyCons( )
-{
-	T_TextBuilder tb;
-	tb << "test";
-
-	T_Text t( tb );
-	T_Text t2( t );
-
-	CPPUNIT_ASSERT( t.string( ) == "test" );
-	CPPUNIT_ASSERT( t2.string( ) == "test" );
-	for ( int i = 0 ; i < 4 ; i ++ ) {
-		CPPUNIT_ASSERT_EQUAL( uint8_t( 0 ) , t.styleAt( i ) );
-		CPPUNIT_ASSERT( E_TextColor::WHITE == t.colorAt( i ).type );
-		CPPUNIT_ASSERT_EQUAL( uint8_t( 0 ) , t2.styleAt( i ) );
-		CPPUNIT_ASSERT( E_TextColor::WHITE == t2.colorAt( i ).type );
-	}
-}
-
-void ConsoleTextTest::testTextCopyAss( )
-{
-	T_TextBuilder tb;
-	tb << "test";
-	T_Text t( tb );
-
-	tb.clear( );
-	tb << "blargh";
-	T_Text t2( tb );
-
-	t2 = t;
-
-	CPPUNIT_ASSERT( t.string( ) == "test" );
-	CPPUNIT_ASSERT( t2.string( ) == "test" );
-	for ( int i = 0 ; i < 4 ; i ++ ) {
-		CPPUNIT_ASSERT_EQUAL( uint8_t( 0 ) , t.styleAt( i ) );
-		CPPUNIT_ASSERT( E_TextColor::WHITE == t.colorAt( i ).type );
-		CPPUNIT_ASSERT_EQUAL( uint8_t( 0 ) , t2.styleAt( i ) );
-		CPPUNIT_ASSERT( E_TextColor::WHITE == t2.colorAt( i ).type );
-	}
-}
-
-void ConsoleTextTest::testTextMoveCons( )
-{
-	T_TextBuilder tb;
-	tb << "test";
-	T_Text t( tb );
-	T_Text t2( std::move( t ) );
-
-	CPPUNIT_ASSERT( t.string( ) == "" );
-	CPPUNIT_ASSERT( t2.string( ) == "test" );
-	for ( int i = 0 ; i < 4 ; i ++ ) {
-		CPPUNIT_ASSERT_EQUAL( uint8_t( 0 ) , t2.styleAt( i ) );
-		CPPUNIT_ASSERT( E_TextColor::WHITE == t2.colorAt( i ).type );
-	}
-}
-
-void ConsoleTextTest::testTextMoveAss( )
-{
-	T_TextBuilder tb;
-	tb << "te";
-	T_Text t2( tb );
-	tb << "st";
-	T_Text t( tb );
-
-	t2 = std::move( t );
-
-	CPPUNIT_ASSERT( t.string( ) == "" );
-	CPPUNIT_ASSERT( t2.string( ) == "test" );
-	for ( int i = 0 ; i < 4 ; i ++ ) {
-		CPPUNIT_ASSERT_EQUAL( uint8_t( 0 ) , t2.styleAt( i ) );
-		CPPUNIT_ASSERT( E_TextColor::WHITE == t2.colorAt( i ).type );
-	}
-}
-
-void ConsoleTextTest::testTextSwap( )
-{
-	T_TextBuilder tb;
-	tb << "test";
-	T_Text t( tb );
-
-	tb.clear( );
-	tb << E_TextStyle::BOLD << "blah";
-	T_Text t2( tb );
-
-	swap( t , t2 );
-
-	CPPUNIT_ASSERT( t.string( ) == "blah" );
-	CPPUNIT_ASSERT( t2.string( ) == "test" );
-	for ( int i = 0 ; i < 4 ; i ++ ) {
-		CPPUNIT_ASSERT_EQUAL( uint8_t( E_TextStyle::BOLD ) , t.styleAt( i ) );
-		CPPUNIT_ASSERT( E_TextColor::WHITE == t.colorAt( i ).type );
-		CPPUNIT_ASSERT_EQUAL( uint8_t( 0 ) , t2.styleAt( i ) );
-		CPPUNIT_ASSERT( E_TextColor::WHITE == t2.colorAt( i ).type );
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-void ConsoleTextTest::testBuilderCopyCons( )
-{
-	T_TextBuilder tb;
-	tb << "test";
-
-	T_TextBuilder tb2( tb );
-	T_Text t( tb ) , t2( tb2 );
-
-	CPPUNIT_ASSERT( t.string( ) == "test" );
-	CPPUNIT_ASSERT( t2.string( ) == "test" );
-	for ( int i = 0 ; i < 4 ; i ++ ) {
-		CPPUNIT_ASSERT_EQUAL( uint8_t( 0 ) , t.styleAt( i ) );
-		CPPUNIT_ASSERT( E_TextColor::WHITE == t.colorAt( i ).type );
-		CPPUNIT_ASSERT_EQUAL( uint8_t( 0 ) , t2.styleAt( i ) );
-		CPPUNIT_ASSERT( E_TextColor::WHITE == t2.colorAt( i ).type );
-	}
-}
-
-void ConsoleTextTest::testBuilderCopyAss( )
-{
-	T_TextBuilder tb , tb2;
-	tb << "test";
-	tb2 << "blah";
-	tb2 = tb;
-	T_Text t( tb ) , t2( tb2 );
-
-	CPPUNIT_ASSERT( t.string( ) == "test" );
-	CPPUNIT_ASSERT( t2.string( ) == "test" );
-	for ( int i = 0 ; i < 4 ; i ++ ) {
-		CPPUNIT_ASSERT_EQUAL( uint8_t( 0 ) , t.styleAt( i ) );
-		CPPUNIT_ASSERT( E_TextColor::WHITE == t.colorAt( i ).type );
-		CPPUNIT_ASSERT_EQUAL( uint8_t( 0 ) , t2.styleAt( i ) );
-		CPPUNIT_ASSERT( E_TextColor::WHITE == t2.colorAt( i ).type );
-	}
-}
-
-void ConsoleTextTest::testBuilderMoveCons( )
-{
-	T_TextBuilder tb;
-	tb << "test";
-
-	T_TextBuilder tb2( std::move( tb ) );
-	T_Text t( tb ) , t2( tb2 );
-
-	CPPUNIT_ASSERT( t.string( ) == "" );
-	CPPUNIT_ASSERT( t2.string( ) == "test" );
-	for ( int i = 0 ; i < 4 ; i ++ ) {
-		CPPUNIT_ASSERT_EQUAL( uint8_t( 0 ) , t2.styleAt( i ) );
-		CPPUNIT_ASSERT( E_TextColor::WHITE == t2.colorAt( i ).type );
-	}
-}
-
-void ConsoleTextTest::testBuilderMoveAss( )
-{
-	T_TextBuilder tb , tb2;
-	tb << "test";
-	tb2 << "blah";
-	tb2 = std::move( tb );
-
-	T_Text t( tb ) , t2( tb2 );
-
-	CPPUNIT_ASSERT( t.string( ) == "" );
-	CPPUNIT_ASSERT( t2.string( ) == "test" );
-	for ( int i = 0 ; i < 4 ; i ++ ) {
-		CPPUNIT_ASSERT_EQUAL( uint8_t( 0 ) , t2.styleAt( i ) );
-		CPPUNIT_ASSERT( E_TextColor::WHITE == t2.colorAt( i ).type );
-	}
-}
-
-void ConsoleTextTest::testBuilderSwap( )
-{
-	T_TextBuilder tb , tb2;
-	tb << "test";
-	tb2 << E_TextStyle::BOLD << "blah";
-	swap( tb , tb2 );
-
-	T_Text t( tb ) , t2( tb2 );
-
-	CPPUNIT_ASSERT( t.string( ) == "blah" );
-	CPPUNIT_ASSERT( t2.string( ) == "test" );
-	for ( int i = 0 ; i < 4 ; i ++ ) {
-		CPPUNIT_ASSERT_EQUAL( uint8_t( E_TextStyle::BOLD ) , t.styleAt( i ) );
-		CPPUNIT_ASSERT( E_TextColor::WHITE == t.colorAt( i ).type );
-		CPPUNIT_ASSERT_EQUAL( uint8_t( 0 ) , t2.styleAt( i ) );
-		CPPUNIT_ASSERT( E_TextColor::WHITE == t2.colorAt( i ).type );
-	}
-}
-
diff --git a/tests/list.mk b/tests/list.mk
index f033b11..e6ddbc5 100644
--- a/tests/list.mk
+++ b/tests/list.mk
@@ -1,4 +1,6 @@
 TESTS = \
+	alloc-pool \
+	ring-buffer \
 	buffers \
 	ptr-owned \
 	ptr-shared \
@@ -22,34 +24,12 @@ TESTS = \
 	hash-index \
 	key-value-table \
 	object-table \
-
-#TESTS = \
-#	alloc-pool \
-#	ring-buffer \
-#	stream-file-input \
-#	srd-bin-reader \
-#	srd-bin-writer \
-#	srd-lexer \
-#	srd-text-writer \
-#	srd-mem-target \
-#	srd-parser \
-#	srd-parser-defs \
-#	srd-parser-cfg \
-#	srd-preproc-core \
-#	srd-preproc-cmd-core \
-#	srd-preproc-cmd-variables \
-#	srd-preproc-cmd-functions \
-#	srd-preproc-cmd-macros \
-#	srd-preproc-cmd-introspect \
-#	srd-preproc-cmd-compare \
-#	srd-preproc-cmd-casts \
-#	srd-preproc-cmd-arithmetic \
-#	srd-preproc-cmd-logic \
-#	srd-preproc-cmd-strings \
-#	srd-preproc-cmd-misc \
-#	srd-preproc-cmd-input \
-#	srd-preproc-tracking \
-#	log-data \
-#	console-text \
-#	console-edit \
-#	vfs
+	srd-mem-target \
+	srd-lexer \
+	srd-text-writer \
+	srd-bin-reader \
+	srd-bin-writer \
+	srd-parser-defs \
+	srd-parser-cfg \
+	srd-parser \
+# END
diff --git a/tests/log-data.cc b/tests/log-data.cc
deleted file mode 100644
index 009c1f0..0000000
--- a/tests/log-data.cc
+++ /dev/null
@@ -1,649 +0,0 @@
-#include <lw/lib/Log.hh>
-#include <cppunit/extensions/HelperMacros.h>
-using namespace lw;
-
-
-class LogLevelTest : public CppUnit::TestFixture
-{
-	CPPUNIT_TEST_SUITE( LogLevelTest );
-		CPPUNIT_TEST( testToString );
-	CPPUNIT_TEST_SUITE_END( );
-
-public:
-	void testToString( );
-};
-CPPUNIT_TEST_SUITE_REGISTRATION( LogLevelTest );
-
-/*----------------------------------------------------------------------------*/
-
-class LogPathTest : public CppUnit::TestFixture
-{
-	CPPUNIT_TEST_SUITE( LogPathTest );
-		CPPUNIT_TEST( testEmpty );
-
-		CPPUNIT_TEST( testArrayCopy );
-		CPPUNIT_TEST( testArrayCopyEmpty );
-		CPPUNIT_TEST( testArrayCopyInvalidControl );
-		CPPUNIT_TEST( testArrayCopyInvalidSlash );
-		CPPUNIT_TEST( testArrayCopyInvalidEmpty );
-
-		CPPUNIT_TEST( testArrayMove );
-		CPPUNIT_TEST( testArrayMoveEmpty );
-		CPPUNIT_TEST( testArrayMoveInvalidControl );
-		CPPUNIT_TEST( testArrayMoveInvalidSlash );
-		CPPUNIT_TEST( testArrayMoveInvalidEmpty );
-
-		CPPUNIT_TEST( testInitList );
-		CPPUNIT_TEST( testInitListEmpty );
-		CPPUNIT_TEST( testInitListInvalidControl );
-		CPPUNIT_TEST( testInitListInvalidSlash );
-		CPPUNIT_TEST( testInitListInvalidEmpty );
-
-		CPPUNIT_TEST( testFromStringEmpty );
-		CPPUNIT_TEST( testFromStringSlash );
-		CPPUNIT_TEST( testFromStringSlashes );
-		CPPUNIT_TEST( testFromStringValid );
-		CPPUNIT_TEST( testFromStringValidSlashes );
-		CPPUNIT_TEST( testFromStringValidInitialSlash );
-		CPPUNIT_TEST( testFromStringValidTrailingSlash );
-		CPPUNIT_TEST( testFromStringInvalid );
-
-		CPPUNIT_TEST( testSwap );
-
-		CPPUNIT_TEST( testParentEmpty );
-		CPPUNIT_TEST( testParentOne );
-		CPPUNIT_TEST( testParentValid );
-		CPPUNIT_TEST( testParentInvalidChild );
-		CPPUNIT_TEST( testParentInvalid );
-
-		CPPUNIT_TEST( testChildValid );
-		CPPUNIT_TEST( testChildInvalidName );
-		CPPUNIT_TEST( testChildInvalidParent );
-
-		CPPUNIT_TEST( testToStringEmpty );
-		CPPUNIT_TEST( testToStringValid );
-		CPPUNIT_TEST( testToStringInvalidSlash );
-		CPPUNIT_TEST( testToStringInvalidControl );
-		CPPUNIT_TEST( testToStringInvalidEmpty );
-
-		CPPUNIT_TEST( testIsParentYes );
-		CPPUNIT_TEST( testIsParentNo );
-		CPPUNIT_TEST( testIsParentYesInvalidParent );
-		CPPUNIT_TEST( testIsParentYesInvalidChild );
-		CPPUNIT_TEST( testIsParentNoInvalidParent );
-		CPPUNIT_TEST( testIsParentNoInvalidChild );
-
-		CPPUNIT_TEST( testEquals );
-		CPPUNIT_TEST( testNotEquals );
-	CPPUNIT_TEST_SUITE_END( );
-
-public:
-	void testEmpty( );
-
-	void testArrayCopy( );
-	void testArrayCopyEmpty( );
-	void testArrayCopyInvalidControl( );
-	void testArrayCopyInvalidSlash( );
-	void testArrayCopyInvalidEmpty( );
-
-	void testArrayMove( );
-	void testArrayMoveEmpty( );
-	void testArrayMoveInvalidControl( );
-	void testArrayMoveInvalidSlash( );
-	void testArrayMoveInvalidEmpty( );
-
-	void testInitList( );
-	void testInitListEmpty( );
-	void testInitListInvalidControl( );
-	void testInitListInvalidSlash( );
-	void testInitListInvalidEmpty( );
-
-	void testFromStringEmpty( );
-	void testFromStringSlash( );
-	void testFromStringSlashes( );
-	void testFromStringValid( );
-	void testFromStringValidSlashes( );
-	void testFromStringValidInitialSlash( );
-	void testFromStringValidTrailingSlash( );
-	void testFromStringInvalid( );
-
-	void testSwap( );
-
-	void testParentEmpty( );
-	void testParentOne( );
-	void testParentValid( );
-	void testParentInvalidChild( );
-	void testParentInvalid( );
-
-	void testChildValid( );
-	void testChildInvalidName( );
-	void testChildInvalidParent( );
-
-	void testToStringEmpty( );
-	void testToStringValid( );
-	void testToStringInvalidSlash( );
-	void testToStringInvalidControl( );
-	void testToStringInvalidEmpty( );
-
-	void testIsParentYes( );
-	void testIsParentNo( );
-	void testIsParentYesInvalidParent( );
-	void testIsParentYesInvalidChild( );
-	void testIsParentNoInvalidParent( );
-	void testIsParentNoInvalidChild( );
-
-	void testEquals( );
-	void testNotEquals( );
-};
-CPPUNIT_TEST_SUITE_REGISTRATION( LogPathTest );
-
-/*----------------------------------------------------------------------------*/
-
-void LogLevelTest::testToString( )
-{
-	T_StringBuilder sb;
-	sb << E_LogLevel::TRACE << ' ' << E_LogLevel::DEBUG << ' '
-		<< E_LogLevel::INFO << ' ' << E_LogLevel::NOTICE << ' '
-		<< E_LogLevel::WARNING << ' ' << E_LogLevel::ERROR << ' '
-		<< E_LogLevel::CRITICAL;
-
-	T_String s( std::move( sb ) );
-	CPPUNIT_ASSERT( s == "trace debug info notice warning error critical" );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void LogPathTest::testEmpty( )
-{
-	T_LogPath lp;
-	CPPUNIT_ASSERT( lp.isValid( ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , lp.size( ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void LogPathTest::testArrayCopy( )
-{
-	T_Array< T_String > test;
-	test.add( T_String::Pooled( "a" ) );
-	test.add( T_String::Pooled( "b" ) );
-	test.add( T_String::Pooled( "c" ) );
-
-	T_LogPath lp( test );
-	CPPUNIT_ASSERT( lp.isValid( ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 3 ) , lp.size( ) );
-	CPPUNIT_ASSERT( lp[ 0 ] == "a" );
-	CPPUNIT_ASSERT( lp[ 1 ] == "b" );
-	CPPUNIT_ASSERT( lp[ 2 ] == "c" );
-}
-
-void LogPathTest::testArrayCopyEmpty( )
-{
-	T_Array< T_String > test;
-	T_LogPath lp( test );
-	CPPUNIT_ASSERT( lp.isValid( ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , lp.size( ) );
-}
-
-void LogPathTest::testArrayCopyInvalidControl( )
-{
-	T_Array< T_String > test;
-	test.add( T_String::Pooled( "a" ) );
-	test.add( T_String::Pooled( "b" ) );
-	test.add( T_String::Pooled( "c\n" ) );
-
-	T_LogPath lp( test );
-	CPPUNIT_ASSERT( !lp.isValid( ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 3 ) , lp.size( ) );
-	CPPUNIT_ASSERT( lp[ 0 ] == "a" );
-	CPPUNIT_ASSERT( lp[ 1 ] == "b" );
-	CPPUNIT_ASSERT( lp[ 2 ] == "c\n" );
-}
-
-void LogPathTest::testArrayCopyInvalidSlash( )
-{
-	T_Array< T_String > test;
-	test.add( T_String::Pooled( "a" ) );
-	test.add( T_String::Pooled( "b" ) );
-	test.add( T_String::Pooled( "c/" ) );
-
-	T_LogPath lp( test );
-	CPPUNIT_ASSERT( !lp.isValid( ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 3 ) , lp.size( ) );
-	CPPUNIT_ASSERT( lp[ 0 ] == "a" );
-	CPPUNIT_ASSERT( lp[ 1 ] == "b" );
-	CPPUNIT_ASSERT( lp[ 2 ] == "c/" );
-}
-
-void LogPathTest::testArrayCopyInvalidEmpty( )
-{
-	T_Array< T_String > test;
-	test.add( T_String::Pooled( "a" ) );
-	test.add( T_String::Pooled( "b" ) );
-	test.add( T_String::Pooled( "" ) );
-
-	T_LogPath lp( test );
-	CPPUNIT_ASSERT( !lp.isValid( ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 3 ) , lp.size( ) );
-	CPPUNIT_ASSERT( lp[ 0 ] == "a" );
-	CPPUNIT_ASSERT( lp[ 1 ] == "b" );
-	CPPUNIT_ASSERT( lp[ 2 ] == "" );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void LogPathTest::testArrayMove( )
-{
-	T_Array< T_String > test;
-	test.add( T_String::Pooled( "a" ) );
-	test.add( T_String::Pooled( "b" ) );
-	test.add( T_String::Pooled( "c" ) );
-
-	RPC_String s0( &test[ 0 ] );
-	RPC_String s1( &test[ 1 ] );
-	RPC_String s2( &test[ 2 ] );
-
-	T_LogPath lp( std::move( test ) );
-	CPPUNIT_ASSERT( lp.isValid( ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 3 ) , lp.size( ) );
-	CPPUNIT_ASSERT( lp[ 0 ] == "a" );
-	CPPUNIT_ASSERT( lp[ 1 ] == "b" );
-	CPPUNIT_ASSERT( lp[ 2 ] == "c" );
-	CPPUNIT_ASSERT_EQUAL( s0 , &lp[ 0 ] );
-	CPPUNIT_ASSERT_EQUAL( s1 , &lp[ 1 ] );
-	CPPUNIT_ASSERT_EQUAL( s2 , &lp[ 2 ] );
-}
-
-void LogPathTest::testArrayMoveEmpty( )
-{
-	T_Array< T_String > test;
-	T_LogPath lp( std::move( test ) );
-	CPPUNIT_ASSERT( lp.isValid( ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , lp.size( ) );
-}
-
-void LogPathTest::testArrayMoveInvalidControl( )
-{
-	T_Array< T_String > test;
-	test.add( T_String::Pooled( "a" ) );
-	test.add( T_String::Pooled( "b" ) );
-	test.add( T_String::Pooled( "c\n" ) );
-
-	T_LogPath lp( std::move( test ) );
-	CPPUNIT_ASSERT( !lp.isValid( ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 3 ) , lp.size( ) );
-	CPPUNIT_ASSERT( lp[ 0 ] == "a" );
-	CPPUNIT_ASSERT( lp[ 1 ] == "b" );
-	CPPUNIT_ASSERT( lp[ 2 ] == "c\n" );
-}
-
-void LogPathTest::testArrayMoveInvalidSlash( )
-{
-	T_Array< T_String > test;
-	test.add( T_String::Pooled( "a" ) );
-	test.add( T_String::Pooled( "b" ) );
-	test.add( T_String::Pooled( "c/" ) );
-
-	T_LogPath lp( std::move( test ) );
-	CPPUNIT_ASSERT( !lp.isValid( ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 3 ) , lp.size( ) );
-	CPPUNIT_ASSERT( lp[ 0 ] == "a" );
-	CPPUNIT_ASSERT( lp[ 1 ] == "b" );
-	CPPUNIT_ASSERT( lp[ 2 ] == "c/" );
-}
-
-void LogPathTest::testArrayMoveInvalidEmpty( )
-{
-	T_Array< T_String > test;
-	test.add( T_String::Pooled( "a" ) );
-	test.add( T_String::Pooled( "b" ) );
-	test.add( T_String::Pooled( "" ) );
-
-	T_LogPath lp( std::move( test ) );
-	CPPUNIT_ASSERT( !lp.isValid( ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 3 ) , lp.size( ) );
-	CPPUNIT_ASSERT( lp[ 0 ] == "a" );
-	CPPUNIT_ASSERT( lp[ 1 ] == "b" );
-	CPPUNIT_ASSERT( lp[ 2 ] == "" );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void LogPathTest::testInitList( )
-{
-	T_LogPath lp{ "a" , "b" , "c" };
-	CPPUNIT_ASSERT( lp.isValid( ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 3 ) , lp.size( ) );
-	CPPUNIT_ASSERT( lp[ 0 ] == "a" );
-	CPPUNIT_ASSERT( lp[ 1 ] == "b" );
-	CPPUNIT_ASSERT( lp[ 2 ] == "c" );
-}
-
-void LogPathTest::testInitListEmpty( )
-{
-	T_LogPath lp{ };
-	CPPUNIT_ASSERT( lp.isValid( ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , lp.size( ) );
-}
-
-void LogPathTest::testInitListInvalidControl( )
-{
-	T_LogPath lp{ "a" , "b" , "c\n" };
-	CPPUNIT_ASSERT( !lp.isValid( ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 3 ) , lp.size( ) );
-	CPPUNIT_ASSERT( lp[ 0 ] == "a" );
-	CPPUNIT_ASSERT( lp[ 1 ] == "b" );
-	CPPUNIT_ASSERT( lp[ 2 ] == "c\n" );
-}
-
-void LogPathTest::testInitListInvalidSlash( )
-{
-	T_LogPath lp{ "a" , "b" , "c/" };
-	CPPUNIT_ASSERT( !lp.isValid( ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 3 ) , lp.size( ) );
-	CPPUNIT_ASSERT( lp[ 0 ] == "a" );
-	CPPUNIT_ASSERT( lp[ 1 ] == "b" );
-	CPPUNIT_ASSERT( lp[ 2 ] == "c/" );
-}
-
-void LogPathTest::testInitListInvalidEmpty( )
-{
-	T_LogPath lp{ "a" , "b" , "" };
-	CPPUNIT_ASSERT( !lp.isValid( ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 3 ) , lp.size( ) );
-	CPPUNIT_ASSERT( lp[ 0 ] == "a" );
-	CPPUNIT_ASSERT( lp[ 1 ] == "b" );
-	CPPUNIT_ASSERT( lp[ 2 ] == "" );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void LogPathTest::testFromStringEmpty( )
-{
-	T_LogPath lp( T_LogPath::FromString( "" ) );
-	CPPUNIT_ASSERT( lp.isValid( ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , lp.size( ) );
-}
-
-void LogPathTest::testFromStringSlash( )
-{
-	T_LogPath lp( T_LogPath::FromString( "/" ) );
-	CPPUNIT_ASSERT( lp.isValid( ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , lp.size( ) );
-}
-
-void LogPathTest::testFromStringSlashes( )
-{
-	T_LogPath lp( T_LogPath::FromString( "/////" ) );
-	CPPUNIT_ASSERT( lp.isValid( ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , lp.size( ) );
-}
-
-void LogPathTest::testFromStringValid( )
-{
-	T_LogPath lp( T_LogPath::FromString( "a/b/c" ) );
-	CPPUNIT_ASSERT( lp.isValid( ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 3 ) , lp.size( ) );
-	CPPUNIT_ASSERT( lp[ 0 ] == "a" );
-	CPPUNIT_ASSERT( lp[ 1 ] == "b" );
-	CPPUNIT_ASSERT( lp[ 2 ] == "c" );
-}
-
-void LogPathTest::testFromStringValidSlashes( )
-{
-	T_LogPath lp( T_LogPath::FromString( "a//b////c" ) );
-	CPPUNIT_ASSERT( lp.isValid( ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 3 ) , lp.size( ) );
-	CPPUNIT_ASSERT( lp[ 0 ] == "a" );
-	CPPUNIT_ASSERT( lp[ 1 ] == "b" );
-	CPPUNIT_ASSERT( lp[ 2 ] == "c" );
-}
-
-void LogPathTest::testFromStringValidInitialSlash( )
-{
-	T_LogPath lp( T_LogPath::FromString( "/a/b/c" ) );
-	CPPUNIT_ASSERT( lp.isValid( ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 3 ) , lp.size( ) );
-	CPPUNIT_ASSERT( lp[ 0 ] == "a" );
-	CPPUNIT_ASSERT( lp[ 1 ] == "b" );
-	CPPUNIT_ASSERT( lp[ 2 ] == "c" );
-}
-
-void LogPathTest::testFromStringValidTrailingSlash( )
-{
-	T_LogPath lp( T_LogPath::FromString( "a/b/c/" ) );
-	CPPUNIT_ASSERT( lp.isValid( ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 3 ) , lp.size( ) );
-	CPPUNIT_ASSERT( lp[ 0 ] == "a" );
-	CPPUNIT_ASSERT( lp[ 1 ] == "b" );
-	CPPUNIT_ASSERT( lp[ 2 ] == "c" );
-}
-
-void LogPathTest::testFromStringInvalid( )
-{
-	T_LogPath lp( T_LogPath::FromString( "a/b\n/c" ) );
-	CPPUNIT_ASSERT( !lp.isValid( ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 3 ) , lp.size( ) );
-	CPPUNIT_ASSERT( lp[ 0 ] == "a" );
-	CPPUNIT_ASSERT( lp[ 1 ] == "b\n" );
-	CPPUNIT_ASSERT( lp[ 2 ] == "c" );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void LogPathTest::testSwap( )
-{
-	T_LogPath lp1{ "a" };
-	T_LogPath lp2{ "b" , "c" };
-
-	RPC_String p[] = {
-		&lp1[ 0 ] , &lp2[ 0 ] , &lp2[ 1 ]
-	};
-
-	swap( lp1 , lp2 );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , lp1.size( ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , lp2.size( ) );
-	CPPUNIT_ASSERT_EQUAL( p[ 0 ] , &lp2[ 0 ] );
-	CPPUNIT_ASSERT_EQUAL( p[ 1 ] , &lp1[ 0 ] );
-	CPPUNIT_ASSERT_EQUAL( p[ 2 ] , &lp1[ 1 ] );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void LogPathTest::testParentEmpty( )
-{
-	T_LogPath lp;
-	T_LogPath plp( lp.parent( ) );
-	CPPUNIT_ASSERT( plp.isValid( ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , plp.size( ) );
-}
-
-void LogPathTest::testParentOne( )
-{
-	T_LogPath lp{ "a" };
-	T_LogPath plp( lp.parent( ) );
-	CPPUNIT_ASSERT( plp.isValid( ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , plp.size( ) );
-}
-
-void LogPathTest::testParentValid( )
-{
-	T_LogPath lp{ "a" , "b" };
-	T_LogPath plp( lp.parent( ) );
-	CPPUNIT_ASSERT( plp.isValid( ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , plp.size( ) );
-	CPPUNIT_ASSERT( plp[ 0 ] == "a" );
-}
-
-void LogPathTest::testParentInvalidChild( )
-{
-	T_LogPath lp{ "a" , "b/" };
-	T_LogPath plp( lp.parent( ) );
-	CPPUNIT_ASSERT( plp.isValid( ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , plp.size( ) );
-	CPPUNIT_ASSERT( plp[ 0 ] == "a" );
-}
-
-void LogPathTest::testParentInvalid( )
-{
-	T_LogPath lp{ "a/" , "b" };
-	T_LogPath plp( lp.parent( ) );
-	CPPUNIT_ASSERT( !plp.isValid( ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , plp.size( ) );
-	CPPUNIT_ASSERT( plp[ 0 ] == "a/" );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void LogPathTest::testChildValid( )
-{
-	T_LogPath lp{ "a" };
-	T_LogPath clp( lp.child( "b" ) );
-
-	CPPUNIT_ASSERT( clp.isValid( ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , clp.size( ) );
-	CPPUNIT_ASSERT( clp[ 0 ] == "a" );
-	CPPUNIT_ASSERT( clp[ 1 ] == "b" );
-}
-
-void LogPathTest::testChildInvalidName( )
-{
-	T_LogPath lp{ "a" };
-	T_LogPath clp( lp.child( "b\n" ) );
-
-	CPPUNIT_ASSERT( !clp.isValid( ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , clp.size( ) );
-	CPPUNIT_ASSERT( clp[ 0 ] == "a" );
-	CPPUNIT_ASSERT( clp[ 1 ] == "b\n" );
-}
-
-void LogPathTest::testChildInvalidParent( )
-{
-	T_LogPath lp{ "a\n" };
-	T_LogPath clp( lp.child( "b" ) );
-
-	CPPUNIT_ASSERT( !clp.isValid( ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , clp.size( ) );
-	CPPUNIT_ASSERT( clp[ 0 ] == "a\n" );
-	CPPUNIT_ASSERT( clp[ 1 ] == "b" );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void LogPathTest::testToStringEmpty( )
-{
-	T_LogPath lp;
-	CPPUNIT_ASSERT( lp.toString( ) == "/" );
-}
-
-void LogPathTest::testToStringValid( )
-{
-	T_LogPath lp{ "a" , "b" , "c" };
-	CPPUNIT_ASSERT( lp.toString( ) == "/a/b/c" );
-}
-
-void LogPathTest::testToStringInvalidSlash( )
-{
-	T_LogPath lp{ "a" , "/b" , "c" };
-	CPPUNIT_ASSERT( lp.toString( ) == "/a//b/c" );
-}
-
-void LogPathTest::testToStringInvalidControl( )
-{
-	T_LogPath lp{ "a" , "b\n" , "c" };
-	CPPUNIT_ASSERT( lp.toString( ) == "/a/b\n/c" );
-}
-
-void LogPathTest::testToStringInvalidEmpty( )
-{
-	T_LogPath lp{ "a" , "" , "c" };
-	CPPUNIT_ASSERT( lp.toString( ) == "/a//c" );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void LogPathTest::testIsParentYes( )
-{
-	T_LogPath gc{ "a" , "b" };
-	T_LogPath c{ "a" };
-	T_LogPath p;
-
-	CPPUNIT_ASSERT( p.isParentOf( c ) );
-	CPPUNIT_ASSERT( c.isParentOf( gc ) );
-
-	CPPUNIT_ASSERT( c.isChildOf( p ) );
-	CPPUNIT_ASSERT( gc.isChildOf( c ) );
-}
-
-void LogPathTest::testIsParentNo( )
-{
-	T_LogPath p1{ "a" , "b" , "c" };
-	T_LogPath p2{ "a" , "b" , "d" , "e" };
-	CPPUNIT_ASSERT( !p1.isParentOf( p2 ) );
-	CPPUNIT_ASSERT( !p2.isParentOf( p1 ) );
-	CPPUNIT_ASSERT( !p1.isChildOf( p2 ) );
-	CPPUNIT_ASSERT( !p2.isChildOf( p1 ) );
-}
-
-void LogPathTest::testIsParentYesInvalidParent( )
-{
-	T_LogPath p1{ "a\n" };
-	T_LogPath p2{ "a\n" , "b" };
-	CPPUNIT_ASSERT( p1.isParentOf( p2 ) );
-	CPPUNIT_ASSERT( p2.isChildOf( p1 ) );
-}
-
-void LogPathTest::testIsParentYesInvalidChild( )
-{
-	T_LogPath p1{ "a" };
-	T_LogPath p2{ "a" , "b\n" };
-	CPPUNIT_ASSERT( p1.isParentOf( p2 ) );
-	CPPUNIT_ASSERT( p2.isChildOf( p1 ) );
-}
-
-void LogPathTest::testIsParentNoInvalidParent( )
-{
-	T_LogPath p1{ "b\n" };
-	T_LogPath p2{ "c" , "b" };
-	CPPUNIT_ASSERT( !p1.isParentOf( p2 ) );
-	CPPUNIT_ASSERT( !p2.isParentOf( p1 ) );
-	CPPUNIT_ASSERT( !p1.isChildOf( p2 ) );
-	CPPUNIT_ASSERT( !p2.isChildOf( p1 ) );
-}
-
-void LogPathTest::testIsParentNoInvalidChild( )
-{
-	T_LogPath p1{ "b" };
-	T_LogPath p2{ "c" , "b\n" };
-	CPPUNIT_ASSERT( !p1.isParentOf( p2 ) );
-	CPPUNIT_ASSERT( !p2.isParentOf( p1 ) );
-	CPPUNIT_ASSERT( !p1.isChildOf( p2 ) );
-	CPPUNIT_ASSERT( !p2.isChildOf( p1 ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void LogPathTest::testEquals( )
-{
-	T_LogPath p1{ "a" };
-	T_LogPath p2( p1 );
-	T_LogPath p3{ "b" , "c" };
-	T_LogPath p4{ "d" };
-	CPPUNIT_ASSERT( p1 == p1 );
-	CPPUNIT_ASSERT( p1 == p2 );
-	CPPUNIT_ASSERT( !( p1 == p3 ) );
-	CPPUNIT_ASSERT( !( p1 == p4 ) );
-}
-
-void LogPathTest::testNotEquals( )
-{
-	T_LogPath p1{ "a" };
-	T_LogPath p2( p1 );
-	T_LogPath p3{ "b" , "c" };
-	T_LogPath p4{ "d" };
-	CPPUNIT_ASSERT( !( p1 != p1 ) );
-	CPPUNIT_ASSERT( !( p1 != p2 ) );
-	CPPUNIT_ASSERT( p1 != p3 );
-	CPPUNIT_ASSERT( p1 != p4 );
-}
-
diff --git a/tests/ring-buffer.cc b/tests/ring-buffer.cc
index 3733ad8..cc5ce01 100644
--- a/tests/ring-buffer.cc
+++ b/tests/ring-buffer.cc
@@ -1,6 +1,6 @@
-#include <lw/lib/Threading.hh>
+#include <ebcl/Threading.hh>
 #include <cppunit/extensions/HelperMacros.h>
-using namespace lw;
+using namespace ebcl;
 
 
 class RingBufferTest : public CppUnit::TestFixture
diff --git a/tests/run-test.cc b/tests/run-test.cc
index 1e01f5f..7de4179 100644
--- a/tests/run-test.cc
+++ b/tests/run-test.cc
@@ -2,7 +2,7 @@
 #include <cppunit/extensions/TestFactoryRegistry.h>
 #include <cppunit/ui/text/TextTestRunner.h>
 
-int main( int argc , char * argv[] )
+int main( int , char *[] )
 {
 	CppUnit::TextTestRunner runner;
 	runner.addTest( CppUnit::TestFactoryRegistry::getRegistry( )
diff --git a/tests/srd-bin-reader.cc b/tests/srd-bin-reader.cc
index 2062c90..9394f81 100644
--- a/tests/srd-bin-reader.cc
+++ b/tests/srd-bin-reader.cc
@@ -1,7 +1,7 @@
-#include <lw/lib/SRDBinary.hh>
-#include <lw/lib/MemoryStreams.hh>
+#include <ebcl/SRDBinary.hh>
+#include <ebcl/MemoryStreams.hh>
 #include <cppunit/extensions/HelperMacros.h>
-using namespace lw;
+using namespace ebcl;
 
 
 #define V1PROLOGUE_ \
diff --git a/tests/srd-bin-writer.cc b/tests/srd-bin-writer.cc
index 60759a1..d5d66df 100644
--- a/tests/srd-bin-writer.cc
+++ b/tests/srd-bin-writer.cc
@@ -1,7 +1,7 @@
-#include <lw/lib/SRDBinary.hh>
-#include <lw/lib/MemoryStreams.hh>
+#include <ebcl/SRDBinary.hh>
+#include <ebcl/MemoryStreams.hh>
 #include <cppunit/extensions/HelperMacros.h>
-using namespace lw;
+using namespace ebcl;
 
 
 class SRDBinWriterTest : public CppUnit::TestFixture
diff --git a/tests/srd-lexer.cc b/tests/srd-lexer.cc
index 4b956c6..aef548f 100644
--- a/tests/srd-lexer.cc
+++ b/tests/srd-lexer.cc
@@ -1,6 +1,6 @@
-#include <lw/lib/SRDText.hh>
+#include <ebcl/SRDText.hh>
 #include <cppunit/extensions/HelperMacros.h>
-using namespace lw;
+using namespace ebcl;
 
 
 class SRDLexerTest : public CppUnit::TestFixture
diff --git a/tests/srd-mem-target.cc b/tests/srd-mem-target.cc
index 9a144b7..17930c5 100644
--- a/tests/srd-mem-target.cc
+++ b/tests/srd-mem-target.cc
@@ -1,6 +1,6 @@
-#include <lw/lib/SRDIO.hh>
+#include <ebcl/SRDIO.hh>
 #include <cppunit/extensions/HelperMacros.h>
-using namespace lw;
+using namespace ebcl;
 
 /* - SRDMemTargetTest ---------------------------------------------------{{{-*/
 class SRDMemTargetTest : public CppUnit::TestFixture
diff --git a/tests/srd-parser-cfg.cc b/tests/srd-parser-cfg.cc
index 81a8d1a..fd10543 100644
--- a/tests/srd-parser-cfg.cc
+++ b/tests/srd-parser-cfg.cc
@@ -1,6 +1,6 @@
-#include <lw/lib/SRDParserConfig.hh>
+#include <ebcl/SRDParserConfig.hh>
 #include <cppunit/extensions/HelperMacros.h>
-using namespace lw;
+using namespace ebcl;
 
 
 class SRDParserConfigTest : public CppUnit::TestFixture
diff --git a/tests/srd-parser-defs.cc b/tests/srd-parser-defs.cc
index 708a3a8..6e9e678 100644
--- a/tests/srd-parser-defs.cc
+++ b/tests/srd-parser-defs.cc
@@ -1,6 +1,6 @@
-#include <lw/lib/SRDDefinitions.hh>
+#include <ebcl/SRDDefinitions.hh>
 #include <cppunit/extensions/HelperMacros.h>
-using namespace lw;
+using namespace ebcl;
 
 
 class SRDInputItemTest : public CppUnit::TestFixture
diff --git a/tests/srd-parser.cc b/tests/srd-parser.cc
index b078e39..a321e2b 100644
--- a/tests/srd-parser.cc
+++ b/tests/srd-parser.cc
@@ -1,7 +1,7 @@
-#include <lw/lib/SRDParser.hh>
-#include <lw/lib/SRDText.hh>
+#include <ebcl/SRDParser.hh>
+#include <ebcl/SRDText.hh>
 #include <cppunit/extensions/HelperMacros.h>
-using namespace lw;
+using namespace ebcl;
 
 
 class SRDParserTest : public CppUnit::TestFixture
@@ -302,7 +302,7 @@ T_SRDParserDefs SRDParserTest::makeOLBCDefs( )
 void SRDParserTest::testTokenTypes( )
 {
 	using F_InitRule = std::function< void( T_SRDContext& ) >;
-	using namespace lw::SRD;
+	using namespace ebcl::SRD;
 	const F_InitRule rules[] = {
 		[]( T_SRDContext& c ) { c << ( Rule() << Word( ) ); } ,
 		[]( T_SRDContext& c ) { c << ( Rule() << String( ) ); } ,
diff --git a/tests/srd-preproc-cmd-arithmetic.cc b/tests/srd-preproc-cmd-arithmetic.cc
deleted file mode 100644
index 8624203..0000000
--- a/tests/srd-preproc-cmd-arithmetic.cc
+++ /dev/null
@@ -1,877 +0,0 @@
-#include "srd-preproc-cmd-common.hh"
-
-
-class SRDPreprocCmdArithmeticTest : public CppUnit::TestFixture
-{
-	CPPUNIT_TEST_SUITE( SRDPreprocCmdArithmeticTest );
-
-	CPPUNIT_TEST( testAddNoArgs );
-	CPPUNIT_TEST( testAddOneArg );
-	CPPUNIT_TEST( testAddIntInt );
-	CPPUNIT_TEST( testAddIntLong );
-	CPPUNIT_TEST( testAddLongInt );
-	CPPUNIT_TEST( testAddLongLong );
-	CPPUNIT_TEST( testAddIntFloat );
-	CPPUNIT_TEST( testAddLongFloat );
-	CPPUNIT_TEST( testAddFloatInt );
-	CPPUNIT_TEST( testAddFloatLong );
-	CPPUNIT_TEST( testAddFloatFloat );
-	CPPUNIT_TEST( testAddManyInt );
-	CPPUNIT_TEST( testAddManyFloat );
-	CPPUNIT_TEST( testAddManyWithError );
-
-	CPPUNIT_TEST( testSubNoArgs );
-	CPPUNIT_TEST( testSubOneArg );
-	CPPUNIT_TEST( testSubIntInt );
-	CPPUNIT_TEST( testSubIntLong );
-	CPPUNIT_TEST( testSubLongInt );
-	CPPUNIT_TEST( testSubLongLong );
-	CPPUNIT_TEST( testSubIntFloat );
-	CPPUNIT_TEST( testSubLongFloat );
-	CPPUNIT_TEST( testSubFloatInt );
-	CPPUNIT_TEST( testSubFloatLong );
-	CPPUNIT_TEST( testSubFloatFloat );
-	CPPUNIT_TEST( testSubManyInt );
-	CPPUNIT_TEST( testSubManyFloat );
-	CPPUNIT_TEST( testSubManyWithError );
-
-	CPPUNIT_TEST( testMulNoArgs );
-	CPPUNIT_TEST( testMulOneArg );
-	CPPUNIT_TEST( testMulIntInt );
-	CPPUNIT_TEST( testMulIntLong );
-	CPPUNIT_TEST( testMulLongInt );
-	CPPUNIT_TEST( testMulLongLong );
-	CPPUNIT_TEST( testMulIntFloat );
-	CPPUNIT_TEST( testMulLongFloat );
-	CPPUNIT_TEST( testMulFloatInt );
-	CPPUNIT_TEST( testMulFloatLong );
-	CPPUNIT_TEST( testMulFloatFloat );
-	CPPUNIT_TEST( testMulManyInt );
-	CPPUNIT_TEST( testMulManyFloat );
-	CPPUNIT_TEST( testMulManyWithError );
-
-	CPPUNIT_TEST( testDivNoArgs );
-	CPPUNIT_TEST( testDivOneArg );
-	CPPUNIT_TEST( testDivIntInt );
-	CPPUNIT_TEST( testDivIntLong );
-	CPPUNIT_TEST( testDivLongInt );
-	CPPUNIT_TEST( testDivLongLong );
-	CPPUNIT_TEST( testDivIntFloat );
-	CPPUNIT_TEST( testDivLongFloat );
-	CPPUNIT_TEST( testDivFloatInt );
-	CPPUNIT_TEST( testDivFloatLong );
-	CPPUNIT_TEST( testDivFloatFloat );
-	CPPUNIT_TEST( testDivIntZero );
-	CPPUNIT_TEST( testDivFloatZero );
-	CPPUNIT_TEST( testDivManyInt );
-	CPPUNIT_TEST( testDivManyFloat );
-	CPPUNIT_TEST( testDivManyWithError );
-
-	CPPUNIT_TEST( testModNoArgs );
-	CPPUNIT_TEST( testModOneArg );
-	CPPUNIT_TEST( testModIntInt );
-	CPPUNIT_TEST( testModIntLong );
-	CPPUNIT_TEST( testModLongInt );
-	CPPUNIT_TEST( testModLongLong );
-	CPPUNIT_TEST( testModIntFloat );
-	CPPUNIT_TEST( testModLongFloat );
-	CPPUNIT_TEST( testModFloatInt );
-	CPPUNIT_TEST( testModFloatLong );
-	CPPUNIT_TEST( testModFloatFloat );
-	CPPUNIT_TEST( testModIntZero );
-	CPPUNIT_TEST( testModFloatZero );
-	CPPUNIT_TEST( testModManyInt );
-	CPPUNIT_TEST( testModManyFloat );
-	CPPUNIT_TEST( testModManyWithError );
-
-	CPPUNIT_TEST( testNegNoArgs );
-	CPPUNIT_TEST( testNegTooManyArgs );
-	CPPUNIT_TEST( testNegBadArg );
-	CPPUNIT_TEST( testNegInt );
-	CPPUNIT_TEST( testNegLong );
-	CPPUNIT_TEST( testNegReal );
-
-	CPPUNIT_TEST_SUITE_END( );
-
-   public:
-	void testAddNoArgs( );
-	void testAddOneArg( );
-	void testAddIntInt( );
-	void testAddIntLong( );
-	void testAddLongInt( );
-	void testAddLongLong( );
-	void testAddIntFloat( );
-	void testAddLongFloat( );
-	void testAddFloatInt( );
-	void testAddFloatLong( );
-	void testAddFloatFloat( );
-	void testAddManyInt( );
-	void testAddManyFloat( );
-	void testAddManyWithError( );
-
-	void testSubNoArgs( );
-	void testSubOneArg( );
-	void testSubIntInt( );
-	void testSubIntLong( );
-	void testSubLongInt( );
-	void testSubLongLong( );
-	void testSubIntFloat( );
-	void testSubLongFloat( );
-	void testSubFloatInt( );
-	void testSubFloatLong( );
-	void testSubFloatFloat( );
-	void testSubManyInt( );
-	void testSubManyFloat( );
-	void testSubManyWithError( );
-
-	void testMulNoArgs( );
-	void testMulOneArg( );
-	void testMulIntInt( );
-	void testMulIntLong( );
-	void testMulLongInt( );
-	void testMulLongLong( );
-	void testMulIntFloat( );
-	void testMulLongFloat( );
-	void testMulFloatInt( );
-	void testMulFloatLong( );
-	void testMulFloatFloat( );
-	void testMulManyInt( );
-	void testMulManyFloat( );
-	void testMulManyWithError( );
-
-	void testDivNoArgs( );
-	void testDivOneArg( );
-	void testDivIntInt( );
-	void testDivIntLong( );
-	void testDivLongInt( );
-	void testDivLongLong( );
-	void testDivIntFloat( );
-	void testDivLongFloat( );
-	void testDivFloatInt( );
-	void testDivFloatLong( );
-	void testDivFloatFloat( );
-	void testDivIntZero( );
-	void testDivFloatZero( );
-	void testDivManyInt( );
-	void testDivManyFloat( );
-	void testDivManyWithError( );
-
-	void testModNoArgs( );
-	void testModOneArg( );
-	void testModIntInt( );
-	void testModIntLong( );
-	void testModLongInt( );
-	void testModLongLong( );
-	void testModIntFloat( );
-	void testModLongFloat( );
-	void testModFloatInt( );
-	void testModFloatLong( );
-	void testModFloatFloat( );
-	void testModIntZero( );
-	void testModFloatZero( );
-	void testModManyInt( );
-	void testModManyFloat( );
-	void testModManyWithError( );
-
-	void testNegNoArgs( );
-	void testNegTooManyArgs( );
-	void testNegBadArg( );
-	void testNegInt( );
-	void testNegLong( );
-	void testNegReal( );
-};
-CPPUNIT_TEST_SUITE_REGISTRATION( SRDPreprocCmdArithmeticTest );
-
-/*----------------------------------------------------------------------------*/
-
-#define M_MKTEST_( OP , A1 , A2 ) \
-	"( -set out ( -" OP " " A1 " " A2 " ) )\n" \
-	"( -type-of $out )\n" \
-	"( -if ( -eq ( -type-of $out ) long ) ( (-to-best-integer $out) ) ($out) )"
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdArithmeticTest::testAddNoArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -add )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 8 );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testAddOneArg( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -add 1 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testAddIntInt( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( M_MKTEST_( "add" , "1" , "1" )  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "int 2" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testAddIntLong( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( M_MKTEST_( "add" , "1" , "12123456789" )  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "long 12123456790" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testAddLongInt( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( M_MKTEST_( "add" , "12123456789" , "1" )  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "long 12123456790" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testAddLongLong( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( M_MKTEST_( "add" , "12123456789" , "( -to-long 1 )" )  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "long 12123456790" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testAddIntFloat( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( M_MKTEST_( "add" , "1" , ".5" )  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "real 1.5" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testAddLongFloat( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( M_MKTEST_( "add" , "( -to-long 1 )" , ".5" )  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "real 1.5" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testAddFloatInt( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( M_MKTEST_( "add" , ".5" , "1" )  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "real 1.5" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testAddFloatLong( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( M_MKTEST_( "add" , ".5" , "( -to-long 1 )" )  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "real 1.5" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testAddFloatFloat( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( M_MKTEST_( "add" , ".5" , "1.5" )  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "real 2.0" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testAddManyInt( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -add 1 2 3 4 5 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "15" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testAddManyFloat( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -add 1 .5 .25 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1.75" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testAddManyWithError( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -add 1 ( ) .25 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "integer or real number expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 10 );
-	CPPUNIT_ASSERT( check( "1.25" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdArithmeticTest::testSubNoArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -sub )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 8 );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testSubOneArg( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -sub 1 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testSubIntInt( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( M_MKTEST_( "sub" , "1" , "1" )  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "int 0" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testSubIntLong( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( M_MKTEST_( "sub" , "1" , "12123456789" )  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "long -12123456788" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testSubLongInt( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( M_MKTEST_( "sub" , "12123456789" , "1" )  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "long 12123456788" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testSubLongLong( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( M_MKTEST_( "sub" , "12123456789" , "( -to-long 1 )" )  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "long 12123456788" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testSubIntFloat( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( M_MKTEST_( "sub" , "1" , ".5" )  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "real .5" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testSubLongFloat( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( M_MKTEST_( "sub" , "( -to-long 1 )" , ".5" )  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "real .5" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testSubFloatInt( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( M_MKTEST_( "sub" , ".5" , "1" )  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "real -.5" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testSubFloatLong( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( M_MKTEST_( "sub" , ".5" , "( -to-long 1 )" )  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "real -.5" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testSubFloatFloat( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( M_MKTEST_( "sub" , ".5" , "1.5" )  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "real -1.0" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testSubManyInt( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -sub 20 1 2 3 4 5 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "5" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testSubManyFloat( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -sub 1 .5 .25 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( ".25" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testSubManyWithError( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -sub 1 ( ) .25 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "integer or real number expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 10 );
-	CPPUNIT_ASSERT( check( ".75" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdArithmeticTest::testMulNoArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -mul )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 8 );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testMulOneArg( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -mul 1 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testMulIntInt( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( M_MKTEST_( "mul" , "2" , "3" )  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "int 6" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testMulIntLong( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( M_MKTEST_( "mul" , "2" , "6000000000" )  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "long 12000000000" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testMulLongInt( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( M_MKTEST_( "mul" , "6000000000" , "2" )  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "long 12000000000" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testMulLongLong( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( M_MKTEST_( "mul" , "6000000000" , "( -to-long 2 )" )  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "long 12000000000" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testMulIntFloat( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( M_MKTEST_( "mul" , "2" , ".5" )  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "real 1." , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testMulLongFloat( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( M_MKTEST_( "mul" , "( -to-long 2 )" , ".5" )  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "real 1." , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testMulFloatInt( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( M_MKTEST_( "mul" , ".5" , "2" )  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "real 1." , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testMulFloatLong( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( M_MKTEST_( "mul" , ".5" , "( -to-long 2 )" )  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "real 1." , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testMulFloatFloat( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( M_MKTEST_( "mul" , ".5" , "1.5" )  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "real .75" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testMulManyInt( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -mul 2 3 4 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "24" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testMulManyFloat( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -mul 2. .5 .1 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( ".1" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testMulManyWithError( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -mul 2 ( ) .25 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "integer or real number expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 10 );
-	CPPUNIT_ASSERT( check( ".5" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdArithmeticTest::testDivNoArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -div )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 8 );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testDivOneArg( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -div 1 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testDivIntInt( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( M_MKTEST_( "div" , "4" , "2" )  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "int 2" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testDivIntLong( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( M_MKTEST_( "div" , "200" , "( -to-long 10 )" )  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "int 20" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testDivLongInt( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( M_MKTEST_( "div" , "12000000000" , "2" )  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "long 6000000000" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testDivLongLong( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( M_MKTEST_( "div" , "12000000000" , "6000000000" )  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "int 2" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testDivIntFloat( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( M_MKTEST_( "div" , "2" , ".5" )  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "real 4." , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testDivLongFloat( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( M_MKTEST_( "div" , "6000000000" , ".5" )  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "real 12e9" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testDivFloatInt( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( M_MKTEST_( "div" , ".5" , "2" )  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "real .25" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testDivFloatLong( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( M_MKTEST_( "div" , "12e9" , "6000000000" )  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "real 2." , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testDivFloatFloat( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( M_MKTEST_( "div" , "1.5" , ".5" )  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "real 3." , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testDivIntZero( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -div 10 0 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "non-zero argument expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 11 );
-	CPPUNIT_ASSERT( check( "10" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testDivFloatZero( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -div 2. 0. )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "non-zero argument expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 11 );
-	CPPUNIT_ASSERT( check( "2." , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testDivManyInt( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -div 20 2 5 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "2" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testDivManyFloat( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -div 2. .5 4. )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1." , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testDivManyWithError( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -div 2 ( ) .25 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "integer or real number expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 10 );
-	CPPUNIT_ASSERT( check( "8." , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdArithmeticTest::testModNoArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -mod )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 8 );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testModOneArg( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -mod 1 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testModIntInt( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( M_MKTEST_( "mod" , "4" , "3" )  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "int 1" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testModIntLong( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( M_MKTEST_( "mod" , "20" , "6000000000" )  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "int 20" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testModLongInt( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( M_MKTEST_( "mod" , "6000000000" , "7" )  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "int 1" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testModLongLong( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( M_MKTEST_( "mod" , "12000000000" , "7000000000" )  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "long 5000000000" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testModIntFloat( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( M_MKTEST_( "mod" , "2" , "1.5" )  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "real .5" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testModLongFloat( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( M_MKTEST_( "mod" , "6000000000" , "1e10" )  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "real 6e9" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testModFloatInt( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( M_MKTEST_( "mod" , "3.0" , "2" )  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "real 1." , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testModFloatLong( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( M_MKTEST_( "mod" , "12e9" , "7000000000" )  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "real 5e9" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testModFloatFloat( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( M_MKTEST_( "mod" , "1.5" , ".6" )  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "real .3" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testModIntZero( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -mod 10 0 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "non-zero argument expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 11 );
-	CPPUNIT_ASSERT( check( "10" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testModFloatZero( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -mod 2. 0. )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "non-zero argument expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 11 );
-	CPPUNIT_ASSERT( check( "2." , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testModManyInt( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -mod 23 5 2 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testModManyFloat( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -mod 2. .6 .15 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( ".05" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testModManyWithError( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -mod 2 ( ) .25 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "integer or real number expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 10 );
-	CPPUNIT_ASSERT( check( "0." , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdArithmeticTest::testNegNoArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -neg )"  , errors ) );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 8 );
-}
-
-void SRDPreprocCmdArithmeticTest::testNegTooManyArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -neg 1 2 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "too many arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 10 );
-	CPPUNIT_ASSERT( check( "-1" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testNegBadArg( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -neg nope )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "integer or real argument expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 8 );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testNegInt( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -neg 12 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "-12" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testNegLong( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -neg 12000000000 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "-12000000000" , output ) );
-}
-
-void SRDPreprocCmdArithmeticTest::testNegReal( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -neg -1.2 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1.2" , output ) );
-}
-
diff --git a/tests/srd-preproc-cmd-casts.cc b/tests/srd-preproc-cmd-casts.cc
deleted file mode 100644
index dc02135..0000000
--- a/tests/srd-preproc-cmd-casts.cc
+++ /dev/null
@@ -1,1100 +0,0 @@
-#include "srd-preproc-cmd-common.hh"
-
-
-class SRDPreprocCmdCastsTest : public CppUnit::TestFixture
-{
-	CPPUNIT_TEST_SUITE( SRDPreprocCmdCastsTest );
-
-	CPPUNIT_TEST( testToStringEmpty );
-	CPPUNIT_TEST( testToStringString );
-	CPPUNIT_TEST( testToStringWord );
-	CPPUNIT_TEST( testToStringInt );
-	CPPUNIT_TEST( testToStringLong );
-	CPPUNIT_TEST( testToStringReal );
-	CPPUNIT_TEST( testToStringVar );
-	CPPUNIT_TEST( testToStringList );
-	CPPUNIT_TEST( testToStringBinary );
-	CPPUNIT_TEST( testToStringBinaryInvalid );
-	CPPUNIT_TEST( testToStringMultiple );
-
-	CPPUNIT_TEST( testToWordEmpty );
-	CPPUNIT_TEST( testToWordStringOk );
-	CPPUNIT_TEST( testToWordStringBad );
-	CPPUNIT_TEST( testToWordWord );
-	CPPUNIT_TEST( testToWordInt );
-	CPPUNIT_TEST( testToWordLong );
-	CPPUNIT_TEST( testToWordReal );
-	CPPUNIT_TEST( testToWordVar );
-	CPPUNIT_TEST( testToWordList );
-	CPPUNIT_TEST( testToWordMultiple );
-
-	CPPUNIT_TEST( testToIntEmpty );
-	CPPUNIT_TEST( testToIntStringOk );
-	CPPUNIT_TEST( testToIntStringBad );
-	CPPUNIT_TEST( testToIntWord );
-	CPPUNIT_TEST( testToIntInt );
-	CPPUNIT_TEST( testToIntLongOk );
-	CPPUNIT_TEST( testToIntLongBad );
-	CPPUNIT_TEST( testToIntReal );
-	CPPUNIT_TEST( testToIntVar );
-	CPPUNIT_TEST( testToIntList );
-	CPPUNIT_TEST( testToIntMultiple );
-
-	CPPUNIT_TEST( testToLongEmpty );
-	CPPUNIT_TEST( testToLongStringOk );
-	CPPUNIT_TEST( testToLongStringBad );
-	CPPUNIT_TEST( testToLongWord );
-	CPPUNIT_TEST( testToLongInt );
-	CPPUNIT_TEST( testToLongLong );
-	CPPUNIT_TEST( testToLongReal );
-	CPPUNIT_TEST( testToLongVar );
-	CPPUNIT_TEST( testToLongList );
-	CPPUNIT_TEST( testToLongMultiple );
-
-	CPPUNIT_TEST( testToBestIntEmpty );
-	CPPUNIT_TEST( testToBestIntString32 );
-	CPPUNIT_TEST( testToBestIntString64 );
-	CPPUNIT_TEST( testToBestIntStringBad );
-	CPPUNIT_TEST( testToBestIntWord );
-	CPPUNIT_TEST( testToBestIntInt );
-	CPPUNIT_TEST( testToBestIntLong32 );
-	CPPUNIT_TEST( testToBestIntLong64 );
-	CPPUNIT_TEST( testToBestIntReal32 );
-	CPPUNIT_TEST( testToBestIntReal64 );
-	CPPUNIT_TEST( testToBestIntVar );
-	CPPUNIT_TEST( testToBestIntList );
-	CPPUNIT_TEST( testToBestIntMultiple );
-
-	CPPUNIT_TEST( testToRealEmpty );
-	CPPUNIT_TEST( testToRealStringOk );
-	CPPUNIT_TEST( testToRealStringBad );
-	CPPUNIT_TEST( testToRealWord );
-	CPPUNIT_TEST( testToRealInt );
-	CPPUNIT_TEST( testToRealLong );
-	CPPUNIT_TEST( testToRealReal );
-	CPPUNIT_TEST( testToRealVar );
-	CPPUNIT_TEST( testToRealList );
-	CPPUNIT_TEST( testToRealMultiple );
-
-	CPPUNIT_TEST( testToVarEmpty );
-	CPPUNIT_TEST( testToVarStringOk );
-	CPPUNIT_TEST( testToVarStringOkWithDollar );
-	CPPUNIT_TEST( testToVarStringBadWord );
-	CPPUNIT_TEST( testToVarStringBadVarName );
-	CPPUNIT_TEST( testToVarWordOk );
-	CPPUNIT_TEST( testToVarWordBad );
-	CPPUNIT_TEST( testToVarInt );
-	CPPUNIT_TEST( testToVarLong );
-	CPPUNIT_TEST( testToVarReal );
-	CPPUNIT_TEST( testToVarVar );
-	CPPUNIT_TEST( testToVarList );
-	CPPUNIT_TEST( testToVarMultiple );
-
-	CPPUNIT_TEST( testToListEmpty );
-	CPPUNIT_TEST( testToListString );
-	CPPUNIT_TEST( testToListStringEmpty );
-	CPPUNIT_TEST( testToListWord );
-	CPPUNIT_TEST( testToListBinary );
-	CPPUNIT_TEST( testToListBinaryEmpty );
-	CPPUNIT_TEST( testToListList );
-	CPPUNIT_TEST( testToListListEmpty );
-	CPPUNIT_TEST( testToListOtherTypes );
-
-	CPPUNIT_TEST( testToSourceEmpty );
-	CPPUNIT_TEST( testToSourceWord );
-	CPPUNIT_TEST( testToSourceString );
-	CPPUNIT_TEST( testToSourceInt );
-	CPPUNIT_TEST( testToSourceLong );
-	CPPUNIT_TEST( testToSourceReal );
-	CPPUNIT_TEST( testToSourceVar );
-	CPPUNIT_TEST( testToSourceList );
-	CPPUNIT_TEST( testToSourceMultiple );
-
-	CPPUNIT_TEST_SUITE_END( );
-
-   public:
-	void testToStringEmpty( );
-	void testToStringString( );
-	void testToStringWord( );
-	void testToStringInt( );
-	void testToStringLong( );
-	void testToStringReal( );
-	void testToStringVar( );
-	void testToStringList( );
-	void testToStringBinary( );
-	void testToStringBinaryInvalid( );
-	void testToStringMultiple( );
-
-	void testToWordEmpty( );
-	void testToWordStringOk( );
-	void testToWordStringBad( );
-	void testToWordWord( );
-	void testToWordInt( );
-	void testToWordLong( );
-	void testToWordReal( );
-	void testToWordVar( );
-	void testToWordList( );
-	void testToWordMultiple( );
-
-	void testToIntEmpty( );
-	void testToIntStringOk( );
-	void testToIntStringBad( );
-	void testToIntWord( );
-	void testToIntInt( );
-	void testToIntLongOk( );
-	void testToIntLongBad( );
-	void testToIntReal( );
-	void testToIntVar( );
-	void testToIntList( );
-	void testToIntMultiple( );
-
-	void testToLongEmpty( );
-	void testToLongStringOk( );
-	void testToLongStringBad( );
-	void testToLongWord( );
-	void testToLongInt( );
-	void testToLongLong( );
-	void testToLongReal( );
-	void testToLongVar( );
-	void testToLongList( );
-	void testToLongMultiple( );
-
-	void testToBestIntEmpty( );
-	void testToBestIntString32( );
-	void testToBestIntString64( );
-	void testToBestIntStringBad( );
-	void testToBestIntWord( );
-	void testToBestIntInt( );
-	void testToBestIntLong32( );
-	void testToBestIntLong64( );
-	void testToBestIntReal32( );
-	void testToBestIntReal64( );
-	void testToBestIntVar( );
-	void testToBestIntList( );
-	void testToBestIntMultiple( );
-
-	void testToRealEmpty( );
-	void testToRealStringOk( );
-	void testToRealStringBad( );
-	void testToRealWord( );
-	void testToRealInt( );
-	void testToRealLong( );
-	void testToRealReal( );
-	void testToRealVar( );
-	void testToRealList( );
-	void testToRealMultiple( );
-
-	void testToVarEmpty( );
-	void testToVarStringOk( );
-	void testToVarStringOkWithDollar( );
-	void testToVarStringBadWord( );
-	void testToVarStringBadVarName( );
-	void testToVarWordOk( );
-	void testToVarWordBad( );
-	void testToVarInt( );
-	void testToVarLong( );
-	void testToVarReal( );
-	void testToVarVar( );
-	void testToVarList( );
-	void testToVarMultiple( );
-
-	void testToListEmpty( );
-	void testToListString( );
-	void testToListStringEmpty( );
-	void testToListWord( );
-	void testToListBinary( );
-	void testToListBinaryEmpty( );
-	void testToListList( );
-	void testToListListEmpty( );
-	void testToListOtherTypes( );
-
-	void testToSourceEmpty( );
-	void testToSourceWord( );
-	void testToSourceString( );
-	void testToSourceInt( );
-	void testToSourceLong( );
-	void testToSourceReal( );
-	void testToSourceVar( );
-	void testToSourceList( );
-	void testToSourceMultiple( );
-};
-CPPUNIT_TEST_SUITE_REGISTRATION( SRDPreprocCmdCastsTest );
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdCastsTest::testToStringEmpty( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-string )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToStringString( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-string \"a string\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "\"a string\"" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToStringWord( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-string word )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "\"word\"" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToStringInt( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-string 1 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "\"1\"" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToStringLong( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-string 12123456789 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "\"12123456789\"" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToStringReal( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-string 0.5 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "\"0.5\"" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToStringVar( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-string ( -raw $a ) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "\"$a\"" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToStringList( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-string ( ) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "unsupported type conversion" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 14 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToStringBinary( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-string [ 4c 4f 4c ] )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "\"LOL\"" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToStringBinaryInvalid( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-string [ 80 4c 4f 4c e5 ] )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "invalid UTF-8 data" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 14 );
-	CPPUNIT_ASSERT( check( "\"\"" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToStringMultiple( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-string \"a\" b ( ) ( -raw $c ) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "unsupported type conversion" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 20 );
-	CPPUNIT_ASSERT( check( "\"a\" \"b\" \"$c\"" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdCastsTest::testToWordEmpty( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-word )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToWordStringOk( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-word \"a-word\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "a-word" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToWordStringBad( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-word \"not a word, lol\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "invalid word" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 12 );
-	CPPUNIT_ASSERT( check( "invalid" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToWordWord( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-word word )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "word" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToWordInt( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-word 1 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "unsupported type conversion" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 12 );
-	CPPUNIT_ASSERT( check( "invalid" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToWordLong( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-word 12123456789 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "unsupported type conversion" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 12 );
-	CPPUNIT_ASSERT( check( "invalid" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToWordReal( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-word 0.5 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "unsupported type conversion" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 12 );
-	CPPUNIT_ASSERT( check( "invalid" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToWordVar( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-word ( -raw $x ) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "x" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToWordList( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-word ( ) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "unsupported type conversion" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 12 );
-	CPPUNIT_ASSERT( check( "invalid" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToWordMultiple( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-word ( ) \"a\" ( -raw $b ) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "unsupported type conversion" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 12 );
-	CPPUNIT_ASSERT( check( "invalid a b" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdCastsTest::testToIntEmpty( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-integer )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToIntStringOk( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-integer \"123\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "123" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToIntStringBad( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-integer \"123nope\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "invalid integer value" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 15 );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToIntWord( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-integer word )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "unsupported type conversion" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 15 );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToIntInt( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-integer 123 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "123" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToIntLongOk( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-integer ( -to-long 123 ) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "123" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToIntLongBad( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-integer 12345678912 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "value out of range" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 15 );
-	CPPUNIT_ASSERT( check( "2147483647" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToIntReal( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-integer 0.5 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToIntVar( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-integer ( -raw $x ) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "unsupported type conversion" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 22 );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToIntList( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-integer ( ) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "unsupported type conversion" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 15 );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToIntMultiple( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-integer ( ) 1 \"2\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "unsupported type conversion" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 15 );
-	CPPUNIT_ASSERT( check( "0 1 2" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdCastsTest::testToLongEmpty( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-long )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToLongStringOk( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-long \"12345678912\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "12345678912" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToLongStringBad( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-long \"123nope\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "invalid integer value" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 12 );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , output.size( ) );
-	CPPUNIT_ASSERT( output[ 0 ].type( ) == E_SRDTokenType::LONG );
-	CPPUNIT_ASSERT_EQUAL( int64_t( 0 ) , output[ 0 ].longValue( ) );
-}
-
-void SRDPreprocCmdCastsTest::testToLongWord( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-long word )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "unsupported type conversion" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 12 );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , output.size( ) );
-	CPPUNIT_ASSERT( output[ 0 ].type( ) == E_SRDTokenType::LONG );
-	CPPUNIT_ASSERT_EQUAL( int64_t( 0 ) , output[ 0 ].longValue( ) );
-}
-
-void SRDPreprocCmdCastsTest::testToLongInt( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-long 123 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , output.size( ) );
-	CPPUNIT_ASSERT( output[ 0 ].type( ) == E_SRDTokenType::LONG );
-	CPPUNIT_ASSERT_EQUAL( int64_t( 123 ) , output[ 0 ].longValue( ) );
-}
-
-void SRDPreprocCmdCastsTest::testToLongLong( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-long 12345678912 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "12345678912" , output ) );
-}
-
-
-void SRDPreprocCmdCastsTest::testToLongReal( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-long 1e10 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "10000000000" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToLongVar( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-long ( -raw $x ) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "unsupported type conversion" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 19 );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , output.size( ) );
-	CPPUNIT_ASSERT( output[ 0 ].type( ) == E_SRDTokenType::LONG );
-	CPPUNIT_ASSERT_EQUAL( int64_t( 0 ) , output[ 0 ].longValue( ) );
-}
-
-void SRDPreprocCmdCastsTest::testToLongList( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-long ( ) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "unsupported type conversion" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 12 );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , output.size( ) );
-	CPPUNIT_ASSERT( output[ 0 ].type( ) == E_SRDTokenType::LONG );
-	CPPUNIT_ASSERT_EQUAL( int64_t( 0 ) , output[ 0 ].longValue( ) );
-}
-
-void SRDPreprocCmdCastsTest::testToLongMultiple( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-long ( ) 12345678912 \"12123456789\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "unsupported type conversion" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 12 );
-	CPPUNIT_ASSERT_EQUAL( 3u , output.size( ) );
-	CPPUNIT_ASSERT( output[ 0 ].type( ) == E_SRDTokenType::LONG );
-	CPPUNIT_ASSERT_EQUAL( int64_t( 0 ) , output[ 0 ].longValue( ) );
-	CPPUNIT_ASSERT( output[ 1 ].type( ) == E_SRDTokenType::LONG );
-	CPPUNIT_ASSERT_EQUAL( int64_t( 12345678912L ) , output[ 1 ].longValue( ) );
-	CPPUNIT_ASSERT( output[ 2 ].type( ) == E_SRDTokenType::LONG );
-	CPPUNIT_ASSERT_EQUAL( int64_t( 12123456789L ) , output[ 2 ].longValue( ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdCastsTest::testToBestIntEmpty( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-best-integer )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToBestIntString32( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-best-integer \"123456\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "123456" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToBestIntString64( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-best-integer \"12345678912\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "12345678912" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToBestIntStringBad( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-best-integer \"123nope\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "invalid integer value" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 20 );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToBestIntWord( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-best-integer nope )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "unsupported type conversion" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 20 );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToBestIntInt( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-best-integer 123 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "123" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToBestIntLong32( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-best-integer ( -to-long 123 ) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "123" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToBestIntLong64( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-best-integer 12345678912 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "12345678912" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToBestIntReal32( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-best-integer 12.3 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "12" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToBestIntReal64( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-best-integer 1e10 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "10000000000" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToBestIntVar( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-best-integer ( -raw $x ) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "unsupported type conversion" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 27 );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToBestIntList( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-best-integer ( ) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "unsupported type conversion" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 20 );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToBestIntMultiple( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-best-integer ( ) \"123\" 456 78912345678 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "unsupported type conversion" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 20 );
-	CPPUNIT_ASSERT( check( "0 123 456 78912345678" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdCastsTest::testToRealEmpty( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-real )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToRealStringOk( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-real \"-12e-3\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "-0.012" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToRealStringBad( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-real \"nope\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "invalid real value" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 12 );
-	CPPUNIT_ASSERT( check( "0." , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToRealWord( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-real nope )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "unsupported type conversion" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 12 );
-	CPPUNIT_ASSERT( check( "0." , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToRealInt( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-real 12 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "12.0" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToRealLong( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-real 12345678912 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "12345678912.0" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToRealReal( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-real 1234567891.2 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1234567891.2" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToRealVar( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-real ( -raw $x ) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "unsupported type conversion" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 19 );
-	CPPUNIT_ASSERT( check( "0." , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToRealList( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-real ( ) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "unsupported type conversion" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 12 );
-	CPPUNIT_ASSERT( check( "0." , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToRealMultiple( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-real ( ) 123 456.5 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "unsupported type conversion" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 12 );
-	CPPUNIT_ASSERT( check( "0. 123.0 456.5" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdCastsTest::testToVarEmpty( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-variable )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToVarStringOk( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-variable \"name\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "$name" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToVarStringOkWithDollar( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-variable \"$name\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "$name" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToVarStringBadWord( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-variable \"not a word\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "invalid variable name" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 16 );
-	CPPUNIT_ASSERT( check( "$invalid" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToVarStringBadVarName( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-variable \"-bad\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "invalid variable name" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 16 );
-	CPPUNIT_ASSERT( check( "$invalid" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToVarWordOk( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-variable name )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "$name" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToVarWordBad( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-variable -bad )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "invalid variable name" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 16 );
-	CPPUNIT_ASSERT( check( "$invalid" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToVarInt( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-variable 1 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "unsupported type conversion" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 16 );
-	CPPUNIT_ASSERT( check( "$invalid" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToVarLong( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-variable 12345678912 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "unsupported type conversion" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 16 );
-	CPPUNIT_ASSERT( check( "$invalid" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToVarReal( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-variable 1.5 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "unsupported type conversion" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 16 );
-	CPPUNIT_ASSERT( check( "$invalid" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToVarVar( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-variable ( -raw $x ) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "$x" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToVarList( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-variable ( ) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "unsupported type conversion" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 16 );
-	CPPUNIT_ASSERT( check( "$invalid" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToVarMultiple( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-variable ( ) \"$x\" y )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "unsupported type conversion" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 16 );
-	CPPUNIT_ASSERT( check( "$invalid $x $y" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdCastsTest::testToListEmpty( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-list )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToListString( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-list \"abc\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "\"a\" \"b\" \"c\"" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToListStringEmpty( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-list \"\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToListWord( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-list abc )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "\"a\" \"b\" \"c\"" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToListBinary( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-list [ deadbeef ] )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "222 173 190 239" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToListBinaryEmpty( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-list [ ] )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToListList( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-list ( ab c ) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "ab c" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToListListEmpty( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-list ( ) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToListOtherTypes( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-list 10 1.2 (-raw $x) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "10 1.2 $x" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdCastsTest::testToSourceEmpty( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-source )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "\"\"" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToSourceWord( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-source word )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "\"word\"" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToSourceString( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-source \"some\\nstring\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "\"\\\"some\\\\nstring\\\"\"" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToSourceInt( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-source 123 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "\"123\"" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToSourceLong( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-source 5000000000 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "\"5000000000\"" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToSourceReal( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-source 1.2 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "\"1.2\"" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToSourceVar( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -to-source (-raw $x) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "\"$x\"" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToSourceList( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "(-to-source ( word \"string\" 123 5000000000 1.2 (-raw $x) ))" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "\"( word \\\"string\\\" 123 5000000000 1.2 $x )\"" , output ) );
-}
-
-void SRDPreprocCmdCastsTest::testToSourceMultiple( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "(-to-source word \"string\" 123 5000000000 1.2 (-raw $x) ( some list ))" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "\"word \\\"string\\\" 123 5000000000 1.2 $x ( some list )\"" , output ) );
-}
diff --git a/tests/srd-preproc-cmd-common.hh b/tests/srd-preproc-cmd-common.hh
deleted file mode 100644
index a6990d7..0000000
--- a/tests/srd-preproc-cmd-common.hh
+++ /dev/null
@@ -1,108 +0,0 @@
-#ifndef TESTS_SRDPREPROCCMDCOMMON_H_
-#define TESTS_SRDPREPROCCMDCOMMON_H_
-
-#include <lw/lib/SRDPreproc.hh>
-#include <lw/lib/SRDText.hh>
-#include <lw/lib/SRDIO.hh>
-#include <lw/lib/MemoryStreams.hh>
-#include <cppunit/extensions/HelperMacros.h>
-using namespace lw;
-
-// M_PRINTERR_( index ) - Print an error message
-#define M_PRINTERR_( IDX ) \
-	do { \
-		auto const& _e( errors[ IDX ] ); \
-		char err[ _e.error( ).size( ) + 1 ]; \
-		err[ sizeof( err ) - 1 ] = 0; \
-		memcpy( err , _e.error( ).data( ) , \
-		       sizeof( err ) - 1 ); \
-		printf( "ERR %s l. %u c. %lu\n" , err , \
-		       _e.location( ).line( ) , \
-		       _e.location( ).character( ) ); \
-	} while ( 0 )
-
-// M_CKERR_( index , string , line , character ) - Check an error
-#define M_CKERR_( IDX , STR , L , C ) \
-	do { \
-		auto const& _e( errors[ IDX ] ); \
-		CPPUNIT_ASSERT( T_String( STR ) == _e.error( ) ); \
-		CPPUNIT_ASSERT_EQUAL( uint32_t( L ) , \
-				     _e.location( ).line( ) ); \
-		CPPUNIT_ASSERT_EQUAL( size_t( C ) , \
-				     _e.location( ).character( ) ); \
-	} while ( 0 )
-
-namespace {
-
-void process( char const* input , T_SRDPreprocessor& preproc , T_SRDErrors& errors )
-{
-	T_SRDLexer lexer( T_String( "test" ) , errors , preproc );
-	preproc.start( errors );
-	char const* ptr = input;
-	while ( *ptr != 0 ) {
-		lexer.processCharacter( *ptr ++ );
-	}
-	lexer.processEnd( );
-}
-
-T_SRDList process( char const* input , T_SRDErrors& errors )
-{
-	T_SRDMemoryTarget mt( false );
-	mt.clearFlushToken( true );
-	mt.start( errors );
-
-	T_SRDPreprocessorConfig emptyConfig;
-	emptyConfig.addBuiltinCommands( );
-	T_SRDPreprocessor pp( emptyConfig , mt );
-	process( input , pp , errors );
-	mt.end( errors );
-
-	return mt.list( );
-}
-
-bool checkMatch( T_SRDList const& expected , T_SRDList const& actual )
-{
-	const size_t nExpected( expected.size( ) );
-	const size_t nActual( actual.size( ) );
-
-	bool ok( nExpected == nActual );
-	const size_t nCheck( std::min( nExpected , nActual ) );
-	for ( size_t i = 0 ; i < nCheck ; i ++ ) {
-		T_SRDToken const& tExpected( expected[ i ] );
-		T_SRDToken const& tActual( actual[ i ] );
-		if ( tExpected.type( ) != tActual.type( ) ) {
-			ok = false;
-		} else if ( tExpected.stringValue( ) != tActual.stringValue( ) ) {
-			ok = false;
-		}
-	}
-	return ok;
-}
-
-bool check( char const* expected , T_SRDList const& actual )
-{
-	T_SRDMemoryTarget mt( false );
-	T_SRDErrors errors;
-	T_SRDLexer lexer( T_String( "expected" ) , errors , mt );
-	mt.start( errors );
-	char const* ptr = expected;
-	while ( *ptr != 0 ) {
-		lexer.processCharacter( *ptr ++ );
-	}
-	lexer.processEnd( );
-
-	const bool ok( checkMatch( mt.list( ) , actual ) );
-	if ( ok ) {
-		return true;
-	}
-	T_Buffer< char > output;
-	T_MemoryOutputStream stream{ output };
-	lw::SRDWriteAsText( stream , actual );
-	stream.write( "" , 1 );
-	std::cerr << "\nExpected:\n\t" << expected << "\nActual:\n" << output.data( ) << '\n';
-	return false;
-}
-
-}
-
-#endif // TESTS_SRDPREPROCCMDCOMMON_H_
diff --git a/tests/srd-preproc-cmd-compare.cc b/tests/srd-preproc-cmd-compare.cc
deleted file mode 100644
index 8d924e7..0000000
--- a/tests/srd-preproc-cmd-compare.cc
+++ /dev/null
@@ -1,340 +0,0 @@
-#include "srd-preproc-cmd-common.hh"
-
-
-class SRDPreprocCmdCompareTest : public CppUnit::TestFixture
-{
-	CPPUNIT_TEST_SUITE( SRDPreprocCmdCompareTest );
-
-		CPPUNIT_TEST( testCmpMissingArgs );
-		CPPUNIT_TEST( testCmpExtraArgs );
-		CPPUNIT_TEST( testCmp );
-
-		CPPUNIT_TEST( testEqMissingArgs );
-		CPPUNIT_TEST( testEqExtraArgs );
-		CPPUNIT_TEST( testEq );
-
-		CPPUNIT_TEST( testNeMissingArgs );
-		CPPUNIT_TEST( testNeExtraArgs );
-		CPPUNIT_TEST( testNe );
-
-		CPPUNIT_TEST( testLtMissingArgs );
-		CPPUNIT_TEST( testLtExtraArgs );
-		CPPUNIT_TEST( testLt );
-
-		CPPUNIT_TEST( testGtMissingArgs );
-		CPPUNIT_TEST( testGtExtraArgs );
-		CPPUNIT_TEST( testGt );
-
-		CPPUNIT_TEST( testLeMissingArgs );
-		CPPUNIT_TEST( testLeExtraArgs );
-		CPPUNIT_TEST( testLe );
-
-		CPPUNIT_TEST( testGeMissingArgs );
-		CPPUNIT_TEST( testGeExtraArgs );
-		CPPUNIT_TEST( testGe );
-
-	CPPUNIT_TEST_SUITE_END( );
-
-   public:
-	void testCmpMissingArgs( );
-	void testCmpExtraArgs( );
-	void testCmp( );
-
-	void testEqMissingArgs( );
-	void testEqExtraArgs( );
-	void testEq( );
-
-	void testNeMissingArgs( );
-	void testNeExtraArgs( );
-	void testNe( );
-
-	void testLtMissingArgs( );
-	void testLtExtraArgs( );
-	void testLt( );
-
-	void testGtMissingArgs( );
-	void testGtExtraArgs( );
-	void testGt( );
-
-	void testLeMissingArgs( );
-	void testLeExtraArgs( );
-	void testLe( );
-
-	void testGeMissingArgs( );
-	void testGeExtraArgs( );
-	void testGe( );
-};
-CPPUNIT_TEST_SUITE_REGISTRATION( SRDPreprocCmdCompareTest );
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdCompareTest::testCmpMissingArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -cmp )\n( -cmp a )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 4u , errors.size( ) );
-	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 8 );
-	M_CKERR_( 2 , "not enough arguments" , 2 , 3 );
-	M_CKERR_( 3 , "previous error cause" , 2 , 10 );
-	CPPUNIT_ASSERT( check( "0 0" , output ) );
-}
-
-void SRDPreprocCmdCompareTest::testCmpExtraArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -cmp a b c )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "too many arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 12 );
-	CPPUNIT_ASSERT( check( "-1" , output ) );
-}
-
-void SRDPreprocCmdCompareTest::testCmp( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"( -cmp a a )\n"
-				"( -cmp a b )\n"
-				"( -cmp ((a)) b )\n"
-				"( -cmp a ((b)) )\n"
-				"( -cmp ((a)) ((b)) )\n"
-				"( -cmp ((a)) ((a)) )\n"
-				, errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "0 -1 -1 1 -1 0" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdCompareTest::testEqMissingArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -eq )\n( -eq a )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 4u , errors.size( ) );
-	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 7 );
-	M_CKERR_( 2 , "not enough arguments" , 2 , 3 );
-	M_CKERR_( 3 , "previous error cause" , 2 , 9 );
-	CPPUNIT_ASSERT( check( "1 1" , output ) );
-}
-
-void SRDPreprocCmdCompareTest::testEqExtraArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -eq a b c )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "too many arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 11 );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdCompareTest::testEq( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"( -eq a a )\n"
-				"( -eq a b )\n"
-				"( -eq ((a)) b )\n"
-				"( -eq a ((b)) )\n"
-				"( -eq ((a)) ((b)) )\n"
-				"( -eq ((a)) ((a)) )\n"
-				, errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1 0 0 0 0 1" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdCompareTest::testNeMissingArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -ne )\n( -ne a )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 4u , errors.size( ) );
-	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 7 );
-	M_CKERR_( 2 , "not enough arguments" , 2 , 3 );
-	M_CKERR_( 3 , "previous error cause" , 2 , 9 );
-	CPPUNIT_ASSERT( check( "0 0" , output ) );
-}
-
-void SRDPreprocCmdCompareTest::testNeExtraArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -ne a b c )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "too many arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 11 );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-void SRDPreprocCmdCompareTest::testNe( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"( -ne a a )\n"
-				"( -ne a b )\n"
-				"( -ne ((a)) b )\n"
-				"( -ne a ((b)) )\n"
-				"( -ne ((a)) ((b)) )\n"
-				"( -ne ((a)) ((a)) )\n"
-				, errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "0 1 1 1 1 0" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdCompareTest::testLtMissingArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -lt )\n( -lt a )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 4u , errors.size( ) );
-	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 7 );
-	M_CKERR_( 2 , "not enough arguments" , 2 , 3 );
-	M_CKERR_( 3 , "previous error cause" , 2 , 9 );
-	CPPUNIT_ASSERT( check( "0 0" , output ) );
-}
-
-void SRDPreprocCmdCompareTest::testLtExtraArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -lt a b c )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "too many arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 11 );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-void SRDPreprocCmdCompareTest::testLt( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"( -lt a a )\n"
-				"( -lt a b )\n"
-				"( -lt ((a)) b )\n"
-				"( -lt a ((b)) )\n"
-				"( -lt ((a)) ((b)) )\n"
-				"( -lt ((a)) ((a)) )\n"
-				, errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "0 1 1 0 1 0" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdCompareTest::testGtMissingArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -gt )\n( -gt a )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 4u , errors.size( ) );
-	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 7 );
-	M_CKERR_( 2 , "not enough arguments" , 2 , 3 );
-	M_CKERR_( 3 , "previous error cause" , 2 , 9 );
-	CPPUNIT_ASSERT( check( "0 0" , output ) );
-}
-
-void SRDPreprocCmdCompareTest::testGtExtraArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -gt a b c )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "too many arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 11 );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdCompareTest::testGt( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"( -gt a a )\n"
-				"( -gt a b )\n"
-				"( -gt ((a)) b )\n"
-				"( -gt a ((b)) )\n"
-				"( -gt ((a)) ((b)) )\n"
-				"( -gt ((a)) ((a)) )\n"
-				, errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "0 0 0 1 0 0" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdCompareTest::testLeMissingArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -le )\n( -le a )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 4u , errors.size( ) );
-	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 7 );
-	M_CKERR_( 2 , "not enough arguments" , 2 , 3 );
-	M_CKERR_( 3 , "previous error cause" , 2 , 9 );
-	CPPUNIT_ASSERT( check( "1 1" , output ) );
-}
-
-void SRDPreprocCmdCompareTest::testLeExtraArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -le a b c )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "too many arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 11 );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-void SRDPreprocCmdCompareTest::testLe( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"( -le a a )\n"
-				"( -le a b )\n"
-				"( -le ((a)) b )\n"
-				"( -le a ((b)) )\n"
-				"( -le ((a)) ((b)) )\n"
-				"( -le ((a)) ((a)) )\n"
-				, errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1 1 1 0 1 1" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdCompareTest::testGeMissingArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -ge )\n( -ge a )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 4u , errors.size( ) );
-	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 7 );
-	M_CKERR_( 2 , "not enough arguments" , 2 , 3 );
-	M_CKERR_( 3 , "previous error cause" , 2 , 9 );
-	CPPUNIT_ASSERT( check( "1 1" , output ) );
-}
-
-void SRDPreprocCmdCompareTest::testGeExtraArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -ge a b c )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "too many arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 11 );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdCompareTest::testGe( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"( -ge a a )\n"
-				"( -ge a b )\n"
-				"( -ge ((a)) b )\n"
-				"( -ge a ((b)) )\n"
-				"( -ge ((a)) ((b)) )\n"
-				"( -ge ((a)) ((a)) )\n"
-				, errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1 0 0 1 0 1" , output ) );
-}
diff --git a/tests/srd-preproc-cmd-core.cc b/tests/srd-preproc-cmd-core.cc
deleted file mode 100644
index de8826f..0000000
--- a/tests/srd-preproc-cmd-core.cc
+++ /dev/null
@@ -1,1303 +0,0 @@
-#include "srd-preproc-cmd-common.hh"
-#include "srd-preproc-location.hh"
-
-
-class SRDPreprocCmdCoreTest : public CppUnit::TestFixture
-{
-	CPPUNIT_TEST_SUITE( SRDPreprocCmdCoreTest );
-
-	CPPUNIT_TEST( testRaw );
-	CPPUNIT_TEST( testRawEmpty );
-	CPPUNIT_TEST( testRawSkipComments );
-	CPPUNIT_TEST( testRawUnterminated );
-
-	CPPUNIT_TEST( testIfMissingArgs );
-	CPPUNIT_TEST( testIfExtraArgs );
-	CPPUNIT_TEST( testIfBadCondition );
-	CPPUNIT_TEST( testIfBadThenBlock );
-	CPPUNIT_TEST( testIfBadElseBlock );
-	CPPUNIT_TEST( testIfTrueThen );
-	CPPUNIT_TEST( testIfFalseThen );
-	CPPUNIT_TEST( testIfTrueThenElse );
-	CPPUNIT_TEST( testIfFalseThenElse );
-	CPPUNIT_TEST( testIfArgSubst );
-	CPPUNIT_TEST( testIfThenInnerList );
-	CPPUNIT_TEST( testIfElseInnerList );
-
-	CPPUNIT_TEST( testEvalEmpty );
-	CPPUNIT_TEST( testEval );
-	CPPUNIT_TEST( testEvalErrors );
-	CPPUNIT_TEST( testEvalSkipComments );
-	CPPUNIT_TEST( testEvalUnterminated );
-	CPPUNIT_TEST( testEvalInnerList );
-	CPPUNIT_TEST( testEvalCalls );
-
-	CPPUNIT_TEST( testScope );
-	CPPUNIT_TEST( testScopeValues );
-	CPPUNIT_TEST( testScopeInnerList );
-
-	CPPUNIT_TEST( testClearScopeInstruction );
-	CPPUNIT_TEST( testClearScopeBlock );
-	CPPUNIT_TEST( testClearScopeInnerList );
-
-	CPPUNIT_TEST( testTryEmpty );
-	CPPUNIT_TEST( testTryNoErrors );
-	CPPUNIT_TEST( testTryErrors );
-	CPPUNIT_TEST( testTryErrorsChained );
-	CPPUNIT_TEST( testTryUnterminated );
-	CPPUNIT_TEST( testTryTooManyErrors );
-	CPPUNIT_TEST( testTryInnerList );
-
-	CPPUNIT_TEST( testOutput );
-	CPPUNIT_TEST( testOutputErrors );
-
-	CPPUNIT_TEST( testErrorEmpty );
-	CPPUNIT_TEST( testErrorWord );
-	CPPUNIT_TEST( testErrorString );
-	CPPUNIT_TEST( testErrorVar );
-	CPPUNIT_TEST( testErrorInt );
-	CPPUNIT_TEST( testErrorLong );
-	CPPUNIT_TEST( testErrorReal );
-	CPPUNIT_TEST( testErrorList );
-	CPPUNIT_TEST( testErrorConcat );
-
-	CPPUNIT_TEST( testBreakMain );
-	CPPUNIT_TEST( testBreakMainList );
-	CPPUNIT_TEST( testBreakEvalInput );
-	CPPUNIT_TEST( testBreakEvalOutput );
-	CPPUNIT_TEST( testBreakFunction );
-	CPPUNIT_TEST( testBreakRecursiveFunction );
-	CPPUNIT_TEST( testBreakMacro );
-	CPPUNIT_TEST( testBreakArgs );
-
-	CPPUNIT_TEST( testRethrowNothing );
-	CPPUNIT_TEST( testRethrowList );
-	CPPUNIT_TEST( testRethrowEmptyList );
-	CPPUNIT_TEST( testRethrowUnwrapped );
-	CPPUNIT_TEST( testRethrowErrorWord );
-	CPPUNIT_TEST( testRethrowSourceWord );
-	CPPUNIT_TEST( testRethrowDetails );
-	CPPUNIT_TEST( testRethrowChained );
-	CPPUNIT_TEST( testRethrowChainedDepth );
-
-	CPPUNIT_TEST( testRethrowNoList );
-	CPPUNIT_TEST( testRethrowBadMessage );
-	CPPUNIT_TEST( testRethrowNoLocation );
-	CPPUNIT_TEST( testRethrowBadLocation );
-	CPPUNIT_TEST( testRethrowLocationBadSource );
-	CPPUNIT_TEST( testRethrowLocationBadLine );
-	CPPUNIT_TEST( testRethrowLocationNegativeLine );
-	CPPUNIT_TEST( testRethrowLocationLineTooHigh );
-	CPPUNIT_TEST( testRethrowLocationBadChar );
-	CPPUNIT_TEST( testRethrowLocationNegativeChar );
-	CPPUNIT_TEST( testRethrowChainedBad );
-	CPPUNIT_TEST( testRethrowChainedInvalid );
-	CPPUNIT_TEST( testRethrowChainedNoLocation );
-	CPPUNIT_TEST( testRethrowChainedBadLocation );
-	CPPUNIT_TEST( testRethrowChainedNegativeDepth );
-	CPPUNIT_TEST( testRethrowChainedDepthTooHigh );
-	CPPUNIT_TEST( testRethrowChainedDepthNoLocation );
-	CPPUNIT_TEST( testRethrowChainedDepthBadLocation );
-
-	CPPUNIT_TEST_SUITE_END( );
-
-   public:
-	void testRaw( );
-	void testRawEmpty( );
-	void testRawSkipComments( );
-	void testRawUnterminated( );
-
-	void testIfMissingArgs( );
-	void testIfExtraArgs( );
-	void testIfBadCondition( );
-	void testIfBadThenBlock( );
-	void testIfBadElseBlock( );
-	void testIfTrueThen( );
-	void testIfFalseThen( );
-	void testIfTrueThenElse( );
-	void testIfFalseThenElse( );
-	void testIfArgSubst( );
-	void testIfThenInnerList( );
-	void testIfElseInnerList( );
-
-	void testEvalEmpty( );
-	void testEval( );
-	void testEvalErrors( );
-	void testEvalSkipComments( );
-	void testEvalUnterminated( );
-	void testEvalInnerList( );
-	void testEvalCalls( );
-
-	void testScope( );
-	void testScopeValues( );
-	void testScopeInnerList( );
-
-	void testClearScopeInstruction( );
-	void testClearScopeBlock( );
-	void testClearScopeInnerList( );
-
-	void testTryEmpty( );
-	void testTryNoErrors( );
-	void testTryErrors( );
-	void testTryErrorsChained( );
-	void testTryUnterminated( );
-	void testTryTooManyErrors( );
-	void testTryInnerList( );
-
-	void testOutput( );
-	void testOutputErrors( );
-
-	void testErrorEmpty( );
-	void testErrorWord( );
-	void testErrorString( );
-	void testErrorVar( );
-	void testErrorInt( );
-	void testErrorLong( );
-	void testErrorReal( );
-	void testErrorList( );
-	void testErrorConcat( );
-
-	void testBreakMain( );
-	void testBreakMainList( );
-	void testBreakEvalInput( );
-	void testBreakEvalOutput( );
-	void testBreakFunction( );
-	void testBreakRecursiveFunction( );
-	void testBreakMacro( );
-	void testBreakArgs( );
-
-	void testRethrowNothing( );
-	void testRethrowList( );
-	void testRethrowEmptyList( );
-	void testRethrowUnwrapped( );
-	void testRethrowErrorWord( );
-	void testRethrowSourceWord( );
-	void testRethrowDetails( );
-	void testRethrowChained( );
-	void testRethrowChainedDepth( );
-
-	void testRethrowNoList( );
-	void testRethrowBadMessage( );
-	void testRethrowNoLocation( );
-	void testRethrowBadLocation( );
-	void testRethrowLocationBadSource( );
-	void testRethrowLocationBadLine( );
-	void testRethrowLocationNegativeLine( );
-	void testRethrowLocationLineTooHigh( );
-	void testRethrowLocationBadChar( );
-	void testRethrowLocationNegativeChar( );
-	void testRethrowChainedBad( );
-	void testRethrowChainedInvalid( );
-	void testRethrowChainedNoLocation( );
-	void testRethrowChainedBadLocation( );
-	void testRethrowChainedNegativeDepth( );
-	void testRethrowChainedDepthTooHigh( );
-	void testRethrowChainedDepthNoLocation( );
-	void testRethrowChainedDepthBadLocation( );
-};
-CPPUNIT_TEST_SUITE_REGISTRATION( SRDPreprocCmdCoreTest );
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdCoreTest::testRaw( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -raw ok $x ( -raw ) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "ok $x ( -raw )" , output ) );
-	M_CKTOKFULL_( 0 , "test" , 1 , 8 , 0 );
-	M_CKTOKFULL_( 1 , "test" , 1 , 11 , 0 );
-	M_CKTOKFULL_( 2 , "test" , 1 , 14 , 0 );
-	M_CKTOKFULL_( 3 , "test" , 1 , 16 , 0 );
-	M_CKTOKFULL_( 4 , "test" , 1 , 21 , 0 );
-}
-
-void SRDPreprocCmdCoreTest::testRawEmpty( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -raw )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testRawSkipComments( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -raw { a comment } x # another comment!\n)" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "x" , output ) );
-	M_CKTOKFULL_( 0 , "test" , 1 , 22 , 0 );
-}
-
-void SRDPreprocCmdCoreTest::testRawUnterminated( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -raw\n(\n(" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 3u , errors.size( ) );
-	M_CKERRFULL_( 0 , "unterminated list" , false , "test" , 1 , 1 , 0 );
-	M_CKERRFULL_( 1 , "unterminated list" , false , "test" , 2 , 1 , 0 );
-	M_CKERRFULL_( 2 , "unterminated list" , false , "test" , 3 , 1 , 0 );
-	CPPUNIT_ASSERT( check( "(())" , output ) );
-	M_CKTOKFULL_( 0 , "test" , 2 , 1 , 0 );
-	M_CKTOKFULL_( 1 , "test" , 3 , 1 , 0 );
-	M_CKTOKFULL_( 2 , "*unexpected end of file*" , 0 , 2 , 0 );
-	M_CKTOKFULL_( 3 , "*unexpected end of file*" , 0 , 1 , 0 );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdCoreTest::testIfMissingArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -if )\n( -if 0 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 4u , errors.size( ) );
-	M_CKERRFULL_( 0 , "not enough arguments" , false , "test" , 1 , 3 , 0 );
-	M_CKERRFULL_( 1 , "previous error cause" , true , "test" , 1 , 7 , 0 );
-	M_CKERRFULL_( 2 , "not enough arguments" , false , "test" , 2 , 3 , 0 );
-	M_CKERRFULL_( 3 , "previous error cause" , true , "test" , 2 , 9 , 0 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testIfExtraArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -if 0 (a) (b) (blah()) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERRFULL_( 0 , "too many arguments" , false , "test" , 1 , 3 , 0 );
-	M_CKERRFULL_( 1 , "previous error cause" , true , "test" , 1 , 17 , 0 );
-	CPPUNIT_ASSERT( check( "b" , output ) );
-	M_CKTOKFULL_( 0 , "test" , 1 , 14 , 0 );
-}
-
-void SRDPreprocCmdCoreTest::testIfBadCondition( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -if nope () )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERRFULL_( 0 , "numeric value expected" , false , "test" , 1 , 3 , 0 );
-	M_CKERRFULL_( 1 , "previous error cause" , true , "test" , 1 , 7 , 0 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testIfBadThenBlock( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -if 1 nope )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERRFULL_( 0 , "list expected" , false , "test" , 1 , 3 , 0 );
-	M_CKERRFULL_( 1 , "previous error cause" , true , "test" , 1 , 9 , 0 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testIfBadElseBlock( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -if 1 (a) nope )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERRFULL_( 0 , "list expected" , false , "test" , 1 , 3 , 0 );
-	M_CKERRFULL_( 1 , "previous error cause" , true , "test" , 1 , 13 , 0 );
-	CPPUNIT_ASSERT( check( "a" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testIfTrueThen( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -if 1 (x) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "x" , output ) );
-	M_CKTOKFULL_( 0 , "test" , 1 , 10 , 0 );
-}
-
-void SRDPreprocCmdCoreTest::testIfFalseThen( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -if 0 (x) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testIfTrueThenElse( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -if 1 (x) (y) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "x" , output ) );
-	M_CKTOKFULL_( 0 , "test" , 1 , 10 , 0 );
-}
-
-void SRDPreprocCmdCoreTest::testIfFalseThenElse( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -if 0 (x) (y) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "y" , output ) );
-	M_CKTOKFULL_( 0 , "test" , 1 , 14 , 0 );
-}
-
-void SRDPreprocCmdCoreTest::testIfArgSubst( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"( -set x 1 )\n"
-				"( -if $x (x) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "x" , output ) );
-	M_CKTOKFULL_( 0 , "test" , 2 , 11 , 0 );
-}
-
-void SRDPreprocCmdCoreTest::testIfThenInnerList( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"( -set x (-raw ( () ) ) )\n"
-				"( -bless x )\n"
-				"( -if 1 (-not-a-command) )\n"
-				"( -if 1 ($x) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "-not-a-command (())" , output ) );
-	M_CKTOKFULL_( 0 , "test" , 3 , 10 , 0 );
-	M_CKTOKFULL_( 1 , "$x" , 0 , 0 , 1 );
-		M_CKTOKCHAIN_( 1 , 0 , SUBSTITUTED , "test" , 4 , 10 , 0 );
-	M_CKTOKFULL_( 2 , "$x" , 0 , 1 , 1 );
-		M_CKTOKCHAIN_( 2 , 0 , SUBSTITUTED , "test" , 4 , 10 , 0 );
-	M_CKTOKFULL_( 3 , "$x" , 0 , 2 , 1 );
-		M_CKTOKCHAIN_( 3 , 0 , SUBSTITUTED , "test" , 4 , 10 , 0 );
-	M_CKTOKFULL_( 4 , "$x" , 0 , 3 , 1 );
-		M_CKTOKCHAIN_( 4 , 0 , SUBSTITUTED , "test" , 4 , 10 , 0 );
-}
-
-void SRDPreprocCmdCoreTest::testIfElseInnerList( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"( -set x (-raw ( () ) ) )\n"
-				"( -bless x )\n"
-				"( -if 0 () (-not-a-command) )\n"
-				"( -if 0 () ($x) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "-not-a-command (())" , output ) );
-	M_CKTOKFULL_( 0 , "test" , 3 , 13 , 0 );
-	M_CKTOKFULL_( 1 , "$x" , 0 , 0 , 1 );
-		M_CKTOKCHAIN_( 1 , 0 , SUBSTITUTED , "test" , 4 , 13 , 0 );
-	M_CKTOKFULL_( 2 , "$x" , 0 , 1 , 1 );
-		M_CKTOKCHAIN_( 2 , 0 , SUBSTITUTED , "test" , 4 , 13 , 0 );
-	M_CKTOKFULL_( 3 , "$x" , 0 , 2 , 1 );
-		M_CKTOKCHAIN_( 3 , 0 , SUBSTITUTED , "test" , 4 , 13 , 0 );
-	M_CKTOKFULL_( 4 , "$x" , 0 , 3 , 1 );
-		M_CKTOKCHAIN_( 4 , 0 , SUBSTITUTED , "test" , 4 , 13 , 0 );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdCoreTest::testEvalEmpty( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -eval )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testEval( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"( -set (x y)\n"
-					"( -raw $y )\n"
-					"this-is-y\n"
-				")\n"
-				"eval ( -eval $x ) actual $x" ,
-				errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "eval this-is-y actual $y" , output ) );
-	M_CKTOKFULL_( 0 , "test" , 5 , 1 , 0 );
-	M_CKTOKFULL_( 1 , "$y" , 0 , 0 , 2 );
-		M_CKTOKCHAIN_( 1 , 0 , SUBSTITUTED , "$x" , 0 , 0 , 0 );
-		M_CKTOKCHAIN_( 1 , 1 , EVALUATED , "test" , 5 , 8 , 0 );
-	M_CKTOKFULL_( 2 , "test" , 5 , 19 , 0 );
-	M_CKTOKFULL_( 3 , "$x" , 0 , 0 , 1 );
-		M_CKTOKCHAIN_( 3 , 0 , SUBSTITUTED , "test" , 5 , 26 , 0 );
-}
-
-void SRDPreprocCmdCoreTest::testEvalErrors( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"( -set x ( -raw $does-not-exist ) )\n"
-				"( -eval $x )" ,
-				errors ) );
-	CPPUNIT_ASSERT_EQUAL( 1u , errors.size( ) );
-	M_CKERRFULL_( 0 , "unknown variable" , false , "$x" , 0 , 0 , 1 );
-		M_CKERRCHAIN_( 0 , 0 , EVALUATED , "test" , 2 , 3 , 0 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testEvalSkipComments( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -eval (-from-source \"{ a comment } x # another comment!\")\n)" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "x" , output ) );
-	M_CKTOKFULL_( 0 , "-from-source" , 1 , 15 , 1 );
-		M_CKTOKCHAIN_( 0 , 0 , GENERATED , "test" , 1 , 10 , 0 );
-}
-
-void SRDPreprocCmdCoreTest::testEvalUnterminated( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -eval\n(\n(" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 3u , errors.size( ) );
-	M_CKERR_( 0 , "unterminated list" , 1 , 1 );
-	M_CKERR_( 1 , "unterminated list" , 2 , 1 );
-	M_CKERR_( 2 , "unterminated list" , 3 , 1 );
-	CPPUNIT_ASSERT( check( "(())" , output ) );
-	M_CKTOKFULL_( 0 , "test" , 2 , 1 , 0 );
-	M_CKTOKFULL_( 1 , "test" , 3 , 1 , 0 );
-	M_CKTOKFULL_( 2 , "*unexpected end of file*" , 0 , 2 , 0 );
-	M_CKTOKFULL_( 3 , "*unexpected end of file*" , 0 , 1 , 0 );
-}
-
-void SRDPreprocCmdCoreTest::testEvalInnerList( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"( -set x (-raw ( () ) ) )\n"
-				"( -bless x )\n"
-				"( -eval -not-a-command )\n"
-				"( -eval $x )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "-not-a-command (())" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testEvalCalls( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"( -set (x y) (-raw (() f1 (-raw $y) f2)) x)\n"
-				"(-bless x)\n"
-				"( -eval a $y b ($x) c ($x) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "a x b f1 x f2 c f1 x f2" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdCoreTest::testScope( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"( -set-macro dump ( ( ) ( -raw ( ( -raw\n"
-					"( -is-set x )\n"
-					"( -is-blessed f )\n"
-					"( -is-set y )\n"
-					"( -is-macro m )\n"
-					"( -is-macro n )\n"
-				") ) ) ) )\n"
-				"( -set x 1 )\n"
-				"( -set f (()) )\n"
-				"( -set-macro m ( ( ) ) )\n"
-				"( -scope\n"
-					"( -unset x )\n"
-					"( -bless f )\n"
-					"( -set y 0 )\n"
-					"( -unset-macro m )\n"
-					"( -set-macro n ( ( ) ) )\n"
-					"(dump)\n"
-				")\n"
-				"(dump)\n"
-				"" ,
-				errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "( 0 1 1 0 1 ) ( 1 0 0 1 0 )" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testScopeValues( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"( -set x 1 )\n"
-				"$x\n"
-				"( -scope\n"
-					"( -set x 2 )\n"
-					"$x\n"
-				")\n"
-				"$x\n" ,
-				errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1 2 1" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testScopeInnerList( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"( -set x (-raw ( () ) ) )\n"
-				"( -bless x )\n"
-				"( -scope -not-a-command )\n"
-				"( -scope $x )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "-not-a-command (())" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdCoreTest::testClearScopeInstruction( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"( -set x )\n"
-				"( -set-macro y ( ( ) ) )\n"
-				"( -is-set x )\n"
-				"( -is-macro y )\n"
-				"( -clear-scope )\n"
-				"( -is-set x )\n"
-				"( -is-macro y )\n"
-				, errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1 1 0 0" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testClearScopeBlock( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"( -set x )\n"
-				"( -set-macro y ( ( ) ) )\n"
-				"( -is-set x )\n"
-				"( -is-macro y )\n"
-				"( -clear-scope\n"
-					"( -is-set x )\n"
-					"( -is-macro y )\n"
-				")\n"
-				"( -is-set x )\n"
-				"( -is-macro y )\n"
-				, errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1 1 0 0 1 1" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testClearScopeInnerList( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -clear-scope -not-a-command )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "-not-a-command" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdCoreTest::testTryEmpty( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "(-try )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "() ()" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testTryNoErrors( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "(-try 1 2 3)" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "(1 2 3) ()" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testTryErrors( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -try $x 2 $y )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "( 2 ) ( "
-				"( \"unknown variable\" ( \"test\" 1 8 ) )"
-				"( \"unknown variable\" ( \"test\" 1 13 ) )"
-				")" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testTryErrorsChained( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-set (f1 f2) (-raw\n"
-					"(() f1 $x)\n"
-					"((a)\n"
-						"f2 $a\n"
-						"(-if (-gt $a 0) (\n"
-							"($f2 (-sub $a 1))\n"
-						")(\n"
-							"($f1)\n"
-						"))\n"
-					")\n"
-				"))\n"
-				"(-bless f1 f2)\n"
-				"( -try ($f1) ($f2 5))"
-				, errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check(
-			"( f1 f2 5 f2 4 f2 3 f2 2 f2 1 f2 0 f1 ) ( "
-				"( \"unknown variable\""
-					"( \"test\" 2 8 )"
-					"called ( \"test\" 13 9 )"
-				")"
-				"( \"unknown variable\""
-					"( \"test\" 2 8 )"
-					"called ( \"test\" 8 2 )"
-					"called 4 ( \"test\" 6 2 )"
-					"called ( \"test\" 13 15 )"
-				")"
-			")" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testTryUnterminated( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -try\n(\n(" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 3u , errors.size( ) );
-	M_CKERR_( 0 , "unterminated list" , 1 , 1 );
-	M_CKERR_( 1 , "unterminated list" , 2 , 1 );
-	M_CKERR_( 2 , "unterminated list" , 3 , 1 );
-	CPPUNIT_ASSERT( check( "((()))()" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testTryTooManyErrors( )
-{
-	T_StringBuilder sb;
-	sb << "(-set (output errors) (-try (\n";
-	for ( uint32_t i = 0 ; i < T_SRDErrors::MAX_ERRORS + 1 ; i ++ ) {
-		sb << "$missing\n";
-	}
-	sb << ") ) )\n"
-		<< "(-set last-error ( ((list)) (-raw\n"
-			<< "(-set (a b) $list)\n"
-			<< "(-if (-eq ($b) ()) ($a) (($last-error $b)))\n"
-		<< ")))\n"
-		<< "(-bless last-error)\n"
-		<< "$output (-length $errors) ($last-error (-unwrap $errors))\n"
-		<< '\0';
-
-	T_SRDErrors errors;
-	T_SRDList output( process( sb.data( ) , errors ) );
-
-	sb.clear( );
-	sb << "(()) 41 ( \"too many errors\" ( \"test\" " << ( T_SRDErrors::MAX_ERRORS + 1 ) << " 1 ) )" << '\0';
-	CPPUNIT_ASSERT( check( sb.data( ) , output ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-}
-
-void SRDPreprocCmdCoreTest::testTryInnerList( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"( -set x (-raw ( () ) ) )\n"
-				"( -bless x )\n"
-				"( -try -not-a-command )\n"
-				"( -try $x )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "(-not-a-command) () ((())) ()" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-namespace {
-
-class T_OutputErrorGen_ : public A_SRDReaderTarget
-{
-private:
-	A_SRDReaderTarget& next_;
-
-public:
-	explicit T_OutputErrorGen_( A_SRDReaderTarget& next )
-		: A_SRDReaderTarget( ) , next_( next )
-	{}
-
-	void start( T_SRDErrors & errors ) override
-	{
-		next_.start( errors );
-	}
-
-	void push( T_SRDErrors & errors , T_SRDToken && token ) override
-	{
-		if ( token.type( ) == E_SRDTokenType::WORD && token.stringValue( ) == "fail" ) {
-			errors.add( "DO NOT WANT" , token );
-		}
-		next_.push( errors , std::move( token ) );
-	}
-
-	void end( T_SRDErrors & errors ) override
-	{
-		next_.end( errors );
-	}
-};
-
-}
-
-void SRDPreprocCmdCoreTest::testOutput( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "(5 (-output (3 (-output (1 2)) 4)) 6)" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "(1 2) (3 4) (5 6)" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testOutputErrors( )
-{
-	T_SRDErrors errors;
-	T_SRDMemoryTarget mt( false );
-	mt.clearFlushToken( true );
-	T_OutputErrorGen_ eg( mt );
-
-	T_SRDPreprocessorConfig emptyConfig;
-	emptyConfig.addBuiltinCommands( );
-	T_SRDPreprocessor pp( emptyConfig , eg );
-	T_SRDLexer lexer( T_String( "test" ) , errors , pp );
-	pp.start( errors );
-	char const* ptr = "(-try (-output fail))";
-	while ( *ptr != 0 ) {
-		lexer.processCharacter( *ptr ++ );
-	}
-	lexer.processEnd( );
-	mt.end( errors );
-
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "fail () ( ( \"DO NOT WANT\" ( \"test\" 1 16 ) ) )" ,
-				mt.list( ) ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdCoreTest::testErrorEmpty( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -error )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 1u , errors.size( ) );
-	M_CKERR_( 0 , "user error" , 1 , 3 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testErrorWord( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -error fail )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 1u , errors.size( ) );
-	M_CKERR_( 0 , "fail" , 1 , 3 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testErrorString( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -error \"out of cheese\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 1u , errors.size( ) );
-	M_CKERR_( 0 , "out of cheese" , 1 , 3 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testErrorVar( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -error ( -raw $x ) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 1u , errors.size( ) );
-	M_CKERR_( 0 , "$x" , 1 , 3 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testErrorInt( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -error 123 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 1u , errors.size( ) );
-	M_CKERR_( 0 , "123" , 1 , 3 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testErrorLong( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -error 5000000000 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 1u , errors.size( ) );
-	M_CKERR_( 0 , "5000000000" , 1 , 3 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testErrorReal( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -error 1.5 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 1u , errors.size( ) );
-	M_CKERR_( 0 , "1.5" , 1 , 3 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testErrorList( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -error ( a list ( 123 \"wut\" ) ) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 1u , errors.size( ) );
-	M_CKERR_( 0 , "( a list ( 123 wut ) )" , 1 , 3 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testErrorConcat( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -error And this is the real thing \"(or is it?)\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 1u , errors.size( ) );
-	M_CKERR_( 0 , "And this is the real thing (or is it?)" , 1 , 3 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdCoreTest::testBreakMain( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "a (-break) b" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "a" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testBreakMainList( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "(a ((-break)) b)" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "(a())" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testBreakEvalInput( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "a (-eval (b (-break)) c) d" , errors ) );
-	for ( uint32_t i = 0 ; i < errors.size( ) ; i ++ ) {
-		M_PRINTERR_( i );
-	}
-	CPPUNIT_ASSERT( check( "a (b) d" , output ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-}
-
-void SRDPreprocCmdCoreTest::testBreakEvalOutput( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "a (-eval b ((-raw ((-break)))) c) d" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "a b (())" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testBreakFunction( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-set f (-raw ( (a b) $a (-break) $b ) ))\n"
-				"(-bless f)\n"
-				"a ($f b c) d" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "a b d" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testBreakRecursiveFunction( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-set f (-raw ( (a b)\n"
-					"(\n"
-						"(-if (-lt $b $a ) (\n"
-							"(-break)\n"
-						"))\n"
-						"$a\n"
-						"($f (-add $a 1) $b)\n"
-					")\n"
-				")))\n"
-				"(-bless f)\n"
-				"a ($f 1 3) b" , errors ) );
-	for ( auto i = 0u ; i < errors.size( ) ; i ++ ) {
-		M_PRINTERR_( i );
-	}
-	CPPUNIT_ASSERT( check( "a (1(2(3()))) b" , output ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-}
-
-void SRDPreprocCmdCoreTest::testBreakMacro( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-set-macro m (-raw ( (a b) ($a (-break) $b) ) ))\n"
-				"a (m b c) d" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "a (b) d" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testBreakArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "(a (-break even) b)" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "too many arguments" , 1 , 5 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 12 );
-	CPPUNIT_ASSERT( check( "(a)" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-#define M_CKRT_TEXT_( INDEX , TEXT ) \
-	CPPUNIT_ASSERT( errors[ INDEX ].error( ) == (TEXT) )
-#define M_CKRT_SOURCE_( INDEX , EID , NAME , LINE , CHAR ) \
-	do { \
-		RPC_SRDLocation loc( &errors[ INDEX ].location( ) ); \
-		int i( EID ); \
-		while ( i > 0 ) { \
-			assert( loc->isChained( ) ); \
-			loc = RPC_SRDLocation( loc->chaining( ).location ); \
-			i --; \
-		} \
-		auto const& l( *loc ); \
-		CPPUNIT_ASSERT( l.source( ) == (NAME) ); \
-		CPPUNIT_ASSERT( l.line( ) == (LINE) ); \
-		CPPUNIT_ASSERT( l.character( ) == (CHAR) ); \
-	} while ( 0 )
-
-void SRDPreprocCmdCoreTest::testRethrowNothing( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "(-rethrow)" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testRethrowList( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-rethrow ( ( \"error text\"\n"
-					"( \"source\" 2 3 )\n"
-				") ( \"second error\"\n"
-					"( \"source 2\" 4 5 )\n"
-				") ) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERRFULL_( 0 , "error text" , false , "source" , 2 , 3 , 0 );
-	M_CKERRFULL_( 1 , "second error" , false , "source 2" , 4 , 5 , 0 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testRethrowEmptyList( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-rethrow ( ) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testRethrowUnwrapped( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-rethrow ( \"error text\"\n"
-					"( \"source\" 2 3 )\n"
-				") ( \"second error\"\n"
-					"( \"source 2\" 4 5 )\n"
-				") )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERRFULL_( 0 , "error text" , false , "source" , 2 , 3 , 0 );
-	M_CKERRFULL_( 1 , "second error" , false , "source 2" , 4 , 5 , 0 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testRethrowErrorWord( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "(-rethrow ( error ( \"source\" 2 3 ) ) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 1u , errors.size( ) );
-	M_CKERRFULL_( 0 , "error" , false , "source" , 2 , 3 , 0 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testRethrowSourceWord( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-rethrow ( \"error\"\n"
-					"( source 2 3 )\n"
-				") )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 1u , errors.size( ) );
-	M_CKERRFULL_( 0 , "error" , false , "source" , 2 , 3 , 0 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testRethrowDetails( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-rethrow ( \"not an error\" details\n"
-					"( source 2 3 )\n"
-				") )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 1u , errors.size( ) );
-	M_CKERRFULL_( 0 , "not an error" , true , "source" , 2 , 3 , 0 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testRethrowChained( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-rethrow ( \"error\"\n"
-					"( \"src\" 1 1 )\n"
-					"called ( \"src\" 2 2 )\n"
-					"loaded ( \"src\" 3 3 )\n"
-					"included ( \"src\" 4 4 )\n"
-					"generated ( \"src\" 5 5 )\n"
-					"expanded ( \"src\" 6 6 )\n"
-					"evaluated ( \"src\" 7 7 )\n"
-					"substituted ( \"src\" 8 8 )\n"
-				") )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 1u , errors.size( ) );
-	M_CKERRFULL_( 0 , "error" , false , "src" , 1 , 1 , 7 );
-		M_CKERRCHAIN_( 0 , 0 , CALLED , "src" , 2 , 2 , 0 );
-		M_CKERRCHAIN_( 0 , 1 , LOADED , "src" , 3 , 3 , 0 );
-		M_CKERRCHAIN_( 0 , 2 , INCLUDED , "src" , 4 , 4 , 0 );
-		M_CKERRCHAIN_( 0 , 3 , GENERATED , "src" , 5 , 5 , 0 );
-		M_CKERRCHAIN_( 0 , 4 , EXPANDED , "src" , 6 , 6 , 0 );
-		M_CKERRCHAIN_( 0 , 5 , EVALUATED , "src" , 7 , 7 , 0 );
-		M_CKERRCHAIN_( 0 , 6 , SUBSTITUTED , "src" , 8 , 8 , 0 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testRethrowChainedDepth( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-rethrow ( \"error\"\n"
-					"( \"src\" 1 1 )\n"
-					"called 5 ( \"src\" 2 2 )\n"
-				") )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 1u , errors.size( ) );
-	M_CKERRFULL_( 0 , "error" , false , "src" , 1 , 1 , 1 );
-		M_CKERRCHAIN_( 0 , 0 , CALLED , "src" , 2 , 2 , 5 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdCoreTest::testRethrowNoList( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "(-rethrow nope)" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "start of list expected" , 1 , 2 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 11 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testRethrowBadMessage( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "(-rethrow ( 12 ) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "error message expected" , 1 , 2 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 13 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testRethrowNoLocation( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "(-rethrow ( error ) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "'details' or start of list expected" , 1 , 2 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 19 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testRethrowBadLocation( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "(-rethrow ( \"error\" nope ) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "'details' or start of list expected" , 1 , 2 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 21 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testRethrowLocationBadSource( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "(-rethrow ( \"error\" ( 12 1 2 ) ) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "source name expected" , 1 , 2 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 23 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testRethrowLocationBadLine( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-rethrow ( \"error\"\n"
-					"( \"src\" nope 3 )\n"
-				") )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "line number expected" , 1 , 2 );
-	M_CKERR_( 1 , "previous error cause" , 2 , 9 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testRethrowLocationNegativeLine( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-rethrow ( \"error\"\n"
-					"( \"src\" -1 3 )\n"
-				") )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "invalid line number" , 1 , 2 );
-	M_CKERR_( 1 , "previous error cause" , 2 , 9 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testRethrowLocationLineTooHigh( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-rethrow ( \"error\"\n"
-					"( \"src\" 5000000000 3 )\n"
-				") )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "invalid line number" , 1 , 2 );
-	M_CKERR_( 1 , "previous error cause" , 2 , 9 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testRethrowLocationBadChar( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-rethrow ( \"error\"\n"
-					"( \"src\" 2 nope )\n"
-				") )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "character/byte number expected" , 1 , 2 );
-	M_CKERR_( 1 , "previous error cause" , 2 , 11 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testRethrowLocationNegativeChar( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-rethrow ( \"error\"\n"
-					"( \"src\" 2 -3 )\n"
-				") )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "invalid character/byte number" , 1 , 2 );
-	M_CKERR_( 1 , "previous error cause" , 2 , 11 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testRethrowChainedBad( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-rethrow ( \"error\"\n"
-					"( \"src\" 2 3 )\n"
-					"12\n"
-				") )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "chaining type or end of list expected" , 1 , 2 );
-	M_CKERR_( 1 , "previous error cause" , 3 , 1 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testRethrowChainedInvalid( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-rethrow ( \"error\"\n"
-					"( \"src\" 2 3 )\n"
-					"blah\n"
-				") )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "invalid chaining type" , 1 , 2 );
-	M_CKERR_( 1 , "previous error cause" , 3 , 1 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testRethrowChainedNoLocation( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-rethrow ( \"error\"\n"
-					"( \"src\" 2 3 )\n"
-					"loaded\n"
-				") )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "depth or start of list expected" , 1 , 2 );
-	M_CKERR_( 1 , "previous error cause" , 4 , 1 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testRethrowChainedBadLocation( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-rethrow ( \"error\"\n"
-					"( \"src\" 2 3 )\n"
-					"loaded nope\n"
-				") )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "depth or start of list expected" , 1 , 2 );
-	M_CKERR_( 1 , "previous error cause" , 3 , 8 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testRethrowChainedNegativeDepth( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-rethrow ( \"error\"\n"
-					"( \"src\" 2 3 )\n"
-					"loaded -1\n"
-				") )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "invalid recursion depth" , 1 , 2 );
-	M_CKERR_( 1 , "previous error cause" , 3 , 8 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testRethrowChainedDepthTooHigh( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-rethrow ( \"error\"\n"
-					"( \"src\" 2 3 )\n"
-					"loaded 5000000000\n"
-				") )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "invalid recursion depth" , 1 , 2 );
-	M_CKERR_( 1 , "previous error cause" , 3 , 8 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testRethrowChainedDepthNoLocation( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-rethrow ( \"error\"\n"
-					"( \"src\" 2 3 )\n"
-					"loaded 5\n"
-				") )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "start of list expected" , 1 , 2 );
-	M_CKERR_( 1 , "previous error cause" , 4 , 1 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdCoreTest::testRethrowChainedDepthBadLocation( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-rethrow ( \"error\"\n"
-					"( \"src\" 2 3 )\n"
-					"loaded 5 nope\n"
-				") )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "start of list expected" , 1 , 2 );
-	M_CKERR_( 1 , "previous error cause" , 3 , 10 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
diff --git a/tests/srd-preproc-cmd-functions.cc b/tests/srd-preproc-cmd-functions.cc
deleted file mode 100644
index b8d32c3..0000000
--- a/tests/srd-preproc-cmd-functions.cc
+++ /dev/null
@@ -1,441 +0,0 @@
-#include "srd-preproc-cmd-common.hh"
-
-class SRDPreprocCmdFunctionsTest : public CppUnit::TestFixture
-{
-	CPPUNIT_TEST_SUITE( SRDPreprocCmdFunctionsTest );
-
-	CPPUNIT_TEST( testBlessNoArgs );
-	CPPUNIT_TEST( testBlessMissing );
-	CPPUNIT_TEST( testBlessEmpty );
-	CPPUNIT_TEST( testBlessInvalid1 );
-	CPPUNIT_TEST( testBlessInvalid2 );
-	CPPUNIT_TEST( testBlessInvalid3 );
-	CPPUNIT_TEST( testBlessInvalid4 );
-	CPPUNIT_TEST( testBlessEmptyFunction );
-	CPPUNIT_TEST( testBlessFnWithArgs );
-	CPPUNIT_TEST( testBlessFnWithDupArgs );
-	CPPUNIT_TEST( testBlessFnWithOptArgs );
-	CPPUNIT_TEST( testBlessFnWithDupOptArgs );
-	CPPUNIT_TEST( testBlessFnWithOptArgsOnly );
-	CPPUNIT_TEST( testBlessFnWithDupArgsAll );
-
-	CPPUNIT_TEST( testCallNoArg );
-	CPPUNIT_TEST( testCallBlessedVar );
-	CPPUNIT_TEST( testCallBadArg );
-	CPPUNIT_TEST( testCallInvalidFunction );
-	CPPUNIT_TEST( testCallValidFunction );
-	CPPUNIT_TEST( testCallTooManyArgs );
-	CPPUNIT_TEST( testCallNotEnoughArgs );
-	CPPUNIT_TEST( testCallNotEnoughArgsOpt );
-
-	CPPUNIT_TEST( testBodyInnerList );
-	CPPUNIT_TEST( testDashFunction );
-
-	CPPUNIT_TEST( testBug00 );
-	CPPUNIT_TEST( testBug01 );
-	CPPUNIT_TEST( testBug02 );
-	CPPUNIT_TEST( testBug03 );
-
-	CPPUNIT_TEST_SUITE_END( );
-
-   public:
-	void testBlessNoArgs( );
-	void testBlessMissing( );
-	void testBlessEmpty( );
-	void testBlessInvalid1( );
-	void testBlessInvalid2( );
-	void testBlessInvalid3( );
-	void testBlessInvalid4( );
-	void testBlessEmptyFunction( );
-	void testBlessFnWithArgs( );
-	void testBlessFnWithDupArgs( );
-	void testBlessFnWithOptArgs( );
-	void testBlessFnWithDupOptArgs( );
-	void testBlessFnWithOptArgsOnly( );
-	void testBlessFnWithDupArgsAll( );
-
-	void testCallNoArg( );
-	void testCallBlessedVar( );
-	void testCallBadArg( );
-	void testCallInvalidFunction( );
-	void testCallValidFunction( );
-	void testCallTooManyArgs( );
-	void testCallNotEnoughArgs( );
-	void testCallNotEnoughArgsOpt( );
-
-	void testBodyInnerList( );
-	void testDashFunction( );
-
-	void testBug00( );
-	void testBug01( );
-	void testBug02( );
-	void testBug03( );
-
-};
-CPPUNIT_TEST_SUITE_REGISTRATION( SRDPreprocCmdFunctionsTest );
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdFunctionsTest::testBlessNoArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -bless )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 10 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdFunctionsTest::testBlessMissing( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -bless a ) " , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "unknown variable" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 10 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdFunctionsTest::testBlessEmpty( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				  "( -set a )\n"
-				  "( -bless a )\n"
-				  "( $a ) " ,
-				  errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "invalid function" , 2 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 2 , 10 );
-	CPPUNIT_ASSERT( check( "( )" , output ) );
-}
-
-void SRDPreprocCmdFunctionsTest::testBlessInvalid1( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-		"(-set x\n"
-			"nope\n"
-		")\n"
-		"( -bless x )\n"
-		"($x)" ,
-		errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "invalid function" , 4 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 4 , 10 );
-	CPPUNIT_ASSERT( check( "(nope)" , output ) );
-}
-
-void SRDPreprocCmdFunctionsTest::testBlessInvalid2( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-		"(-set x\n"
-			"()\n"
-		")\n"
-		"( -bless x )\n"
-		"($x)" ,
-		errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "invalid function" , 4 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 4 , 10 );
-	CPPUNIT_ASSERT( check( "(())" , output ) );
-}
-
-void SRDPreprocCmdFunctionsTest::testBlessInvalid3( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-		"(-set x\n"
-			"(nope)\n"
-		")\n"
-		"( -bless x )\n"
-		"($x)" ,
-		errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "invalid function" , 4 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 4 , 10 );
-	CPPUNIT_ASSERT( check( "((nope))" , output ) );
-}
-
-void SRDPreprocCmdFunctionsTest::testBlessInvalid4( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-		"(-set x\n"
-			"(()) nope\n"
-		")\n"
-		"( -bless x )\n"
-		"($x)" ,
-		errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "invalid function" , 4 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 4 , 10 );
-	CPPUNIT_ASSERT( check( "((()) nope)" , output ) );
-}
-
-void SRDPreprocCmdFunctionsTest::testBlessEmptyFunction( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				  "( -set a ( ( ) x ) )\n"
-				  "( -bless a )\n"
-				  "( $a ) " ,
-				  errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "x" , output ) );
-}
-
-void SRDPreprocCmdFunctionsTest::testBlessFnWithArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				  "( -set a ( ( u v w ) ( -raw $u $v $w ) ) )\n"
-				  "( -bless a )\n"
-				  "( $a b c d ) " ,
-				  errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "b c d" , output ) );
-}
-
-void SRDPreprocCmdFunctionsTest::testBlessFnWithDupArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				  "( -set a ( ( u v u ) ( -raw $u $v ) ) )\n"
-				  "( -bless a )\n"
-				  "( $a b c d ) " ,
-				  errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "invalid function" , 2 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 2 , 10 );
-	CPPUNIT_ASSERT( check( "( ( ( u v u ) $u $v ) b c d )" , output ) );
-}
-
-void SRDPreprocCmdFunctionsTest::testBlessFnWithOptArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				  "( -set a ( ( u ( v ) ) ( -raw ( $u ) ( $v ) ) ) )\n"
-				  "( -bless a )\n"
-				  "($a b c d)\n"
-				  "($a e)\n"
-				  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "( b ) ( c d ) ( e ) ( )" , output ) );
-}
-
-void SRDPreprocCmdFunctionsTest::testBlessFnWithDupOptArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				  "( -set a ( ( u ( v v ) ) ( -raw ( $u ) ( $v ) ) ) )\n"
-				  "( -bless a )\n"
-				  "( $a b )" ,
-				  errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "invalid function" , 2 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 2 , 10 );
-	CPPUNIT_ASSERT( check( "( ( ( u ( v v ) ) ( $u ) ( $v ) ) b )" , output ) );
-}
-
-void SRDPreprocCmdFunctionsTest::testBlessFnWithOptArgsOnly( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				  "( -set a ( ( ( v ) ) ( -raw ( $v ) ) ) )\n"
-				  "( -bless a )\n"
-				  "( $a ) ( $a b ) ( $a c d )" ,
-				  errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "( ) ( b ) ( c d )" , output ) );
-}
-
-void SRDPreprocCmdFunctionsTest::testBlessFnWithDupArgsAll( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				  "( -set a ( ( u ( v u ) ) ( -raw ( $u ) ( $v ) ) ) )\n"
-				  "( -bless a )\n"
-				  "( $a b )" ,
-				  errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "invalid function" , 2 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 2 , 10 );
-	CPPUNIT_ASSERT( check( "( ( ( u ( v u ) ) ( $u ) ( $v ) ) b )" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdFunctionsTest::testCallNoArg( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -call )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 9 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdFunctionsTest::testCallBlessedVar( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-set f (() x))\n"
-				"(-bless f)\n"
-				"( -call $f )"
-				, errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "x" , output ) );
-}
-
-void SRDPreprocCmdFunctionsTest::testCallBadArg( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -call x )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "list expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 9 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdFunctionsTest::testCallInvalidFunction( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -call ( nope ) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "list expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 11 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdFunctionsTest::testCallValidFunction( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -call ( -raw ( ( x ( y ) ) $y $x ) ) a b c )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "b c a" , output ) );
-}
-
-void SRDPreprocCmdFunctionsTest::testCallTooManyArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -call ( -raw ( ( x ) $x ) ) a b )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "too many arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 33 );
-	CPPUNIT_ASSERT( check( "a" , output ) );
-}
-
-void SRDPreprocCmdFunctionsTest::testCallNotEnoughArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -call ( -raw ( ( x ) $x ) ) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 31 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdFunctionsTest::testCallNotEnoughArgsOpt( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -call ( -raw ( ( x y ( z ) ) $x ) ) a )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 41 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdFunctionsTest::testBodyInnerList( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"( -set x (-raw ( () ) ) )\n"
-				"( -bless x )\n"
-				"( -call ( -raw ( () -not-a-command ) ) )\n"
-				"( -call ( -raw ( () $x ) ) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "-not-a-command (())" , output ) );
-}
-
-void SRDPreprocCmdFunctionsTest::testDashFunction( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-set -f ((x) (-raw yo $x)))\n"
-				"(-bless -f)\n"
-				"(-f bob)\n"
-				, errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "yo bob" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdFunctionsTest::testBug00( )
-{
-	/* A bug with tail calls - the code below would output "y x" */
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-set f1 ((-raw (a) $a)))\n"
-				"(-set f2 ((-raw (a) ($f1 $a))))\n"
-				"(-bless f1 f2)\n"
-				"($f2 x) y\n"
-				, errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "x y" , output ) );
-}
-
-void SRDPreprocCmdFunctionsTest::testBug01( )
-{
-	/* Similar to bug 00, except with an ending parens. */
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-set f1 ((-raw (a) $a)))\n"
-				"(-set f2 ((-raw (a) ($f1 $a))))\n"
-				"(-bless f1 f2)\n"
-				"(($f2 x))\n"
-				, errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "(x)" , output ) );
-}
-
-void SRDPreprocCmdFunctionsTest::testBug02( )
-{
-	/* Causes a crash due to a missing location */
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-set fn (-raw (((list))\n"
-					"(-set (first rest) $list)\n"
-					"(-if (-length ($first)) (\n"
-						"($first ($fn $rest))\n"
-					"))\n"
-				")))\n"
-				"(-bless fn)\n"
-				"($fn a b)\n"
-				, errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "(a (b))" , output ) );
-}
-
-void SRDPreprocCmdFunctionsTest::testBug03( )
-{
-	/* More tail-call problems (interaction between the "unswallow"
-	 * part of the evaluator/function feeders and stuff that stands
-	 * between them).
-	 */
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-set (f1 f2) (-raw\n"
-				   "(() (-if 1 ()))\n"
-				   "(() ($f1))\n"
-				"))\n"
-				"(-bless f1 f2)\n"
-				"(-eval ((-raw -eval) ((-raw $f2))))\n"
-				, errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "(a (b))" , output ) );
-}
diff --git a/tests/srd-preproc-cmd-input.cc b/tests/srd-preproc-cmd-input.cc
deleted file mode 100644
index 91e11bb..0000000
--- a/tests/srd-preproc-cmd-input.cc
+++ /dev/null
@@ -1,543 +0,0 @@
-#include "srd-preproc-cmd-common.hh"
-#include "srd-preproc-location.hh"
-
-
-class SRDPreprocCmdInputTest : public CppUnit::TestFixture
-{
-	CPPUNIT_TEST_SUITE( SRDPreprocCmdInputTest );
-
-	CPPUNIT_TEST( testFromSourceNoName );
-	CPPUNIT_TEST( testFromSourceNamed );
-	CPPUNIT_TEST( testFromSourceError );
-	CPPUNIT_TEST( testFromSourceErrorNamed );
-	CPPUNIT_TEST( testFromSourceTooManyErrors );
-	CPPUNIT_TEST( testFromSourceLocation );
-	CPPUNIT_TEST( testFromSourceLocationNamed );
-	CPPUNIT_TEST( testFromSourceLocationChaining );
-	CPPUNIT_TEST( testFromSourceLocationRewind );
-	CPPUNIT_TEST( testFromSourceLocationRewindTooMuch );
-
-	CPPUNIT_TEST( testFromSourceArgsNone );
-	CPPUNIT_TEST( testFromSourceArgsExtra );
-	CPPUNIT_TEST( testFromSourceArgsBadSource );
-	CPPUNIT_TEST( testFromSourceArgsBadName );
-	CPPUNIT_TEST( testFromSourceArgsBadChaining );
-	CPPUNIT_TEST( testFromSourceArgsBadRewind );
-
-	CPPUNIT_TEST( testFromSRBNoName );
-	CPPUNIT_TEST( testFromSRBNamed );
-	CPPUNIT_TEST( testFromSRBError );
-	CPPUNIT_TEST( testFromSRBErrorNamed );
-	CPPUNIT_TEST( testFromSRBLocation );
-	CPPUNIT_TEST( testFromSRBLocationNamed );
-	CPPUNIT_TEST( testFromSRBLocationChaining );
-	CPPUNIT_TEST( testFromSRBLocationRewind );
-	CPPUNIT_TEST( testFromSRBLocationRewindTooMuch );
-
-	CPPUNIT_TEST( testFromSRBArgsNone );
-	CPPUNIT_TEST( testFromSRBArgsExtra );
-	CPPUNIT_TEST( testFromSRBArgsBadInput );
-	CPPUNIT_TEST( testFromSRBArgsBadName );
-	CPPUNIT_TEST( testFromSRBArgsBadChaining );
-	CPPUNIT_TEST( testFromSRBArgsBadRewind );
-
-	CPPUNIT_TEST_SUITE_END( );
-
-   public:
-	void testFromSourceNoName( );
-	void testFromSourceNamed( );
-	void testFromSourceError( );
-	void testFromSourceErrorNamed( );
-	void testFromSourceTooManyErrors( );
-	void testFromSourceLocation( );
-	void testFromSourceLocationNamed( );
-	void testFromSourceLocationChaining( );
-	void testFromSourceLocationRewind( );
-	void testFromSourceLocationRewindTooMuch( );
-
-	void testFromSourceArgsNone( );
-	void testFromSourceArgsExtra( );
-	void testFromSourceArgsBadSource( );
-	void testFromSourceArgsBadName( );
-	void testFromSourceArgsBadChaining( );
-	void testFromSourceArgsBadRewind( );
-
-	void testFromSRBNoName( );
-	void testFromSRBNamed( );
-	void testFromSRBError( );
-	void testFromSRBErrorNamed( );
-	void testFromSRBLocation( );
-	void testFromSRBLocationNamed( );
-	void testFromSRBLocationChaining( );
-	void testFromSRBLocationRewind( );
-	void testFromSRBLocationRewindTooMuch( );
-
-	void testFromSRBArgsNone( );
-	void testFromSRBArgsExtra( );
-	void testFromSRBArgsBadInput( );
-	void testFromSRBArgsBadName( );
-	void testFromSRBArgsBadChaining( );
-	void testFromSRBArgsBadRewind( );
-};
-CPPUNIT_TEST_SUITE_REGISTRATION( SRDPreprocCmdInputTest );
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdInputTest::testFromSourceNoName( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -from-source \"word \\\"string\\\" 123 5000000000 1.2 $x ( some list )\" )" ,
-				errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "word \"string\" 123 5000000000 1.2 $x ( some list )" , output ) );
-}
-
-void SRDPreprocCmdInputTest::testFromSourceNamed( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"( -from-source \"word \\\"string\\\" 123 5000000000 1.2 $x ( some list )\"\n"
-				"\"some_random_file.srd\" )" ,
-				errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "word \"string\" 123 5000000000 1.2 $x ( some list )" , output ) );
-}
-
-void SRDPreprocCmdInputTest::testFromSourceError( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -from-source\n\"( a\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , errors.size( ) );
-	M_CKERR_( 0 , "unterminated list" , 1 , 1 );
-	CPPUNIT_ASSERT( errors[ 0 ].location( ).source( ) == "-from-source" );
-	CPPUNIT_ASSERT( check( "( a )" , output ) );
-}
-
-void SRDPreprocCmdInputTest::testFromSourceErrorNamed( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -from-source\n\"( a\" \"some_random_file.srd\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , errors.size( ) );
-	M_CKERR_( 0 , "unterminated list" , 1 , 1 );
-	CPPUNIT_ASSERT( errors[ 0 ].location( ).source( ) == "some_random_file.srd" );
-	CPPUNIT_ASSERT( check( "( a )" , output ) );
-}
-
-void SRDPreprocCmdInputTest::testFromSourceTooManyErrors( )
-{
-	T_StringBuilder sb( "( -from-source \"" );
-	for ( auto i = 0u ; i < T_SRDErrors::MAX_ERRORS + 1 ; i ++ ) {
-		sb << "(\\u00a1";
-	}
-	sb << "\" )" << '\0';
-
-	try {
-		T_SRDErrors errors;
-		T_SRDList output( process( sb.data( ) , errors ) );
-		CPPUNIT_ASSERT_EQUAL( uint32_t( T_SRDErrors::MAX_ERRORS + 1 ) , errors.size( ) );
-		for ( auto i = 0u ; i < T_SRDErrors::MAX_ERRORS ; i ++ ) {
-			M_CKERR_( i , "unexpected character" , 1 , ( i + 1 ) * 2 );
-		}
-		M_CKERR_( T_SRDErrors::MAX_ERRORS , "too many errors" , 1 , 80 );
-
-		sb.clear( );
-		for ( auto i = 0u ; i < T_SRDErrors::MAX_ERRORS ; i ++ ) {
-			sb << '(';
-		}
-		for ( auto i = 0u ; i < T_SRDErrors::MAX_ERRORS ; i ++ ) {
-			sb << ')';
-		}
-		sb << '\0';
-		CPPUNIT_ASSERT( check( sb.data( ) , output ) );
-	} catch ( X_SRDErrors const& e ) {
-		auto const& errors( e.errors );
-		for ( auto i = 0u ; i < errors.size( ) ; i ++ ) {
-			M_PRINTERR_( i );
-		}
-		CPPUNIT_FAIL( "Shouldn't fail with exception" );
-	}
-}
-
-void SRDPreprocCmdInputTest::testFromSourceLocation( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -from-source \"test\\ntest\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "test test" , output ) );
-	M_CKTOKDEPTH_( 0 , 1 );
-		M_CKTOKLOC_( 0 , "-from-source" , 1 , 1 );
-		M_CKTOKCHAIN_( 0 , 0 , GENERATED , "test" , 1 , 3 , 0 );
-	M_CKTOKDEPTH_( 1 , 1 );
-		M_CKTOKLOC_( 1 , "-from-source" , 2 , 1 );
-		M_CKTOKCHAIN_( 1 , 0 , GENERATED , "test" , 1 , 3 , 0 );
-}
-
-void SRDPreprocCmdInputTest::testFromSourceLocationNamed( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -from-source \"test\\ntest\" \"test.srd\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "test test" , output ) );
-	M_CKTOKDEPTH_( 0 , 1 );
-		M_CKTOKLOC_( 0 , "test.srd" , 1 , 1 );
-		M_CKTOKCHAIN_( 0 , 0 , GENERATED , "test" , 1 , 3 , 0 );
-	M_CKTOKDEPTH_( 1 , 1 );
-		M_CKTOKLOC_( 1 , "test.srd" , 2 , 1 );
-		M_CKTOKCHAIN_( 1 , 0 , GENERATED , "test" , 1 , 3 , 0 );
-}
-
-void SRDPreprocCmdInputTest::testFromSourceLocationChaining( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -from-source \"test\\ntest\" \"test.srd\" loaded )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "test test" , output ) );
-	M_CKTOKDEPTH_( 0 , 1 );
-		M_CKTOKLOC_( 0 , "test.srd" , 1 , 1 );
-		M_CKTOKCHAIN_( 0 , 0 , LOADED , "test" , 1 , 3 , 0 );
-	M_CKTOKDEPTH_( 1 , 1 );
-		M_CKTOKLOC_( 1 , "test.srd" , 2 , 1 );
-		M_CKTOKCHAIN_( 1 , 0 , LOADED , "test" , 1 , 3 , 0 );
-}
-
-void SRDPreprocCmdInputTest::testFromSourceLocationRewind( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-set doit ((-raw ()\n"
-					"( -from-source \"test\" \"test.srd\" loaded 2 )\n"
-				")))\n"
-				"(-set tfn ((-raw (x)\n"
-					"(-if (-lt $x 1) (\n"
-						"($doit)\n"
-					")(\n"
-						"($tfn (-sub $x 1))\n"
-					"))\n"
-				")))\n"
-				"(-bless tfn doit)\n"
-				"($tfn 5)" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "test" , output ) );
-	M_CKTOKDEPTH_( 0 , 1 );
-		M_CKTOKLOC_( 0 , "test.srd" , 1 , 1 );
-		M_CKTOKCHAIN_( 0 , 0 , LOADED , "test" , 12 , 2 , 0 );
-}
-
-void SRDPreprocCmdInputTest::testFromSourceLocationRewindTooMuch( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -from-source \"test\" \"test.srd\" loaded 2 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "test" , output ) );
-	M_CKTOKDEPTH_( 0 , 1 );
-		M_CKTOKLOC_( 0 , "test.srd" , 1 , 1 );
-		M_CKTOKCHAIN_( 0 , 0 , LOADED , "test" , 1 , 3 , 0 );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdInputTest::testFromSourceArgsNone( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -from-source )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 16 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdInputTest::testFromSourceArgsExtra( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -from-source \"x\" \"y\" generated 0 c )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "too many arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 36 );
-	CPPUNIT_ASSERT( check( "x" , output ) );
-}
-
-void SRDPreprocCmdInputTest::testFromSourceArgsBadSource( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -from-source 12 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "text argument expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 16 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdInputTest::testFromSourceArgsBadName( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"( -from-source \"test\"\n"
-				"12 )" ,
-				errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "text argument expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 2 , 1 );
-	CPPUNIT_ASSERT( check( "test" , output ) );
-	M_CKTOKDEPTH_( 0 , 1 );
-		M_CKTOKLOC_( 0 , "-from-source" , 1 , 1 );
-		M_CKTOKCHAIN_( 0 , 0 , GENERATED , "test" , 1 , 3 , 0 );
-}
-
-void SRDPreprocCmdInputTest::testFromSourceArgsBadChaining( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"( -from-source \"test\" \"test.srd\"\n"
-				"nope )\n"
-				"( -from-source \"test\" \"test2.srd\"\n"
-				"12 )\n" ,
-				errors ) );
-	CPPUNIT_ASSERT_EQUAL( 4u , errors.size( ) );
-	M_CKERR_( 0 , "'generated', 'included' or 'loaded' expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 2 , 1 );
-	M_CKERR_( 2 , "'generated', 'included' or 'loaded' expected" , 3 , 3 );
-	M_CKERR_( 3 , "previous error cause" , 4 , 1 );
-	CPPUNIT_ASSERT( check( "test test" , output ) );
-	M_CKTOKDEPTH_( 0 , 1 );
-		M_CKTOKLOC_( 0 , "test.srd" , 1 , 1 );
-		M_CKTOKCHAIN_( 0 , 0 , GENERATED , "test" , 1 , 3 , 0 );
-	M_CKTOKDEPTH_( 1 , 1 );
-		M_CKTOKLOC_( 1 , "test2.srd" , 1 , 1 );
-		M_CKTOKCHAIN_( 1 , 0 , GENERATED , "test" , 3 , 3 , 0 );
-}
-
-void SRDPreprocCmdInputTest::testFromSourceArgsBadRewind( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"( -from-source \"test\" \"test.srd\" generated\n"
-				"-1 )\n"
-				"( -from-source \"test\" \"test2.srd\" generated\n"
-				"nope )\n" ,
-				errors ) );
-	CPPUNIT_ASSERT_EQUAL( 4u , errors.size( ) );
-	M_CKERR_( 0 , "invalid argument value" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 2 , 1 );
-	M_CKERR_( 2 , "integer argument expected" , 3 , 3 );
-	M_CKERR_( 3 , "previous error cause" , 4 , 1 );
-	CPPUNIT_ASSERT( check( "test test" , output ) );
-	M_CKTOKDEPTH_( 0 , 1 );
-		M_CKTOKLOC_( 0 , "test.srd" , 1 , 1 );
-		M_CKTOKCHAIN_( 0 , 0 , GENERATED , "test" , 1 , 3 , 0 );
-	M_CKTOKDEPTH_( 1 , 1 );
-		M_CKTOKLOC_( 1 , "test2.srd" , 1 , 1 );
-		M_CKTOKCHAIN_( 1 , 0 , GENERATED , "test" , 3 , 3 , 0 );
-}
-
-/*----------------------------------------------------------------------------*/
-
-#define SRB_PROLOGUE_ \
-	"ce a1 7c ea " \
-	"00 ee ff c0"
-
-#define SRB_DATA_ \
-	"[ " \
-		SRB_PROLOGUE_ \
-		"02 03 00 00 00 4c 4f 4c" \
-		"00" \
-	"]"
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdInputTest::testFromSRBNoName( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -from-srb " SRB_DATA_ " )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "LOL" , output ) );
-}
-
-void SRDPreprocCmdInputTest::testFromSRBNamed( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"( -from-srb " SRB_DATA_ "\n"
-				"\"some_random_file.srb\" )" ,
-				errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "LOL" , output ) );
-}
-
-void SRDPreprocCmdInputTest::testFromSRBError( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -from-srb\n[ " SRB_PROLOGUE_ " ] )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , errors.size( ) );
-	M_CKERR_( 0 , "unexpected end of file" , 0 , 8 );
-	CPPUNIT_ASSERT( errors[ 0 ].location( ).source( ) == "-from-srb" );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdInputTest::testFromSRBErrorNamed( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"( -from-srb\n[ "
-				SRB_PROLOGUE_
-				" ] \"some_random_file.srb\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , errors.size( ) );
-	M_CKERR_( 0 , "unexpected end of file" , 0 , 8 );
-	CPPUNIT_ASSERT( errors[ 0 ].location( ).source( ) == "some_random_file.srb" );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdInputTest::testFromSRBLocation( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -from-srb " SRB_DATA_ " )\n" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "LOL" , output ) );
-	M_CKTOKDEPTH_( 0 , 1 );
-		M_CKTOKLOC_( 0 , "-from-srb" , 0 , 8 );
-		M_CKTOKCHAIN_( 0 , 0 , GENERATED , "test" , 1 , 3 , 0 );
-}
-
-void SRDPreprocCmdInputTest::testFromSRBLocationNamed( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -from-srb " SRB_DATA_ " \"test.srb\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "LOL" , output ) );
-	M_CKTOKDEPTH_( 0 , 1 );
-		M_CKTOKLOC_( 0 , "test.srb" , 0 , 8 );
-		M_CKTOKCHAIN_( 0 , 0 , GENERATED , "test" , 1 , 3 , 0 );
-}
-
-void SRDPreprocCmdInputTest::testFromSRBLocationChaining( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -from-srb " SRB_DATA_ " \"test.srb\" loaded )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "LOL" , output ) );
-	M_CKTOKDEPTH_( 0 , 1 );
-		M_CKTOKLOC_( 0 , "test.srb" , 0 , 8 );
-		M_CKTOKCHAIN_( 0 , 0 , LOADED , "test" , 1 , 3 , 0 );
-}
-
-void SRDPreprocCmdInputTest::testFromSRBLocationRewind( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-set doit ((-raw ()\n"
-					"( -from-srb " SRB_DATA_ " \"test.srb\" loaded 2 )\n"
-				")))\n"
-				"(-set tfn ((-raw (x)\n"
-					"(-if (-lt $x 1) (\n"
-						"($doit)\n"
-					")(\n"
-						"($tfn (-sub $x 1))\n"
-					"))\n"
-				")))\n"
-				"(-bless tfn doit)\n"
-				"($tfn 5)" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "LOL" , output ) );
-	M_CKTOKDEPTH_( 0 , 1 );
-		M_CKTOKLOC_( 0 , "test.srb" , 0 , 8 );
-		M_CKTOKCHAIN_( 0 , 0 , LOADED , "test" , 12 , 2 , 0 );
-}
-
-void SRDPreprocCmdInputTest::testFromSRBLocationRewindTooMuch( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -from-srb " SRB_DATA_ " \"test.srb\" loaded 2 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "LOL" , output ) );
-	M_CKTOKDEPTH_( 0 , 1 );
-		M_CKTOKLOC_( 0 , "test.srb" , 0 , 8 );
-		M_CKTOKCHAIN_( 0 , 0 , LOADED , "test" , 1 , 3 , 0 );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdInputTest::testFromSRBArgsNone( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -from-srb )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 13 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdInputTest::testFromSRBArgsExtra( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -from-srb " SRB_DATA_ " a loaded 0\nnope )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "too many arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 2 , 1 );
-	CPPUNIT_ASSERT( check( "LOL" , output ) );
-}
-
-void SRDPreprocCmdInputTest::testFromSRBArgsBadInput( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -from-srb \"x\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "binary array argument expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 13 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdInputTest::testFromSRBArgsBadName( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"( -from-srb " SRB_DATA_ "\n12 )" ,
-				errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "text argument expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 2 , 1 );
-	CPPUNIT_ASSERT( check( "LOL" , output ) );
-}
-
-void SRDPreprocCmdInputTest::testFromSRBArgsBadChaining( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"( -from-srb " SRB_DATA_ " \"test.srb\"\n"
-				"nope )\n"
-				"( -from-srb " SRB_DATA_ " \"test2.srb\"\n"
-				"12 )\n" ,
-				errors ) );
-	CPPUNIT_ASSERT_EQUAL( 4u , errors.size( ) );
-	M_CKERR_( 0 , "'generated', 'included' or 'loaded' expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 2 , 1 );
-	M_CKERR_( 2 , "'generated', 'included' or 'loaded' expected" , 3 , 3 );
-	M_CKERR_( 3 , "previous error cause" , 4 , 1 );
-	CPPUNIT_ASSERT( check( "LOL LOL" , output ) );
-	M_CKTOKDEPTH_( 0 , 1 );
-		M_CKTOKLOC_( 0 , "test.srb" , 0 , 8 );
-		M_CKTOKCHAIN_( 0 , 0 , GENERATED , "test" , 1 , 3 , 0 );
-	M_CKTOKDEPTH_( 1 , 1 );
-		M_CKTOKLOC_( 1 , "test2.srb" , 0 , 8 );
-		M_CKTOKCHAIN_( 1 , 0 , GENERATED , "test" , 3 , 3 , 0 );
-}
-
-void SRDPreprocCmdInputTest::testFromSRBArgsBadRewind( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"( -from-srb " SRB_DATA_ " \"test.srd\" generated\n"
-				"-1 )\n"
-				"( -from-srb " SRB_DATA_ " \"test2.srd\" generated\n"
-				"nope )\n" ,
-				errors ) );
-	CPPUNIT_ASSERT_EQUAL( 4u , errors.size( ) );
-	M_CKERR_( 0 , "invalid argument value" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 2 , 1 );
-	M_CKERR_( 2 , "integer argument expected" , 3 , 3 );
-	M_CKERR_( 3 , "previous error cause" , 4 , 1 );
-	CPPUNIT_ASSERT( check( "LOL LOL" , output ) );
-	M_CKTOKDEPTH_( 0 , 1 );
-		M_CKTOKLOC_( 0 , "test.srd" , 0 , 8 );
-		M_CKTOKCHAIN_( 0 , 0 , GENERATED , "test" , 1 , 3 , 0 );
-	M_CKTOKDEPTH_( 1 , 1 );
-		M_CKTOKLOC_( 1 , "test2.srd" , 0 , 8 );
-		M_CKTOKCHAIN_( 1 , 0 , GENERATED , "test" , 3 , 3 , 0 );
-}
diff --git a/tests/srd-preproc-cmd-introspect.cc b/tests/srd-preproc-cmd-introspect.cc
deleted file mode 100644
index e51d727..0000000
--- a/tests/srd-preproc-cmd-introspect.cc
+++ /dev/null
@@ -1,322 +0,0 @@
-#include "srd-preproc-cmd-common.hh"
-
-
-class SRDPreprocCmdIntrospectTest : public CppUnit::TestFixture
-{
-	CPPUNIT_TEST_SUITE( SRDPreprocCmdIntrospectTest );
-
-	CPPUNIT_TEST( testIsSetMissingArgs );
-	CPPUNIT_TEST( testIsSetExtraArgs );
-	CPPUNIT_TEST( testIsSetBadArg );
-	CPPUNIT_TEST( testIsSetTrue );
-	CPPUNIT_TEST( testIsSetFalse );
-
-	CPPUNIT_TEST( testIsMacroMissingArgs );
-	CPPUNIT_TEST( testIsMacroExtraArgs );
-	CPPUNIT_TEST( testIsMacroBadArg );
-	CPPUNIT_TEST( testIsMacroTrue );
-	CPPUNIT_TEST( testIsMacroFalse );
-
-	CPPUNIT_TEST( testIsBlessedMissingArgs );
-	CPPUNIT_TEST( testIsBlessedExtraArgs );
-	CPPUNIT_TEST( testIsBlessedBadArg );
-	CPPUNIT_TEST( testIsBlessedUnset );
-	CPPUNIT_TEST( testIsBlessedUnblessed );
-	CPPUNIT_TEST( testIsBlessedTrue );
-
-	CPPUNIT_TEST( testTypeOfMissingArg );
-	CPPUNIT_TEST( testTypeOfExtraArgs );
-	CPPUNIT_TEST( testTypeOfList );
-	CPPUNIT_TEST( testTypeOfWord );
-	CPPUNIT_TEST( testTypeOfString );
-	CPPUNIT_TEST( testTypeOfInt );
-	CPPUNIT_TEST( testTypeOfLong );
-	CPPUNIT_TEST( testTypeOfReal );
-	CPPUNIT_TEST( testTypeOfVar );
-	CPPUNIT_TEST( testTypeOfBinary );
-	CPPUNIT_TEST( testTypeOfComment );
-
-	CPPUNIT_TEST_SUITE_END( );
-
-   public:
-	void testIsSetMissingArgs( );
-	void testIsSetExtraArgs( );
-	void testIsSetBadArg( );
-	void testIsSetTrue( );
-	void testIsSetFalse( );
-
-	void testIsMacroMissingArgs( );
-	void testIsMacroExtraArgs( );
-	void testIsMacroBadArg( );
-	void testIsMacroTrue( );
-	void testIsMacroFalse( );
-
-	void testIsBlessedMissingArgs( );
-	void testIsBlessedExtraArgs( );
-	void testIsBlessedBadArg( );
-	void testIsBlessedUnset( );
-	void testIsBlessedUnblessed( );
-	void testIsBlessedTrue( );
-
-	void testTypeOfMissingArg( );
-	void testTypeOfExtraArgs( );
-	void testTypeOfList( );
-	void testTypeOfWord( );
-	void testTypeOfString( );
-	void testTypeOfInt( );
-	void testTypeOfLong( );
-	void testTypeOfReal( );
-	void testTypeOfVar( );
-	void testTypeOfBinary( );
-	void testTypeOfComment( );
-};
-CPPUNIT_TEST_SUITE_REGISTRATION( SRDPreprocCmdIntrospectTest );
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdIntrospectTest::testIsSetMissingArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -is-set )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 11 );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdIntrospectTest::testIsSetExtraArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -is-set a b c )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "too many arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 13 );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdIntrospectTest::testIsSetBadArg( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -is-set 1 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "word expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 11 );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdIntrospectTest::testIsSetTrue( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "(-set x 1)( -is-set x )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-void SRDPreprocCmdIntrospectTest::testIsSetFalse( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -is-set x )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdIntrospectTest::testIsMacroMissingArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -is-macro )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 13 );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdIntrospectTest::testIsMacroExtraArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -is-macro a b c )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "too many arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 15 );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdIntrospectTest::testIsMacroBadArg( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -is-macro 1 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "word expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 13 );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdIntrospectTest::testIsMacroTrue( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "(-set-macro x (()))( -is-macro x )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-void SRDPreprocCmdIntrospectTest::testIsMacroFalse( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -is-macro x )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdIntrospectTest::testIsBlessedMissingArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -is-blessed )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 15 );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdIntrospectTest::testIsBlessedExtraArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -is-blessed a b c )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "too many arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 17 );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdIntrospectTest::testIsBlessedBadArg( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -is-blessed 1 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "word expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 15 );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdIntrospectTest::testIsBlessedUnset( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -is-blessed x )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdIntrospectTest::testIsBlessedUnblessed( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "(-set x 1)( -is-blessed x )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdIntrospectTest::testIsBlessedTrue( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -set x (()) )\n"
-				"( -bless x )\n"
-				"( -is-blessed x )" ,
-				errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdIntrospectTest::testTypeOfMissingArg( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -type-of )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 12 );
-	CPPUNIT_ASSERT( check( "none" , output ) );
-}
-
-void SRDPreprocCmdIntrospectTest::testTypeOfExtraArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -type-of a b c )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "too many arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 14 );
-	CPPUNIT_ASSERT( check( "word" , output ) );
-}
-
-void SRDPreprocCmdIntrospectTest::testTypeOfList( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -type-of ( ) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "list" , output ) );
-}
-
-void SRDPreprocCmdIntrospectTest::testTypeOfWord( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -type-of w )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "word" , output ) );
-}
-
-void SRDPreprocCmdIntrospectTest::testTypeOfString( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -type-of \"w\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "string" , output ) );
-}
-
-void SRDPreprocCmdIntrospectTest::testTypeOfInt( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -type-of 0 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "int" , output ) );
-}
-
-void SRDPreprocCmdIntrospectTest::testTypeOfLong( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -type-of 12123456789 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "long" , output ) );
-}
-
-void SRDPreprocCmdIntrospectTest::testTypeOfReal( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -type-of 0. )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "real" , output ) );
-}
-
-void SRDPreprocCmdIntrospectTest::testTypeOfVar( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -type-of ( -raw $x ) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "var" , output ) );
-}
-
-void SRDPreprocCmdIntrospectTest::testTypeOfBinary( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -type-of [] )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "binary" , output ) );
-}
-
-void SRDPreprocCmdIntrospectTest::testTypeOfComment( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -type-of (-from-source \"{x}\") )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "comment" , output ) );
-}
diff --git a/tests/srd-preproc-cmd-logic.cc b/tests/srd-preproc-cmd-logic.cc
deleted file mode 100644
index 52374a3..0000000
--- a/tests/srd-preproc-cmd-logic.cc
+++ /dev/null
@@ -1,609 +0,0 @@
-#include "srd-preproc-cmd-common.hh"
-
-
-class SRDPreprocCmdLogicTest : public CppUnit::TestFixture
-{
-	CPPUNIT_TEST_SUITE( SRDPreprocCmdLogicTest );
-
-	CPPUNIT_TEST( testNotNoArgs );
-	CPPUNIT_TEST( testNotTooManyArgs );
-	CPPUNIT_TEST( testNotBadArg );
-	CPPUNIT_TEST( testNotZero );
-	CPPUNIT_TEST( testNotNonZeroInt );
-	CPPUNIT_TEST( testNotNonZeroLong );
-
-	CPPUNIT_TEST( testBwNotNoArgs );
-	CPPUNIT_TEST( testBwNotTooManyArgs );
-	CPPUNIT_TEST( testBwNotBadArg );
-	CPPUNIT_TEST( testBwNotInt );
-	CPPUNIT_TEST( testBwNotLong );
-
-	CPPUNIT_TEST( testAndNoArgs );
-	CPPUNIT_TEST( testAndBadArgs );
-	CPPUNIT_TEST( testAnd00 );
-	CPPUNIT_TEST( testAnd01 );
-	CPPUNIT_TEST( testAnd10 );
-	CPPUNIT_TEST( testAnd11 );
-	CPPUNIT_TEST( testAndMultiple );
-	CPPUNIT_TEST( testAndLong );
-	CPPUNIT_TEST( testAndSillyValues );
-
-	CPPUNIT_TEST( testBwAndNoArgs );
-	CPPUNIT_TEST( testBwAndBadArgs );
-	CPPUNIT_TEST( testBwAndInts );
-	CPPUNIT_TEST( testBwAndLongs );
-	CPPUNIT_TEST( testBwAndMultiple );
-
-	CPPUNIT_TEST( testOrNoArgs );
-	CPPUNIT_TEST( testOrBadArgs );
-	CPPUNIT_TEST( testOr00 );
-	CPPUNIT_TEST( testOr01 );
-	CPPUNIT_TEST( testOr10 );
-	CPPUNIT_TEST( testOr11 );
-	CPPUNIT_TEST( testOrMultiple );
-	CPPUNIT_TEST( testOrLong );
-	CPPUNIT_TEST( testOrSillyValues );
-
-	CPPUNIT_TEST( testBwOrNoArgs );
-	CPPUNIT_TEST( testBwOrBadArgs );
-	CPPUNIT_TEST( testBwOrInts );
-	CPPUNIT_TEST( testBwOrLongs );
-	CPPUNIT_TEST( testBwOrMultiple );
-
-	CPPUNIT_TEST( testXorNoArgs );
-	CPPUNIT_TEST( testXorBadArgs );
-	CPPUNIT_TEST( testXor00 );
-	CPPUNIT_TEST( testXor01 );
-	CPPUNIT_TEST( testXor10 );
-	CPPUNIT_TEST( testXor11 );
-	CPPUNIT_TEST( testXorMultiple );
-	CPPUNIT_TEST( testXorLong );
-	CPPUNIT_TEST( testXorSillyValues );
-
-	CPPUNIT_TEST( testBwXorNoArgs );
-	CPPUNIT_TEST( testBwXorBadArgs );
-	CPPUNIT_TEST( testBwXorInts );
-	CPPUNIT_TEST( testBwXorLongs );
-	CPPUNIT_TEST( testBwXorMultiple );
-
-	CPPUNIT_TEST_SUITE_END( );
-
-   public:
-	void testNotNoArgs( );
-	void testNotTooManyArgs( );
-	void testNotBadArg( );
-	void testNotZero( );
-	void testNotNonZeroInt( );
-	void testNotNonZeroLong( );
-
-	void testBwNotNoArgs( );
-	void testBwNotTooManyArgs( );
-	void testBwNotBadArg( );
-	void testBwNotInt( );
-	void testBwNotLong( );
-
-	void testAndNoArgs( );
-	void testAndBadArgs( );
-	void testAnd00( );
-	void testAnd01( );
-	void testAnd10( );
-	void testAnd11( );
-	void testAndMultiple( );
-	void testAndLong( );
-	void testAndSillyValues( );
-
-	void testBwAndNoArgs( );
-	void testBwAndBadArgs( );
-	void testBwAndInts( );
-	void testBwAndLongs( );
-	void testBwAndMultiple( );
-
-	void testOrNoArgs( );
-	void testOrBadArgs( );
-	void testOr00( );
-	void testOr01( );
-	void testOr10( );
-	void testOr11( );
-	void testOrMultiple( );
-	void testOrLong( );
-	void testOrSillyValues( );
-
-	void testBwOrNoArgs( );
-	void testBwOrBadArgs( );
-	void testBwOrInts( );
-	void testBwOrLongs( );
-	void testBwOrMultiple( );
-
-	void testXorNoArgs( );
-	void testXorBadArgs( );
-	void testXor00( );
-	void testXor01( );
-	void testXor10( );
-	void testXor11( );
-	void testXorMultiple( );
-	void testXorLong( );
-	void testXorSillyValues( );
-
-	void testBwXorNoArgs( );
-	void testBwXorBadArgs( );
-	void testBwXorInts( );
-	void testBwXorLongs( );
-	void testBwXorMultiple( );
-};
-CPPUNIT_TEST_SUITE_REGISTRATION( SRDPreprocCmdLogicTest );
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdLogicTest::testNotNoArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -not )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 8 );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdLogicTest::testNotTooManyArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -not 0 2 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "too many arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 10 );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-void SRDPreprocCmdLogicTest::testNotBadArg( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -not 0. )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "integer argument expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 8 );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-void SRDPreprocCmdLogicTest::testNotZero( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -not 0 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-void SRDPreprocCmdLogicTest::testNotNonZeroInt( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -not 12 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdLogicTest::testNotNonZeroLong( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "(-set x ( -not 12000000000 ))(-to-integer $x)(-type-of $x)"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "0 long" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdLogicTest::testBwNotNoArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -bw-not )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 11 );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdLogicTest::testBwNotTooManyArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -bw-not 1 2 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "too many arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 13 );
-	CPPUNIT_ASSERT( check( "-2" , output ) );
-}
-
-void SRDPreprocCmdLogicTest::testBwNotBadArg( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -bw-not 2.2 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "integer argument expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 11 );
-	CPPUNIT_ASSERT( check( "-3" , output ) );
-}
-
-void SRDPreprocCmdLogicTest::testBwNotInt( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -bw-not 129 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "-130" , output ) );
-}
-
-void SRDPreprocCmdLogicTest::testBwNotLong( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -bw-not 12000000000 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "-12000000001" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdLogicTest::testAndNoArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -and )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 8 );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdLogicTest::testAndBadArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -and 1 1. ( ) )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "integer argument expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 10 );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-void SRDPreprocCmdLogicTest::testAnd00( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -and 0 0 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdLogicTest::testAnd01( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -and 0 1 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdLogicTest::testAnd10( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -and 1 0 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdLogicTest::testAnd11( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -and 1 1 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-void SRDPreprocCmdLogicTest::testAndMultiple( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -and 1 1 1 1 )( -and 1 0 1 1 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1 0" , output ) );
-}
-
-void SRDPreprocCmdLogicTest::testAndLong( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -and 1 ( -to-long 1 ) )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-void SRDPreprocCmdLogicTest::testAndSillyValues( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -and -42384 35845 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdLogicTest::testBwAndNoArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -bw-and )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 11 );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdLogicTest::testBwAndBadArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -bw-and 1.2 ( ) )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "integer argument expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 11 );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-void SRDPreprocCmdLogicTest::testBwAndInts( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -bw-and 5 6 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "4" , output ) );
-}
-
-void SRDPreprocCmdLogicTest::testBwAndLongs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -bw-and 12884901888 4294967296 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "4294967296" , output ) );
-}
-
-void SRDPreprocCmdLogicTest::testBwAndMultiple( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -bw-and 15 7 3 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "3" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdLogicTest::testOrNoArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -or )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 7 );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdLogicTest::testOrBadArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -or 1 1. ( ) )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "integer argument expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 9 );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-void SRDPreprocCmdLogicTest::testOr00( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -or 0 0 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdLogicTest::testOr01( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -or 0 1 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-void SRDPreprocCmdLogicTest::testOr10( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -or 1 0 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-void SRDPreprocCmdLogicTest::testOr11( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -or 1 1 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-void SRDPreprocCmdLogicTest::testOrMultiple( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -or 1 1 1 1 )( -or 1 0 1 1 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1 1" , output ) );
-}
-
-void SRDPreprocCmdLogicTest::testOrLong( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -or 1 ( -to-long 1 ) )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-void SRDPreprocCmdLogicTest::testOrSillyValues( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -or 0 35845 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdLogicTest::testBwOrNoArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -bw-or )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 10 );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdLogicTest::testBwOrBadArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -bw-or 1.2 ( ) )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "integer argument expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 10 );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-void SRDPreprocCmdLogicTest::testBwOrInts( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -bw-or 5 6 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "7" , output ) );
-}
-
-void SRDPreprocCmdLogicTest::testBwOrLongs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -bw-or 8589934592 4294967296 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "12884901888" , output ) );
-}
-
-void SRDPreprocCmdLogicTest::testBwOrMultiple( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -bw-or 2 4 8 6 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "14" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdLogicTest::testXorNoArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -xor )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 8 );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdLogicTest::testXorBadArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -xor 1 1. ( ) )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "integer argument expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 10 );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdLogicTest::testXor00( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -xor 0 0 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdLogicTest::testXor01( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -xor 0 1 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-void SRDPreprocCmdLogicTest::testXor10( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -xor 1 0 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-void SRDPreprocCmdLogicTest::testXor11( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -xor 1 1 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdLogicTest::testXorMultiple( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -xor 1 0 0 0 )( -xor 1 0 1 0 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1 0" , output ) );
-}
-
-void SRDPreprocCmdLogicTest::testXorLong( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -xor 1 ( -to-long 1 ) )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdLogicTest::testXorSillyValues( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -xor 0 35845 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdLogicTest::testBwXorNoArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -bw-xor )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 11 );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdLogicTest::testBwXorBadArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -bw-xor 1.2 ( ) )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "integer argument expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 11 );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-void SRDPreprocCmdLogicTest::testBwXorInts( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -bw-xor 5 6 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "3" , output ) );
-}
-
-void SRDPreprocCmdLogicTest::testBwXorLongs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -bw-xor 21474836480 25769803776 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "12884901888" , output ) );
-}
-
-void SRDPreprocCmdLogicTest::testBwXorMultiple( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -bw-xor 2 4 8 6 )"  , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "8" , output ) );
-}
diff --git a/tests/srd-preproc-cmd-macros.cc b/tests/srd-preproc-cmd-macros.cc
deleted file mode 100644
index 1f0105e..0000000
--- a/tests/srd-preproc-cmd-macros.cc
+++ /dev/null
@@ -1,243 +0,0 @@
-#include "srd-preproc-cmd-common.hh"
-
-
-class SRDPreprocCmdMacrosTest : public CppUnit::TestFixture
-{
-	CPPUNIT_TEST_SUITE( SRDPreprocCmdMacrosTest );
-
-	CPPUNIT_TEST( testSetMacroEmpty );
-	CPPUNIT_TEST( testSetMacroMissingArgs );
-	CPPUNIT_TEST( testSetMacroExtraArgs );
-	CPPUNIT_TEST( testSetMacroBadName );
-	CPPUNIT_TEST( testSetMacroBadBody );
-	CPPUNIT_TEST( testSetMacroInvalidBody );
-	CPPUNIT_TEST( testSetMacroSuccess );
-	CPPUNIT_TEST( testSetMacroDuplicate );
-
-	CPPUNIT_TEST( testUnsetMacroNoArgs );
-	CPPUNIT_TEST( testUnsetMacro );
-	CPPUNIT_TEST( testUnsetMacroMissing );
-	CPPUNIT_TEST( testUnsetMacroMultiple );
-
-	CPPUNIT_TEST( testListMacros );
-	CPPUNIT_TEST( testListMacrosArgs );
-
-	CPPUNIT_TEST( testMacroBodyInnerList );
-	CPPUNIT_TEST( testMacroOutputInnerList );
-
-	CPPUNIT_TEST_SUITE_END( );
-
-   public:
-	void testSetMacroEmpty( );
-	void testSetMacroMissingArgs( );
-	void testSetMacroExtraArgs( );
-	void testSetMacroBadName( );
-	void testSetMacroBadBody( );
-	void testSetMacroInvalidBody( );
-	void testSetMacroSuccess( );
-	void testSetMacroDuplicate( );
-
-	void testUnsetMacroNoArgs( );
-	void testUnsetMacro( );
-	void testUnsetMacroMissing( );
-	void testUnsetMacroMultiple( );
-
-	void testListMacros( );
-	void testListMacrosArgs( );
-
-	void testMacroBodyInnerList( );
-	void testMacroOutputInnerList( );
-};
-CPPUNIT_TEST_SUITE_REGISTRATION( SRDPreprocCmdMacrosTest );
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdMacrosTest::testSetMacroEmpty( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -set-macro )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 14 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdMacrosTest::testSetMacroMissingArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -set-macro a )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "invalid macro" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 14 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdMacrosTest::testSetMacroExtraArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -set-macro a ( () ) x )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "too many arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 23 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdMacrosTest::testSetMacroBadName( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -set-macro 1 ( () ) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "word expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 14 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdMacrosTest::testSetMacroBadBody( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -set-macro a x )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "invalid macro" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 14 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdMacrosTest::testSetMacroInvalidBody( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -set-macro a ( nope ) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "invalid macro" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 14 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdMacrosTest::testSetMacroSuccess( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"( -set-macro test ( -raw ( ((list)) ( (-raw -raw) $list ) ) ) )\n"
-				"(test $x $y $z (-set x 1))",
-				errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "$x $y $z (-set x 1)" , output ) );
-}
-
-void SRDPreprocCmdMacrosTest::testSetMacroDuplicate( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"( -set-macro a (()) )\n"
-				"( -set-macro a (()) )" ,
-				errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "duplicate macro" , 2 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 2 , 14 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdMacrosTest::testUnsetMacroNoArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -unset-macro ) " , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdMacrosTest::testUnsetMacro( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"( -set-macro a (()1) )\n"
-				"(a)\n"
-				"( -unset-macro a )\n"
-				"(a)" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1 (a)" , output ) );
-}
-
-void SRDPreprocCmdMacrosTest::testUnsetMacroMissing( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -unset-macro a )(a)" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "(a)" , output ) );
-}
-
-void SRDPreprocCmdMacrosTest::testUnsetMacroMultiple( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				  "( -set-macro a (()1) )\n"
-				  "( -set-macro b (()2) )\n"
-				  "( -set-macro c (()3) )\n"
-				  "( -unset-macro a c d )\n"
-				  "(a)(b)(c)\n" ,
-				  errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "(a) 2 (c)" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdMacrosTest::testListMacros( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"( -set x )\n"
-				"( -set-macro y ( ( ) ) )\n"
-				"( -set f (-raw (() ((-ls-macros))) ))\n"
-				"( -bless f )\n"
-				"( ( -ls-macros ) )\n"
-				"( -scope\n"
-					"( -unset-macro y )\n"
-					"( ( -ls-macros ) )\n"
-				")\n"
-				"($f)\n"
-				, errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "( y ) ( ) ( y )" , output ) );
-}
-
-void SRDPreprocCmdMacrosTest::testListMacrosArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"( -set-macro y ( ( ) ) )\n"
-				"( -ls-macros blah )\n"
-				, errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "too many arguments" , 2 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 2 , 14 );
-	CPPUNIT_ASSERT( check( "y" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdMacrosTest::testMacroBodyInnerList( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-			"( -set-macro x (-raw ( () -not-a-command ) ) )\n"
-			"( -set x (-raw ( () ) ) )\n"
-			"( -bless x )\n"
-			"( -set-macro y (-raw ( () $x ) ) )\n"
-			"(x)(y)" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "-not-a-command (())" , output ) );
-}
-
-void SRDPreprocCmdMacrosTest::testMacroOutputInnerList( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-			"( -set-macro x (-raw ( () (-raw -not-a-command) ) ) )\n"
-			"( -set x (-raw ( () ) ) )\n"
-			"( -bless x )\n"
-			"( -set-macro y (-raw ( () (-raw $x ) ) ) )\n"
-			"(x)(y)" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "-not-a-command (())" , output ) );
-}
diff --git a/tests/srd-preproc-cmd-misc.cc b/tests/srd-preproc-cmd-misc.cc
deleted file mode 100644
index 335578a..0000000
--- a/tests/srd-preproc-cmd-misc.cc
+++ /dev/null
@@ -1,165 +0,0 @@
-#include "srd-preproc-cmd-common.hh"
-
-
-class SRDPreprocCmdMiscTest : public CppUnit::TestFixture
-{
-	CPPUNIT_TEST_SUITE( SRDPreprocCmdMiscTest );
-
-	CPPUNIT_TEST( testIgnore );
-
-	CPPUNIT_TEST( testUnwrapMissingArg );
-	CPPUNIT_TEST( testUnwrapBadArg );
-	CPPUNIT_TEST( testUnwrapEmptyList );
-	CPPUNIT_TEST( testUnwrapList );
-	CPPUNIT_TEST( testUnwrapExtraArgs );
-
-	CPPUNIT_TEST( testLengthMissingArg );
-	CPPUNIT_TEST( testLengthExtraArgs );
-	CPPUNIT_TEST( testLengthBadArg );
-	CPPUNIT_TEST( testLengthList );
-	CPPUNIT_TEST( testLengthWord );
-	CPPUNIT_TEST( testLengthString );
-	CPPUNIT_TEST( testLengthBinary );
-
-	CPPUNIT_TEST_SUITE_END( );
-
-   public:
-	void testIgnore( );
-
-	void testUnwrapMissingArg( );
-	void testUnwrapBadArg( );
-	void testUnwrapEmptyList( );
-	void testUnwrapList( );
-	void testUnwrapExtraArgs( );
-
-	void testLengthMissingArg( );
-	void testLengthExtraArgs( );
-	void testLengthBadArg( );
-	void testLengthList( );
-	void testLengthWord( );
-	void testLengthString( );
-	void testLengthBinary( );
-};
-CPPUNIT_TEST_SUITE_REGISTRATION( SRDPreprocCmdMiscTest );
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdMiscTest::testIgnore( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -ignore $does-not-exist ( -fail ) bleh )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdMiscTest::testUnwrapMissingArg( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -unwrap )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 11 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdMiscTest::testUnwrapBadArg( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -unwrap a )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "list expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 11 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdMiscTest::testUnwrapEmptyList( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -unwrap ( ) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdMiscTest::testUnwrapList( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -unwrap ( a b c ) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "a b c" , output ) );
-}
-
-void SRDPreprocCmdMiscTest::testUnwrapExtraArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -unwrap ( a ) ( b c ) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "too many arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 17 );
-	CPPUNIT_ASSERT( check( "a" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdMiscTest::testLengthMissingArg( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -length )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 11 );
-	CPPUNIT_ASSERT( check( "-1" , output ) );
-}
-
-void SRDPreprocCmdMiscTest::testLengthExtraArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -length a b c )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "too many arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 13 );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-void SRDPreprocCmdMiscTest::testLengthBadArg( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -length 1 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "list, word, string or binary array expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 11 );
-	CPPUNIT_ASSERT( check( "-1" , output ) );
-}
-
-void SRDPreprocCmdMiscTest::testLengthList( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -length ( a ( b ) ) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "2" , output ) );
-}
-
-void SRDPreprocCmdMiscTest::testLengthWord( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -length abc )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "3" , output ) );
-}
-
-void SRDPreprocCmdMiscTest::testLengthString( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -length \"some string\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "11" , output ) );
-}
-
-void SRDPreprocCmdMiscTest::testLengthBinary( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -length [ 01 02 03 ] )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "3" , output ) );
-}
diff --git a/tests/srd-preproc-cmd-strings.cc b/tests/srd-preproc-cmd-strings.cc
deleted file mode 100644
index 8927566..0000000
--- a/tests/srd-preproc-cmd-strings.cc
+++ /dev/null
@@ -1,931 +0,0 @@
-#include "srd-preproc-cmd-common.hh"
-
-
-class SRDPreprocCmdStringsTest : public CppUnit::TestFixture
-{
-	CPPUNIT_TEST_SUITE( SRDPreprocCmdStringsTest );
-
-	CPPUNIT_TEST( testConcatNoArgs );
-	CPPUNIT_TEST( testConcatBadArgs );
-	CPPUNIT_TEST( testConcatOneString );
-	CPPUNIT_TEST( testConcatStrings );
-	CPPUNIT_TEST( testConcatStringWord );
-	CPPUNIT_TEST( testConcatStringNumeric );
-	CPPUNIT_TEST( testConcatStringBinary );
-	CPPUNIT_TEST( testConcatOneBinary );
-	CPPUNIT_TEST( testConcatBinary );
-
-	CPPUNIT_TEST( testSubstrNotEnoughArgs );
-	CPPUNIT_TEST( testSubstrStringNotEnoughArgs );
-	CPPUNIT_TEST( testSubstrBinaryNotEnoughArgs );
-	CPPUNIT_TEST( testSubstrStringTooManyArgs );
-	CPPUNIT_TEST( testSubstrBinaryTooManyArgs );
-	CPPUNIT_TEST( testSubstrBadTooManyArgs );
-	CPPUNIT_TEST( testSubstrStringOffset );
-	CPPUNIT_TEST( testSubstrBinaryOffset );
-	CPPUNIT_TEST( testSubstrBadOffset );
-	CPPUNIT_TEST( testSubstrStringBad );
-	CPPUNIT_TEST( testSubstrStringInvalid );
-	CPPUNIT_TEST( testSubstrStringHigh );
-	CPPUNIT_TEST( testSubstrStringOffsetLength );
-	CPPUNIT_TEST( testSubstrBinaryOffsetLength );
-	CPPUNIT_TEST( testSubstrStringOffsetBad );
-	CPPUNIT_TEST( testSubstrStringOffsetToOffset );
-	CPPUNIT_TEST( testSubstrBinaryOffsetToOffset );
-	CPPUNIT_TEST( testSubstrStringRangeInverted );
-	CPPUNIT_TEST( testSubstrBinaryRangeInverted );
-	CPPUNIT_TEST( testSubstrStringOffsetBadOffset );
-	CPPUNIT_TEST( testSubstrStringOffsetToBad );
-	CPPUNIT_TEST( testSubstrRangeInvalidStart );
-	CPPUNIT_TEST( testSubstrRangeInvalidEnd );
-
-	CPPUNIT_TEST( testSplitNotEnoughArgs );
-	CPPUNIT_TEST( testSplitTooManyArgs );
-	CPPUNIT_TEST( testSplitBadString );
-	CPPUNIT_TEST( testSplitStringBad );
-	CPPUNIT_TEST( testSplitStringEmpty );
-	CPPUNIT_TEST( testSplitStringStringBad );
-	CPPUNIT_TEST( testSplitStringStringNegative );
-	CPPUNIT_TEST( testSplitSingleNormal );
-	CPPUNIT_TEST( testSplitSingleStart );
-	CPPUNIT_TEST( testSplitSingleEnd );
-	CPPUNIT_TEST( testSplitSingleNowhere );
-	CPPUNIT_TEST( testSplitMultiNormal );
-	CPPUNIT_TEST( testSplitMultiStart );
-	CPPUNIT_TEST( testSplitMultiEnd );
-	CPPUNIT_TEST( testSplitMultiNowhere );
-	CPPUNIT_TEST( testSplitMultiLonger );
-	CPPUNIT_TEST( testSplitLimitZero );
-	CPPUNIT_TEST( testSplitLimit );
-	CPPUNIT_TEST( testSplitLimitGreater );
-
-	CPPUNIT_TEST( testSWNotEnoughArgs );
-	CPPUNIT_TEST( testSWTooManyArgs );
-	CPPUNIT_TEST( testSWStringYes );
-	CPPUNIT_TEST( testSWStringYesEqual );
-	CPPUNIT_TEST( testSWStringYesEmpty );
-	CPPUNIT_TEST( testSWStringNoShorter );
-	CPPUNIT_TEST( testSWStringNoLonger );
-	CPPUNIT_TEST( testSWBinaryYes );
-	CPPUNIT_TEST( testSWBinaryYesEqual );
-	CPPUNIT_TEST( testSWBinaryYesEmpty );
-	CPPUNIT_TEST( testSWBinaryNoShorter );
-	CPPUNIT_TEST( testSWBinaryNoLonger );
-	CPPUNIT_TEST( testSWWordString );
-	CPPUNIT_TEST( testSWStringWord );
-	CPPUNIT_TEST( testSWStringBad );
-	CPPUNIT_TEST( testSWBadString );
-
-	CPPUNIT_TEST( testEWNotEnoughArgs );
-	CPPUNIT_TEST( testEWTooManyArgs );
-	CPPUNIT_TEST( testEWStringYes );
-	CPPUNIT_TEST( testEWStringYesEqual );
-	CPPUNIT_TEST( testEWStringYesEmpty );
-	CPPUNIT_TEST( testEWStringNoShorter );
-	CPPUNIT_TEST( testEWStringNoLonger );
-	CPPUNIT_TEST( testEWBinaryYes );
-	CPPUNIT_TEST( testEWBinaryYesEqual );
-	CPPUNIT_TEST( testEWBinaryYesEmpty );
-	CPPUNIT_TEST( testEWBinaryNoShorter );
-	CPPUNIT_TEST( testEWBinaryNoLonger );
-	CPPUNIT_TEST( testEWWordString );
-	CPPUNIT_TEST( testEWStringWord );
-	CPPUNIT_TEST( testEWStringBad );
-	CPPUNIT_TEST( testEWBadString );
-
-	CPPUNIT_TEST_SUITE_END( );
-
-   public:
-	// -concat
-	void testConcatNoArgs( );
-	void testConcatBadArgs( );
-	void testConcatOneString( );
-	void testConcatStrings( );
-	void testConcatStringWord( );
-	void testConcatStringNumeric( );
-	void testConcatStringBinary( );
-	void testConcatOneBinary( );
-	void testConcatBinary( );
-
-	// -substr
-	void testSubstrNotEnoughArgs( );	// Not enough arguments
-	void testSubstrStringNotEnoughArgs( );	// String
-	void testSubstrBinaryNotEnoughArgs( );	// Binary
-	void testSubstrStringTooManyArgs( );	// String + too many arguments
-	void testSubstrBinaryTooManyArgs( );	// Binary + too many arguments
-	void testSubstrBadTooManyArgs( );	// Invalid argument + too many arguments
-	void testSubstrStringOffset( );		// String and offset arguments
-	void testSubstrBinaryOffset( );		// Binary data and offset arguments
-	void testSubstrBadOffset( );		// Invalid argument + offset
-	void testSubstrStringBad( );		// String + invalid argument
-	void testSubstrStringInvalid( );	// String, offset < 0
-	void testSubstrStringHigh( );		// String, offset > length
-	void testSubstrStringOffsetLength( );	// String, offset and length arguments
-	void testSubstrBinaryOffsetLength( );	// Binary, offset and length arguments
-	void testSubstrStringOffsetBad( );	// String and offset followed by invalid argument
-	void testSubstrStringOffsetToOffset( );	// String, range mode
-	void testSubstrBinaryOffsetToOffset( );	// Binary, range mode
-	void testSubstrStringRangeInverted( );	// String, range mode, end < start
-	void testSubstrBinaryRangeInverted( );	// Binary, range mode, end < start
-	void testSubstrStringOffsetBadOffset( );
-						// String, range mode, wrong "to" argument
-	void testSubstrStringOffsetToBad( );	// String, range mode, wrong end argument
-	void testSubstrRangeInvalidStart( );	// String, range mode, start < 0
-	void testSubstrRangeInvalidEnd( );	// String, range mode, end < 0
-
-	// -str-split
-	void testSplitNotEnoughArgs( );		// Not enough arguments
-	void testSplitTooManyArgs( );		// Too many arguments
-	void testSplitBadString( );		// Invalid argument, string
-	void testSplitStringBad( );		// String, invalid argument
-	void testSplitStringEmpty( );		// String, empty string
-	void testSplitStringStringBad( );	// String, string, invalid argument
-	void testSplitStringStringNegative( );	// String, string, negative integer
-	void testSplitSingleNormal( );		// Single-character delimiter, inside string
-	void testSplitSingleStart( );		// Single-character delimiter, start of string
-	void testSplitSingleEnd( );		// Single-character delimiter, end of string
-	void testSplitSingleNowhere( );		// Single-character delimiter, not in string
-	void testSplitMultiNormal( );		// Multi-character delimiter, inside string
-	void testSplitMultiStart( );		// Multi-character delimiter, start of string
-	void testSplitMultiEnd( );		// Multi-character delimiter, end of string
-	void testSplitMultiNowhere( );		// Multi-character delimiter, not in string
-	void testSplitMultiLonger( );		// Multi-character delimiter, longer than string
-	void testSplitLimitZero( );		// With limit set to 0
-	void testSplitLimit( );			// With a non-zero limit
-	void testSplitLimitGreater( );		// With a limit higher than the result count
-
-	// -starts-with
-	void testSWNotEnoughArgs( );
-	void testSWTooManyArgs( );
-	void testSWStringYes( );
-	void testSWStringYesEqual( );
-	void testSWStringYesEmpty( );
-	void testSWStringNoShorter( );
-	void testSWStringNoLonger( );
-	void testSWBinaryYes( );
-	void testSWBinaryYesEqual( );
-	void testSWBinaryYesEmpty( );
-	void testSWBinaryNoShorter( );
-	void testSWBinaryNoLonger( );
-	void testSWWordString( );
-	void testSWStringWord( );
-	void testSWStringBad( );
-	void testSWBadString( );
-
-	// -ends-with
-	void testEWNotEnoughArgs( );
-	void testEWTooManyArgs( );
-	void testEWStringYes( );
-	void testEWStringYesEqual( );
-	void testEWStringYesEmpty( );
-	void testEWStringNoShorter( );
-	void testEWStringNoLonger( );
-	void testEWBinaryYes( );
-	void testEWBinaryYesEqual( );
-	void testEWBinaryYesEmpty( );
-	void testEWBinaryNoShorter( );
-	void testEWBinaryNoLonger( );
-	void testEWWordString( );
-	void testEWStringWord( );
-	void testEWStringBad( );
-	void testEWBadString( );
-};
-CPPUNIT_TEST_SUITE_REGISTRATION( SRDPreprocCmdStringsTest );
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdStringsTest::testConcatNoArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -concat )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 11 );
-	CPPUNIT_ASSERT( check( "\"\"" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testConcatBadArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -concat ( nope ) [ 01 ] )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "binary array, text or numeric argument expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 11 );
-	CPPUNIT_ASSERT( check( "[ 01 ]" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testConcatOneString( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -concat \"string\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "\"string\"" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testConcatStrings( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -concat \"str\" \"ing\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "\"string\"" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testConcatStringWord( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -concat \"str\" ing )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "\"string\"" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testConcatStringNumeric( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -concat \"i\" 2 \"l\" ( -to-long 2 ) \"f\" 1.2 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "\"i2l2f1.2\"" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testConcatStringBinary( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -concat \"string\"\n[ 01 ] )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "text or numeric argument expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 2 , 1 );
-	CPPUNIT_ASSERT( check( "\"string\"" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testConcatOneBinary( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -concat [ ] )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "[ ]" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testConcatBinary( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -concat [ 01 ] [] [ 02 ] )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "[ 01 02 ]" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdStringsTest::testSubstrNotEnoughArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -substr )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 11 );
-	CPPUNIT_ASSERT( check( "\"\"" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSubstrStringNotEnoughArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -substr \"abcdef\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 20 );
-	CPPUNIT_ASSERT( check( "\"\"" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSubstrBinaryNotEnoughArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -substr [ 01 02 03 04 05 06 ] )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 33 );
-	CPPUNIT_ASSERT( check( "[]" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSubstrStringTooManyArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -substr \"abcdef\" 1 to 2 blah )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "too many arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 27 );
-	CPPUNIT_ASSERT( check( "\"bc\"" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSubstrBinaryTooManyArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -substr [ 01 02 03 04 05 06 ] 1 to 2 blah )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "too many arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 40 );
-	CPPUNIT_ASSERT( check( "[]" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSubstrBadTooManyArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -substr -12 1 to 2 blah )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "binary array or text argument expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 11 );
-	CPPUNIT_ASSERT( check( "\"\"" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSubstrStringOffset( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -substr \"abcdef\" 3 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "\"def\"" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSubstrBinaryOffset( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -substr [ 01 02 03 04 05 06 ] 3 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "[ 04 05 06 ]" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSubstrBadOffset( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -substr 12 3 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "binary array or text argument expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 11 );
-	CPPUNIT_ASSERT( check( "\"\"" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSubstrStringBad( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -substr \"\" \"\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "integer argument expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 14 );
-	CPPUNIT_ASSERT( check( "\"\"" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSubstrStringInvalid( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -substr \"abcdef\" -1 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "invalid argument value" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 20 );
-	CPPUNIT_ASSERT( check( "\"\"" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSubstrStringHigh( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -substr \"abcdef\" 7 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "\"\"" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSubstrStringOffsetLength( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -substr \"abcdef\" 2 3 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "\"cde\"" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSubstrBinaryOffsetLength( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -substr [ 01 02 03 04 05 06 ] 2 3 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "[ 03 04 05 ]" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSubstrStringOffsetBad( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -substr \"abcdef\" 2 nope )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "'to' or integer argument expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 22 );
-	CPPUNIT_ASSERT( check( "\"\"" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSubstrStringOffsetToOffset( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -substr \"abcdef\" 2 to 3 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "\"cd\"" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSubstrBinaryOffsetToOffset( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -substr [ 01 02 03 04 05 06 ] 2 to 3 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "[ 03 04 ]" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSubstrStringRangeInverted( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -substr \"abcdef\" 3 to 2 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "\"\"" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSubstrBinaryRangeInverted( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -substr [ 01 02 03 04 05 06 ] 3 to 2 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "[ ]" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSubstrStringOffsetBadOffset( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -substr \"abcdef\" 2 ot 3 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "'to' or integer argument expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 22 );
-	CPPUNIT_ASSERT( check( "\"\"" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSubstrStringOffsetToBad( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -substr \"abcdef\" 2 to meh )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "integer argument expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 25 );
-	CPPUNIT_ASSERT( check( "\"\"" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSubstrRangeInvalidStart( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -substr \"abcdef\" -2 to 12 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "invalid argument value" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 20 );
-	CPPUNIT_ASSERT( check( "\"\"" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSubstrRangeInvalidEnd( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -substr \"abcdef\" 2 to -2 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "invalid argument value" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 25 );
-	CPPUNIT_ASSERT( check( "\"\"" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdStringsTest::testSplitNotEnoughArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -str-split \"x\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 18 );
-	CPPUNIT_ASSERT( check( "\"\"" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSplitTooManyArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -str-split \"a\" \"b\" 12 a b c )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "too many arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 25 );
-	CPPUNIT_ASSERT( check( "\"b\"" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSplitBadString( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -str-split 12 \"x\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "text argument expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 14 );
-	CPPUNIT_ASSERT( check( "\"\"" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSplitStringBad( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -str-split \"x\" 12 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "text argument expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 18 );
-	CPPUNIT_ASSERT( check( "\"\"" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSplitStringEmpty( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -str-split \"\" \"...\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "invalid argument value" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 14 );
-	CPPUNIT_ASSERT( check( "\"\"" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSplitStringStringBad( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -str-split \"a\" \"...\" x )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "integer argument or end of list expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 24 );
-	CPPUNIT_ASSERT( check( "\"...\"" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSplitStringStringNegative( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -str-split \"a\" \"bab\" -1 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "invalid argument value" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 24 );
-	CPPUNIT_ASSERT( check( "\"b\" \"b\"" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSplitSingleNormal( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -str-split \"a\" \"babaab\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "\"b\" \"b\" \"\" \"b\"" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSplitSingleStart( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -str-split \"a\" \"ab\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "\"\" \"b\"" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSplitSingleEnd( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -str-split \"a\" \"ba\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "\"b\" \"\"" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSplitSingleNowhere( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -str-split \"a\" \"nope\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "\"nope\"" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSplitMultiNormal( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -str-split \"aba\" \"babaxabaababa\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "\"b\" \"x\" \"\" \"ba\"" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSplitMultiStart( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -str-split \"aba\" \"abab\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "\"\" \"b\"" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSplitMultiEnd( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -str-split \"aba\" \"baba\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "\"b\" \"\"" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSplitMultiNowhere( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -str-split \"aba\" \"nope\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "\"nope\"" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSplitMultiLonger( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -str-split \"moomoo\" \"nope\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "\"nope\"" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSplitLimitZero( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -str-split \"x\" \"abababa\" 0 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "\"abababa\"" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSplitLimit( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -str-split \"b\" \"abababa\" 2 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "\"a\" \"a\" \"aba\"" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSplitLimitGreater( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -str-split \"b\" \"abababa\" 12 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "\"a\" \"a\" \"a\" \"a\"" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdStringsTest::testSWNotEnoughArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -starts-with \"x\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 20 );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSWTooManyArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -starts-with x y z )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "too many arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 20 );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSWStringYes( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -starts-with \"abc\" \"abcdef\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSWStringYesEqual( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -starts-with \"abc\" \"abc\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSWStringYesEmpty( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -starts-with \"\" \"abc\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSWStringNoShorter( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -starts-with \"abc\" \"defg\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSWStringNoLonger( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -starts-with \"defg\" \"abc\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSWBinaryYes( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -starts-with [ 00 ] [ 00 01 02 ] )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSWBinaryYesEqual( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -starts-with [ 00 01 02 ] [ 00 01 02 ] )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSWBinaryYesEmpty( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -starts-with [ ] [ 00 01 02 ] )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSWBinaryNoShorter( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -starts-with [ 01 ] [ 00 01 02 ] )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSWBinaryNoLonger( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -starts-with [ 00 01 02 ] [ 00 ] )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSWWordString( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -starts-with abc \"abc d\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSWStringWord( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -starts-with \"abc\" abc-d )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSWStringBad( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -starts-with \"abc\" 12 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "text argument expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 22 );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testSWBadString( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -starts-with 12 \"abc\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "binary array or text argument expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 16 );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdStringsTest::testEWNotEnoughArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -ends-with \"x\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 18 );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testEWTooManyArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -ends-with x y z )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "too many arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 18 );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testEWStringYes( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -ends-with \"def\" \"abcdef\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testEWStringYesEqual( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -ends-with \"abc\" \"abc\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testEWStringYesEmpty( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -ends-with \"\" \"abc\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testEWStringNoShorter( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -ends-with \"abc\" \"defg\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testEWStringNoLonger( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -ends-with \"defg\" \"abc\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testEWBinaryYes( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -ends-with [ 02 ] [ 00 01 02 ] )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testEWBinaryYesEqual( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -ends-with [ 00 01 02 ] [ 00 01 02 ] )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testEWBinaryYesEmpty( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -ends-with [ ] [ 00 01 02 ] )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testEWBinaryNoShorter( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -ends-with [ 01 ] [ 00 01 02 ] )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testEWBinaryNoLonger( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -ends-with [ 00 01 02 ] [ 00 ] )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testEWWordString( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -ends-with d \"abc d\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testEWStringWord( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -ends-with \"c-d\" abc-d )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testEWStringBad( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -ends-with \"abc\" 12 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "text argument expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 20 );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
-
-void SRDPreprocCmdStringsTest::testEWBadString( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -ends-with 12 \"abc\" )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "binary array or text argument expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 14 );
-	CPPUNIT_ASSERT( check( "0" , output ) );
-}
diff --git a/tests/srd-preproc-cmd-variables.cc b/tests/srd-preproc-cmd-variables.cc
deleted file mode 100644
index 5b1b654..0000000
--- a/tests/srd-preproc-cmd-variables.cc
+++ /dev/null
@@ -1,372 +0,0 @@
-#include "srd-preproc-cmd-common.hh"
-
-
-class SRDPreprocCmdVariablesTest : public CppUnit::TestFixture
-{
-	CPPUNIT_TEST_SUITE( SRDPreprocCmdVariablesTest );
-
-	CPPUNIT_TEST( testSetVarNoArgs );
-	CPPUNIT_TEST( testSetVarBadName );
-	CPPUNIT_TEST( testSetVarEmpty );
-	CPPUNIT_TEST( testSetVarBasic );
-	CPPUNIT_TEST( testSetVarList );
-	CPPUNIT_TEST( testSetVarExisting );
-
-	CPPUNIT_TEST( testSetVarsNoNames );
-	CPPUNIT_TEST( testSetVarsBadName );
-	CPPUNIT_TEST( testSetVarsEmpty );
-	CPPUNIT_TEST( testSetVarsMissing );
-	CPPUNIT_TEST( testSetVarsMultiple );
-	CPPUNIT_TEST( testSetVarsRest );
-	CPPUNIT_TEST( testSetVarsRepeatName );
-	CPPUNIT_TEST( testSetVarsExisting );
-	CPPUNIT_TEST( testSetVarsExistingAndRepeated );
-
-	CPPUNIT_TEST( testUnsetNoArgs );
-	CPPUNIT_TEST( testUnset );
-	CPPUNIT_TEST( testUnsetMissing );
-	CPPUNIT_TEST( testUnsetMultiple );
-	CPPUNIT_TEST( testUnsetFromVarBeingUnset );
-
-	CPPUNIT_TEST( testGetEmpty );
-	CPPUNIT_TEST( testGetBadArg );
-	CPPUNIT_TEST( testGetMissing );
-	CPPUNIT_TEST( testGetVar );
-	CPPUNIT_TEST( testGetVars );
-	CPPUNIT_TEST( testGetVarsWithErrors );
-
-	CPPUNIT_TEST( testListVariables );
-	CPPUNIT_TEST( testListVariablesArgs );
-
-	CPPUNIT_TEST_SUITE_END( );
-
-   public:
-	void testSetVarNoArgs( );
-	void testSetVarBadName( );
-	void testSetVarEmpty( );
-	void testSetVarBasic( );
-	void testSetVarList( );
-	void testSetVarExisting( );
-
-	void testSetVarsNoNames( );
-	void testSetVarsBadName( );
-	void testSetVarsEmpty( );
-	void testSetVarsMissing( );
-	void testSetVarsMultiple( );
-	void testSetVarsRest( );
-	void testSetVarsRepeatName( );
-	void testSetVarsExisting( );
-	void testSetVarsExistingAndRepeated( );
-
-	void testUnsetNoArgs( );
-	void testUnset( );
-	void testUnsetMissing( );
-	void testUnsetMultiple( );
-	void testUnsetFromVarBeingUnset( );
-
-	void testGetEmpty( );
-	void testGetBadArg( );
-	void testGetMissing( );
-	void testGetVar( );
-	void testGetVars( );
-	void testGetVarsWithErrors( );
-
-	void testListVariables( );
-	void testListVariablesArgs( );
-};
-CPPUNIT_TEST_SUITE_REGISTRATION( SRDPreprocCmdVariablesTest );
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdVariablesTest::testSetVarNoArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -set )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 8 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdVariablesTest::testSetVarBadName( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -set 1 )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "word or list expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 8 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdVariablesTest::testSetVarEmpty( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -set x )\n$x" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdVariablesTest::testSetVarBasic( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -set x y )\n$x" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "y" , output ) );
-}
-
-void SRDPreprocCmdVariablesTest::testSetVarList( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -set x y z )\n$x" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "y z" , output ) );
-}
-
-void SRDPreprocCmdVariablesTest::testSetVarExisting( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -set x a )\n$x\n( -set x b )\n$x" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "duplicate variable name" , 3 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 3 , 8 );
-	CPPUNIT_ASSERT( check( "a a" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdVariablesTest::testSetVarsNoNames( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -set ( ) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "no variable names" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 10 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdVariablesTest::testSetVarsBadName( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -set ( 1 ( ) ) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 4u , errors.size( ) );
-	M_CKERR_( 0 , "word expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 10 );
-	M_CKERR_( 2 , "word expected" , 1 , 3 );
-	M_CKERR_( 3 , "previous error cause" , 1 , 12 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdVariablesTest::testSetVarsEmpty( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -set ( a b ) )\n( $b ) ( $a )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "()()" , output ) );
-}
-
-void SRDPreprocCmdVariablesTest::testSetVarsMissing( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -set ( a b ) a )\n( $b ) ( $a )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "( ) ( a )" , output ) );
-}
-
-void SRDPreprocCmdVariablesTest::testSetVarsMultiple( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -set ( a b ) a b )\n( $b ) ( $a )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "( b ) ( a )" , output ) );
-}
-
-void SRDPreprocCmdVariablesTest::testSetVarsRest( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -set ( a b ) a b c )\n( $b ) ( $a )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "( b c ) ( a )" , output ) );
-}
-
-void SRDPreprocCmdVariablesTest::testSetVarsRepeatName( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -set ( a a ) a b c )\n( $a )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 3u , errors.size( ) );
-	M_CKERR_( 0 , "duplicate variable name" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 10 );
-	M_CKERR_( 2 , "unknown variable" , 2 , 3 );
-	CPPUNIT_ASSERT( check( "( )" , output ) );
-}
-
-void SRDPreprocCmdVariablesTest::testSetVarsExisting( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -set b x )\n( -set ( a b ) u v )\n( $a )( $b )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 3u , errors.size( ) );
-	M_CKERR_( 0 , "duplicate variable name" , 2 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 2 , 12 );
-	M_CKERR_( 2 , "unknown variable" , 3 , 3 );
-	CPPUNIT_ASSERT( check( "( )( x )" , output ) );
-}
-
-void SRDPreprocCmdVariablesTest::testSetVarsExistingAndRepeated( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -set b x )\n( -set ( a b b a ) u v )\n( $a )( $b )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 5u , errors.size( ) );
-	M_CKERR_( 0 , "duplicate variable name" , 2 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 2 , 10 );
-	M_CKERR_( 2 , "duplicate variable name" , 2 , 3 );
-	M_CKERR_( 3 , "previous error cause" , 2 , 12 );
-	M_CKERR_( 4 , "unknown variable" , 3 , 3 );
-	CPPUNIT_ASSERT( check( "( )( x )" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdVariablesTest::testUnsetNoArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -unset ) " , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdVariablesTest::testUnset( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -set a 1 )\n$a\n( -unset a )\n$a" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , errors.size( ) );
-	M_CKERR_( 0 , "unknown variable" , 4 , 1 );
-	CPPUNIT_ASSERT( check( "1" , output ) );
-}
-
-void SRDPreprocCmdVariablesTest::testUnsetMissing( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -unset a )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdVariablesTest::testUnsetMultiple( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				  "( -set ( a b c ) 1 2 3)\n"
-				  "( -unset a c )\n"
-				  "( $a $b $c )" ,
-				  errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , errors.size( ) );
-	M_CKERR_( 0 , "unknown variable" , 3 , 3 );
-	M_CKERR_( 1 , "unknown variable" , 3 , 9 );
-	CPPUNIT_ASSERT( check( "( 2 )" , output ) );
-}
-
-void SRDPreprocCmdVariablesTest::testUnsetFromVarBeingUnset( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				  "( -set ( c b a ) d c a b)\n"
-				  "( -unset $a $b )\n"
-				  "( $a $b $c )" ,
-				  errors ) );
-	CPPUNIT_ASSERT_EQUAL( 3u , errors.size( ) );
-	M_CKERR_( 0 , "unknown variable" , 2 , 13 );
-	M_CKERR_( 1 , "unknown variable" , 3 , 3 );
-	M_CKERR_( 2 , "unknown variable" , 3 , 6 );
-	CPPUNIT_ASSERT( check( "( d )" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdVariablesTest::testGetEmpty( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -get )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdVariablesTest::testGetBadArg( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -get 1 ( ) )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 4u , errors.size( ) );
-	M_CKERR_( 0 , "word expected" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 8 );
-	M_CKERR_( 2 , "word expected" , 1 , 3 );
-	M_CKERR_( 3 , "previous error cause" , 1 , 10 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdVariablesTest::testGetMissing( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -get a )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "unknown variable" , 1 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 1 , 8 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCmdVariablesTest::testGetVar( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "(-set a x)\n( -get a )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "x" , output ) );
-}
-
-void SRDPreprocCmdVariablesTest::testGetVars( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "(-set ( a b c ) x y z w )\n( -get c b a )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "z w y x" , output ) );
-}
-
-void SRDPreprocCmdVariablesTest::testGetVarsWithErrors( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "(-set ( a b ) x y )\n( -get b c a )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "unknown variable" , 2 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 2 , 10 );
-	CPPUNIT_ASSERT( check( "y x" , output ) );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCmdVariablesTest::testListVariables( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"( -set x )\n"
-				"( -set-macro y ( ( ) ) )\n"
-				"( -set f (-raw (() ((-ls-variables))) ))\n"
-				"( -bless f )\n"
-				"( ( -ls-variables ) )\n"
-				"( -scope\n"
-					"( -unset x )\n"
-					"( ( -ls-variables ) )\n"
-				")\n"
-				"($f)\n"
-				, errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "( x f ) ( f ) ( f )" , output ) );
-}
-
-void SRDPreprocCmdVariablesTest::testListVariablesArgs( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"( -set x )\n"
-				"( -ls-variables blah )\n"
-				, errors ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-	M_CKERR_( 0 , "too many arguments" , 2 , 3 );
-	M_CKERR_( 1 , "previous error cause" , 2 , 17 );
-	CPPUNIT_ASSERT( check( "x" , output ) );
-}
diff --git a/tests/srd-preproc-core.cc b/tests/srd-preproc-core.cc
deleted file mode 100644
index 1395f3b..0000000
--- a/tests/srd-preproc-core.cc
+++ /dev/null
@@ -1,245 +0,0 @@
-#include <lw/lib/SRDPreproc.hh>
-#include <lw/lib/SRDText.hh>
-#include <lw/lib/SRDIO.hh>
-#include <cppunit/extensions/HelperMacros.h>
-using namespace lw;
-
-
-class SRDPreprocCoreTest : public CppUnit::TestFixture
-{
-	CPPUNIT_TEST_SUITE( SRDPreprocCoreTest );
-		CPPUNIT_TEST( testEmptyInput );
-		CPPUNIT_TEST( testBasicInput );
-		CPPUNIT_TEST( testCommentsSkipped );
-		CPPUNIT_TEST( testCommandWordInInput );
-		CPPUNIT_TEST( testBadCommand );
-		CPPUNIT_TEST( testBadVariable );
-		CPPUNIT_TEST( testUnterminatedLists );
-		CPPUNIT_TEST( testTooManyErrorsInside );
-		CPPUNIT_TEST( testTooManyErrorsAtEnd );
-	CPPUNIT_TEST_SUITE_END( );
-
-   public:
-	void testEmptyInput( );
-	void testBasicInput( );
-	void testCommentsSkipped( );
-	void testCommandWordInInput( );
-	void testBadCommand( );
-	void testBadVariable( );
-	void testUnterminatedLists( );
-	void testTooManyErrorsInside( );
-	void testTooManyErrorsAtEnd( );
-};
-CPPUNIT_TEST_SUITE_REGISTRATION( SRDPreprocCoreTest );
-
-/*----------------------------------------------------------------------------*/
-
-// M_PRINTERR_( index ) - Print an error message
-#define M_PRINTERR_( IDX ) \
-	do { \
-		auto const& _e( errors[ IDX ] ); \
-		char err[ _e.error( ).size( ) + 1 ]; \
-		err[ sizeof( err ) - 1 ] = 0; \
-		memcpy( err , _e.error( ).data( ) , \
-		       sizeof( err ) - 1 ); \
-		printf( "ERR %s l. %u c. %lu\n" , err , \
-		       _e.location( ).line( ) , \
-		       _e.location( ).character( ) ); \
-	} while ( 0 )
-
-// M_CKERR_( index , string , line , character ) - Check an error
-#define M_CKERR_( IDX , STR , L , C ) \
-	do { \
-		auto const& _e( errors[ IDX ] ); \
-		CPPUNIT_ASSERT( T_String( STR ) == _e.error( ) ); \
-		CPPUNIT_ASSERT_EQUAL( uint32_t( L ) , \
-				     _e.location( ).line( ) ); \
-		CPPUNIT_ASSERT_EQUAL( size_t( C ) , \
-				     _e.location( ).character( ) ); \
-	} while ( 0 )
-
-namespace {
-
-T_SRDList process(
-		char const* const input ,
-		T_SRDErrors& errors ,
-		const bool clearFlushToken = true )
-{
-	T_SRDMemoryTarget mt( false );
-	mt.clearFlushToken( clearFlushToken );
-	mt.start( errors );
-
-	T_SRDPreprocessorConfig cmd;
-	cmd.addBuiltinCommands( );
-	T_SRDPreprocessor pp( cmd , mt );
-	T_SRDLexer lexer( T_String( "test" ) , errors , pp );
-	pp.start( errors );
-	char const* ptr = input;
-	while ( *ptr != 0 ) {
-		lexer.processCharacter( *ptr ++ );
-	}
-	lexer.processEnd( );
-	mt.end( errors );
-
-	return mt.list( );
-}
-
-bool checkMatch( T_SRDList const& expected , T_SRDList const& actual )
-{
-	const uint32_t nExpected( expected.size( ) );
-	const uint32_t nActual( actual.size( ) );
-
-	bool ok( nExpected == nActual );
-	const uint32_t nCheck( std::min( nExpected , nActual ) );
-	for ( uint32_t i = 0 ; i < nCheck ; i ++ ) {
-		T_SRDToken const& tExpected( expected[ i ] );
-		T_SRDToken const& tActual( actual[ i ] );
-		if ( tExpected.type( ) != tActual.type( ) ) {
-			std::cerr << "Expected token at "
-				  << tExpected.location( ).line( ) << ":"
-				  << tExpected.location( ).character( )
-				  << " has type " << int( tExpected.type( ) ) << "; actual token has type "
-				  << int( tActual.type( ) ) << "\n";
-			ok = false;
-		} else if ( tExpected.stringValue( ) != tActual.stringValue( ) ) {
-			std::cerr << "Expected token at "
-				  << tExpected.location( ).line( ) << ":"
-				  << tExpected.location( ).character( )
-				  << " has different text\n";
-			ok = false;
-		}
-	}
-
-	if ( nExpected != nActual ) {
-		std::cerr << "List size mismatch (" << nExpected << " expected, "
-			  << nActual << " found)\n";
-	}
-	return ok;
-}
-
-bool check( char const* expected , T_SRDList const& actual )
-{
-	T_SRDMemoryTarget mt( false );
-	T_SRDErrors errors;
-	T_SRDLexer lexer( T_String( "expected" ) , errors , mt );
-	mt.start( errors );
-	char const* ptr = expected;
-	while ( *ptr != 0 ) {
-		lexer.processCharacter( *ptr ++ );
-	}
-	lexer.processEnd( );
-
-	return checkMatch( mt.list( ) , actual );
-}
-
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocCoreTest::testEmptyInput( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCoreTest::testBasicInput( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "this is a simple test 123 \"yes\" ( a test )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "this is a simple test 123 \"yes\" ( a test )" , output ) );
-}
-
-void SRDPreprocCoreTest::testCommentsSkipped( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "a {comment!} ( is #skipped!\n)" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "a ( is )" , output ) );
-}
-
-void SRDPreprocCoreTest::testCommandWordInInput( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "-blah" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
-	CPPUNIT_ASSERT( check( "-blah" , output ) );
-}
-
-void SRDPreprocCoreTest::testBadCommand( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( -blah )" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , errors.size( ) );
-	M_CKERR_( 0 , "unknown command" , 1 , 3 );
-	CPPUNIT_ASSERT( check( "( -blah )" , output ) );
-}
-
-void SRDPreprocCoreTest::testBadVariable( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "$blah does not exist" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , errors.size( ) );
-	M_CKERR_( 0 , "unknown variable" , 1 , 1 );
-	CPPUNIT_ASSERT( check( "does not exist" , output ) );
-}
-
-void SRDPreprocCoreTest::testUnterminatedLists( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process( "( ( ) ( (" , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( 3 ) , errors.size( ) );
-	M_CKERR_( 0 , "unterminated list" , 1 , 1 );
-	M_CKERR_( 1 , "unterminated list" , 1 , 7 );
-	M_CKERR_( 2 , "unterminated list" , 1 , 9 );
-	CPPUNIT_ASSERT( check( "( ( ) ( ( ) ) )" , output ) );
-}
-
-namespace {
-
-T_StringBuilder RepeatError_( char const* string )
-{
-	T_StringBuilder sb;
-	for ( uint32_t i = 0 ; i < T_SRDErrors::MAX_ERRORS * 2 ; i ++ ) {
-		if ( i > 0 ) {
-			sb << ' ';
-		}
-		sb << string;
-	}
-	sb << " x" << '\0';
-	return sb;
-}
-
-}
-
-void SRDPreprocCoreTest::testTooManyErrorsInside( )
-{
-	T_StringBuilder input( RepeatError_( "$x" ) );
-	T_SRDErrors errors;
-	T_SRDList output( process( input.data( ) , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( T_SRDErrors::MAX_ERRORS + 1 ) , errors.size( ) );
-	M_CKERR_( T_SRDErrors::MAX_ERRORS , "too many errors" , 1 , T_SRDErrors::MAX_ERRORS * 3 - 2 );
-	CPPUNIT_ASSERT( check( "" , output ) );
-}
-
-void SRDPreprocCoreTest::testTooManyErrorsAtEnd( )
-{
-	T_StringBuilder input( RepeatError_( "(" ) );
-	T_StringBuilder expectedOutput;
-	for ( uint32_t i = 0 ; i < T_SRDErrors::MAX_ERRORS * 2 ; i ++ ) {
-		expectedOutput << '(';
-	}
-	expectedOutput << 'x';
-	for ( uint32_t i = 0 ; i < T_SRDErrors::MAX_ERRORS * 2 ; i ++ ) {
-		expectedOutput << ')';
-	}
-	expectedOutput << '\0';
-
-	T_SRDErrors errors;
-	T_SRDList output( process( input.data( ) , errors ) );
-	CPPUNIT_ASSERT_EQUAL( uint32_t( T_SRDErrors::MAX_ERRORS + 1 ) , errors.size( ) );
-	M_CKERR_( T_SRDErrors::MAX_ERRORS , "too many errors" , 1 , T_SRDErrors::MAX_ERRORS * 2 - 1 );
-	CPPUNIT_ASSERT( check( expectedOutput.data( ) , output ) );
-}
diff --git a/tests/srd-preproc-location.hh b/tests/srd-preproc-location.hh
deleted file mode 100644
index bd66621..0000000
--- a/tests/srd-preproc-location.hh
+++ /dev/null
@@ -1,133 +0,0 @@
-#ifndef TESTS_SRDPREPROCLOCATION_H_
-#define TESTS_SRDPREPROCLOCATION_H_
-
-#include <lw/lib/SRDPreproc.hh>
-#include <lw/lib/SRDText.hh>
-#include <lw/lib/SRDIO.hh>
-#include <lw/lib/MemoryStreams.hh>
-#include <cppunit/extensions/HelperMacros.h>
-using namespace lw;
-
-
-namespace {
-
-inline T_SRDLocationChaining const* NextChain_(
-		T_SRDLocation const* from ) noexcept
-{
-	return (from && from->isChained( ) ) ? &from->chaining( ) : nullptr;
-}
-
-uint32_t LocationDepth_(
-		const RPC_SRDLocation location ) noexcept
-{
-	uint32_t depth( 0 );
-	auto lc( NextChain_( location ) );
-	while ( lc ) {
-		depth ++;
-		lc = NextChain_( RPC_SRDLocation( lc->location ) );
-	}
-	return depth;
-}
-
-uint32_t ErrorDepth_(
-		T_SRDErrors const& errors ,
-		const size_t index ) noexcept
-{
-	auto const& error( errors[ index ] );
-	return LocationDepth_( &error.location( ) );
-}
-
-uint32_t TokenDepth_(
-		T_SRDList const& tokens ,
-		const size_t index ) noexcept
-{
-	auto const& tok( tokens[ index ] );
-	assert( tok.hasLocation( ) );
-	return LocationDepth_( &tok.location( ) );
-}
-
-T_SRDLocationChaining const& GetChain_(
-		RPC_SRDLocation const& top ,
-		uint32_t depth ) noexcept
-{
-	auto lc( NextChain_( top ) );
-	assert( lc );
-	while ( depth ) {
-		depth --;
-		lc = NextChain_( RPC_SRDLocation( lc->location ) );
-		assert( lc );
-	}
-	return *lc;
-}
-
-void PrintLoc_( RPC_SRDLocation location ) noexcept
-{
-	printf( "at %s, l. %d c. %lu\n" , location->source( ).toOSString( ).data( ) ,
-			location->line( ) , location->character( ) );
-	if ( location->isChained( ) ) {
-		auto const& chain( location->chaining( ) );
-		printf( "\tChain type %d, depth %d, " ,
-				int( chain.circumstances ) , chain.depth );
-		PrintLoc_( RPC_SRDLocation( chain.location ) );
-	}
-}
-
-}
-
-#define M_CKTOKDEPTH_( IDX , DEPTH ) \
-	CPPUNIT_ASSERT_EQUAL( uint32_t( DEPTH ) , TokenDepth_( output , IDX ) )
-
-#define M_CKTOKLOC_( IDX , NAME , LINE , CHAR ) \
-	do { \
-		auto const& loc( output[ IDX ].location( ) ); \
-		CPPUNIT_ASSERT( T_String{ NAME } == loc.source( ) ); \
-		CPPUNIT_ASSERT_EQUAL( uint32_t( LINE ) , loc.line( ) ); \
-		CPPUNIT_ASSERT_EQUAL( size_t( CHAR ) , loc.character( ) ); \
-	} while ( 0 )
-
-#define M_CKTOKFULL_( IDX , NAME , LINE , CHAR , DEPTH ) \
-	do { \
-		auto const& loc( output[ IDX ].location( ) ); \
-		CPPUNIT_ASSERT( T_String{ NAME } == loc.source( ) ); \
-		CPPUNIT_ASSERT_EQUAL( uint32_t( LINE ) , loc.line( ) ); \
-		CPPUNIT_ASSERT_EQUAL( size_t( CHAR ) , loc.character( ) ); \
-		M_CKTOKDEPTH_( IDX , DEPTH ); \
-	} while ( 0 )
-
-#define M_CKTOKCHAIN_( IDX , DEPTH , HOW , NAME , LINE , CHAR , REC ) \
-	do { \
-		auto const& chain( GetChain_( &output[ IDX ].location( ) , DEPTH ) ); \
-		CPPUNIT_ASSERT( E_SRDLocationChaining::HOW == chain.circumstances ); \
-		CPPUNIT_ASSERT_EQUAL( uint32_t( REC ) , chain.depth ); \
-		CPPUNIT_ASSERT( T_String{ NAME } == chain.location->source( ) ); \
-		CPPUNIT_ASSERT_EQUAL( uint32_t( LINE ) , chain.location->line( ) ); \
-		CPPUNIT_ASSERT_EQUAL( size_t( CHAR ) , chain.location->character( ) ); \
-	} while ( 0 )
-
-
-#define M_CKERRDEPTH_( IDX , DEPTH ) \
-	CPPUNIT_ASSERT_EQUAL( uint32_t( DEPTH ) , ErrorDepth_( errors , IDX ) )
-
-#define M_CKERRFULL_( IDX , TEXT , DETAILS , NAME , LINE , CHAR , DEPTH ) \
-	do { \
-		CPPUNIT_ASSERT( T_String{ TEXT } == errors[ IDX ].error( ) ); \
-		CPPUNIT_ASSERT_EQUAL( bool( DETAILS ) , errors[ IDX ].isDetails( ) ); \
-		auto const& loc( errors[ IDX ].location( ) ); \
-		CPPUNIT_ASSERT( T_String{ NAME } == loc.source( ) ); \
-		CPPUNIT_ASSERT_EQUAL( uint32_t( LINE ) , loc.line( ) ); \
-		CPPUNIT_ASSERT_EQUAL( size_t( CHAR ) , loc.character( ) ); \
-		CPPUNIT_ASSERT_EQUAL( uint32_t( DEPTH ) , ErrorDepth_( errors , IDX ) ); \
-	} while ( 0 )
-
-#define M_CKERRCHAIN_( IDX , DEPTH , HOW , NAME , LINE , CHAR , REC ) \
-	do { \
-		auto const& chain( GetChain_( &errors[ IDX ].location( ) , DEPTH ) ); \
-		CPPUNIT_ASSERT( E_SRDLocationChaining::HOW == chain.circumstances ); \
-		CPPUNIT_ASSERT_EQUAL( uint32_t( REC ) , chain.depth ); \
-		CPPUNIT_ASSERT( T_String{ NAME } == chain.location->source( ) ); \
-		CPPUNIT_ASSERT_EQUAL( uint32_t( LINE ) , chain.location->line( ) ); \
-		CPPUNIT_ASSERT_EQUAL( size_t( CHAR ) , chain.location->character( ) ); \
-	} while ( 0 )
-
-
-#endif // TESTS_SRDPREPROCLOCATION_H_
diff --git a/tests/srd-preproc-tracking.cc b/tests/srd-preproc-tracking.cc
deleted file mode 100644
index 64cf5f9..0000000
--- a/tests/srd-preproc-tracking.cc
+++ /dev/null
@@ -1,676 +0,0 @@
-#include "srd-preproc-cmd-common.hh"
-#include "srd-preproc-location.hh"
-using namespace lw;
-
-
-class SRDPreprocTrackingTest : public CppUnit::TestFixture
-{
-	CPPUNIT_TEST_SUITE( SRDPreprocTrackingTest );
-
-		CPPUNIT_TEST( testTopLevel );
-
-		CPPUNIT_TEST( testVar );
-		CPPUNIT_TEST( testVarGet );
-
-		CPPUNIT_TEST( testCall );
-		CPPUNIT_TEST( testCalls );
-		CPPUNIT_TEST( testCallRecursive );
-
-		CPPUNIT_TEST( testEval );
-		CPPUNIT_TEST( testEvalCalls );
-
-		CPPUNIT_TEST( testCommandOutput );
-
-#if 0
-		CPPUNIT_TEST( testMacroBody );
-		CPPUNIT_TEST( testMacroBodyCall );
-		CPPUNIT_TEST( testMacroBodyEval );
-		CPPUNIT_TEST( testCallMacroBody );
-		CPPUNIT_TEST( testEvalMacroBody );
-
-		CPPUNIT_TEST( testMacroOutput );
-		CPPUNIT_TEST( testMacroOutputCall );
-		CPPUNIT_TEST( testMacroOutputEval );
-		CPPUNIT_TEST( testCallMacroOutput );
-		CPPUNIT_TEST( testEvalMacroOutput );
-
-#endif
-//		CPPUNIT_TEST( testErrorTopLevel );
-#if 0
-		CPPUNIT_TEST( testErrorCall );
-#endif
-
-	CPPUNIT_TEST_SUITE_END( );
-
-   public:
-	void testTopLevel( );
-
-	void testVar( );
-	void testVarGet( );
-
-	void testCall( );
-	void testCalls( );
-	void testCallRecursive( );
-
-	void testEval( );
-	void testEvalCalls( );
-
-	void testCommandOutput( );
-
-#if 0
-	void testMacroBody( );
-	void testMacroBodyCall( );
-	void testMacroBodyEval( );
-	void testCallMacroBody( );
-	void testEvalMacroBody( );
-
-	void testMacroOutput( );
-	void testMacroOutputCall( );
-	void testMacroOutputEval( );
-	void testCallMacroOutput( );
-	void testEvalMacroOutput( );
-
-#endif
-	void testErrorTopLevel( );
-#if 0
-	void testErrorCall( );
-#endif
-};
-CPPUNIT_TEST_SUITE_REGISTRATION( SRDPreprocTrackingTest );
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocTrackingTest::testTopLevel( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"a\n"
-				"(-scope b)\n"
-				, errors ) );
-	CPPUNIT_ASSERT( check( "a b" , output ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-
-	M_CKTOKDEPTH_( 0 , 0 );
-		M_CKTOKLOC_( 0 , "test" , 1 , 1 );
-	M_CKTOKDEPTH_( 1 , 0 );
-		M_CKTOKLOC_( 1 , "test" , 2 , 9 );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocTrackingTest::testVar( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-set var value)\n"
-				"$var\n"
-				, errors ) );
-	CPPUNIT_ASSERT( check( "value" , output ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-
-	M_CKTOKDEPTH_( 0 , 1 );
-		M_CKTOKLOC_( 0 , "$var" , 0 , 0 );
-		M_CKTOKCHAIN_( 0 , 0 , SUBSTITUTED , "test" , 2 , 1 , 0 );
-}
-
-void SRDPreprocTrackingTest::testVarGet( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-set (var vn) value var)\n"
-				"(-get var $vn)\n"
-				, errors ) );
-	CPPUNIT_ASSERT( check( "value value" , output ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-
-	M_CKTOKDEPTH_( 0 , 1 );
-		M_CKTOKLOC_( 0 , "$var" , 0 , 0 );
-		M_CKTOKCHAIN_( 0 , 0 , SUBSTITUTED , "test" , 2 , 2 , 0 );
-	M_CKTOKDEPTH_( 1 , 1 );
-		M_CKTOKLOC_( 1 , "$var" , 0 , 0 );
-		M_CKTOKCHAIN_( 1 , 0 , SUBSTITUTED , "test" , 2 , 2 , 0 );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocTrackingTest::testCall( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-set fn (-raw ( () b )))\n"
-				"(-bless fn)\n"
-				"a ($fn)\n"
-				, errors ) );
-	CPPUNIT_ASSERT( check( "a b" , output ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-
-	M_CKTOKDEPTH_( 0 , 0 );
-		M_CKTOKLOC_( 0 , "test" , 3 , 1 );
-	M_CKTOKDEPTH_( 1 , 1 );
-		M_CKTOKLOC_( 1 , "test" , 1 , 21 );
-		M_CKTOKCHAIN_( 1 , 0 , CALLED , "test" , 3 , 4 , 0 );
-}
-
-void SRDPreprocTrackingTest::testCalls( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-set ( fn1 fn2 ) (-raw\n"
-					"((d)\n"
-						"I ($fn2 $d) )\n"
-					"((d)\n"
-						"got $d)\n"
-				"))\n"
-				"(-bless fn1 fn2)\n"
-				"($fn1 it)\n"
-				, errors ) );
-	CPPUNIT_ASSERT( check( "I got it" , output ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-
-	M_CKTOKDEPTH_( 0 , 1 );
-		M_CKTOKLOC_( 0 , "test" , 3 , 1 );
-		M_CKTOKCHAIN_( 0 , 0 , CALLED , "test" , 8 , 2 , 0 );
-	M_CKTOKDEPTH_( 1 , 2 );
-		M_CKTOKLOC_( 1 , "test" , 5 , 1 );
-		M_CKTOKCHAIN_( 1 , 0 , CALLED , "test" , 3 , 4 , 0 );
-		M_CKTOKCHAIN_( 1 , 1 , CALLED , "test" , 8 , 2 , 0 );
-	M_CKTOKDEPTH_( 2 , 3 );
-		M_CKTOKLOC_( 2 , "$d" , 0 , 0 );
-		M_CKTOKCHAIN_( 2 , 0 , SUBSTITUTED , "test" , 5 , 5 , 0 );
-		M_CKTOKCHAIN_( 2 , 1 , CALLED , "test" , 3 , 4 , 0 );
-		M_CKTOKCHAIN_( 2 , 2 , CALLED , "test" , 8 , 2 , 0 );
-}
-
-void SRDPreprocTrackingTest::testCallRecursive( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-set fn (-raw ( (d)\n"
-					"$d\n"
-					"(-if (-gt $d 0) (\n"
-						"($fn (-sub $d 1))\n"
-					")))))\n"
-				"(-bless fn)\n"
-				"($fn 6)\n"
-				, errors ) );
-	CPPUNIT_ASSERT( check( "6 5 4 3 2 1 0" , output ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-
-	M_CKTOKDEPTH_( 0 , 2 );
-	M_CKTOKCHAIN_( 0 , 0 , SUBSTITUTED , "test" , 2 , 1 , 0 );
-	M_CKTOKCHAIN_( 0 , 1 , CALLED , "test" , 7 , 2 , 0 );
-
-	for ( auto i = 1u ; i < 7 ; i ++ ) {
-		M_CKTOKDEPTH_( i , 3 );
-		M_CKTOKCHAIN_( i , 0 , SUBSTITUTED , "test" , 2 , 1 , 0 );
-		M_CKTOKCHAIN_( i , 1 , CALLED , "test" , 4 , 2 , i - 1 );
-		M_CKTOKCHAIN_( i , 2 , CALLED , "test" , 7 , 2 , 0 );
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocTrackingTest::testEval( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-set (x y f)\n"
-					"(-raw $y)\n"
-					"x\n"
-					"(() (-raw a (-raw $y) b))\n"
-				")\n"
-				"(-bless f)\n"
-				"(-eval x $y $x ($f))\n"
-				, errors ) );
-	CPPUNIT_ASSERT( check( "x x x a x b" , output ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-
-	M_CKTOKDEPTH_( 0 , 0 );
-		M_CKTOKLOC_( 0 , "test" , 7 , 8 );
-	M_CKTOKDEPTH_( 1 , 1 );
-		M_CKTOKLOC_( 1 , "$y" , 0 , 0 );
-		M_CKTOKCHAIN_( 1 , 0 , SUBSTITUTED , "test" , 7 , 10 , 0 );
-	M_CKTOKDEPTH_( 2 , 2 );
-		M_CKTOKLOC_( 2 , "$y" , 0 , 0 );
-		M_CKTOKCHAIN_( 2 , 0 , SUBSTITUTED , "$x" , 0 , 0 , 0 );
-		M_CKTOKCHAIN_( 2 , 1 , EVALUATED , "test" , 7 , 2 , 0 );
-	M_CKTOKDEPTH_( 3 , 1 );
-		M_CKTOKLOC_( 3 , "test" , 4 , 11 );
-		M_CKTOKCHAIN_( 3 , 0 , CALLED , "test" , 7 , 17 , 0 );
-	M_CKTOKDEPTH_( 4 , 2 );
-		M_CKTOKLOC_( 4 , "$y" , 0 , 0 );
-		M_CKTOKCHAIN_( 4 , 0 , SUBSTITUTED , "test" , 4 , 19 , 0 );
-		M_CKTOKCHAIN_( 4 , 1 , EVALUATED , "test" , 7 , 2 , 0 );
-	M_CKTOKDEPTH_( 5 , 1 );
-		M_CKTOKLOC_( 5 , "test" , 4 , 23 );
-		M_CKTOKCHAIN_( 5 , 0 , CALLED , "test" , 7 , 17 , 0 );
-}
-
-void SRDPreprocTrackingTest::testEvalCalls( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-set (x y f)\n"
-					"(-raw ($f 2))\n"
-					"(-raw $x)\n"
-					"(-raw ((x) a $x b))\n"
-				")\n"
-				"(-bless f)\n"
-				"(-eval ($f 1) $x $y $x)\n"
-				, errors ) );
-#if 0
-	printf( "\n\n" );
-	for ( auto i = 0u ; i < output.size( ) ; i ++ ) {
-		PrintLoc_( &output[ i ].location( ) );
-		printf( "\n" );
-	}
-#endif
-	CPPUNIT_ASSERT( check( "a 1 b a 2 b ($f 2) a 2 b" , output ) );
-
-	M_CKTOKDEPTH_( 0 , 1 );
-		M_CKTOKLOC_( 0 , "test" , 4 , 12 );
-		M_CKTOKCHAIN_( 0 , 0 , CALLED , "test" , 7 , 9 , 0 );
-	M_CKTOKDEPTH_( 1 , 2 );
-		M_CKTOKLOC_( 1 , "$x" , 0 , 0 );
-		M_CKTOKCHAIN_( 1 , 0 , SUBSTITUTED , "test" , 4 , 14 , 0 );
-		M_CKTOKCHAIN_( 1 , 1 , CALLED , "test" , 7 , 9 , 0 );
-	M_CKTOKDEPTH_( 2 , 1 );
-		M_CKTOKLOC_( 2 , "test" , 4 , 17 );
-		M_CKTOKCHAIN_( 2 , 0 , CALLED , "test" , 7 , 9 , 0 );
-
-	M_CKTOKDEPTH_( 3 , 2 );
-		M_CKTOKLOC_( 3 , "test" , 4 , 12 );
-		M_CKTOKCHAIN_( 3 , 0 , CALLED , "$x" , 0 , 1 , 0 );
-		M_CKTOKCHAIN_( 3 , 1 , EVALUATED , "test" , 7 , 2 , 0 );
-	M_CKTOKDEPTH_( 4 , 3 );
-		M_CKTOKLOC_( 4 , "$x" , 0 , 0 );
-		M_CKTOKCHAIN_( 4 , 0 , SUBSTITUTED , "test" , 4 , 14 , 0 );
-		M_CKTOKCHAIN_( 4 , 1 , CALLED , "$x" , 0 , 1 , 0 );
-		M_CKTOKCHAIN_( 4 , 2 , EVALUATED , "test" , 7 , 2 , 0 );
-	M_CKTOKDEPTH_( 5 , 2 );
-		M_CKTOKLOC_( 5 , "test" , 4 , 17 );
-		M_CKTOKCHAIN_( 5 , 0 , CALLED , "$x" , 0 , 1 , 0 );
-		M_CKTOKCHAIN_( 5 , 1 , EVALUATED , "test" , 7 , 2 , 0 );
-
-	for ( auto i = 0u ; i < 4 ; i ++ ) {
-		M_CKTOKDEPTH_( i + 6 , 2 );
-		M_CKTOKLOC_( i + 6 , "$x" , 0 , i );
-		M_CKTOKCHAIN_( i + 6 , 0 , SUBSTITUTED , "$y" , 0 , 0 , 0 );
-		M_CKTOKCHAIN_( i + 6 , 1 , EVALUATED , "test" , 7 , 2 , 0 );
-	}
-
-	M_CKTOKDEPTH_( 10 , 2 );
-		M_CKTOKLOC_( 10 , "test" , 4 , 12 );
-		M_CKTOKCHAIN_( 10 , 0 , CALLED , "$x" , 0 , 1 , 0 );
-		M_CKTOKCHAIN_( 10 , 1 , EVALUATED , "test" , 7 , 2 , 0 );
-	M_CKTOKDEPTH_( 11 , 3 );
-		M_CKTOKLOC_( 11 , "$x" , 0 , 0 );
-		M_CKTOKCHAIN_( 11 , 0 , SUBSTITUTED , "test" , 4 , 14 , 0 );
-		M_CKTOKCHAIN_( 11 , 1 , CALLED , "$x" , 0 , 1 , 0 );
-		M_CKTOKCHAIN_( 11 , 2 , EVALUATED , "test" , 7 , 2 , 0 );
-	M_CKTOKDEPTH_( 12 , 2 );
-		M_CKTOKLOC_( 12 , "test" , 4 , 17 );
-		M_CKTOKCHAIN_( 12 , 0 , CALLED , "$x" , 0 , 1 , 0 );
-		M_CKTOKCHAIN_( 12 , 1 , EVALUATED , "test" , 7 , 2 , 0 );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocTrackingTest::testCommandOutput( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-add 1 2)\n"
-				"(-is-set x)\n"
-				"(-type-of w)\n"
-				"(-eq a b)\n"
-				"(-to-string x \"x\")\n"
-				"(-length abcdef)\n"
-				, errors ) );
-	CPPUNIT_ASSERT( check( "3 0 word 0 \"x\" \"x\" 6" , output ) );
-	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
-
-	M_CKTOKDEPTH_( 0 , 1 );
-		M_CKTOKLOC_( 0 , "-add" , 0 , 0 );
-		M_CKTOKCHAIN_( 0 , 0 , GENERATED , "test" , 1 , 2 , 0 );
-	M_CKTOKDEPTH_( 1 , 1 );
-		M_CKTOKLOC_( 1 , "-is-set" , 0 , 0 );
-		M_CKTOKCHAIN_( 1 , 0 , GENERATED , "test" , 2 , 2 , 0 );
-	M_CKTOKDEPTH_( 2 , 1 );
-		M_CKTOKLOC_( 2 , "-type-of" , 0 , 0 );
-		M_CKTOKCHAIN_( 2 , 0 , GENERATED , "test" , 3 , 2 , 0 );
-	M_CKTOKDEPTH_( 3 , 1 );
-		M_CKTOKLOC_( 3 , "-eq" , 0 , 0 );
-		M_CKTOKCHAIN_( 3 , 0 , GENERATED , "test" , 4 , 2 , 0 );
-	M_CKTOKDEPTH_( 4 , 1 );
-		M_CKTOKLOC_( 4 , "-to-string" , 0 , 0 );
-		M_CKTOKCHAIN_( 4 , 0 , GENERATED , "test" , 5 , 2 , 0 );
-	M_CKTOKDEPTH_( 5 , 0 );
-		M_CKTOKLOC_( 5 , "test" , 5 , 15 );
-	M_CKTOKDEPTH_( 6 , 1 );
-		M_CKTOKLOC_( 6 , "-length" , 0 , 0 );
-		M_CKTOKCHAIN_( 6 , 0 , GENERATED , "test" , 6 , 2 , 0 );
-}
-
-#if 0
-void SRDPreprocTrackingTest::testCallRecursive( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-set fn (-raw ( (d)\n"
-					"(-if $d (\n"
-						"($fn (-sub $d 1))\n"
-					") (\n"
-						"(-error)\n"
-					")))))\n"
-				"(-bless fn)\n"
-				"($fn 6)\n"
-				, errors ) );
-	CPPUNIT_ASSERT( check( "" , output ) );
-	CPPUNIT_ASSERT_EQUAL( 1u , errors.size( ) );
-
-	M_CKERR_( 0 , "user error" , 5 , 1 );
-	M_CKERRDEPTH_( 0 , 2 );
-	M_CKERRCHAIN_( 0 , 0 , E_SRDLocationChaining::CALLED , 3 , 1 , 6 );
-	M_CKERRCHAIN_( 0 , 1 , E_SRDLocationChaining::CALLED , 8 , 1 , 1 );
-}
-
-void SRDPreprocTrackingTest::testCalls( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-set fn1 (-raw ( (d)\n"
-					"(-if $d (\n"
-						"($fn1 (-sub $d 1))\n"
-					") (\n"
-						"($fn2 4)\n"
-					")))))\n"
-				"(-set fn2 (-raw ( (d)\n"
-					"(-if $d (\n"
-						"($fn2 (-sub $d 1))\n"
-					") (\n"
-						"(-error)\n"
-					")))))\n"
-				"(-bless fn1 fn2)\n"
-				"($fn1 6)\n"
-				, errors ) );
-	CPPUNIT_ASSERT( check( "" , output ) );
-	CPPUNIT_ASSERT_EQUAL( 1u , errors.size( ) );
-
-	M_CKERR_( 0 , "user error" , 11 , 1 );
-	M_CKERRDEPTH_( 0 , 4 );
-	M_CKERRCHAIN_( 0 , 0 , E_SRDLocationChaining::CALLED , 9 , 1 , 4 );
-	M_CKERRCHAIN_( 0 , 1 , E_SRDLocationChaining::CALLED , 5 , 1 , 1 );
-	M_CKERRCHAIN_( 0 , 2 , E_SRDLocationChaining::CALLED , 3 , 1 , 6 );
-	M_CKERRCHAIN_( 0 , 3 , E_SRDLocationChaining::CALLED , 14 , 1 , 1 );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocTrackingTest::testEval( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-eval\n"
-					"( (-raw -error ) )\n"
-				")\n"
-				, errors ) );
-	CPPUNIT_ASSERT( check( "" , output ) );
-	CPPUNIT_ASSERT_EQUAL( 1u , errors.size( ) );
-
-	M_CKERR_( 0 , "user error" , 2 , 1 );
-	M_CKERRDEPTH_( 0 , 1 );
-	M_CKERRCHAIN_( 0 , 0 , E_SRDLocationChaining::EVALUATED , 1 , 1 , 1 );
-}
-
-void SRDPreprocTrackingTest::testEvalCall( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-set fn (-raw ( (d)\n"
-					"(-if $d (\n"
-						"($fn (-sub $d 1))\n"
-					") (\n"
-						"(-error)\n"
-					")))))\n"
-				"(-bless fn)\n"
-				"(-eval (-raw ($fn 6)))\n"
-				, errors ) );
-	CPPUNIT_ASSERT( check( "" , output ) );
-	CPPUNIT_ASSERT_EQUAL( 1u , errors.size( ) );
-
-	M_CKERR_( 0 , "user error" , 5 , 1 );
-	M_CKERRDEPTH_( 0 , 3 );
-	M_CKERRCHAIN_( 0 , 0 , E_SRDLocationChaining::CALLED , 3 , 1 , 6 );
-	M_CKERRCHAIN_( 0 , 1 , E_SRDLocationChaining::CALLED , 8 , 14 , 1 );
-	M_CKERRCHAIN_( 0 , 2 , E_SRDLocationChaining::EVALUATED , 8 , 1 , 1 );
-}
-
-void SRDPreprocTrackingTest::testCallEval( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-set fn (-raw ( (d)\n"
-					"(-if $d (\n"
-						"($fn (-sub $d 1))\n"
-					") (\n"
-						"(-eval (-raw (-error)))\n"
-					")))))\n"
-				"(-bless fn)\n"
-				"($fn 6)\n"
-				, errors ) );
-	CPPUNIT_ASSERT( check( "" , output ) );
-	CPPUNIT_ASSERT_EQUAL( 1u , errors.size( ) );
-
-	M_CKERR_( 0 , "user error" , 5 , 14 );
-	M_CKERRDEPTH_( 0 , 3 );
-	M_CKERRCHAIN_( 0 , 0 , E_SRDLocationChaining::EVALUATED , 5 , 1 , 1 );
-	M_CKERRCHAIN_( 0 , 1 , E_SRDLocationChaining::CALLED , 3 , 1 , 6 );
-	M_CKERRCHAIN_( 0 , 2 , E_SRDLocationChaining::CALLED , 8 , 1 , 1 );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocTrackingTest::testMacroBody( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-set-macro m (-raw ( () (-error) )))\n"
-				"(m)\n"
-				, errors ) );
-	CPPUNIT_ASSERT( check( "" , output ) );
-	CPPUNIT_ASSERT_EQUAL( 1u , errors.size( ) );
-
-	M_CKERR_( 0 , "user error" , 1 , 26 );
-	M_CKERRDEPTH_( 0 , 1 );
-	M_CKERRCHAIN_( 0 , 0 , E_SRDLocationChaining::CALLED , 2 , 1 , 1 );
-}
-
-void SRDPreprocTrackingTest::testMacroBodyCall( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-set fn (-raw ( () (-error) )))\n"
-				"(-bless fn)\n"
-				"(-set-macro m (-raw ( () ($fn) )))\n"
-				"(m)\n"
-				, errors ) );
-	CPPUNIT_ASSERT( check( "" , output ) );
-	CPPUNIT_ASSERT_EQUAL( 1u , errors.size( ) );
-
-	M_CKERR_( 0 , "user error" , 1 , 21 );
-	M_CKERRDEPTH_( 0 , 2 );
-	M_CKERRCHAIN_( 0 , 0 , E_SRDLocationChaining::CALLED , 3 , 26 , 1 );
-	M_CKERRCHAIN_( 0 , 1 , E_SRDLocationChaining::CALLED , 4 , 1 , 1 );
-}
-
-void SRDPreprocTrackingTest::testMacroBodyEval( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-set-macro m (-raw ( () (-eval (-raw (-error))) )))\n"
-				"(m)\n"
-				, errors ) );
-	CPPUNIT_ASSERT( check( "" , output ) );
-	CPPUNIT_ASSERT_EQUAL( 1u , errors.size( ) );
-
-	M_CKERR_( 0 , "user error" , 1 , 39 );
-	M_CKERRDEPTH_( 0 , 2 );
-	M_CKERRCHAIN_( 0 , 0 , E_SRDLocationChaining::EVALUATED , 1 , 26 , 1 );
-	M_CKERRCHAIN_( 0 , 1 , E_SRDLocationChaining::CALLED , 2 , 1 , 1 );
-}
-
-void SRDPreprocTrackingTest::testCallMacroBody( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-set-macro m (-raw ( () (-error) )))\n"
-				"(-set fn (-raw ( () (m))))\n"
-				"(-bless fn)\n"
-				"($fn)\n"
-				, errors ) );
-	CPPUNIT_ASSERT( check( "" , output ) );
-	CPPUNIT_ASSERT_EQUAL( 1u , errors.size( ) );
-
-	M_CKERR_( 0 , "user error" , 1 , 26 );
-	M_CKERRDEPTH_( 0 , 2 );
-	M_CKERRCHAIN_( 0 , 0 , E_SRDLocationChaining::CALLED , 2 , 21 , 1 );
-	M_CKERRCHAIN_( 0 , 1 , E_SRDLocationChaining::CALLED , 4 , 1 , 1 );
-}
-
-void SRDPreprocTrackingTest::testEvalMacroBody( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-set-macro m (-raw ( () (-error) )))\n"
-				"(-eval (-raw (m)))\n"
-				, errors ) );
-	CPPUNIT_ASSERT( check( "" , output ) );
-	CPPUNIT_ASSERT_EQUAL( 1u , errors.size( ) );
-
-	M_CKERR_( 0 , "user error" , 1 , 26 );
-	M_CKERRDEPTH_( 0 , 2 );
-	M_CKERRCHAIN_( 0 , 0 , E_SRDLocationChaining::CALLED , 2 , 14 , 1 );
-	M_CKERRCHAIN_( 0 , 1 , E_SRDLocationChaining::EVALUATED , 2 , 1 , 1 );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocTrackingTest::testMacroOutput( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-set-macro m (-raw ( () (-raw (-error)) )))\n"
-				"(m)\n"
-				, errors ) );
-	CPPUNIT_ASSERT( check( "" , output ) );
-	CPPUNIT_ASSERT_EQUAL( 1u , errors.size( ) );
-
-	M_CKERR_( 0 , "user error" , 1 , 32 );
-	M_CKERRDEPTH_( 0 , 3 );
-	M_CKERRCHAIN_( 0 , 0 , E_SRDLocationChaining::EVALUATED , 2 , 1 , 1 );
-	M_CKERRCHAIN_( 0 , 1 , E_SRDLocationChaining::GENERATED , 1 , 32 , 1 );
-	M_CKERRCHAIN_( 0 , 2 , E_SRDLocationChaining::CALLED , 2 , 1 , 1 );
-}
-
-void SRDPreprocTrackingTest::testMacroOutputCall( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-set fn (-raw ( () (-error) )))\n"
-				"(-bless fn)\n"
-				"(-set-macro m (-raw ( () (-raw ($fn)) )))\n"
-				"(m)\n"
-				, errors ) );
-	CPPUNIT_ASSERT( check( "" , output ) );
-	CPPUNIT_ASSERT_EQUAL( 1u , errors.size( ) );
-
-	M_CKERR_( 0 , "user error" , 1 , 21 );
-	M_CKERRDEPTH_( 0 , 4 );
-	M_CKERRCHAIN_( 0 , 0 , E_SRDLocationChaining::CALLED , 3 , 32 , 1 );
-	M_CKERRCHAIN_( 0 , 1 , E_SRDLocationChaining::EVALUATED , 4 , 1 , 1 );
-	M_CKERRCHAIN_( 0 , 2 , E_SRDLocationChaining::GENERATED , 3 , 32 , 1 );
-	M_CKERRCHAIN_( 0 , 3 , E_SRDLocationChaining::CALLED , 4 , 1 , 1 );
-}
-
-void SRDPreprocTrackingTest::testMacroOutputEval( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-set-macro m (-raw ( () (-raw\n"
-					"(-eval (-raw (-error)))\n"
-				") )))\n"
-				"(m)\n"
-				, errors ) );
-	CPPUNIT_ASSERT( check( "" , output ) );
-	CPPUNIT_ASSERT_EQUAL( 1u , errors.size( ) );
-
-	M_CKERR_( 0 , "user error" , 2 , 14 );
-	M_CKERRDEPTH_( 0 , 4 );
-	M_CKERRCHAIN_( 0 , 0 , E_SRDLocationChaining::EVALUATED , 2 , 1 , 1 );
-	M_CKERRCHAIN_( 0 , 1 , E_SRDLocationChaining::EVALUATED , 4 , 1 , 1 );
-	M_CKERRCHAIN_( 0 , 2 , E_SRDLocationChaining::GENERATED , 2 , 1 , 1 );
-	M_CKERRCHAIN_( 0 , 3 , E_SRDLocationChaining::CALLED , 4 , 1 , 1 );
-}
-
-void SRDPreprocTrackingTest::testCallMacroOutput( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-set-macro m (-raw ( () (-raw\n"
-					"(-error)\n"
-				") )))\n"
-				"(-set fn (-raw ( () (m) )))\n"
-				"(-bless fn)\n"
-				"($fn)\n"
-				, errors ) );
-	CPPUNIT_ASSERT( check( "" , output ) );
-	CPPUNIT_ASSERT_EQUAL( 1u , errors.size( ) );
-
-	M_CKERR_( 0 , "user error" , 2 , 1 );
-	M_CKERRDEPTH_( 0 , 4 );
-	M_CKERRCHAIN_( 0 , 0 , E_SRDLocationChaining::EVALUATED , 4 , 21 , 1 );
-	M_CKERRCHAIN_( 0 , 1 , E_SRDLocationChaining::GENERATED , 2 , 1 , 1 );
-	M_CKERRCHAIN_( 0 , 2 , E_SRDLocationChaining::CALLED , 4 , 21 , 1 );
-	M_CKERRCHAIN_( 0 , 3 , E_SRDLocationChaining::CALLED , 6 , 1 , 1 );
-}
-
-void SRDPreprocTrackingTest::testEvalMacroOutput( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-set-macro m (-raw ( () (-raw\n"
-					"(-error)\n"
-				") )))\n"
-				"(-eval (-raw (m)))\n"
-				, errors ) );
-	CPPUNIT_ASSERT( check( "" , output ) );
-	CPPUNIT_ASSERT_EQUAL( 1u , errors.size( ) );
-
-	M_CKERR_( 0 , "user error" , 2 , 1 );
-	M_CKERRDEPTH_( 0 , 4 );
-	M_CKERRCHAIN_( 0 , 0 , EVALUATED , 4 , 14 , 1 );
-	M_CKERRCHAIN_( 0 , 1 , GENERATED , 2 , 1 , 1 );
-	M_CKERRCHAIN_( 0 , 2 , CALLED , 4 , 14 , 1 );
-	M_CKERRCHAIN_( 0 , 3 , EVALUATED , 4 , 1 , 1 );
-}
-#endif
-
-/*----------------------------------------------------------------------------*/
-
-void SRDPreprocTrackingTest::testErrorTopLevel( )
-{
-	T_SRDErrors errors;
-	T_SRDList output( process(
-				"(-error)\n"
-				"(-scope (-error))\n"
-				, errors ) );
-	CPPUNIT_ASSERT( check( "" , output ) );
-	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
-
-	M_CKERR_( 0 , "user error" , 1 , 2 );
-	M_CKERRDEPTH_( 0 , 0 );
-
-	M_CKERR_( 1 , "user error" , 2 , 10 );
-	M_CKERRDEPTH_( 1 , 0 );
-}
diff --git a/tests/srd-text-writer.cc b/tests/srd-text-writer.cc
index 2e90d32..d2586ad 100644
--- a/tests/srd-text-writer.cc
+++ b/tests/srd-text-writer.cc
@@ -1,8 +1,8 @@
-#include <lw/lib/SRDText.hh>
-#include <lw/lib/MemoryStreams.hh>
+#include <ebcl/SRDText.hh>
+#include <ebcl/MemoryStreams.hh>
 #include <cmath>
 #include <cppunit/extensions/HelperMacros.h>
-using namespace lw;
+using namespace ebcl;
 
 
 class SRDTextWriterTest : public CppUnit::TestFixture
diff --git a/tests/stream-file-input.cc b/tests/stream-file-input.cc
deleted file mode 100644
index 70e2017..0000000
--- a/tests/stream-file-input.cc
+++ /dev/null
@@ -1,268 +0,0 @@
-#include <lw/lib/Files.hh>
-#include <cppunit/extensions/HelperMacros.h>
-using namespace lw;
-
-#if 0
-
-/*= FileInputStreamTest =====================================================*/
-
-class FileInputStreamTest : public CppUnit::TestFixture
-{
-	CPPUNIT_TEST_SUITE( FileInputStreamTest );
-		CPPUNIT_TEST( testInitRealFile );
-		CPPUNIT_TEST( testInitBadFile );
-
-		CPPUNIT_TEST( testOpenRealFile );
-		CPPUNIT_TEST( testOpenBadFile );
-		CPPUNIT_TEST( testClose );
-
-		CPPUNIT_TEST( testReadOpensFile );
-		CPPUNIT_TEST( testReadAll );
-		CPPUNIT_TEST( testReadPartial );
-
-		CPPUNIT_TEST( testSetPosOpensFile );
-		CPPUNIT_TEST( testSetPosStart );
-		CPPUNIT_TEST( testSetPosEnd );
-		CPPUNIT_TEST( testSetPosEndBad );
-
-		CPPUNIT_TEST( testMoveOpensFile );
-		CPPUNIT_TEST( testMoveForward );
-		CPPUNIT_TEST( testMoveBack );
-		CPPUNIT_TEST( testMoveBad );
-	CPPUNIT_TEST_SUITE_END( );
-
-	T_String OK_FILE( )
-	{
-		return T_String::Pooled( "tests/data/inputstream.txt" );
-	}
-
-	T_String BAD_FILE( )
-	{
-		return T_String::Pooled( "tests/data/no_such_file.txt" );
-	}
-
-	char const* CONTENTS( )
-	{
-		return "THIS IS A TEST\n";
-	}
-
-public:
-	void testInitRealFile( );
-	void testInitBadFile( );
-
-	void testOpenRealFile( );
-	void testOpenBadFile( );
-	void testClose( );
-
-	void testReadOpensFile( );
-	void testReadAll( );
-	void testReadPartial( );
-
-	void testSetPosOpensFile( );
-	void testSetPosStart( );
-	void testSetPosEnd( );
-	void testSetPosEndBad( );
-
-	void testMoveOpensFile( );
-	void testMoveForward( );
-	void testMoveBack( );
-	void testMoveBad( );
-};
-CPPUNIT_TEST_SUITE_REGISTRATION( FileInputStreamTest );
-
-/*---------------------------------------------------------------------------*/
-
-void FileInputStreamTest::testInitRealFile( )
-{
-	T_FileInputStream fis( OK_FILE( ) );
-	CPPUNIT_ASSERT( fis.path( ) == OK_FILE( ) );
-	CPPUNIT_ASSERT( fis.canUseSize( ) );
-	CPPUNIT_ASSERT( fis.canRead( ) );
-	CPPUNIT_ASSERT( fis.size( ) == 0 );
-	CPPUNIT_ASSERT( fis.position( ) == 0 );
-}
-
-/*---------------------------------------------------------------------------*/
-
-void FileInputStreamTest::testInitBadFile( )
-{
-	T_FileInputStream fis( BAD_FILE( ) );
-	CPPUNIT_ASSERT( fis.path( ) == BAD_FILE( ) );
-	CPPUNIT_ASSERT( fis.canUseSize( ) );
-	CPPUNIT_ASSERT( fis.canRead( ) );
-	CPPUNIT_ASSERT( fis.size( ) == 0 );
-	CPPUNIT_ASSERT( fis.position( ) == 0 );
-}
-
-/*---------------------------------------------------------------------------*/
-
-void FileInputStreamTest::testOpenRealFile( )
-{
-	T_FileInputStream fis( OK_FILE( ) );
-	fis.open( );
-	CPPUNIT_ASSERT( fis.size( ) == 15 );
-	CPPUNIT_ASSERT( fis.position( ) == 0 );
-	CPPUNIT_ASSERT( fis.isOpen( ) );
-}
-
-/*---------------------------------------------------------------------------*/
-
-void FileInputStreamTest::testOpenBadFile( )
-{
-	T_FileInputStream fis( BAD_FILE( ) );
-	try {
-		fis.open( );
-		CPPUNIT_FAIL( "No exception thrown" );
-	} catch ( X_StreamError const& e ) {
-		CPPUNIT_ASSERT( e.code( ) == E_StreamError::SYSTEM_ERROR );
-		CPPUNIT_ASSERT( e.systemError( ) == ENOENT );
-	}
-	CPPUNIT_ASSERT( fis.size( ) == 0 );
-	CPPUNIT_ASSERT( fis.position( ) == 0 );
-}
-
-/*---------------------------------------------------------------------------*/
-
-void FileInputStreamTest::testClose( )
-{
-	T_FileInputStream fis( OK_FILE( ) );
-	fis.open( );
-	fis.close( );
-	CPPUNIT_ASSERT( !fis.isOpen( ) );
-	CPPUNIT_ASSERT_EQUAL( size_t( 0 ) , fis.size( ) );
-	CPPUNIT_ASSERT_EQUAL( size_t( 0 ) , fis.position( ) );
-}
-
-/*---------------------------------------------------------------------------*/
-
-void FileInputStreamTest::testReadOpensFile( )
-{
-	T_FileInputStream fis( OK_FILE( ) );
-	uint8_t x;
-	fis.read( &x , 0 );
-	CPPUNIT_ASSERT( fis.isOpen( ) );
-}
-
-/*---------------------------------------------------------------------------*/
-
-void FileInputStreamTest::testReadAll( )
-{
-	T_FileInputStream fis( OK_FILE( ) );
-	uint8_t buffer[ 1024 ];
-	auto rv( fis.read( buffer , sizeof( buffer ) ) );
-	CPPUNIT_ASSERT_EQUAL( fis.size( ) , rv );
-	CPPUNIT_ASSERT_EQUAL( fis.size( ) , fis.position( ) );
-	CPPUNIT_ASSERT( !memcmp( buffer , CONTENTS( ) , rv ) );
-}
-
-/*---------------------------------------------------------------------------*/
-
-void FileInputStreamTest::testReadPartial( )
-{
-	T_FileInputStream fis( OK_FILE( ) );
-	uint8_t buffer[ 1024 ];
-	auto rv( fis.read( buffer , 4 ) );
-	CPPUNIT_ASSERT_EQUAL( size_t( 4 ) , rv );
-	CPPUNIT_ASSERT_EQUAL( size_t( 4 ) , fis.position( ) );
-	CPPUNIT_ASSERT( !memcmp( buffer , CONTENTS( ) , 4 ) );
-}
-
-/*---------------------------------------------------------------------------*/
-
-void FileInputStreamTest::testSetPosOpensFile( )
-{
-	T_FileInputStream fis( OK_FILE( ) );
-	fis.position( 4 , false );
-	CPPUNIT_ASSERT( fis.isOpen( ) );
-}
-
-/*---------------------------------------------------------------------------*/
-
-void FileInputStreamTest::testSetPosStart( )
-{
-	T_FileInputStream fis( OK_FILE( ) );
-	fis.open( );
-	fis.position( 4 , false );
-	CPPUNIT_ASSERT_EQUAL( size_t( 4 ) , fis.position( ) );
-
-	uint8_t buffer[ 1024 ];
-	auto rv( fis.read( buffer , 3 ) );
-	CPPUNIT_ASSERT_EQUAL( size_t( 3 ) , rv );
-	CPPUNIT_ASSERT( !memcmp( buffer , CONTENTS( ) + 4 , 3 ) );
-}
-
-/*---------------------------------------------------------------------------*/
-
-void FileInputStreamTest::testSetPosEnd( )
-{
-	T_FileInputStream fis( OK_FILE( ) );
-	fis.open( );
-	fis.position( 4 , true );
-	CPPUNIT_ASSERT_EQUAL( size_t( 11 ) , fis.position( ) );
-
-	uint8_t buffer[ 1024 ];
-	auto rv( fis.read( buffer , 1024 ) );
-	CPPUNIT_ASSERT_EQUAL( size_t( 4 ) , rv );
-	CPPUNIT_ASSERT( !memcmp( buffer , CONTENTS( ) + 11 , 4 ) );
-}
-
-/*---------------------------------------------------------------------------*/
-
-void FileInputStreamTest::testSetPosEndBad( )
-{
-	T_FileInputStream fis( OK_FILE( ) );
-	fis.open( );
-	CPPUNIT_ASSERT_THROW( fis.position( fis.size( ) + 1 , true ) ,
-			X_StreamError );
-}
-
-/*---------------------------------------------------------------------------*/
-
-void FileInputStreamTest::testMoveOpensFile( )
-{
-	T_FileInputStream fis( OK_FILE( ) );
-	fis.move( 0 );
-	CPPUNIT_ASSERT( fis.isOpen( ) );
-}
-
-/*---------------------------------------------------------------------------*/
-
-void FileInputStreamTest::testMoveForward( )
-{
-	T_FileInputStream fis( OK_FILE( ) );
-	fis.open( );
-	fis.move( 4  );
-	CPPUNIT_ASSERT_EQUAL( size_t( 4 ) , fis.position( ) );
-
-	uint8_t buffer[ 1024 ];
-	auto rv( fis.read( buffer , 3 ) );
-	CPPUNIT_ASSERT_EQUAL( size_t( 3 ) , rv );
-	CPPUNIT_ASSERT( !memcmp( buffer , CONTENTS( ) + 4 , 3 ) );
-}
-
-/*---------------------------------------------------------------------------*/
-
-void FileInputStreamTest::testMoveBack( )
-{
-	T_FileInputStream fis( OK_FILE( ) );
-	fis.open( );
-	fis.position( 8 );
-	fis.move( -4 );
-	CPPUNIT_ASSERT_EQUAL( size_t( 4 ) , fis.position( ) );
-
-	uint8_t buffer[ 1024 ];
-	auto rv( fis.read( buffer , 3 ) );
-	CPPUNIT_ASSERT_EQUAL( size_t( 3 ) , rv );
-	CPPUNIT_ASSERT( !memcmp( buffer , CONTENTS( ) + 4 , 3 ) );
-}
-
-/*---------------------------------------------------------------------------*/
-
-void FileInputStreamTest::testMoveBad( )
-{
-	T_FileInputStream fis( OK_FILE( ) );
-	fis.open( );
-	CPPUNIT_ASSERT_THROW( fis.move( -1 ) , X_StreamError );
-}
-
-#endif
diff --git a/tests/vfs.cc b/tests/vfs.cc
deleted file mode 100644
index 03be00b..0000000
--- a/tests/vfs.cc
+++ /dev/null
@@ -1,318 +0,0 @@
-#include <lw/lib/VFS.hh>
-#include <cppunit/extensions/HelperMacros.h>
-using namespace lw;
-
-
-/*= VFSPathTest ===============================================================*/
-
-class VFSPathTest : public CppUnit::TestFixture
-{
-	CPPUNIT_TEST_SUITE( VFSPathTest );
-		CPPUNIT_TEST( testUnknown );
-		CPPUNIT_TEST( testRoot );
-		CPPUNIT_TEST( testAbsolute );
-		CPPUNIT_TEST( testRelative );
-
-		CPPUNIT_TEST( testValid );
-		CPPUNIT_TEST( testInvalid );
-
-		CPPUNIT_TEST( testDotDirs );
-		CPPUNIT_TEST( testDotInNames );
-		CPPUNIT_TEST( testLeadingDots );
-
-		CPPUNIT_TEST( testTrailingSlash );
-		CPPUNIT_TEST( testExtraSlashes );
-
-		CPPUNIT_TEST( testEquals );
-		CPPUNIT_TEST( testToString );
-		CPPUNIT_TEST( testAppend );
-		CPPUNIT_TEST( testNormalize );
-	CPPUNIT_TEST_SUITE_END( );
-
-public:
-	void testUnknown( );
-	void testRoot( );
-	void testAbsolute( );
-	void testRelative( );
-
-	void testValid( );
-	void testInvalid( );
-
-	void testDotDirs( );
-	void testDotInNames( );
-	void testLeadingDots( );
-
-	void testTrailingSlash( );
-	void testExtraSlashes( );
-
-	void testEquals( );
-	void testToString( );
-	void testAppend( );
-	void testNormalize( );
-};
-
-CPPUNIT_TEST_SUITE_REGISTRATION( VFSPathTest );
-
-/*----------------------------------------------------------------------------*/
-
-void VFSPathTest::testUnknown( )
-{
-	{
-		T_VFSPath path;
-		CPPUNIT_ASSERT( path.type( ) == E_VFSPathType::UNKNOWN );
-		CPPUNIT_ASSERT( path.elements( ) == 0 );
-	}
-	{
-		T_VFSPath path( "" );
-		CPPUNIT_ASSERT( path.type( ) == E_VFSPathType::UNKNOWN );
-		CPPUNIT_ASSERT( path.elements( ) == 0 );
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-void VFSPathTest::testRoot( )
-{
-	T_VFSPath path( "/" );
-	CPPUNIT_ASSERT( path.type( ) == E_VFSPathType::ABSOLUTE );
-	CPPUNIT_ASSERT( path.elements( ) == 0 );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void VFSPathTest::testAbsolute( )
-{
-	T_VFSPath path( "/this/is/a/test" );
-	CPPUNIT_ASSERT( path.type( ) == E_VFSPathType::ABSOLUTE );
-	CPPUNIT_ASSERT( path.elements( ) == 4 );
-	CPPUNIT_ASSERT( path[ 0 ] == "this" );
-	CPPUNIT_ASSERT( path[ 1 ] == "is" );
-	CPPUNIT_ASSERT( path[ 2 ] == "a" );
-	CPPUNIT_ASSERT( path[ 3 ] == "test" );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void VFSPathTest::testRelative( )
-{
-	T_VFSPath path( "this/is/a/test" );
-	CPPUNIT_ASSERT( path.type( ) == E_VFSPathType::RELATIVE );
-	CPPUNIT_ASSERT( path.elements( ) == 4 );
-	CPPUNIT_ASSERT( path[ 0 ] == "this" );
-	CPPUNIT_ASSERT( path[ 1 ] == "is" );
-	CPPUNIT_ASSERT( path[ 2 ] == "a" );
-	CPPUNIT_ASSERT( path[ 3 ] == "test" );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void VFSPathTest::testValid( )
-{
-	char const* const NAMES[] = {
-		"test" , "123" , "test-123" , "-test-123-" , "test_123" , "_" , "-"
-	};
-
-	for ( size_t i = 0 ; i < sizeof( NAMES ) / sizeof( NAMES[ 0 ] ) ; i ++ ) {
-		T_VFSPath path( NAMES[ i ] );
-		CPPUNIT_ASSERT( path.type( ) == E_VFSPathType::RELATIVE );
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-void VFSPathTest::testInvalid( )
-{
-	char const* const NAMES[] = {
-		"bad name" , "bad\\name" , "bad\u00e9name" , "bad\x09name" ,
-		"BadName"
-	};
-
-	for ( size_t i = 0 ; i < sizeof( NAMES ) / sizeof( NAMES[ 0 ] ) ; i ++ ) {
-		T_VFSPath path( NAMES[ i ] );
-		CPPUNIT_ASSERT( path.type( ) == E_VFSPathType::INVALID );
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-void VFSPathTest::testDotDirs( )
-{
-	{
-		T_VFSPath path( "./.././test" );
-		CPPUNIT_ASSERT( path.type( ) == E_VFSPathType::RELATIVE );
-		CPPUNIT_ASSERT( path.elements( ) == 4 );
-		CPPUNIT_ASSERT( path[ 0 ] == "." );
-		CPPUNIT_ASSERT( path[ 1 ] == ".." );
-		CPPUNIT_ASSERT( path[ 2 ] == "." );
-		CPPUNIT_ASSERT( path[ 3 ] == "test" );
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-void VFSPathTest::testDotInNames( )
-{
-	{
-		T_VFSPath path( "test.test/test...test/test." );
-		CPPUNIT_ASSERT( path.type( ) == E_VFSPathType::RELATIVE );
-		CPPUNIT_ASSERT( path.elements( ) == 3 );
-		CPPUNIT_ASSERT( path[ 0 ] == "test.test" );
-		CPPUNIT_ASSERT( path[ 1 ] == "test...test" );
-		CPPUNIT_ASSERT( path[ 2 ] == "test." );
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-void VFSPathTest::testLeadingDots( )
-{
-	{
-		T_VFSPath path( ".test" );
-		CPPUNIT_ASSERT( path.type( ) == E_VFSPathType::INVALID );
-		CPPUNIT_ASSERT( path.elements( ) == 1 );
-		CPPUNIT_ASSERT( path[ 0 ] == ".test" );
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-void VFSPathTest::testTrailingSlash( )
-{
-	T_VFSPath path( "/this/is/a/test/" );
-	CPPUNIT_ASSERT( path.type( ) == E_VFSPathType::ABSOLUTE );
-	CPPUNIT_ASSERT( path.elements( ) == 4 );
-	CPPUNIT_ASSERT( path[ 0 ] == "this" );
-	CPPUNIT_ASSERT( path[ 1 ] == "is" );
-	CPPUNIT_ASSERT( path[ 2 ] == "a" );
-	CPPUNIT_ASSERT( path[ 3 ] == "test" );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void VFSPathTest::testExtraSlashes( )
-{
-	T_VFSPath path( "///this////is//a////test///" );
-	CPPUNIT_ASSERT( path.type( ) == E_VFSPathType::ABSOLUTE );
-	CPPUNIT_ASSERT( path.elements( ) == 4 );
-	CPPUNIT_ASSERT( path[ 0 ] == "this" );
-	CPPUNIT_ASSERT( path[ 1 ] == "is" );
-	CPPUNIT_ASSERT( path[ 2 ] == "a" );
-	CPPUNIT_ASSERT( path[ 3 ] == "test" );
-}
-
-/*----------------------------------------------------------------------------*/
-
-void VFSPathTest::testEquals( )
-{
-	const T_VFSPath PATHS[] = {
-		{} , ".bad" , "test" , "/test" , "this/is/a/test"
-	};
-	const auto n( sizeof( PATHS ) / sizeof( PATHS[ 0 ] ) );
-
-	T_VFSPath copies[ n ];
-	for ( size_t i = 0 ; i < n ; i ++ ) {
-		copies[ i ] = PATHS[ i ];
-	}
-
-	for ( size_t i = 0 ; i < n ; i ++ ) {
-		for ( size_t j = 0 ; j < n ; j ++ ) {
-			if ( i == j ) {
-				CPPUNIT_ASSERT( PATHS[ i ] == PATHS[ j ] );
-				CPPUNIT_ASSERT( PATHS[ i ] == copies[ j ] );
-			} else {
-				CPPUNIT_ASSERT( PATHS[ i ] != PATHS[ j ] );
-				CPPUNIT_ASSERT( PATHS[ i ] != copies[ j ] );
-			}
-		}
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-void VFSPathTest::testToString( )
-{
-	char const* const PATHS[] = {
-		"/test" , "test" , "test/test" , "/test/test" , "" , ".bad"
-	};
-	for ( size_t i = 0 ; i < sizeof( PATHS ) / sizeof( PATHS[ 0 ] ) ; i ++ ) {
-		T_VFSPath path( PATHS[ i ] );
-		CPPUNIT_ASSERT( T_String( path ) == PATHS[ i ] );
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-void VFSPathTest::testAppend( )
-{
-	const T_VFSPath paths[] = {
-		"/test" , "test" , ".bad" , {}
-	};
-	const E_VFSPathType combos[] = {
-		// Parent is absolute
-		E_VFSPathType::ABSOLUTE , E_VFSPathType::ABSOLUTE ,
-		E_VFSPathType::INVALID , E_VFSPathType::UNKNOWN ,
-		// Parent is relative
-		E_VFSPathType::RELATIVE , E_VFSPathType::RELATIVE ,
-		E_VFSPathType::INVALID , E_VFSPathType::UNKNOWN ,
-		// Parent is invalid
-		E_VFSPathType::INVALID , E_VFSPathType::INVALID ,
-		E_VFSPathType::INVALID , E_VFSPathType::UNKNOWN ,
-		// Parent is unknown
-		E_VFSPathType::UNKNOWN , E_VFSPathType::UNKNOWN ,
-		E_VFSPathType::UNKNOWN , E_VFSPathType::UNKNOWN
-	};
-
-	int cid = 0;
-	for ( int i = 0 ; i < 4 ; i ++ ) {
-		for ( int j = 0 ; j < 4 ; j ++ , cid ++ ) {
-			T_VFSPath parent( paths[ i ] ) , child( paths[ j ] );
-			T_VFSPath path( parent , child );
-			//printf( "i = %d j = %d t = %d\n" , i , j , int( path.type( ) ) );
-			CPPUNIT_ASSERT( path.type( ) == combos[ cid ] );
-			if ( combos[ cid ] == E_VFSPathType::UNKNOWN ) {
-				CPPUNIT_ASSERT( path.elements( ) == 0 );
-			} else {
-				CPPUNIT_ASSERT( path.elements( ) == parent.elements( ) + child.elements( ) );
-				CPPUNIT_ASSERT( path[ 0 ] == parent[ 0 ] );
-				CPPUNIT_ASSERT( path[ 1 ] == child[ 0 ] );
-			}
-		}
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-void VFSPathTest::testNormalize( )
-{
-	const T_VFSPath INPUTS[] = {
-		{} , ".bad" , "/test" , "test" ,
-		"./test" ,
-		"/." ,
-		"/.." ,
-		"." ,
-		".." ,
-		"wat/../wet/../wut" ,
-		"wat/../.." ,
-		"wat/.." ,
-		"/wat/../.."
-	};
-	const T_VFSPath EXPECTED[] = {
-		{} , {} , "/test" , "test" ,
-		"test" ,
-		"/" ,
-		"/" ,
-		"." ,
-		".." ,
-		"wut" ,
-		".." ,
-		"." ,
-		"/"
-	};
-	static_assert( sizeof( INPUTS ) / sizeof( INPUTS[ 0 ] )
-				== sizeof( EXPECTED ) / sizeof( EXPECTED[ 0 ] ) ,
-		       "yo, your test sucks!" );
-
-	for ( size_t i = 0 ; i < sizeof( INPUTS ) / sizeof( INPUTS[ 0 ] ) ; i ++ ) {
-		CPPUNIT_ASSERT( T_String( INPUTS[ i ].normalize( ) ) == T_String( EXPECTED[ i ] ) );
-	}
-}