First commit for GitHub
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..d3a1e13
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+Test/build
+*.pbxuser
+*.mode1v3
diff --git a/LICENSE_1_0.txt b/LICENSE_1_0.txt
new file mode 100644
index 0000000..1dad8e9
--- /dev/null
+++ b/LICENSE_1_0.txt
@@ -0,0 +1,23 @@
+Boost Software License - Version 1.0 - August 17th, 2003

+

+Permission is hereby granted, free of charge, to any person or organization

+obtaining a copy of the software and accompanying documentation covered by

+this license (the "Software") to use, reproduce, display, distribute,

+execute, and transmit the Software, and to prepare derivative works of the

+Software, and to permit third-parties to whom the Software is furnished to

+do so, all subject to the following:

+

+The copyright notices in the Software and this entire statement, including

+the above license grant, this restriction and the following disclaimer,

+must be included in all copies of the Software, in whole or in part, and

+all derivative works of the Software, unless such copies or derivative

+works are solely in the form of machine-executable object code generated by

+a source language processor.

+

+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR

+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,

+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT

+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE

+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,

+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER

+DEALINGS IN THE SOFTWARE.

diff --git a/README b/README
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/README
diff --git a/Test/ClassTests.cpp b/Test/ClassTests.cpp
new file mode 100644
index 0000000..9dd7147
--- /dev/null
+++ b/Test/ClassTests.cpp
@@ -0,0 +1,37 @@
+/*
+ *  ClassTests.cpp
+ *  Catch - Test
+ *
+ *  Created by Phil on 09/11/2010.
+ *  Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
+ *
+ *  Distributed under the Boost Software License, Version 1.0. (See accompanying
+ *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+
+#include "catch.hpp"
+
+namespace
+{
+    class TestClass
+    {
+        std::string s;
+        
+    public:
+        TestClass()
+        : s( "hello" )
+        {}
+        
+        void succeedingCase()
+        {            
+            EXPECT( s == "hello" );
+        }
+        void failingCase()
+        {            
+            EXPECT( s == "world" );
+        }
+    };
+}
+METHOD_AS_TEST_CASE( TestClass::succeedingCase, "succeeding/TestClass/succeedingCase", "A method based test run that succeeds" );
+METHOD_AS_TEST_CASE( TestClass::failingCase, "failing/TestClass/failingCase", "A method based test run that fails" );
diff --git a/Test/ConditionTests.cpp b/Test/ConditionTests.cpp
new file mode 100644
index 0000000..b310681
--- /dev/null
+++ b/Test/ConditionTests.cpp
@@ -0,0 +1,185 @@
+/*
+ *  ConditionTests.cpp
+ *  Catch - Test
+ *
+ *  Created by Phil on 08/11/2010.
+ *  Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
+ *
+ *  Distributed under the Boost Software License, Version 1.0. (See accompanying
+ *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+
+#include "catch.hpp"
+
+#include <string>
+
+struct TestData
+{
+    TestData()
+    :   int_seven( 7 ),
+        str_hello( "hello" ),
+        float_nine_point_one( 9.1f ),
+        double_pi( 3.1415926535 )
+    {}
+    
+    int int_seven;
+    std::string str_hello;
+    float float_nine_point_one;
+    double double_pi;
+};
+
+// These tests all use the CHECK macro, which continues if the specific test fails.
+// This allows us to see all results, even if an earlier check fails - which is 
+// particularly important for the "should fail" checks
+
+// Equality tests
+TEST_CASE( "succeeding/conditions/equality", "Equality checks that should succeed" )
+{
+    TestData data;
+    
+    CHECK( data.int_seven == 7 );
+    CHECK( data.float_nine_point_one == Approx( 9.1f ) );
+    CHECK( data.double_pi == Approx( 3.1415926535 ) );
+    CHECK( data.str_hello == "hello" );
+    CHECK( data.str_hello.size() == 5 );
+
+    double x = 1.1 + 0.1 + 0.1;
+    CHECK( x == Approx( 1.3 ) );
+}
+
+TEST_CASE( "failing/conditions/equality", "Equality checks that should fail" )
+{
+    TestData data;
+    
+    CHECK( data.int_seven == 6 );
+    CHECK( data.int_seven == 8 );
+    CHECK( data.int_seven == 0 );
+    CHECK( data.float_nine_point_one == Approx( 9.11f ) );
+    CHECK( data.float_nine_point_one == Approx( 9.0f ) );
+    CHECK( data.float_nine_point_one == 1 );
+    CHECK( data.float_nine_point_one == 0 );
+    CHECK( data.double_pi == Approx( 3.1415 ) );
+    CHECK( data.str_hello == "goodbye" );
+    CHECK( data.str_hello == "hell" );
+    CHECK( data.str_hello == "hello1" );
+    CHECK( data.str_hello.size() == 6 );
+
+    double x = 1.1 + 0.1 + 0.1;
+    CHECK( x == Approx( 1.301 ) );
+}
+
+TEST_CASE( "succeeding/conditions/inequality", "Inequality checks that should succeed" )
+{
+    TestData data;
+    
+    CHECK( data.int_seven != 6 );
+    CHECK( data.int_seven != 8 );
+    CHECK( data.float_nine_point_one != Approx( 9.11f ) );
+    CHECK( data.float_nine_point_one != Approx( 9.0f ) );
+    CHECK( data.float_nine_point_one != 1 );
+    CHECK( data.float_nine_point_one != 0 );
+    CHECK( data.double_pi != Approx( 3.1415 ) );
+    CHECK( data.str_hello != "goodbye" );
+    CHECK( data.str_hello != "hell" );
+    CHECK( data.str_hello != "hello1" );
+    CHECK( data.str_hello.size() != 6 );
+}
+
+TEST_CASE( "failing/conditions/inequality", "Inequality checks that should fails" )
+{
+    TestData data;
+    
+    CHECK( data.int_seven != 7 );
+    CHECK( data.float_nine_point_one != Approx( 9.1f ) );
+    CHECK( data.double_pi != Approx( 3.1415926535 ) );
+    CHECK( data.str_hello != "hello" );
+    CHECK( data.str_hello.size() != 5 );
+}
+
+// Ordering comparison tests
+TEST_CASE( "succeeding/conditions/ordered", "Ordering comparison checks that should succeed" )
+{
+    TestData data;
+    
+    CHECK( data.int_seven < 8 );
+    CHECK( data.int_seven > 6 );
+    CHECK( data.int_seven > 0 );
+    CHECK( data.int_seven > -1 );
+
+    CHECK( data.int_seven >= 7 );
+    CHECK( data.int_seven >= 6 );
+    CHECK( data.int_seven <= 7 );
+    CHECK( data.int_seven <= 8 );
+    
+    CHECK( data.float_nine_point_one > 9 );
+    CHECK( data.float_nine_point_one < 10 );
+    CHECK( data.float_nine_point_one < 9.2 );
+    
+    CHECK( data.str_hello <= "hello" );
+    CHECK( data.str_hello >= "hello" );
+    
+    CHECK( data.str_hello < "hellp" );
+    CHECK( data.str_hello < "z" );
+    CHECK( data.str_hello > "hellm" );
+    CHECK( data.str_hello > "a" );
+}
+
+TEST_CASE( "failing/conditions/ordered", "Ordering comparison checks that should fail" )
+{
+    TestData data;
+    
+    CHECK( data.int_seven > 7 );
+    CHECK( data.int_seven < 7 );
+    CHECK( data.int_seven > 8 );
+    CHECK( data.int_seven < 6 );
+    CHECK( data.int_seven < 0 );
+    CHECK( data.int_seven < -1 );
+
+    CHECK( data.int_seven >= 8 );
+    CHECK( data.int_seven <= 6 );
+    
+    CHECK( data.float_nine_point_one < 9 );
+    CHECK( data.float_nine_point_one > 10 );
+    CHECK( data.float_nine_point_one > 9.2 );
+    
+    CHECK( data.str_hello > "hello" );
+    CHECK( data.str_hello < "hello" );
+    CHECK( data.str_hello > "hellp" );
+    CHECK( data.str_hello > "z" );
+    CHECK( data.str_hello < "hellm" );
+    CHECK( data.str_hello < "a" );
+
+    CHECK( data.str_hello >= "z" );
+    CHECK( data.str_hello <= "a" );
+}
+
+// Not (!) tests
+TEST_CASE( "succeeding/conditions/not", "'Not' checks that should succeed" )
+{
+    bool falseValue = false;
+    
+    CHECK( !false );
+    CHECK_NOT( false );
+
+    CHECK( !falseValue );
+    CHECK_NOT( falseValue );
+
+    CHECK( !(1 == 2) );
+    CHECK_NOT( 1 == 2 );
+}
+
+TEST_CASE( "failing/conditions/not", "'Not' checks that should fail" )
+{
+    bool trueValue = true;
+    
+    CHECK( !true );
+    CHECK_NOT( true );
+    
+    CHECK( !trueValue );
+    CHECK_NOT( trueValue );
+    
+    CHECK( !(1 == 1) );
+    CHECK_NOT( 1 == 1 );
+}
+
diff --git a/Test/ExceptionTests.cpp b/Test/ExceptionTests.cpp
new file mode 100644
index 0000000..3bb222e
--- /dev/null
+++ b/Test/ExceptionTests.cpp
@@ -0,0 +1,58 @@
+/*
+ *  ExceptionTests.cpp
+ *  Catch - Test
+ *
+ *  Created by Phil on 09/11/2010.
+ *  Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
+ *
+ *  Distributed under the Boost Software License, Version 1.0. (See accompanying
+ *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+
+#include "catch.hpp"
+
+#include <string>
+
+namespace
+{
+    int thisThrows()
+    {
+        throw std::domain_error( "expected exception" );
+    }
+
+    int thisDoesntThrow()
+    {
+        return 0;
+    }
+}
+
+TEST_CASE( "succeeding/exceptions/explicit", "When checked exceptions are thrown they can be expected or unexpected" )
+{
+    CHECK_THROWS_AS( thisThrows(), std::domain_error );
+    CHECK_NOTHROW( thisDoesntThrow() );
+    EXPECT_THROWS( thisThrows() );
+}
+
+TEST_CASE( "failing/exceptions/explicit", "When checked exceptions are thrown they can be expected or unexpected" )
+{
+    CHECK_THROWS_AS( thisThrows(), std::string );
+    CHECK_THROWS_AS( thisDoesntThrow(), std::domain_error );
+    CHECK_NOTHROW( thisThrows() );
+}
+
+TEST_CASE( "failing/exceptions/implicit", "When unchecked exceptions are thrown they are always failures" )
+{
+    throw std::domain_error( "unexpected exception" );
+}
+
+TEST_CASE( "succeeding/exceptions/implicit", "When unchecked exceptions are thrown, but caught, they do not affect the test" )
+{
+    try
+    {
+        throw std::domain_error( "unexpected exception" );
+    }
+    catch(...)
+    {
+    }
+}
diff --git a/Test/MessageTests.cpp b/Test/MessageTests.cpp
new file mode 100644
index 0000000..be62f05
--- /dev/null
+++ b/Test/MessageTests.cpp
@@ -0,0 +1,24 @@
+/*
+ *  MessageTests.cpp
+ *  Catch - Test
+ *
+ *  Created by Phil on 09/11/2010.
+ *  Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
+ *
+ *  Distributed under the Boost Software License, Version 1.0. (See accompanying
+ *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+
+#include "catch.hpp"
+
+TEST_CASE( "succeeding/message", "INFO and WARN do not abort tests" )
+{
+    INFO( "this is a message" );    // This should output the message but continue
+    WARN( "this is a warning" );    // This should output the message but continue
+}
+
+TEST_CASE( "failing/message", "FAIL aborts the test" )
+{
+    FAIL( "This is a failure" );    // This should output the message and abort
+}
\ No newline at end of file
diff --git a/Test/Test.1 b/Test/Test.1
new file mode 100644
index 0000000..69da656
--- /dev/null
+++ b/Test/Test.1
@@ -0,0 +1,79 @@
+.\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples.
+.\"See Also:
+.\"man mdoc.samples for a complete listing of options
+.\"man mdoc for the short list of editing options
+.\"/usr/share/misc/mdoc.template
+.Dd 02/11/2010               \" DATE 
+.Dt Test 1      \" Program name and manual section number 
+.Os Darwin
+.Sh NAME                 \" Section Header - required - don't modify 
+.Nm Test,
+.\" The following lines are read in generating the apropos(man -k) database. Use only key
+.\" words here as the database is built based on the words here and in the .ND line. 
+.Nm Other_name_for_same_program(),
+.Nm Yet another name for the same program.
+.\" Use .Nm macro to designate other names for the documented program.
+.Nd This line parsed for whatis database.
+.Sh SYNOPSIS             \" Section Header - required - don't modify
+.Nm
+.Op Fl abcd              \" [-abcd]
+.Op Fl a Ar path         \" [-a path] 
+.Op Ar file              \" [file]
+.Op Ar                   \" [file ...]
+.Ar arg0                 \" Underlined argument - use .Ar anywhere to underline
+arg2 ...                 \" Arguments
+.Sh DESCRIPTION          \" Section Header - required - don't modify
+Use the .Nm macro to refer to your program throughout the man page like such:
+.Nm
+Underlining is accomplished with the .Ar macro like this:
+.Ar underlined text .
+.Pp                      \" Inserts a space
+A list of items with descriptions:
+.Bl -tag -width -indent  \" Begins a tagged list 
+.It item a               \" Each item preceded by .It macro
+Description of item a
+.It item b
+Description of item b
+.El                      \" Ends the list
+.Pp
+A list of flags and their descriptions:
+.Bl -tag -width -indent  \" Differs from above in tag removed 
+.It Fl a                 \"-a flag as a list item
+Description of -a flag
+.It Fl b
+Description of -b flag
+.El                      \" Ends the list
+.Pp
+.\" .Sh ENVIRONMENT      \" May not be needed
+.\" .Bl -tag -width "ENV_VAR_1" -indent \" ENV_VAR_1 is width of the string ENV_VAR_1
+.\" .It Ev ENV_VAR_1
+.\" Description of ENV_VAR_1
+.\" .It Ev ENV_VAR_2
+.\" Description of ENV_VAR_2
+.\" .El                      
+.Sh FILES                \" File used or created by the topic of the man page
+.Bl -tag -width "/Users/joeuser/Library/really_long_file_name" -compact
+.It Pa /usr/share/file_name
+FILE_1 description
+.It Pa /Users/joeuser/Library/really_long_file_name
+FILE_2 description
+.El                      \" Ends the list
+.\" .Sh DIAGNOSTICS       \" May not be needed
+.\" .Bl -diag
+.\" .It Diagnostic Tag
+.\" Diagnostic informtion here.
+.\" .It Diagnostic Tag
+.\" Diagnostic informtion here.
+.\" .El
+.Sh SEE ALSO 
+.\" List links in ascending order by section, alphabetically within a section.
+.\" Please do not reference files that do not exist without filing a bug report
+.Xr a 1 , 
+.Xr b 1 ,
+.Xr c 1 ,
+.Xr a 2 ,
+.Xr b 2 ,
+.Xr a 3 ,
+.Xr b 3 
+.\" .Sh BUGS              \" Document known, unremedied bugs 
+.\" .Sh HISTORY           \" Document history if command behaves in a unique manner 
\ No newline at end of file
diff --git a/Test/Test.xcodeproj/project.pbxproj b/Test/Test.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..1113be1
--- /dev/null
+++ b/Test/Test.xcodeproj/project.pbxproj
@@ -0,0 +1,271 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 45;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		4AFC340C128099F5003A0C29 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4AFC340B128099F5003A0C29 /* main.cpp */; };
+		4AFC38CD12887D80003A0C29 /* ConditionTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4AFC38CC12887D80003A0C29 /* ConditionTests.cpp */; };
+		4AFC3A9912893C56003A0C29 /* ExceptionTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4AFC3A9812893C56003A0C29 /* ExceptionTests.cpp */; };
+		4AFC3AA912893E54003A0C29 /* MessageTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4AFC3AA812893E54003A0C29 /* MessageTests.cpp */; };
+		4AFC3B0B12894114003A0C29 /* ClassTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4AFC3B0A12894114003A0C29 /* ClassTests.cpp */; };
+		4AFC3B671289C7E3003A0C29 /* TrickyTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4AFC3B661289C7E3003A0C29 /* TrickyTests.cpp */; };
+		8DD76F6A0486A84900D96B5E /* Test.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = C6859E8B029090EE04C91782 /* Test.1 */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+		8DD76F690486A84900D96B5E /* CopyFiles */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 8;
+			dstPath = /usr/share/man/man1/;
+			dstSubfolderSpec = 0;
+			files = (
+				8DD76F6A0486A84900D96B5E /* Test.1 in CopyFiles */,
+			);
+			runOnlyForDeploymentPostprocessing = 1;
+		};
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+		4AFC340B128099F5003A0C29 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = "<group>"; };
+		4AFC341512809A36003A0C29 /* catch_capture.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_capture.hpp; path = ../internal/catch_capture.hpp; sourceTree = SOURCE_ROOT; };
+		4AFC341612809A36003A0C29 /* catch_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = catch_common.h; path = ../internal/catch_common.h; sourceTree = SOURCE_ROOT; };
+		4AFC341712809A36003A0C29 /* catch_registry.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_registry.hpp; path = ../internal/catch_registry.hpp; sourceTree = SOURCE_ROOT; };
+		4AFC341812809A36003A0C29 /* catch_reporter_registry.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_reporter_registry.hpp; path = ../internal/catch_reporter_registry.hpp; sourceTree = SOURCE_ROOT; };
+		4AFC341912809A36003A0C29 /* catch_resultinfo.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_resultinfo.hpp; path = ../internal/catch_resultinfo.hpp; sourceTree = SOURCE_ROOT; };
+		4AFC341A12809A36003A0C29 /* catch_runner_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_runner_impl.hpp; path = ../internal/catch_runner_impl.hpp; sourceTree = SOURCE_ROOT; };
+		4AFC341B12809A36003A0C29 /* catch_testcaseinfo.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_testcaseinfo.hpp; path = ../internal/catch_testcaseinfo.hpp; sourceTree = SOURCE_ROOT; };
+		4AFC341C12809A45003A0C29 /* catch_default_main.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_default_main.hpp; path = ../catch_default_main.hpp; sourceTree = SOURCE_ROOT; };
+		4AFC341D12809A45003A0C29 /* catch_reporter_basic.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_reporter_basic.hpp; path = ../catch_reporter_basic.hpp; sourceTree = SOURCE_ROOT; };
+		4AFC341E12809A45003A0C29 /* catch_reporter_xml.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_reporter_xml.hpp; path = ../catch_reporter_xml.hpp; sourceTree = SOURCE_ROOT; };
+		4AFC341F12809A45003A0C29 /* catch_list.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_list.hpp; path = ../internal/catch_list.hpp; sourceTree = SOURCE_ROOT; };
+		4AFC342012809A45003A0C29 /* catch.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch.hpp; path = ../catch.hpp; sourceTree = SOURCE_ROOT; };
+		4AFC346412809D41003A0C29 /* catch_commandline.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_commandline.hpp; path = ../internal/catch_commandline.hpp; sourceTree = SOURCE_ROOT; };
+		4AFC359B1281F00B003A0C29 /* catch_section.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_section.hpp; path = ../internal/catch_section.hpp; sourceTree = SOURCE_ROOT; };
+		4AFC38161284B387003A0C29 /* catch_runner.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_runner.hpp; path = ../catch_runner.hpp; sourceTree = SOURCE_ROOT; };
+		4AFC384F1287E33E003A0C29 /* catch_runnerconfig.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_runnerconfig.hpp; path = ../catch_runnerconfig.hpp; sourceTree = SOURCE_ROOT; };
+		4AFC38CC12887D80003A0C29 /* ConditionTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConditionTests.cpp; sourceTree = "<group>"; };
+		4AFC3A9812893C56003A0C29 /* ExceptionTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExceptionTests.cpp; sourceTree = "<group>"; };
+		4AFC3AA812893E54003A0C29 /* MessageTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MessageTests.cpp; sourceTree = "<group>"; };
+		4AFC3B0A12894114003A0C29 /* ClassTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ClassTests.cpp; sourceTree = "<group>"; };
+		4AFC3B661289C7E3003A0C29 /* TrickyTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TrickyTests.cpp; sourceTree = "<group>"; };
+		8DD76F6C0486A84900D96B5E /* Test */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = Test; sourceTree = BUILT_PRODUCTS_DIR; };
+		C6859E8B029090EE04C91782 /* Test.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = Test.1; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		8DD76F660486A84900D96B5E /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		08FB7794FE84155DC02AAC07 /* Test */ = {
+			isa = PBXGroup;
+			children = (
+				08FB7795FE84155DC02AAC07 /* Source */,
+				C6859E8C029090F304C91782 /* Documentation */,
+				1AB674ADFE9D54B511CA2CBB /* Products */,
+			);
+			name = Test;
+			sourceTree = "<group>";
+		};
+		08FB7795FE84155DC02AAC07 /* Source */ = {
+			isa = PBXGroup;
+			children = (
+				4AFC341312809A12003A0C29 /* Catch */,
+				4AFC340B128099F5003A0C29 /* main.cpp */,
+				4AFC38CC12887D80003A0C29 /* ConditionTests.cpp */,
+				4AFC3A9812893C56003A0C29 /* ExceptionTests.cpp */,
+				4AFC3AA812893E54003A0C29 /* MessageTests.cpp */,
+				4AFC3B0A12894114003A0C29 /* ClassTests.cpp */,
+				4AFC3B661289C7E3003A0C29 /* TrickyTests.cpp */,
+			);
+			name = Source;
+			sourceTree = "<group>";
+		};
+		1AB674ADFE9D54B511CA2CBB /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				8DD76F6C0486A84900D96B5E /* Test */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		4AFC341312809A12003A0C29 /* Catch */ = {
+			isa = PBXGroup;
+			children = (
+				4AFC342012809A45003A0C29 /* catch.hpp */,
+				4AFC341C12809A45003A0C29 /* catch_default_main.hpp */,
+				4AFC341D12809A45003A0C29 /* catch_reporter_basic.hpp */,
+				4AFC341E12809A45003A0C29 /* catch_reporter_xml.hpp */,
+				4AFC38161284B387003A0C29 /* catch_runner.hpp */,
+				4AFC341412809A1B003A0C29 /* Internal */,
+			);
+			name = Catch;
+			sourceTree = "<group>";
+		};
+		4AFC341412809A1B003A0C29 /* Internal */ = {
+			isa = PBXGroup;
+			children = (
+				4AFC341F12809A45003A0C29 /* catch_list.hpp */,
+				4AFC359B1281F00B003A0C29 /* catch_section.hpp */,
+				4AFC346412809D41003A0C29 /* catch_commandline.hpp */,
+				4AFC341512809A36003A0C29 /* catch_capture.hpp */,
+				4AFC341612809A36003A0C29 /* catch_common.h */,
+				4AFC341712809A36003A0C29 /* catch_registry.hpp */,
+				4AFC341812809A36003A0C29 /* catch_reporter_registry.hpp */,
+				4AFC341912809A36003A0C29 /* catch_resultinfo.hpp */,
+				4AFC341A12809A36003A0C29 /* catch_runner_impl.hpp */,
+				4AFC341B12809A36003A0C29 /* catch_testcaseinfo.hpp */,
+				4AFC384F1287E33E003A0C29 /* catch_runnerconfig.hpp */,
+			);
+			name = Internal;
+			sourceTree = "<group>";
+		};
+		C6859E8C029090F304C91782 /* Documentation */ = {
+			isa = PBXGroup;
+			children = (
+				C6859E8B029090EE04C91782 /* Test.1 */,
+			);
+			name = Documentation;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+		8DD76F620486A84900D96B5E /* Test */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 1DEB923108733DC60010E9CD /* Build configuration list for PBXNativeTarget "Test" */;
+			buildPhases = (
+				8DD76F640486A84900D96B5E /* Sources */,
+				8DD76F660486A84900D96B5E /* Frameworks */,
+				8DD76F690486A84900D96B5E /* CopyFiles */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = Test;
+			productInstallPath = "$(HOME)/bin";
+			productName = Test;
+			productReference = 8DD76F6C0486A84900D96B5E /* Test */;
+			productType = "com.apple.product-type.tool";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		08FB7793FE84155DC02AAC07 /* Project object */ = {
+			isa = PBXProject;
+			buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "Test" */;
+			compatibilityVersion = "Xcode 3.1";
+			hasScannedForEncodings = 1;
+			mainGroup = 08FB7794FE84155DC02AAC07 /* Test */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				8DD76F620486A84900D96B5E /* Test */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXSourcesBuildPhase section */
+		8DD76F640486A84900D96B5E /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				4AFC340C128099F5003A0C29 /* main.cpp in Sources */,
+				4AFC38CD12887D80003A0C29 /* ConditionTests.cpp in Sources */,
+				4AFC3A9912893C56003A0C29 /* ExceptionTests.cpp in Sources */,
+				4AFC3AA912893E54003A0C29 /* MessageTests.cpp in Sources */,
+				4AFC3B0B12894114003A0C29 /* ClassTests.cpp in Sources */,
+				4AFC3B671289C7E3003A0C29 /* TrickyTests.cpp in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+		1DEB923208733DC60010E9CD /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				COPY_PHASE_STRIP = NO;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_MODEL_TUNING = G5;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				INSTALL_PATH = /usr/local/bin;
+				PRODUCT_NAME = Test;
+			};
+			name = Debug;
+		};
+		1DEB923308733DC60010E9CD /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				GCC_MODEL_TUNING = G5;
+				INSTALL_PATH = /usr/local/bin;
+				PRODUCT_NAME = Test;
+			};
+			name = Release;
+		};
+		1DEB923608733DC60010E9CD /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				ONLY_ACTIVE_ARCH = YES;
+				PREBINDING = NO;
+				SDKROOT = macosx10.6;
+			};
+			name = Debug;
+		};
+		1DEB923708733DC60010E9CD /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				PREBINDING = NO;
+				SDKROOT = macosx10.6;
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		1DEB923108733DC60010E9CD /* Build configuration list for PBXNativeTarget "Test" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				1DEB923208733DC60010E9CD /* Debug */,
+				1DEB923308733DC60010E9CD /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "Test" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				1DEB923608733DC60010E9CD /* Debug */,
+				1DEB923708733DC60010E9CD /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
+}
diff --git a/Test/TrickyTests.cpp b/Test/TrickyTests.cpp
new file mode 100644
index 0000000..51ee889
--- /dev/null
+++ b/Test/TrickyTests.cpp
@@ -0,0 +1,34 @@
+/*
+ *  TrickyTests.cpp
+ *  Catch - Test
+ *
+ *  Created by Phil on 09/11/2010.
+ *  Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
+ *
+ *  Distributed under the Boost Software License, Version 1.0. (See accompanying
+ *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+
+#include "catch.hpp"
+
+namespace Catch
+{
+    template<>
+    std::string toString<std::pair<int, int> >( const std::pair<int, int>& value )
+    {
+        std::ostringstream oss;
+        oss << "std::pair( " << value.first << ", " << value.second << " )";
+        return oss.str();
+        
+    }
+}
+
+TEST_CASE( "succeeding/Tricky", "Some tricky to parse tests" )
+{
+    std::pair<int, int> aNicePair( 1, 2 );
+
+    // !TBD: would be nice if this could compile without the extra parentheses
+    EXPECT( (std::pair<int, int>( 1, 2 )) == aNicePair );
+    
+}
\ No newline at end of file
diff --git a/Test/main.cpp b/Test/main.cpp
new file mode 100644
index 0000000..ee0806e
--- /dev/null
+++ b/Test/main.cpp
@@ -0,0 +1,53 @@
+/*
+ *  main.cpp
+ *  Catch - Test
+ *
+ *  Created by Phil on 22/10/2010.
+ *  Copyright 2010 Two Blue Cubes Ltd
+ *
+ *  Distributed under the Boost Software License, Version 1.0. (See accompanying
+ *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+
+#include "catch.hpp"
+#include "catch_runner.hpp"
+
+// This code runs the meta tests and verifies that the failing ones failed and the successful ones succeeded
+int main (int argc, char * const argv[])
+{
+    using namespace Catch;
+        
+    ReporterConfig reporterConfig( ReporterConfig::Include::SuccessfulResults );
+    BasicReporter reporter (reporterConfig );
+    Runner runner;
+    runner.setReporter( &reporter );
+
+    std::ostringstream ossSucceeding;
+    reporterConfig.setStreamBuf( ossSucceeding.rdbuf() );
+    runner.runMatching( "succeeding/*" );
+    std::string succeedingResults = ossSucceeding.str();
+    
+    std::ostringstream ossFailing;
+    reporterConfig.setStreamBuf( ossFailing.rdbuf() );
+    runner.runMatching( "failing/*" );
+    std::string failingResults = ossFailing.str();
+
+    int result = 0;
+    if( succeedingResults.find( "failed" ) != std::string::npos )
+    {
+        std::cerr << "Some tests that should have succeeded failed:\n\n" << succeedingResults;
+        result = 1;
+    }
+    if( failingResults.find( "succeeded" ) != std::string::npos )
+    {
+        std::cerr << "Some tests that should have failed succeeded:\n\n" << failingResults;
+        result = 1;
+    }
+    
+    if( result == 0 )
+    {
+        std::cout << "All tests completed successfully" << std::endl;
+    }
+    return result;
+}
diff --git a/catch.hpp b/catch.hpp
new file mode 100644
index 0000000..5bbd469
--- /dev/null
+++ b/catch.hpp
@@ -0,0 +1,65 @@
+/*
+ *  catch.hpp
+ *  Catch
+ *
+ *  Created by Phil on 22/10/2010.
+ *  Copyright 2010 Two Blue Cubes Ltd
+ *
+ *  Distributed under the Boost Software License, Version 1.0. (See accompanying
+ *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+
+/* TBD:
+ 
+ Next:
+
+ Later:
+    Finish command line parser (list as xml, specify FP tolerance)
+    INFO() stores messages until next result
+    Revisit Approx()
+    Extra reports
+    Tags?
+    Detect caught "Catch" exception, offer continuation based iteration instead
+    Finish macros, listed here, later (just CHECK_NOFAIL now)
+ */
+#ifndef TWOBLUECUBES_CATCH_HPP_INCLUDED
+#define TWOBLUECUBES_CATCH_HPP_INCLUDED
+
+#include "internal/catch_registry.hpp"
+#include "internal/catch_capture.hpp"
+#include "internal/catch_section.hpp"
+
+//////
+
+#define EXPECT( pred ) _CATCH_TEST( pred, false, true, "EXPECT" )
+#define EXPECT_NOT( pred ) _CATCH_TEST( pred, true, true, "EXPECT_NOT" )
+
+#define EXPECT_THROWS( expr ) _CATCH_THROWS( expr, ..., false, true, "EXPECT_THROWS" )
+#define EXPECT_THROWS_AS( expr, exceptionType ) _CATCH_THROWS_AS( expr, exceptionType, false, true, "EXPECT_THROWS_AS" )
+
+#define CHECK( pred ) _CATCH_TEST( pred, false, false, "CHECK" )
+#define CHECK_NOT( pred ) _CATCH_TEST( pred, true, false, "CHECK_NOT" )
+
+#define CHECK_THROWS( expr )  _CATCH_THROWS( expr, ..., false. false, "CHECK_THROWS" )
+#define CHECK_THROWS_AS( expr, exceptionType ) _CATCH_THROWS_AS( expr, exceptionType, false, false, "CHECK_THROWS_AS" )
+#define CHECK_NOTHROW( expr ) _CATCH_THROWS_AS( expr, Catch::DummyExceptionType_DontUse, true, false, "CHECK_NOTHROW" )
+
+#define INFO( reason ) _CATCH_MSG( reason, Catch::ResultWas::Info, false, "INFO" )
+#define WARN( reason ) _CATCH_MSG( reason, Catch::ResultWas::Warning, false, "WARN" )
+#define FAIL( reason ) _CATCH_MSG( reason, Catch::ResultWas::ExplicitFailure, true, "FAIL" )
+
+#define SECTION( name, description ) CATCH_SECTION( name, description )
+
+#define TEST_CASE( name, description ) CATCH_TEST_CASE( name, description )
+#define METHOD_AS_TEST_CASE( method, name, description ) CATCH_METHOD_AS_TEST_CASE( method, name, description )
+
+#define REGISTER_REPORTER( name, reporterType ) CATCH_REGISTER_REPORTER( name, reporterType )
+
+///////////////
+// Still to be implemented
+#define CHECK_NOFAIL( pred ) // !TBD - reports violation, but doesn't fail Test
+
+using Catch::Approx;
+
+#endif // TWOBLUECUBES_CATCH_HPP_INCLUDED
\ No newline at end of file
diff --git a/catch_default_main.hpp b/catch_default_main.hpp
new file mode 100644
index 0000000..a22ac97
--- /dev/null
+++ b/catch_default_main.hpp
@@ -0,0 +1,23 @@
+/*
+ *  catch_default_main.hpp
+ *  Catch
+ *
+ *  Created by Phil on 01/11/2010.
+ *  Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
+ *
+ *  Distributed under the Boost Software License, Version 1.0. (See accompanying
+ *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+#ifndef TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
+#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
+
+#include "catch_runner.hpp"
+#include "catch.hpp"
+
+int main (int argc, char * const argv[])
+{
+    return Catch::Main( argc, argv );
+}
+
+#endif // TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
\ No newline at end of file
diff --git a/catch_reporter_basic.hpp b/catch_reporter_basic.hpp
new file mode 100644
index 0000000..bdd52ad
--- /dev/null
+++ b/catch_reporter_basic.hpp
@@ -0,0 +1,99 @@
+/*
+ *  catch_reporter_basic.hpp
+ *  Catch
+ *
+ *  Created by Phil on 28/10/2010.
+ *  Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
+ *
+ *  Distributed under the Boost Software License, Version 1.0. (See accompanying
+ *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+#ifndef TWOBLUECUBES_CATCH_REPORTER_BASIC_HPP_INCLUDED
+#define TWOBLUECUBES_CATCH_REPORTER_BASIC_HPP_INCLUDED
+
+#include "internal/catch_capture.hpp"
+#include "internal/catch_reporter_registry.hpp"
+
+namespace Catch
+{
+    class BasicReporter : public ITestReporter
+    {
+    public:
+        ///////////////////////////////////////////////////////////////////////////
+        BasicReporter( const ReporterConfig& config )
+        :   m_config( config )
+        {
+        }
+
+        ///////////////////////////////////////////////////////////////////////////
+        static std::string getDescription()
+        {
+            return "Reports test results as lines of text";
+        }
+        
+    private: // ITestReporter
+        
+        ///////////////////////////////////////////////////////////////////////////
+        virtual void StartTestCase( const TestCaseInfo& testInfo )
+        {
+            m_config.stream() << std::endl << "[Running: " << testInfo.getName() << "]" << std::endl;
+        }
+        
+        ///////////////////////////////////////////////////////////////////////////
+        virtual void Result( const ResultInfo& resultInfo )
+        {
+            if( !m_config.includeSuccessfulResults() && resultInfo.ok() )
+                return;
+            
+            if( !resultInfo.getFilename().empty() )
+                m_config.stream() << resultInfo.getFilename() << "(" << resultInfo.getLine() << "): ";
+            
+            if( resultInfo.hasExpression() )
+            {
+                m_config.stream() << resultInfo.getExpression();
+                if( resultInfo.ok() )
+                    m_config.stream() << " succeeded";
+                else
+                    m_config.stream() << " failed";
+            }
+            switch( resultInfo.getResultType() )
+            {
+                case ResultWas::ThrewException:
+                    if( resultInfo.hasExpression() )
+                        m_config.stream() << " with unexpected";
+                    else
+                        m_config.stream() << "Unexpected";
+                    m_config.stream() << " exception with message: '" << resultInfo.getMessage() << "'";
+                    break;
+                case ResultWas::Info:
+                    m_config.stream() << "info: '" << resultInfo.getMessage() << "'";
+                    break;
+                case ResultWas::Warning:
+                    m_config.stream() << "warning: '" << resultInfo.getMessage() << "'";
+                    break;
+                case ResultWas::ExplicitFailure:
+                    m_config.stream() << "failed with message: '" << resultInfo.getMessage() << "'";
+                    break;
+            }
+            
+            if( resultInfo.hasExpression() )
+            {
+                m_config.stream() << " for: " << resultInfo.getExpandedExpression();
+            }
+            m_config.stream() << std::endl;        
+        }
+        
+        ///////////////////////////////////////////////////////////////////////////
+        virtual void EndTestCase( const TestCaseInfo& testInfo )
+        {
+            m_config.stream() << "[Finished: " << testInfo.getName() << "]" << std::endl;
+        }    
+        
+    private:
+        const ReporterConfig& m_config;
+    };
+    
+} // end namespace Catch
+    
+#endif // TWOBLUECUBES_CATCH_REPORTER_BASIC_HPP_INCLUDED
\ No newline at end of file
diff --git a/catch_reporter_xml.hpp b/catch_reporter_xml.hpp
new file mode 100644
index 0000000..34dd863
--- /dev/null
+++ b/catch_reporter_xml.hpp
@@ -0,0 +1,98 @@
+/*
+ *  catch_reporter_xml.hpp
+ *  Catch
+ *
+ *  Created by Phil on 28/10/2010.
+ *  Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
+ *
+ *  Distributed under the Boost Software License, Version 1.0. (See accompanying
+ *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+#ifndef TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
+#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
+
+#include "internal/catch_capture.hpp"
+#include "internal/catch_reporter_registry.hpp"
+#include <iostream>
+
+namespace Catch
+{
+    class XmlReporter : public Catch::ITestReporter
+    {
+    public:
+        ///////////////////////////////////////////////////////////////////////////
+        XmlReporter( const ReporterConfig& config = ReporterConfig() )
+        :   m_config( config )
+        {
+        }        
+
+        ///////////////////////////////////////////////////////////////////////////
+        static std::string getDescription()
+        {
+            return "Reports test results as an XML document";
+        }
+        
+    private: // ITestReporter
+
+        ///////////////////////////////////////////////////////////////////////////
+        virtual void StartTestCase( const Catch::TestCaseInfo& testInfo )
+        {
+            m_config.stream() << "<TestCase name='" << testInfo.getName() << "'>\n";
+            m_currentTestSuccess = true;
+        }
+        
+        ///////////////////////////////////////////////////////////////////////////
+        virtual void Result( const Catch::ResultInfo& resultInfo )
+        {
+            if( !m_config.includeSuccessfulResults() && resultInfo.ok() )
+                return;
+
+            if( resultInfo.hasExpression() )
+            {
+                m_config.stream()   << "\t<Expression success='" << (resultInfo.ok() ? "true" : "false") << "' "
+                << "filename='" << resultInfo.getFilename() << "' line='" << resultInfo.getLine() << "'>\n"
+                << "\t\t<Original>" << resultInfo.getExpression() << "</Original>\n"
+                << "\t\t<Expanded>" << resultInfo.getExpandedExpression() << "</Expanded>\n";
+                m_currentTestSuccess |= resultInfo.ok();
+            }
+            switch( resultInfo.getResultType() )
+            {
+                case ResultWas::ThrewException:
+                    if( resultInfo.hasExpression() )
+                        m_config.stream() << "\t";
+                    m_config.stream() << "\t<Exception>" << resultInfo.getMessage() << "</Exception>\n";
+                    m_currentTestSuccess = false;
+                    break;
+                case ResultWas::Info:
+                    m_config.stream() << "\t<Info>" << resultInfo.getMessage() << "</Info>\n";
+                    break;
+                case ResultWas::Warning:
+                    m_config.stream() << "\t<Warning>" << resultInfo.getMessage() << "</Warning>\n";
+                    break;
+                case ResultWas::ExplicitFailure:
+                    m_config.stream() << "\t<Failure>" << resultInfo.getMessage() << "</Failure>\n";
+                    m_currentTestSuccess = false;
+                    break;
+            }            
+            if( resultInfo.hasExpression() )
+            {
+                m_config.stream()   << "\t</Expression>\n";
+            }
+        }
+        
+        ///////////////////////////////////////////////////////////////////////////
+        virtual void EndTestCase( const Catch::TestCaseInfo& testInfo )
+        {
+            m_config.stream() << "\t<OverallResult success='" << (m_currentTestSuccess ? "true" : "false" ) << "/>\n";
+            m_config.stream() << "</TestCase>" << std::endl;
+        }    
+                
+    private:
+        const ReporterConfig& m_config;
+        bool m_currentTestSuccess;
+    };
+
+} // end namespace Catch
+
+#endif // TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
\ No newline at end of file
diff --git a/catch_runner.hpp b/catch_runner.hpp
new file mode 100644
index 0000000..cdf6653
--- /dev/null
+++ b/catch_runner.hpp
@@ -0,0 +1,82 @@
+/*
+ *  catch_runner.hpp
+ *  Catch
+ *
+ *  Created by Phil on 31/10/2010.
+ *  Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
+ *
+ *  Distributed under the Boost Software License, Version 1.0. (See accompanying
+ *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+
+#ifndef TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
+#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
+
+#include "internal/catch_commandline.hpp"
+#include "internal/catch_list.hpp"
+#include "catch_reporter_basic.hpp"
+#include "catch_reporter_xml.hpp"
+
+namespace Catch
+{
+    inline int Main( int argc, char * const argv[] )
+    {
+        ReporterRegistry::instance().registerReporter<BasicReporter>( "basic" );
+        ReporterRegistry::instance().registerReporter<XmlReporter>( "xml" );
+
+        RunnerConfig config;
+        ArgParser( argc, argv, config );     
+        
+        if( !config.m_message.empty() )
+        {
+            std::cerr << config.m_message << std::endl;
+            return std::numeric_limits<int>::max();
+        }
+        
+        // Handle list request
+        if( config.listWhat() != RunnerConfig::listNone )
+            return List( config );
+        
+        // Open output file, if specified
+        std::ofstream ofs;
+        if( !config.getFilename().empty() )
+        {
+            ofs.open( config.getFilename().c_str() );
+            if( ofs.fail() )
+            {
+                std::cerr << "Unable to open file: '" << config.getFilename() << "'" << std::endl;
+                return std::numeric_limits<int>::max();
+            }
+            config.getReporterConfig().setStreamBuf( ofs.rdbuf() );
+        }
+
+        Runner runner;
+        runner.setReporter( config.getReporter() );
+
+        // Run test specs specified on the command line - or default to all
+        if( config.m_testSpecs.size() == 0 )
+        {
+            runner.runAll();
+        }
+        else
+        {
+            // !TBD We should get all the testcases upfront, report any missing,
+            // then just run them
+            std::vector<std::string>::const_iterator it = config.m_testSpecs.begin();
+            std::vector<std::string>::const_iterator itEnd = config.m_testSpecs.end();
+            for(; it != itEnd; ++it )
+            {
+                if( runner.runMatching( *it ) == 0 )
+                {
+                    // Use reporter?
+                    std::cerr << "\n[Unable to match any test cases with: " << *it << "]" << std::endl;
+                }
+            }
+        }
+        return runner.getFailures();
+    }
+    
+} // end namespace Catch
+
+#endif // TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
\ No newline at end of file
diff --git a/catch_runnerconfig.hpp b/catch_runnerconfig.hpp
new file mode 100644
index 0000000..19b4840
--- /dev/null
+++ b/catch_runnerconfig.hpp
@@ -0,0 +1,126 @@
+/*
+ *  catch_runnerconfig.hpp
+ *  Catch
+ *
+ *  Created by Phil on 08/11/2010.
+ *  Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
+ *
+ *  Distributed under the Boost Software License, Version 1.0. (See accompanying
+ *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+
+#ifndef TWOBLUECUBES_CATCH_RUNNERCONFIG_HPP_INCLUDED
+#define TWOBLUECUBES_CATCH_RUNNERCONFIG_HPP_INCLUDED
+
+#include "catch_reporter_registry.hpp"
+
+#include <vector>
+#include <string>
+
+namespace Catch
+{
+    class RunnerConfig
+    {
+    public:
+        
+        enum ListInfo
+        {
+            listNone = 0,
+            
+            listReports = 1,
+            listTests = 2,
+            listAll = 3,
+            
+            listWhatMask = 0xf,
+            
+            listAsText = 0x10,
+            listAsXml = 0x11,
+            
+            listAsMask = 0xf0
+        };
+        
+        
+        RunnerConfig()
+        :   m_listSpec( listNone ),
+            m_reporter( NULL )
+        {}
+        
+        void setReporterInfo( const std::string& reporterName )
+        {
+            if( m_reporter.get() )
+                return setError( "Only one reporter may be specified" );
+            setReporter( ReporterRegistry::instance().create( reporterName, m_reporterConfig ) );
+        }
+        
+        void addTestSpec( const std::string& testSpec )
+        {
+            m_testSpecs.push_back( testSpec );
+        }
+        void setListSpec( ListInfo listSpec )
+        {
+            m_listSpec = listSpec;
+        }
+        
+        void setFilename( const std::string& filename )
+        {
+            m_filename = filename;
+        }
+        
+        std::string getFilename()
+        {
+            return m_filename;
+        }
+        
+        void setError( const std::string& errorMessage )
+        {
+            m_message = errorMessage + "\n\n" + "Usage: ...";
+        }
+        
+        void setReporter( ITestReporter* reporter )
+        {
+            m_reporter = std::auto_ptr<ITestReporter>( reporter );
+        }
+        
+        ITestReporter* getReporter()
+        {
+            if( !m_reporter.get() )
+                setReporter( ReporterRegistry::instance().create( "basic", m_reporterConfig ) );
+            return m_reporter.get();
+        }
+        
+        const ITestReporter* getReporter() const
+        {
+            return const_cast<RunnerConfig*>( this )->getReporter();
+        }
+        
+        ListInfo listWhat() const
+        {
+            return (ListInfo)( m_listSpec & listWhatMask );
+        }
+        
+        ListInfo listAs() const
+        {
+            return (ListInfo)( m_listSpec & listAsMask );
+        }        
+        
+        ReporterConfig& getReporterConfig()
+        {
+            return m_reporterConfig;
+        }
+        void setIncludeAll( bool includeAll )
+        {
+            m_reporterConfig.setIncludeWhat( includeAll ? ReporterConfig::Include::SuccessfulResults : ReporterConfig::Include::FailedOnly );
+        }
+        
+        std::auto_ptr<ITestReporter> m_reporter;
+        std::string m_filename;
+        ReporterConfig m_reporterConfig;
+        std::string m_message;
+        ListInfo m_listSpec;
+        std::vector<std::string> m_testSpecs;
+    };
+    
+} // end namespace Catch
+
+#endif // TWOBLUECUBES_CATCH_RUNNERCONFIG_HPP_INCLUDED
\ No newline at end of file
diff --git a/internal/catch_capture.hpp b/internal/catch_capture.hpp
new file mode 100644
index 0000000..2a01eee
--- /dev/null
+++ b/internal/catch_capture.hpp
@@ -0,0 +1,279 @@
+/*
+ *  catch_capture.hpp
+ *  Catch
+ *
+ *  Created by Phil on 18/10/2010.
+ *  Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
+ *
+ *  Distributed under the Boost Software License, Version 1.0. (See accompanying
+ *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+#ifndef TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
+#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
+
+#include "catch_resultinfo.hpp"
+#include <sstream>
+#include "math.h"
+
+namespace Catch
+{
+
+template<typename T>
+std::string toString( const T& value )
+{
+    std::ostringstream oss;
+    oss << value;
+    return oss.str();
+}
+
+class TestFailureException
+{
+};
+class DummyExceptionType_DontUse
+{
+};
+    
+class MutableResultInfo : public ResultInfo
+{
+public:
+    
+    MutableResultInfo()
+    {}
+    
+    MutableResultInfo( const std::string& expr, bool isNot, const std::string& filename, size_t line, const std::string& macroName )
+    : ResultInfo( ( isNot ? "!" : "" ) + expr, ResultWas::Unknown, isNot, filename, line, macroName )
+    {
+    }
+    void setResultType( ResultWas::OfType result )
+    {
+        // Flip bool results if isNot is set
+        if( m_isNot && result == ResultWas::Ok )
+            m_result = ResultWas::ExpressionFailed;
+        else if( m_isNot && result == ResultWas::ExpressionFailed )
+            m_result = ResultWas::Ok;
+        else
+            m_result = result;        
+    }
+    void setMessage( const std::string& message )
+    {
+        m_message = message;
+    }
+    
+private:
+    friend class ResultBuilder;
+    void setLhs( const std::string& lhs )
+    {
+        m_lhs = lhs;
+    }    
+    MutableResultInfo& setRhs( const std::string& op, const std::string& rhs )
+    {
+        m_op = op;
+        m_rhs = rhs;
+        return *this;
+    }    
+};
+    
+class ResultBuilder
+{
+public:
+    ResultBuilder( const char* expr, bool isNot, const std::string& filename, size_t line, const std::string& macroName )
+    : m_result( expr, isNot, filename, line, macroName )
+    {}
+    
+    template<typename T>
+    ResultBuilder& operator->*(const T & operand)
+    {
+        m_result.setLhs( toString( operand ) );
+        return *this;
+    }
+    
+    template<typename RhsT>
+    MutableResultInfo& operator == ( const RhsT& rhs )
+    {
+        return m_result.setRhs( "==", toString( rhs ) );
+    }    
+    template<typename RhsT>
+    MutableResultInfo& operator != ( const RhsT& rhs )
+    {
+        return m_result.setRhs( "!=", toString( rhs ) );
+    }    
+    template<typename RhsT>
+    MutableResultInfo& operator < ( const RhsT& rhs )
+    {
+        return m_result.setRhs( "<", toString( rhs ) );
+    }    
+    template<typename RhsT>
+    MutableResultInfo& operator > ( const RhsT& rhs )
+    {
+        return m_result.setRhs( ">", toString( rhs ) );
+    }    
+    template<typename RhsT>
+    MutableResultInfo& operator <= ( const RhsT& rhs )
+    {
+        return m_result.setRhs( "<=", toString( rhs ) );
+    }    
+    template<typename RhsT>
+    MutableResultInfo& operator >= ( const RhsT& rhs )
+    {
+        return m_result.setRhs( ">=", toString( rhs ) );
+    }    
+    operator MutableResultInfo&()
+    {
+        return m_result;
+    }
+    
+private:
+    MutableResultInfo m_result;
+    
+};
+
+class TestCaseInfo;
+    
+struct IResultListener
+{
+    virtual ~IResultListener(){}
+    virtual void testEnded( const ResultInfo& result ) = 0;
+};
+    
+class ResultsCapture
+{
+private:
+    ResultsCapture()
+    : m_listener( 0 )
+    {
+    }
+
+    static ResultsCapture& instance()
+    {
+        static ResultsCapture instance;
+        return instance;
+    }
+    
+public:
+    
+    static IResultListener* setListener( IResultListener* listener )
+    {
+        IResultListener* prevListener = instance().m_listener;
+        instance().m_listener = listener;
+        return prevListener;
+    }
+
+    static void acceptExpression( const MutableResultInfo& resultInfo )
+    {
+        instance().currentResult = resultInfo;
+    }
+
+    static void acceptResult( bool result, bool stopOnFail )
+    {
+        acceptResult( result ? ResultWas::Ok : ResultWas::ExpressionFailed, stopOnFail );
+    }
+    
+    static void acceptResult( ResultWas::OfType result, bool stopOnFail )
+    {
+        if( !acceptResult( result ) && stopOnFail )
+        {
+            throw TestFailureException();
+        }
+    }
+    
+    static bool acceptResult( ResultWas::OfType result )
+    {
+        MutableResultInfo& currentResult = instance().currentResult;
+        currentResult.setResultType( result );
+        
+        if( instance().m_listener )
+        {
+            instance().m_listener->testEnded( currentResult );
+        }
+        bool ok = currentResult.ok();
+        instance().currentResult = MutableResultInfo();
+        return ok;
+    }
+
+    static bool acceptResult( bool expressionResult )
+    {
+        return acceptResult( expressionResult ? ResultWas::Ok : ResultWas::ExpressionFailed );
+    }
+    
+    static void acceptMessage( const std::string& msg )
+    {
+        instance().currentResult.setMessage( msg );
+    }
+    
+private:
+    MutableResultInfo currentResult;
+    IResultListener* m_listener;
+};
+
+// !TBD Need to clean this all up
+#define CATCH_absTol 1e-10
+#define CATCH_relTol 1e-10
+
+class Approx
+{
+public:
+    // !TBD more generic
+    Approx( double d )
+    : m_d( d )
+    {
+    }
+    template<typename T>
+    friend bool operator == ( const T& lhs, const Approx& rhs )
+    {
+        // !TBD Use proper tolerance
+        // From: http://realtimecollisiondetection.net/blog/?p=89
+        // see also: http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
+        return fabs( lhs - rhs.m_d ) <= std::max( CATCH_absTol, CATCH_relTol * std::max( fabs(lhs), fabs(rhs.m_d) ) );
+    }
+    
+    template<typename T>
+    friend bool operator != ( const T& lhs, const Approx& rhs )
+    {
+        return ! operator==( lhs, rhs );
+    }
+    
+    double m_d;
+};
+
+template<>
+inline std::string toString<Approx>( const Approx& value )
+{
+    std::ostringstream oss;
+    oss << "Approx( " << value.m_d << ")";
+    return oss.str();
+}
+
+    
+} // end namespace Catch
+
+#define _CATCH_TEST( expr, isNot, stopOnFailure, macroName ) \
+    Catch::ResultsCapture::acceptExpression( Catch::ResultBuilder( #expr, isNot, __FILE__, __LINE__, macroName )->*expr ); \
+    Catch::ResultsCapture::acceptResult( expr, stopOnFailure );
+
+#define _CATCH_THROWS( expr, exceptionType, nothrow, stopOnFailure, macroName ) \
+    Catch::ResultsCapture::acceptExpression( Catch::ResultBuilder( #expr, false, __FILE__, __LINE__, macroName ) ); \
+    try \
+    { \
+        expr; \
+        Catch::ResultsCapture::acceptResult( nothrow, stopOnFailure ); \
+    } \
+    catch( exceptionType ) \
+    { \
+        Catch::ResultsCapture::acceptResult( !(nothrow), stopOnFailure ); \
+    }
+
+#define _CATCH_THROWS_AS( expr, exceptionType, nothrow, stopOnFailure, macroName ) \
+_CATCH_THROWS( expr, exceptionType, nothrow, stopOnFailure, macroName ) \
+catch( ... ) \
+{ \
+    Catch::ResultsCapture::acceptResult( false, stopOnFailure ); \
+}
+
+#define _CATCH_MSG( reason, resultType, stopOnFailure, macroName ) \
+    Catch::ResultsCapture::acceptExpression( Catch::MutableResultInfo( "", false, __FILE__, __LINE__, macroName ) ); \
+    Catch::ResultsCapture::acceptMessage( reason ); \
+    Catch::ResultsCapture::acceptResult( resultType, stopOnFailure );
+
+
+#endif // TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
diff --git a/internal/catch_commandline.hpp b/internal/catch_commandline.hpp
new file mode 100644
index 0000000..28daa27
--- /dev/null
+++ b/internal/catch_commandline.hpp
@@ -0,0 +1,174 @@
+/*
+ *  catch_commandline.hpp
+ *  Catch
+ *
+ *  Created by Phil on 02/11/2010.
+ *  Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
+ *
+ *  Distributed under the Boost Software License, Version 1.0. (See accompanying
+ *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+
+#ifndef TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
+#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
+
+#include "catch_runnerconfig.hpp"
+#include "catch_runner_impl.hpp"
+
+namespace Catch
+{
+    // -l --list:tests [xml] lists available tests (optionally in xml)
+    // -l --list:reports [xml] lists available reports (optionally in xml)
+    // -l --list:all [xml] lists available tests and reports (optionally in xml)
+    // -t --test "testspec" (any number)
+    // -r --report <type>
+    // -o --output filename to write to
+    // -s --success report successful cases too
+    class ArgParser
+    {
+        enum Mode
+        {
+            modeNone,
+            modeList,
+            modeTest,
+            modeReport,
+            modeOutput,
+            modeSuccess,
+
+            modeError
+        };
+        
+    public:
+        ArgParser( int argc, char * const argv[], RunnerConfig& config )
+        :   m_mode( modeNone ),
+            m_config( config )
+        {
+            for(size_t i=1; i < argc; ++i )
+            {
+                if( argv[i][0] == '-' )
+                {
+                    std::string cmd = ( argv[i] );
+                    if( cmd == "-l" || cmd == "--list" )
+                        changeMode( cmd, modeList );
+                    else if( cmd == "-t" || cmd == "--test" )
+                        changeMode( cmd, modeTest );
+                    else if( cmd == "-r" || cmd == "--report" )
+                        changeMode( cmd, modeReport );
+                    else if( cmd == "-o" || cmd == "--output" )
+                        changeMode( cmd, modeOutput );
+                    else if( cmd == "-s" || cmd == "--success" )
+                        changeMode( cmd, modeSuccess );
+                }
+                else
+                {
+                    m_args.push_back( argv[i] );
+                }
+                if( m_mode == modeError )
+                    return;
+            }
+            changeMode( "", modeNone );            
+        }
+        
+    private:
+        std::string argsAsString()
+        {
+            std::ostringstream oss;
+            std::vector<std::string>::const_iterator it = m_args.begin();
+            std::vector<std::string>::const_iterator itEnd = m_args.end();
+            for( bool first = true; it != itEnd; ++it, first = false )
+            {
+                if( !first )
+                    oss << " ";
+                oss << *it;
+            }
+            return oss.str();
+        }
+        
+        void changeMode( const std::string& cmd, Mode mode )
+        {
+            m_command = cmd;
+            switch( m_mode )
+            {
+                case modeNone:
+                    if( m_args.size() > 0 )
+                        return setErrorMode( "Unexpected arguments before " + m_command + ": " + argsAsString() );
+                    break;
+                case modeList:
+                    if( m_args.size() > 2 )
+                    {
+                        return setErrorMode( m_command + " expected upto 2 arguments but recieved: " + argsAsString() );
+                    }
+                    else
+                    {
+                        RunnerConfig::ListInfo listSpec = RunnerConfig::listAll;
+                        if( m_args.size() >= 1 )
+                        {
+                            if( m_args[0] == "tests" )
+                                listSpec = RunnerConfig::listTests;
+                            else if( m_args[0] == "reports" )
+                                listSpec = RunnerConfig::listReports;
+                            else
+                                return setErrorMode( m_command + " expected [tests] or [reports] but recieved: [" + m_args[0] + "]" );                        
+                        }
+                        if( m_args.size() >= 2 )
+                        {
+                            if( m_args[1] == "xml" )
+                                listSpec = (RunnerConfig::ListInfo)( listSpec | RunnerConfig::listAsXml );
+                            else if( m_args[1] == "text" )
+                                listSpec = (RunnerConfig::ListInfo)( listSpec | RunnerConfig::listAsText );
+                            else
+                                return setErrorMode( m_command + " expected [xml] or [text] but recieved: [" + m_args[1] + "]" );                        
+                        }
+                        m_config.m_listSpec = (RunnerConfig::ListInfo)( m_config.m_listSpec | listSpec );
+                    }
+                    break;
+                case modeTest:
+                    if( m_args.size() == 0 )                        
+                        return setErrorMode( m_command + " expected at least 1 argument but recieved none" );
+                    {
+                        std::vector<std::string>::const_iterator it = m_args.begin();
+                        std::vector<std::string>::const_iterator itEnd = m_args.end();
+                        for(; it != itEnd; ++it )
+                            m_config.addTestSpec( *it );
+                    }
+                    break;
+                case modeReport:
+                    if( m_args.size() != 1 )
+                        return setErrorMode( m_command + " expected one argument, recieved: " +  argsAsString() );
+                    m_config.setReporterInfo( m_args[0] );
+                    break;
+                case modeOutput:
+                    if( m_args.size() == 0 )
+                        return setErrorMode( m_command + " expected filename" );
+                    m_config.setFilename( m_args[0] );
+                    break;
+                case modeSuccess:
+                    if( m_args.size() != 0 )
+                        return setErrorMode( m_command + " does not accept arguments" );
+                    m_config.setIncludeAll( true );
+                    break;
+            }
+            m_args.clear();
+            m_mode = mode;
+        }
+        
+        void setErrorMode( const std::string& errorMessage )
+        {
+            m_mode = modeError;
+            m_command = "";
+            m_config.setError( errorMessage );
+        }
+        
+    private:
+        
+        Mode m_mode;
+        std::string m_command;
+        std::vector<std::string> m_args;
+        RunnerConfig& m_config;
+    };
+    
+    
+} // end namespace Catch
+
+#endif // TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
\ No newline at end of file
diff --git a/internal/catch_common.h b/internal/catch_common.h
new file mode 100644
index 0000000..b4d8b16
--- /dev/null
+++ b/internal/catch_common.h
@@ -0,0 +1,20 @@
+/*
+ *  catch_common.h
+ *  Catch
+ *
+ *  Created by Phil on 29/10/2010.
+ *  Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
+ *
+ *  Distributed under the Boost Software License, Version 1.0. (See accompanying
+ *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+
+#ifndef TWOBLUECUBES_CATCH_COMMON_H_INCLUDED
+#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED
+
+#define _CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
+#define _CATCH_UNIQUE_NAME_LINE( name, line ) _CATCH_UNIQUE_NAME_LINE2( name, line )
+#define _CATCH_UNIQUE_NAME( name ) _CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
+
+#endif // TWOBLUECUBES_CATCH_COMMON_H_INCLUDED
\ No newline at end of file
diff --git a/internal/catch_list.hpp b/internal/catch_list.hpp
new file mode 100644
index 0000000..82cc162
--- /dev/null
+++ b/internal/catch_list.hpp
@@ -0,0 +1,66 @@
+/*
+ *  catch_list.hpp
+ *  Catch
+ *
+ *  Created by Phil on 5/11/2010.
+ *  Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
+ *
+ *  Distributed under the Boost Software License, Version 1.0. (See accompanying
+ *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+
+#ifndef TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
+#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
+
+#include "catch_commandline.hpp"
+
+namespace Catch
+{
+    inline int List( const RunnerConfig& config )
+    {
+        if( config.listWhat() & RunnerConfig::listReports )
+        {
+            std::cout << "Available reports:\n";
+            ReporterRegistry::FactoryMap::const_iterator it = ReporterRegistry::instance().m_factories.begin();
+            ReporterRegistry::FactoryMap::const_iterator itEnd = ReporterRegistry::instance().m_factories.end();
+            for(; it != itEnd; ++it )
+            {
+                // !TBD: consider listAs()
+                std::cout << "\t" << it->first << " '" << it->second->getDescription() << "'\n";
+            }
+            std::cout << std::endl;
+        }
+        if( config.listWhat() & RunnerConfig::listTests )
+        {
+            std::cout << "Available tests:\n";
+            std::vector<TestCaseInfo>::const_iterator it = TestRegistry::instance().getAllTests().begin();
+            std::vector<TestCaseInfo>::const_iterator itEnd = TestRegistry::instance().getAllTests().end();
+            for(; it != itEnd; ++it )
+            {
+                // !TBD: consider listAs()
+                std::cout << "\t" << it->getName() << " '" << it->getDescription() << "'\n";
+            }
+            std::cout << std::endl;
+        }
+        if( ( config.listWhat() & RunnerConfig::listAll ) == 0 )
+        {
+            std::cerr << "Unknown list type" << std::endl;
+            return std::numeric_limits<int>::max();
+        }
+        
+        if( config.getReporter() )
+        {
+            std::cerr << "Reporters ignored when listing" << std::endl;
+        }
+        if( config.m_testSpecs.size() == 0 )
+        {
+            std::cerr << "Test specs ignored when listing" << std::endl;
+        }
+        return 0;
+
+    }
+    
+} // end namespace Catch
+
+#endif // TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
\ No newline at end of file
diff --git a/internal/catch_registry.hpp b/internal/catch_registry.hpp
new file mode 100644
index 0000000..b136be6
--- /dev/null
+++ b/internal/catch_registry.hpp
@@ -0,0 +1,116 @@
+/*
+ *  catch_registry.hpp
+ *  Catch
+ *
+ *  Created by Phil on 18/10/2010.
+ *  Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
+ *
+ *  Distributed under the Boost Software License, Version 1.0. (See accompanying
+ *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+#ifndef TWOBLUECUBES_CATCH_REGISTRY_HPP_INCLUDED
+#define TWOBLUECUBES_CATCH_REGISTRY_HPP_INCLUDED
+
+#include "catch_testcaseinfo.hpp"
+#include "catch_common.h"
+
+#include <vector>
+#include <stdexcept>
+
+namespace Catch
+{
+class TestRegistry
+{
+public:
+    
+    static TestRegistry& instance()
+    {
+        static TestRegistry reg;
+        return reg;
+    }
+    
+    void registerTest( const TestCaseInfo& testInfo )
+    {
+        m_functions.push_back( testInfo );
+    }
+        
+    std::vector<TestCaseInfo> getAllTests() const
+    {
+        return m_functions;
+    }
+        
+private:
+        
+    std::vector<TestCaseInfo> m_functions;
+};
+
+typedef void(*TestFunction)();
+    
+struct FreeFunctionTestCase : TestCase
+{
+    FreeFunctionTestCase( TestFunction fun )
+    : fun( fun )
+    {}
+    
+    virtual void invoke() const
+    {
+        fun();
+    }
+    
+    virtual TestCase* clone() const
+    {
+        return new FreeFunctionTestCase( fun );
+    }
+
+private:
+    TestFunction fun;
+};
+
+template<typename C>
+struct MethodTestCase : TestCase
+{
+    MethodTestCase( void (C::*method)() )
+    : method( method )
+    {}
+    
+    virtual void invoke() const
+    {
+        C obj;
+        (obj.*method)();
+    }
+    
+    virtual TestCase* clone() const
+    {
+        return new MethodTestCase<C>( method );
+    }
+    
+private:
+    void (C::*method)();
+};
+    
+struct AutoReg
+{
+    AutoReg( TestFunction function, const std::string& name, const std::string& description )
+    {
+        TestRegistry::instance().registerTest( TestCaseInfo( new FreeFunctionTestCase( function ), name, description ) );
+    }
+    
+    template<typename C>
+    AutoReg( void (C::*method)(), const std::string& name, const std::string& description )
+    {
+        TestRegistry::instance().registerTest( TestCaseInfo( new MethodTestCase<C>( method ), name, description ) );
+    }
+};
+    
+} // end namespace Catch
+
+#define CATCH_TEST_CASE( Name, Desc ) \
+    static void _CATCH_UNIQUE_NAME( __catchTestFunction )(); \
+    namespace{ Catch::AutoReg _CATCH_UNIQUE_NAME( autoRegistrar )( &_CATCH_UNIQUE_NAME( __catchTestFunction ), Name, Desc ); }\
+    static void _CATCH_UNIQUE_NAME( __catchTestFunction )()
+
+#define CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
+    namespace{ Catch::AutoReg _CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, Name, Desc ); }
+
+#endif // TWOBLUECUBES_CATCH_REGISTRY_HPP_INCLUDED
diff --git a/internal/catch_reporter_registry.hpp b/internal/catch_reporter_registry.hpp
new file mode 100644
index 0000000..820703d
--- /dev/null
+++ b/internal/catch_reporter_registry.hpp
@@ -0,0 +1,166 @@
+/*
+ *  catch_registry.hpp
+ *  Catch
+ *
+ *  Created by Phil on 29/10/2010.
+ *  Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
+ *
+ *  Distributed under the Boost Software License, Version 1.0. (See accompanying
+ *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+#ifndef TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
+#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
+
+#include "catch_testcaseinfo.hpp"
+#include "catch_resultinfo.hpp"
+#include "catch_common.h"
+
+#include <map>
+#include <iostream>
+#include <fstream>
+
+namespace Catch
+{
+    class ReporterConfig
+    {
+    private:
+        ReporterConfig( const ReporterConfig& other );
+        ReporterConfig& operator = ( const ReporterConfig& other );
+        
+    public:
+        
+        struct Include { enum What
+            {
+                FailedOnly, 
+                SuccessfulResults
+            }; };
+        
+    public:
+        
+        ///////////////////////////////////////////////////////////////////////////
+        explicit ReporterConfig( Include::What includeWhat = Include::FailedOnly )
+        :   m_includeWhat( includeWhat ),
+            m_os( std::cout.rdbuf() )
+        {
+        }
+        
+        ///////////////////////////////////////////////////////////////////////////
+        bool includeSuccessfulResults() const
+        {
+            return m_includeWhat == Include::SuccessfulResults;
+        }
+        
+        ///////////////////////////////////////////////////////////////////////////
+        void setIncludeWhat(Include::What includeWhat )
+        {
+            m_includeWhat = includeWhat;
+        }
+        
+        ///////////////////////////////////////////////////////////////////////////
+        std::ostream& stream() const
+        {
+            return m_os;
+        }        
+        
+        ///////////////////////////////////////////////////////////////////////////
+        void setStreamBuf( std::streambuf* buf )
+        {
+            m_os.rdbuf( buf );
+        }        
+        
+    private:
+        Include::What m_includeWhat;
+        
+        mutable std::ostream m_os;
+    };
+    
+    struct ITestReporter
+    {
+        virtual ~ITestReporter(){}
+        
+        // !TBD
+        // StartTesting
+        // EndTesting
+        // StartGroup
+        // EndGroup
+        // StartSection
+        // EndSection
+        virtual void StartTestCase( const TestCaseInfo& testInfo ) = 0;
+        virtual void Result( const ResultInfo& result ) = 0;
+        virtual void EndTestCase( const TestCaseInfo& testInfo ) = 0;
+    };
+        
+    struct IReporterFactory
+    {
+        virtual ~IReporterFactory(){}
+        
+        virtual ITestReporter* create( const ReporterConfig& config ) = 0;
+        virtual std::string getDescription() const = 0;
+    };
+    
+    template<typename T>
+    class ReporterFactory : public IReporterFactory
+    {
+        virtual ITestReporter* create( const ReporterConfig& config )
+        {
+            return new T( config );
+        }
+        virtual std::string getDescription() const
+        {
+            return T::getDescription();
+        }
+    };
+    
+    class ReporterRegistry
+    {
+    public:
+        
+        static ReporterRegistry& instance()
+        {
+            static ReporterRegistry instance;
+            return instance;
+        }
+        
+        ~ReporterRegistry()
+        {
+            FactoryMap::const_iterator it =  m_factories.begin();
+            FactoryMap::const_iterator itEnd =  m_factories.end();
+            for(; it != itEnd; ++it )
+            {
+                delete it->second;
+            }        
+        }
+        
+        ITestReporter* create( const std::string& name, const ReporterConfig& config )
+        {
+            FactoryMap::const_iterator it =  m_factories.find( name );
+            if( it == m_factories.end() )
+                return NULL;
+            return it->second->create( config );
+        }
+        
+        template<typename T>
+        void registerReporter( const std::string& name )
+        {
+            m_factories.insert( std::make_pair( name, new ReporterFactory<T>() ) );
+        }
+        
+//    private: // !TBD
+        typedef std::map<std::string, IReporterFactory*> FactoryMap;
+        FactoryMap m_factories;
+    };
+    
+    template<typename T>
+    struct ReporterRegistrar
+    {
+        ReporterRegistrar( const std::string& name )
+        {
+            ReporterRegistry::instance().registerReporter<T>( name );
+        }
+    };    
+}
+
+#define CATCH_REGISTER_REPORTER( name, reporterType ) Catch::ReporterRegistrar<reporterType> _CATCH_UNIQUE_NAME( __catchReporterReg )( name );
+
+#endif // TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
\ No newline at end of file
diff --git a/internal/catch_resultinfo.hpp b/internal/catch_resultinfo.hpp
new file mode 100644
index 0000000..5eae176
--- /dev/null
+++ b/internal/catch_resultinfo.hpp
@@ -0,0 +1,122 @@
+/*
+ *  catch_resultinfo.hpp
+ *  Catch
+ *
+ *  Created by Phil on 28/10/2010.
+ *  Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
+ *
+ *  Distributed under the Boost Software License, Version 1.0. (See accompanying
+ *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+#ifndef TWOBLUECUBES_CATCH_RESULT_INFO_HPP_INCLUDED
+#define TWOBLUECUBES_CATCH_RESULT_INFO_HPP_INCLUDED
+
+#include <string>
+
+namespace Catch
+{    
+    struct ResultWas{ enum OfType
+        {
+            Unknown = -1,
+            Ok = 0,
+            ExpressionFailed = 1,
+            
+            Info = 2,
+            Warning = 3,
+            ExplicitFailure = 4,
+            
+            Exception = 0x100,
+            
+            ThrewException = Exception | 1,
+            DidntThrowException = Exception | 2
+            
+        }; };
+    
+    class ResultInfo
+    {
+    public:
+        
+        ResultInfo()
+        :   m_result( ResultWas::Unknown ),
+            m_isNot( false ),
+            m_line( 0 )
+        {}
+        
+        ResultInfo( const std::string& expr, ResultWas::OfType result, bool isNot, const std::string& filename, size_t line, const std::string& macroName )
+        :   m_expr( expr ),
+            m_result( result ),
+            m_isNot( isNot ),
+            m_op( m_expr[0] == '!' ? "!" : "" ),
+            m_filename( filename ),
+            m_line( line ), 
+            m_macroName( macroName )
+        {
+        }
+        
+        bool ok() const
+        {
+            return m_result == ResultWas::Ok;
+        }
+        
+        ResultWas::OfType getResultType() const
+        {
+            return m_result;
+        }
+        
+        bool hasExpression() const
+        {
+            return !m_expr.empty();
+        }
+        bool hasMessage() const
+        {
+            return !m_message.empty();
+        }
+        std::string getExpression() const
+        {
+            return m_expr;
+        }
+        std::string getExpandedExpression() const
+        {
+            if( m_op == "" || m_isNot )
+                return m_lhs.empty() ? m_expr : m_op + m_lhs;
+            else if( m_op != "!" )
+                return m_lhs + " " + m_op + " " + m_rhs;
+            else
+                return "{can't expand - use " + m_macroName + "_NOT( " + m_expr.substr(1) + " ) instead of " + m_macroName + "( " + m_expr + " ) for better diagnostics}";
+        }
+        
+        std::string getMessage() const
+        {
+            return m_message;
+        }
+        
+        std::string getFilename() const
+        {
+            return m_filename;
+        }
+        
+        size_t getLine() const
+        {
+            return m_line;
+        }
+        
+        std::string getTestMacroName() const
+        {
+            return m_macroName;
+        }
+        
+    protected:
+        std::string m_macroName;
+        std::string m_filename;
+        size_t m_line;
+        std::string m_expr, m_lhs, m_rhs, m_op;
+        std::string m_message;
+        ResultWas::OfType m_result;
+        bool m_isNot;
+    };
+    
+} // end namespace Catch
+
+
+#endif // TWOBLUECUBES_CATCH_RESULT_INFO_HPP_INCLUDED
diff --git a/internal/catch_runner_impl.hpp b/internal/catch_runner_impl.hpp
new file mode 100644
index 0000000..14d8491
--- /dev/null
+++ b/internal/catch_runner_impl.hpp
@@ -0,0 +1,145 @@
+/*
+ *  catch_runner.hpp
+ *  Catch
+ *
+ *  Created by Phil on 22/10/2010.
+ *  Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
+ *
+ *  Distributed under the Boost Software License, Version 1.0. (See accompanying
+ *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+#ifndef TWOBLUECUBES_INTERNAL_CATCH_RUNNER_HPP_INCLUDED
+#define TWOBLUECUBES_INTERNAL_CATCH_RUNNER_HPP_INCLUDED
+
+#include "catch_reporter_registry.hpp"
+#include "catch_registry.hpp"
+#include "catch_capture.hpp"
+
+namespace Catch
+{
+    class TestSpec
+    {
+    public:
+        TestSpec( const std::string& rawSpec )
+        :   m_rawSpec( rawSpec ),
+            m_isWildcarded( false )
+        {
+            if( m_rawSpec[m_rawSpec.size()-1] == '*' )
+            {
+                m_rawSpec = m_rawSpec.substr( 0, m_rawSpec.size()-1 );
+                m_isWildcarded = true;
+            }
+        }
+        
+        bool matches( const std::string& testName ) const
+        {
+            if( !m_isWildcarded )
+                return m_rawSpec == testName;
+            else
+                return testName.size() >= m_rawSpec.size() && testName.substr( 0, m_rawSpec.size() ) == m_rawSpec;            
+        }
+        
+    private:
+        std::string m_rawSpec;
+        bool m_isWildcarded;
+    };
+    
+    class Runner : public IResultListener
+    {
+    public:
+        Runner()
+        :   m_successes( 0 ),
+            m_failures( 0 ),
+            m_reporter( 0 )
+        {
+        }
+        
+        void setReporter( ITestReporter* reporter )
+        {
+            m_reporter = reporter;
+        }
+        
+        void runAll()
+        {
+            std::vector<TestCaseInfo> allTests = TestRegistry::instance().getAllTests();
+            for( size_t i=0; i < allTests.size(); ++i )
+            {
+                runTest( allTests[i] );
+            }
+        }
+        
+        size_t runMatching( const std::string& rawTestSpec )
+        {
+            TestSpec testSpec( rawTestSpec );
+            
+            std::vector<TestCaseInfo> allTests = TestRegistry::instance().getAllTests();
+            size_t testsRun = 0;
+            for( size_t i=0; i < allTests.size(); ++i )
+            {
+                if( testSpec.matches( allTests[i].getName() ) )
+                {
+                    runTest( allTests[i] );
+                    testsRun++;
+                }
+            }
+            return testsRun;
+        }
+        
+        void runTest( const TestCaseInfo& testInfo )
+        {
+            IResultListener* prevListener = ResultsCapture::setListener( this );
+            m_reporter->StartTestCase( testInfo );
+            
+            try
+            {
+                testInfo.invoke();
+            }
+            catch( TestFailureException& ex )
+            {
+                // This just means the test was aborted due to failure
+            }
+            catch( std::exception& ex )
+            {
+                ResultsCapture::acceptMessage( ex.what() );
+                ResultsCapture::acceptResult( ResultWas::ThrewException );
+            }
+            catch(...)
+            {
+                ResultsCapture::acceptMessage( "unknown exception" );
+                ResultsCapture::acceptResult( ResultWas::ThrewException );
+            }
+
+            m_reporter->EndTestCase( testInfo );
+            ResultsCapture::setListener( prevListener );
+        }
+        
+        size_t getSuccessCount() const
+        {
+            return m_successes;
+        }
+        size_t getFailures() const
+        {
+            return m_failures;
+        }
+
+    private: // IResultListener
+        
+        virtual void testEnded( const ResultInfo& result )
+        { 
+            if( result.ok() )
+                m_successes++;
+            else
+                m_failures++;
+            
+            m_reporter->Result( result );
+        }
+        
+    private:
+        size_t m_successes;
+        size_t m_failures;
+        ITestReporter* m_reporter;
+    };
+}
+
+#endif // TWOBLUECUBES_INTERNAL_CATCH_RUNNER_HPP_INCLUDED
\ No newline at end of file
diff --git a/internal/catch_section.hpp b/internal/catch_section.hpp
new file mode 100644
index 0000000..c7df9e8
--- /dev/null
+++ b/internal/catch_section.hpp
@@ -0,0 +1,39 @@
+/*
+ *  catch_section.hpp
+ *  Catch
+ *
+ *  Created by Phil on 03/11/2010.
+ *  Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
+ *
+ *  Distributed under the Boost Software License, Version 1.0. (See accompanying
+ *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+
+#ifndef TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED
+#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED
+
+#include <string>
+
+namespace Catch
+{
+    class Section
+    {
+    public:
+        Section( const std::string& name, const std::string& description )
+        {
+            // !TBD notify the runner
+        }
+        
+        operator bool()
+        {
+            // !TBD get this from runner
+            return true;
+        }
+    };
+    
+} // end namespace Catch
+
+#define CATCH_SECTION( name, desc ) if( Catch::Section __catchSection = Catch::Section( name, desc ) )
+
+#endif // TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED
diff --git a/internal/catch_testcaseinfo.hpp b/internal/catch_testcaseinfo.hpp
new file mode 100644
index 0000000..7a8185c
--- /dev/null
+++ b/internal/catch_testcaseinfo.hpp
@@ -0,0 +1,84 @@
+/*
+ *  catch_testcaseinfo.hpp
+ *  Catch
+ *
+ *  Created by Phil on 29/10/2010.
+ *  Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
+ *
+ *  Distributed under the Boost Software License, Version 1.0. (See accompanying
+ *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+
+#ifndef TWOBLUECUBES_CATCH_TESTCASEINFO_HPP_INCLUDED
+#define TWOBLUECUBES_CATCH_TESTCASEINFO_HPP_INCLUDED
+
+#include <map>
+#include <string>
+
+namespace Catch
+{
+    struct TestCase
+    {
+        virtual ~TestCase(){}
+        virtual void invoke() const = 0;
+        virtual TestCase* clone() const = 0;
+    };
+    
+    class TestCaseInfo
+    {
+    public:
+        TestCaseInfo( TestCase* testCase, const std::string& name, const std::string& description )
+        :   test( testCase ),
+            name( name ),
+            description( description )
+        {
+        }
+        TestCaseInfo()
+        :   test( NULL )
+        {
+        }
+        
+        TestCaseInfo( const TestCaseInfo& other )
+        :   test( other.test->clone() ),
+            name( other.name ),
+            description( other.description )
+        {
+        }
+        
+        TestCaseInfo& operator = ( const TestCaseInfo& other )
+        {
+            test = other.test->clone();
+            name = other.name;
+            description = description;
+            return *this;
+        }
+        
+        ~TestCaseInfo()
+        {
+            delete test;
+        }
+        
+        void invoke() const
+        {
+            test->invoke();
+        }
+        
+        const std::string& getName() const
+        {
+            return name;
+        }
+        const std::string& getDescription() const
+        {
+            return description;
+        }
+        
+    private:
+        TestCase* test;
+        std::string name;
+        std::string description;
+    };
+    
+}
+
+#endif // TWOBLUECUBES_CATCH_TESTCASEINFO_HPP_INCLUDED
\ No newline at end of file