The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
CPP.pm 7150
Changes 096
LICENSE 0201
MANIFEST 2242
MANIFEST.SKIP 55
META.json 1033
META.yml 1630
Makefile.PL 181159
README 87
grammar/Makefile.PL 60
grammar/grammar.pm 5180
grammar/t/00pod_coverage.t 310
grammar/t/01nherit.t 560
grammar/t/02scope.t 280
grammar/t/03inline.t 530
grammar/t/04const.t 210
grammar/t/05virt.t 220
grammar/t/06deflt.t 340
grammar/t/07static.t 190
grammar/t/08anon.t 240
grammar/t/09purevt.t 530
grammar/t/10struct.t 300
grammar/t/11minhrt.t 3030
grammar/t/12retlst.t 390
grammar/t/13vararg.t 280
grammar/t/14const.t 210
grammar/t/15stvar.t 250
grammar/t/16varlst.t 500
grammar/t/17memberarray.t 250
inc/ILCPPConfig/CompilerGuess.pm 051
inc/ILCPPConfig/OldCompilerGuess.pm 0101
lib/Inline/CPP/Config.pm 22
lib/Inline/CPP/Parser/RecDescent.pm 0548
lib/Inline/CPP.pm 0780
lib/Inline/CPP.pod 217422
t/03prefix.t 44
t/06fn_regress.t 11
t/08cppguess.t 15522
t/11rewrite_config.t 11
t/12custom_libs.t 11
t/13version_numbers.t 86
t/15config_case.t 018
t/classes/01empty_ns_is_main.t 049
t/classes/02main_ns_is_main.t 048
t/classes/03baz_ns_is_baz.t 046
t/classes/04invoke_from_non_main.t 035
t/classes/05invalid_classes.t 078
t/classes/06inherit.t 048
t/classes/07conflict_avoid.t 090
t/classes/08auto.t 056
t/classes/09auto_mixed.t 028
t/classes/10auto_inherit.t 074
t/grammar/00pod_coverage.t 031
t/grammar/01nherit.t 056
t/grammar/02scope.t 028
t/grammar/03inline.t 053
t/grammar/04const.t 021
t/grammar/05virt.t 022
t/grammar/06deflt.t 034
t/grammar/07static.t 019
t/grammar/08anon.t 024
t/grammar/09purevt.t 053
t/grammar/10struct.t 030
t/grammar/11minhrt.t 0303
t/grammar/12retlst.t 039
t/grammar/13vararg.t 028
t/grammar/14const.t 021
t/grammar/15stvar.t 025
t/grammar/16varlst.t 050
t/grammar/17memberarray.t 025
t/grammar/18namespace.t 037
t/grammar/19multidimarray.t 042
t/namespace/01empty_ns_is_main.t 047
t/namespace/02main_ns_is_main.t 046
t/namespace/03baz_ns_is_baz.t 044
t/namespace/04invoke_from_non_main.t 035
t/namespace/05invalid_ns.t 027
t/namespace/06inherit.t 047
78 files changed (This is a version diff) 27324269
@@ -1,715 +0,0 @@
-package Inline::CPP;
-
-
-use strict;
-use warnings;
-use 5.006000;
-use Fcntl qw( :DEFAULT :flock );
-
-require Inline::C;
-require Inline::CPP::grammar;
-require Inline::CPP::Config;
-
-# Note: Parse::RecDescent 'require'd within get_parser().
-
-use Carp;
-
-# use base doesn't work because Inline::C cannot be "use"d directly.
-our @ISA = qw( Inline::C ); ## no critic (ISA)
-
-# Development releases will have a _0xx version suffix.
-# We eval the version number to accommodate dev. version numbering, as
-# described in perldoc perlmodstyle.
-our $VERSION = '0.49';
-#$VERSION = eval $VERSION; ## no critic (eval)
-
-my $TYPEMAP_KIND;
-{
-    no warnings 'once'; ## no critic (warnings)
-    $TYPEMAP_KIND = $Inline::CPP::grammar::TYPEMAP_KIND;
-}
-
-#============================================================================
-# Register Inline::CPP as an Inline language module
-#============================================================================
-sub register {
-    use Config;
-    return {
-        language => 'CPP',
-        aliases  =>
-            [ 'cpp','C++', 'c++', 'Cplusplus', 'cplusplus', 'CXX', 'cxx' ],
-        type     => 'compiled',
-        suffix   => $Config{dlext},
-    };
-} ### Tested.
-
-#============================================================================
-# Validate the C++ config options: Now mostly done in Inline::C
-#============================================================================
-sub validate {
-    my ( $o, @config_options     )  =  @_;
-    my ( $flavor_defs, $iostream );
-
-    {   # "used only once" warning. We know it's ok.
-        no warnings 'once'; ## no critic (warnings)
-        ## no critic (package variable)
-
-        # Set default compiler and libraries.
-        $o->{ILSM}{MAKEFILE}{CC}
-            ||= $Inline::CPP::Config::compiler;
-        $o->{ILSM}{MAKEFILE}{LIBS}
-            ||= _make_arrayref( $Inline::CPP::Config::libs );
-        
-        $flavor_defs = $Inline::CPP::Config::cpp_flavor_defs; # "Standard"?
-        $iostream    = $Inline::CPP::Config::iostream_fn; # iostream filename.
-    }
-
-    # I haven't traced it out yet, but $o->{STRUCT} gets set before getting
-    # properly set from Inline::C's validate().
-    $o->{STRUCT} ||= {
-        '.macros' => q{},   '.any' => 0,
-        '.xs'     => q{},   '.all' => 0,
-    };
-
-    _build_auto_include( $o, $flavor_defs, $iostream );
-
-    $o->{ILSM}{PRESERVE_ELLIPSIS} = 0
-        unless defined $o->{ILSM}{PRESERVE_ELLIPSIS};
-
-    # Filter out the parameters we treat differently than Inline::C,
-    # forwarding unknown requests back up to Inline::C.
-    my @propagate = _handle_config_options( $o, @config_options );
-    $o->SUPER::validate(@propagate) if @propagate;
-
-    return;
-}
-
-
-sub _build_auto_include {
-    my ( $o, $flavor_defs, $iostream ) = @_;
-    my $auto_include = <<'END';
-#define __INLINE_CPP 1
-#ifndef bool
-#include <%iostream%>
-#endif
-extern "C" {
-#include "EXTERN.h"
-#include "perl.h"
-#include "XSUB.h"
-#include "INLINE.h"
-}
-#ifdef bool
-#undef bool
-#include <%iostream%>
-#endif
-
-END
-
-    $o->{ILSM}{AUTO_INCLUDE} ||= $auto_include;
-    $o->{ILSM}{AUTO_INCLUDE} =   $flavor_defs  .  $o->{ILSM}{AUTO_INCLUDE};
-    # Replace %iostream% with the correct iostream library
-    $o->{ILSM}{AUTO_INCLUDE} =~ s{%iostream%}{$iostream}xg;
-    return;
-}
-
-
-sub _handle_config_options {
-    my ( $o, @config_options ) = @_;
-    my @propagate;
-
-    while ( @config_options ) {
-        my ( $key, $value )
-            = (  shift @config_options,  shift @config_options  );
-        if ( $key eq 'LIBS' ) {
-            _handle_libs_cfg_option( $o, $value );
-            next;
-        }
-        if ( $key eq 'ALTLIBS' ) {
-            _handle_altlibs_cfg_option( $o, $value );
-            next;
-        }
-        if (     $key eq 'PRESERVE_ELLIPSIS'
-             or  $key eq 'STD_IOSTREAM' )
-        {
-            croak "Argument to $key must be 0 or 1"
-                unless $value == 0
-                    or $value == 1;
-            $o->{ILSM}{$key} = $value;
-            next;
-        }
-        push @propagate, $key, $value;
-    }
-    return @propagate;
-}
-
-
-sub _handle_libs_cfg_option {
-    my( $o, $value ) = @_;
-    $value = _make_arrayref( $value );
-    _add_libs( $o, $value );
-    return;
-}
-
-
-sub _handle_altlibs_cfg_option {
-    my( $o, $value ) = @_;
-    $value = _make_arrayref( $value );
-    push @{ $o->{ILSM}{MAKEFILE}{LIBS} }, q{};
-    _add_libs( $o, $value );
-    return;
-}
-
-
-sub _make_arrayref {
-    my $value = shift;
-    $value = [ $value ] unless ref $value eq 'ARRAY';
-    return $value;
-}
-
-sub _add_libs {
-    my( $o, $libs ) = @_;
-    my $num = scalar @{ $o->{ILSM}{MAKEFILE}{LIBS} } - 1;
-    $o->{ILSM}{MAKEFILE}{LIBS}[$num] .= q{ } . $_
-        for @{ $libs };
-    return;
-}
-
-
-#============================================================================
-# Print a small report if PRINT_INFO option is set
-#============================================================================
-sub info {
-    my $o     = shift;
-    my $info  = q{};
-
-    $o->parse unless $o->{ILSM}{parser};
-    my $data = $o->{ILSM}{parser}{data};
-
-    my ( @class, @func );
-    if ( defined $data->{classes} ) {
-        for my $class ( sort @{ $data->{classes} } ) {
-            my @parents =
-                grep { $_->{thing} eq 'inherits' } @{$data->{class}{$class}};
-            push @class, "\tclass $class";
-            push @class,
-                ( ' : '
-                  . join ( ', ',
-                        map { $_->{scope} . q{ } . $_->{name} } @parents ) )
-                if @parents;
-            push @class, " {\n";
-            for my $thing (
-                sort { $a->{name} cmp $b->{name} }
-                @{ $data->{class}{$class} }
-            ) {
-                my ( $name, $scope, $type )
-                    = @{$thing}{ qw(name scope thing) };
-                next unless $scope eq 'public' and $type eq 'method';
-                next unless $o->check_type(
-                    $thing,
-                    $name eq $class,
-                    $name eq "~$class",
-                );
-                my $rtype = $thing->{rtype} || q{};
-                push @class, "\t\t$rtype" . ( $rtype ? q{ } : q{} );
-                push @class, $class . "::$name(";
-                my @args = grep { $_->{name} ne '...' } @{$thing->{args}};
-                my $ellipsis =
-                    ( scalar @{ $thing->{args} } - scalar @args ) != 0;
-                push @class,
-                    join ', ',
-                        (
-                            map { "$_->{type} $_->{name}" } @args
-                        ),
-                        $ellipsis ? '...' : ();
-                push @class, ");\n";
-            }
-            push @class, "\t};\n"
-        }
-    }
-    if ( defined $data->{functions} ) {
-        for my $function ( sort @{ $data->{functions} } ) {
-            my $func = $data->{function}{$function};
-            next if $function =~ m/::/x;
-            next unless $o->check_type( $func, 0, 0 );
-            push @func, "\t" . $func->{rtype} . q{ };
-            push @func, $func->{name} . '(';
-            my @args = grep { $_->{name} ne '...' } @{ $func->{args} };
-            my $ellipsis = ( scalar @{ $func->{args} } - scalar @args ) != 0;
-            push @func,
-                join ', ',
-                    ( map { "$_->{type} $_->{name}" } @args ),
-                    $ellipsis ? '...' : ();
-            push @func, ");\n";
-        }
-    }
-
-    # Report:
-    {
-        local $" = q{};
-        $info .= "The following classes have been bound to Perl:\n@class\n"
-            if @class;
-        $info .= "The following functions have been bound to Perl:\n@func\n"
-            if @func;
-    }
-    $info .= Inline::Struct::info( $o ) if $o->{STRUCT}{'.any'};
-    return $info;
-}
-
-#============================================================================
-# Generate a C++ parser
-#============================================================================
-sub get_parser {
-    my $o       = shift;
-    my $grammar = Inline::CPP::grammar::grammar()
-        or croak "Can't find C++ grammar\n";
-    no warnings qw/ once /; ## no critic (warnings)
-    $::RD_HINT = 1; # Turns on Parse::RecDescent's warnings/diagnostics.
-    require Parse::RecDescent;
-    my $parser = Parse::RecDescent->new( $grammar );
-    $parser->{data}{typeconv} = $o->{ILSM}{typeconv};
-    $parser->{ILSM} = $o->{ILSM}; # give parser access to config options
-    return $parser;
-}
-
-#============================================================================
-# Intercept xs_generate and create the typemap file
-#============================================================================
-sub xs_generate {
-    my $o = shift;
-    $o->write_typemap;
-    return $o->SUPER::xs_generate;
-}
-
-#============================================================================
-# Return bindings for functions and classes
-#============================================================================
-sub xs_bindings {
-    my $o = shift;
-    my ( $pkg, $module ) = @{ $o->{API} }{ qw(pkg module modfname) };
-    my $data = $o->{ILSM}{parser}{data};
-    my @XS;
-
-    warn "Warning: No Inline C++ functions or classes bound to Perl\n"
-         . "Check your C++ for Inline compatibility.\n\n"
-        if (
-                ( not defined $data->{classes}   )
-            and ( not defined $data->{functions} )
-            and ( $^W )
-        );
-
-    for my $class ( @{ $data->{classes} } ) {
-        my $proper_pkg = $pkg . "::$class";
-        # Set up the proper namespace
-        push @XS, _build_namespace( $module, $proper_pkg );
-        push @XS,
-             _generate_member_xs_wrappers( $o, $pkg, $class, $proper_pkg );
-    }
-
-    push @XS, _remove_xs_prefixes ( $o, $module, $pkg );
-    push @XS, _generate_nonmember_xs_wrappers( $o );
-
-    for ( @{ $data->{enums} } ) {
-        # Global enums.
-        $o->{ILSM}{XS}{BOOT} .= make_enum(  $pkg, @{$_}{ qw( name body ) }  );
-    }
-    return join q{}, @XS;
-}
-
-
-# Set up the proper namespace.
-sub _build_namespace {
-    my ( $module, $proper_pkg ) = @_;
-    return <<"END";
-
-MODULE = $module        PACKAGE = $proper_pkg
-
-PROTOTYPES: DISABLE
-
-END
-}
-
-
-sub _generate_member_xs_wrappers {
-    my( $o, $pkg, $class, $proper_pkg ) = @_;
-    my @XS;
-    my $data = $o->{ILSM}{parser}{data};
-    my ( $ctor, $dtor, $abstract ) = ( 0, 0, 0 ); ## no critic (ambiguous)
-    for my $thing ( @{ $data->{class}{$class} } ) {
-        my ( $name, $scope, $type ) = @{$thing}{ qw| name scope thing | };
-
-        _handle_inheritance ( $o, $type, $scope, $pkg, $class, $name );
-        # Get/set methods will go here:
-        # Cases we skip:
-        $abstract ||= ( $type eq 'method' and $thing->{abstract} );
-        next if ( $type eq 'method' and $thing->{abstract} );
-        next if   $scope ne 'public';
-        if ( $type eq 'enum' ) {
-            $o->{ILSM}{XS}{BOOT} .= make_enum(
-                $proper_pkg, $name, $thing->{body}
-            );
-        } elsif (  $type eq 'method'  and  $name !~ m/operator/  ) {
-            # generate an XS wrapper
-            $ctor ||= ( $name eq $class    );
-            $dtor ||= ( $name eq "~$class" );
-            push @XS, $o->wrap( $thing, $name, $class );
-        }
-    }
-
-    # Provide default constructor and destructor:
-    push @XS, "$class *\n${class}::new()\n\n"
-        unless ( $ctor or $abstract );
-
-    push @XS, "void\n${class}::DESTROY()\n\n"
-        unless ( $dtor or $abstract );
-    return @XS;
-}
-
-
-# Let Perl handle inheritance.
-sub _handle_inheritance {
-    my( $o, $type, $scope, $pkg, $class, $name ) = @_;
-    if ( $type eq 'inherits' and $scope eq 'public' ) {
-        $o->{ILSM}{XS}{BOOT} ||= q{};
-        my $ISA_name = "${pkg}::${class}::ISA";
-        my $parent = "${pkg}::${name}";
-        $o->{ILSM}{XS}{BOOT} .= <<"END";
-{
-#ifndef get_av
-    AV *isa = perl_get_av("$ISA_name", 1);
-#else
-    AV *isa = get_av("$ISA_name", 1);
-#endif
-    av_push(isa, newSVpv("$parent", 0));
-}
-END
-    }
-    return;
-}
-
-
-sub _generate_nonmember_xs_wrappers {
-    my $o = shift;
-    my $data = $o->{ILSM}{parser}{data};
-    my @XS;
-    for my $function ( @{ $data->{functions} } ) {
-        # lose constructor defs outside class decls (and "implicit int")
-        next if $data->{function}{$function}{rtype} eq q{};
-        next if $data->{function}{$function}{rtype} =~ m/static/;  #specl case
-        next if $function =~ m/::/x;       # skip member functions.
-        next if $function =~ m/operator/;  # and operators.
-        push @XS, $o->wrap( $data->{function}{$function}, $function );
-    }
-    return @XS;
-}
-
-
-# Generate XS code to remove prefixes from function names.
-sub _remove_xs_prefixes {
-    my( $o, $module, $pkg ) = @_;
-    my $prefix = (
-        $o->{ILSM}{XS}{PREFIX}
-            ? "PREFIX = $o->{ILSM}{XS}{PREFIX}"
-            : q{}
-    );
-    return <<"END";
-
-MODULE = $module        PACKAGE = $pkg  $prefix
-
-PROTOTYPES: DISABLE
-
-END
-
-}
-
-
-#============================================================================
-# Generate an XS wrapper around anything: a C++ method or function
-#============================================================================
-sub wrap {
-    my( $o, $thing, $name, $class ) = @_;
-    $class ||= q{};
-    my $t  =   q{ } x 4; # indents in 4-space increments.
-    my ( @XS, @PREINIT, @CODE );
-
-    my ( $XS, $ctor, $dtor )
-        = _map_subnames_cpp_to_perl( $thing, $name, $class );
-
-    push @XS, $XS;
-
-    return q{} unless $o->check_type( $thing, $ctor, $dtor );
-
-    # Filter out optional subroutine arguments
-    my ( @args, @opts, $ellipsis, $void );
-
-    $_->{optional} ? push @opts, $_ : push @args, $_
-        for @{ $thing->{args} };
-
-    $ellipsis = pop @args
-        if ( @args and $args[-1]{name} eq '...' );
-
-    $void = ( $thing->{rtype} and $thing->{rtype} eq 'void' );
-
-    push @XS, join q{}, (
-        '(',
-        join( ', ',
-              ( map {$_->{name}} @args ),
-              ( scalar @opts or $ellipsis ) ? '...' : ()
-        ),
-        ")\n",
-    );
-
-    # Declare the non-optional arguments for XS type-checking
-    push @XS, "\t$_->{type}\t$_->{name}\n" for @args;
-
-    # Wrap "complicated" subs in stack-checking code
-    if ( $void or $ellipsis ) {
-        push @PREINIT, "\tI32 *\t__temp_markstack_ptr;\n";
-        push @CODE,    "\t__temp_markstack_ptr = PL_markstack_ptr++;\n";
-    }
-
-    if ( @opts ) {
-        push @PREINIT, "\t$_->{type}\t$_->{name};\n" for @opts;
-        push @CODE,    'switch(items'
-                       . ( $class ? '-1' : q{} )
-                       . ") {\n";
-
-        my $offset = scalar @args; # which is the first optional?
-        my $total  = $offset + scalar @opts;
-        for my $i (  $offset .. $total - 1  ) {
-            push @CODE, 'case ' . ( $i + 1 ) . ":\n";
-            my @tmp;
-            for my $j (  $offset .. $i  ) {
-                my $targ = $opts[ $j - $offset ]{name};
-                my $type = $opts[ $j - $offset ]{type};
-                my $src  = "ST($j)";
-                my $conv = $o->typeconv( $targ,$src,$type,'input_expr' );
-                push @CODE, $conv . ";\n";
-                push @tmp,  $targ;
-            }
-            push @CODE, "\tRETVAL = " unless $void;
-            push @CODE, call_or_instantiate(
-                $name, $ctor, $dtor, $class,
-                $thing->{rconst}, $thing->{rtype},
-                ( map { $_->{name} } @args ),   @tmp
-            );
-            push @CODE, "\tbreak; /* case " . ( $i + 1 ) . " */\n";
-        }
-        push @CODE, "default:\n";
-        push @CODE, "\tRETVAL = " unless $void;
-        push @CODE, call_or_instantiate(
-            $name, $ctor, $dtor, $class, $thing->{rconst}, $thing->{rtype},
-            map { $_->{name} } @args
-        );
-        push @CODE, "} /* switch(items) */ \n";
-    }
-    elsif ( $void ) {
-        push @CODE, "\t";
-        push @CODE, call_or_instantiate(
-            $name, $ctor, $dtor, $class, 0, q{},
-            map { $_->{name} } @args
-        );
-    }
-    elsif ( $ellipsis or $thing->{rconst} ) {
-        push @CODE, "\t";
-        push @CODE, 'RETVAL = ';
-        push @CODE, call_or_instantiate(
-            $name, $ctor, $dtor, $class,
-            $thing->{rconst},   $thing->{rtype},
-            map { $_->{name} } @args
-        );
-    }
-    if ( $void ) {
-        push @CODE, <<'END';
-        if (PL_markstack_ptr != __temp_markstack_ptr) {
-          /* truly void, because dXSARGS not invoked */
-          PL_markstack_ptr = __temp_markstack_ptr;
-          XSRETURN_EMPTY; /* return empty stack */
-        }
-        /* must have used dXSARGS; list context implied */
-        return; /* assume stack size is correct */
-END
-    }
-    elsif ( $ellipsis ) {
-        push @CODE, "\tPL_markstack_ptr = __temp_markstack_ptr;\n";
-    }
-
-    # The actual function:
-    local $" = q{};
-    push @XS, "${t}PREINIT:\n@PREINIT" if @PREINIT;
-    push @XS, $t;
-    push @XS, 'PP' if $void and @CODE;
-    push @XS, "CODE:\n@CODE" if @CODE;
-    push @XS, "${t}OUTPUT:\nRETVAL\n" if @CODE and not $void;
-    push @XS, "\n";
-    return "@XS";
-}
-
-
-sub _map_subnames_cpp_to_perl {
-    my ( $thing, $name, $class ) = @_;
-    my ( $XS,    $ctor, $dtor  ) = ( q{}, 0, 0 );
-
-    if ( $name eq $class ) {  # ctor
-        $XS   = $class . " *\n" . $class . '::new';
-        $ctor = 1;
-    }
-    elsif ( $name eq "~$class" ) { # dtor
-        $XS   = "void\n$class" . '::DESTROY';
-        $dtor = 1;
-    }
-    elsif ( $class ) {        # method
-        $XS   = "$thing->{rtype}\n$class" . "::$thing->{name}";
-    }
-    else {          # function
-        $XS   = "$thing->{rtype}\n$thing->{name}";
-    }
-    return ( $XS, $ctor, $dtor );
-}
-
-
-sub call_or_instantiate {
-    my (  $name,   $ctor,  $dtor,  $class, $const,  $type,  @args  ) = @_;
-
-    # Create an rvalue (which might be const-casted later).
-    my $rval = q{};
-    $rval .= 'new '    if $ctor;
-    $rval .= 'delete ' if $dtor;
-    $rval .= 'THIS->'  if ( $class and not ( $ctor or $dtor ) );
-    $rval .= $name . '(' . join ( q{,}, @args ) . ')';
-
-    return const_cast( $rval, $const, $type ) . ";\n";
-} ### Tested.
-
-sub const_cast {
-    my( $value, $const, $type ) = @_;
-    return $value unless $const and $type =~ m/[*&]/x;
-    return "const_cast<$type>($value)";
-} ### Tested.
-
-sub write_typemap {
-    my $o         = shift;
-    my $filename  = "$o->{API}{build_dir}/CPP.map";
-    my $type_kind = $o->{ILSM}{typeconv}{type_kind};
-    my $typemap   = q{};
-    $typemap  .=  $_  .  "\t" x 2  .  $TYPEMAP_KIND  .  "\n"
-        for grep { $type_kind->{$_} eq $TYPEMAP_KIND } keys %{$type_kind};
-    return unless length $typemap;
-
-    my $tm_output = <<"END";
-TYPEMAP
-$typemap
-OUTPUT
-$TYPEMAP_KIND
-$o->{ILSM}{typeconv}{output_expr}{$TYPEMAP_KIND}
-INPUT
-$TYPEMAP_KIND
-$o->{ILSM}{typeconv}{input_expr}{$TYPEMAP_KIND}
-END
-
-
-    # Open an output file, create if necessary, then lock, then truncate.
-    # This replaces the following, which wasn't lock-safe:
-      #    open my $TYPEMAP_FH, '>', $filename
-      #        or croak "Error: Can't write to $filename: $!";
-
-    sysopen( my $TYPEMAP_FH, $filename, O_WRONLY | O_CREAT )
-      or croak "Error: Can't write to $filename: $!";
-
-    # Flock and truncate (truncating to zero length to simulate '>' mode).
-    flock $TYPEMAP_FH, LOCK_EX
-      or croak "Error: Can't obtain lock for $filename: $!";
-    truncate $TYPEMAP_FH, 0
-      or croak "Error: Can't truncate $filename: $!";
-
-    # End of new lock-safe code.
-    
-    print {$TYPEMAP_FH} $tm_output;
-
-    close $TYPEMAP_FH
-        or croak "Error: Can't close $filename after write: $!";
-
-    $o->validate( TYPEMAPS => $filename );
-    return;
-}
-
-# Generate type conversion code: perl2c or c2perl.
-sub typeconv {
-    my( $o, $var, $arg, $type, $dir, $preproc ) = @_;
-    my $tkind = $o->{ILSM}{typeconv}{type_kind}{$type};
-    my $ret;
-    {
-        no strict;  ## no critic (strict)
-        # The conditional avoids uninitialized warnings if user passes
-        # a C++ function with 'void' as param.
-        if( defined $tkind ) {
-            # Even without the conditional this line must remain.
-            $ret = eval                                    ## no critic (eval)
-                qq{qq{$o->{ILSM}{typeconv}{$dir}{$tkind}}};
-        } else {
-            $ret = q{};
-        }
-    }
-    chomp $ret;
-    $ret =~ s/\n/\\\n/xg if $preproc;
-    return $ret;
-}
-
-# Verify that the return type and all arguments can be bound to Perl.
-sub check_type {
-    my ( $o, $thing, $ctor, $dtor ) = @_;
-    my $badtype;
-
-    # strip "useless" modifiers so the type is found in typemap:
-    BADTYPE: while ( 1 ) {
-    if ( !( $ctor || $dtor ) ) {
-        my $t = $thing->{rtype};
-        $t =~ s/^(\s|const|virtual|static)+//xg;
-        if ( $t ne 'void' && !$o->typeconv( q{}, q{}, $t, 'output_expr' ) ) {
-            $badtype = $t;
-            last BADTYPE;
-        }
-    }
-    foreach ( map { $_->{type} } @{ $thing->{args} } ) {
-        s/^(?:const|\s)+//xgo;
-        if ( $_ ne '...' && !$o->typeconv( q{}, q{}, $_, 'input_expr' ) ) {
-            $badtype = $_;
-            last BADTYPE;
-        }
-    }
-    return 1;
-    }
-    # I don't really like this verbosity. This is what 'info' is for. Maybe we
-    # should ask Brian for an Inline=DEBUG option.
-    warn    "No typemap for type $badtype. "
-            . "Skipping $thing->{rtype} $thing->{name}("
-            . join( ', ', map { $_->{type} } @{ $thing->{args} } )
-            . ")\n"
-        if 0;
-    return 0;
-}
-
-# Generate boot-code for enumeration constants:
-sub make_enum {
-    my ( $class, $name, $body ) = @_;
-    my @enum;
-    push @enum, <<"END";
-\t{
-\t    HV * pkg = gv_stashpv(\"$class\", 1);
-\t    if (pkg == NULL)
-\t        croak("Can't find package '$class'\\n");
-END
-    my $val = 0;
-    foreach ( @{$body} ) {
-        my ( $k, $v ) = @{$_};
-        $val = $v if defined $v;
-        push @enum, "\tnewCONSTSUB(pkg, \"$k\", newSViv($val));\n";
-        ++$val;
-    }
-    push @enum, "\t}\n";
-    return join q{}, @enum;
-}
-
-
-1;
-
-__END__
@@ -1,5 +1,101 @@
 Revision history for Perl extension Inline::CPP.
 
+0.69 2014-12-11
+  - Moved CPP/Grammar.pm to CPP/Parser/RecDescent.pm to facilitate 'using'
+    option for pluggable parsers (INGY++).
+
+0.68 2014-10-25
+  - Found one more namespace test in need of relaxation.
+
+0.67 2014-10-24
+  - Relax namespace tests with respect to ref returning Foo or main::Foo.
+    The distinction is unimportant, and different Perls act differently.
+
+0.66 2014-10-24
+  - Package identifiers may be single character.
+
+0.65 2014-10-23
+  - Identifiers may start with _ (Pre-5.120 regression in 0.64).
+
+0.64 2014-10-23
+  - Fix GH Issue #24: Downgrade gracefully if \p{XID_Start} and 
+    \p{XID_Continue} aren't available (pre-Perl 5.120).
+
+0.63 2014-09-13
+  - Merge pull request from William N. Braswell, Jr, fixing inheritance
+    for 'classes' config option.  (PR6 - wbraswell).
+
+0.62 2014-08-21
+  - Merge pull request from William N. Braswell, Jr. fixing a problem with
+    'classes' config option.
+    Problem is documented: https://github.com/daoswald/Inline-CPP/issues/18
+    Pull request: https://github.com/daoswald/Inline-CPP/pull/20
+  - Fix typos and spelling errors in POD (Suggested by wbraswell)
+    (Typo in copyright year for Neil, misspelling in CONTRIBUTING section.)
+
+0.61 2014-08-21
+  - POD refinement in CONTRIBUTING.
+
+0.60 2014-08-20
+  - Shift from Artistic 1.0 to Artistic 2.0 license.
+    Artistic 2 notes: http://www.perlfoundation.org/artistic_2_0_notes
+    Artistic 2 license: http://www.perlfoundation.org/artistic_license_2_0
+
+0.59 2014-08-14
+  - Restore logic to handle FreeBSD v10+ use of clang++
+    (Until EU::CG is fixed to handle this for us)
+
+0.58 2014-08-11
+  - main:: is no longer prepended to top level of single-level 
+    classnames, per wbraswell's suggestion.
+  - Documentation for main:: quirk no longer needed; removed.
+  - Explicitly support Perl 5.8.1+ (was 5.6.1, but Inline now requires
+    a minimum version of 5.8.1, so we too must.
+
+0.57 2014-08-11
+  - Adapt and apply patches from William Braswell (wbraswell) implementing,
+    documenting, and testing new "classes" configuration option for control
+    over C++ => Perl class name mappings.
+
+0.56 2014-08-11
+  - Merge 0.54_001 changes into stable.
+
+0.55 2014-08-07
+  - Config options are case insensitive.
+
+0.54_001 2014-08-02
+  - Added TODO tests.
+  - New dependency: ExtUtils::CppGuess.
+  - Compiler configuration / default library configuration now provided by
+    ExtUtils::CppGuess.
+  - Test t/08cppguess.t updated to diagnose detection/configuration.
+
+0.54 2014-07-29
+  - Added LICENSE file (no change to licensing, however).
+  - Improved distribution version number consistency test.
+  - Require a modern Inline and Inline::C (>= 0.64, 0.62, respectively).
+  - Minor POD revisions and modernizations.
+  - Refactoring of Makefile.PL
+  - META information updated: GitHub repo, no more RT.
+  - Bug tracking now on GitHub Issues.
+
+0.53 2014-07-29
+  - lib/Inline/CPP/grammar.pm renamed to Grammar.pm.
+
+0.52 2014-07-29
+  - Reorganized distribution file heirarchy to conform to modern structure.
+  - Silence irrelevant ntype warnings from typeconv().
+
+0.51 2014-07-28
+  - Add NAMESPACE configuration option to override a class's base namespace
+    (Eliminates the need for the "Namespace Hack").
+  - Tests now run recursively from subdirectories.
+  - POD updates to explain NAMESPACE config option.
+  - Tests for NAMESPACE config option.
+
+0.50 2014-02-05
+  - Fix POD markup error.
+
 0.49 2014-02-03
   - Eliminate some dead code.
   - Better documentation of parallel compilation issues (which never show up
@@ -0,0 +1,201 @@
+		       The Artistic License 2.0
+
+	    Copyright (c) 2000-2006, The Perl Foundation.
+
+     Everyone is permitted to copy and distribute verbatim copies
+      of this license document, but changing it is not allowed.
+
+Preamble
+
+This license establishes the terms under which a given free software
+Package may be copied, modified, distributed, and/or redistributed.
+The intent is that the Copyright Holder maintains some artistic
+control over the development of that Package while still keeping the
+Package available as open source and free software.
+
+You are always permitted to make arrangements wholly outside of this
+license directly with the Copyright Holder of a given Package.  If the
+terms of this license do not permit the full use that you propose to
+make of the Package, you should contact the Copyright Holder and seek
+a different licensing arrangement. 
+
+Definitions
+
+    "Copyright Holder" means the individual(s) or organization(s)
+    named in the copyright notice for the entire Package.
+
+    "Contributor" means any party that has contributed code or other
+    material to the Package, in accordance with the Copyright Holder's
+    procedures.
+
+    "You" and "your" means any person who would like to copy,
+    distribute, or modify the Package.
+
+    "Package" means the collection of files distributed by the
+    Copyright Holder, and derivatives of that collection and/or of
+    those files. A given Package may consist of either the Standard
+    Version, or a Modified Version.
+
+    "Distribute" means providing a copy of the Package or making it
+    accessible to anyone else, or in the case of a company or
+    organization, to others outside of your company or organization.
+
+    "Distributor Fee" means any fee that you charge for Distributing
+    this Package or providing support for this Package to another
+    party.  It does not mean licensing fees.
+
+    "Standard Version" refers to the Package if it has not been
+    modified, or has been modified only in ways explicitly requested
+    by the Copyright Holder.
+
+    "Modified Version" means the Package, if it has been changed, and
+    such changes were not explicitly requested by the Copyright
+    Holder. 
+
+    "Original License" means this Artistic License as Distributed with
+    the Standard Version of the Package, in its current version or as
+    it may be modified by The Perl Foundation in the future.
+
+    "Source" form means the source code, documentation source, and
+    configuration files for the Package.
+
+    "Compiled" form means the compiled bytecode, object code, binary,
+    or any other form resulting from mechanical transformation or
+    translation of the Source form.
+
+
+Permission for Use and Modification Without Distribution
+
+(1)  You are permitted to use the Standard Version and create and use
+Modified Versions for any purpose without restriction, provided that
+you do not Distribute the Modified Version.
+
+
+Permissions for Redistribution of the Standard Version
+
+(2)  You may Distribute verbatim copies of the Source form of the
+Standard Version of this Package in any medium without restriction,
+either gratis or for a Distributor Fee, provided that you duplicate
+all of the original copyright notices and associated disclaimers.  At
+your discretion, such verbatim copies may or may not include a
+Compiled form of the Package.
+
+(3)  You may apply any bug fixes, portability changes, and other
+modifications made available from the Copyright Holder.  The resulting
+Package will still be considered the Standard Version, and as such
+will be subject to the Original License.
+
+
+Distribution of Modified Versions of the Package as Source 
+
+(4)  You may Distribute your Modified Version as Source (either gratis
+or for a Distributor Fee, and with or without a Compiled form of the
+Modified Version) provided that you clearly document how it differs
+from the Standard Version, including, but not limited to, documenting
+any non-standard features, executables, or modules, and provided that
+you do at least ONE of the following:
+
+    (a)  make the Modified Version available to the Copyright Holder
+    of the Standard Version, under the Original License, so that the
+    Copyright Holder may include your modifications in the Standard
+    Version.
+
+    (b)  ensure that installation of your Modified Version does not
+    prevent the user installing or running the Standard Version. In
+    addition, the Modified Version must bear a name that is different
+    from the name of the Standard Version.
+
+    (c)  allow anyone who receives a copy of the Modified Version to
+    make the Source form of the Modified Version available to others
+    under
+		
+	(i)  the Original License or
+
+	(ii)  a license that permits the licensee to freely copy,
+	modify and redistribute the Modified Version using the same
+	licensing terms that apply to the copy that the licensee
+	received, and requires that the Source form of the Modified
+	Version, and of any works derived from it, be made freely
+	available in that license fees are prohibited but Distributor
+	Fees are allowed.
+
+
+Distribution of Compiled Forms of the Standard Version 
+or Modified Versions without the Source
+
+(5)  You may Distribute Compiled forms of the Standard Version without
+the Source, provided that you include complete instructions on how to
+get the Source of the Standard Version.  Such instructions must be
+valid at the time of your distribution.  If these instructions, at any
+time while you are carrying out such distribution, become invalid, you
+must provide new instructions on demand or cease further distribution.
+If you provide valid instructions or cease distribution within thirty
+days after you become aware that the instructions are invalid, then
+you do not forfeit any of your rights under this license.
+
+(6)  You may Distribute a Modified Version in Compiled form without
+the Source, provided that you comply with Section 4 with respect to
+the Source of the Modified Version.
+
+
+Aggregating or Linking the Package 
+
+(7)  You may aggregate the Package (either the Standard Version or
+Modified Version) with other packages and Distribute the resulting
+aggregation provided that you do not charge a licensing fee for the
+Package.  Distributor Fees are permitted, and licensing fees for other
+components in the aggregation are permitted. The terms of this license
+apply to the use and Distribution of the Standard or Modified Versions
+as included in the aggregation.
+
+(8) You are permitted to link Modified and Standard Versions with
+other works, to embed the Package in a larger work of your own, or to
+build stand-alone binary or bytecode versions of applications that
+include the Package, and Distribute the result without restriction,
+provided the result does not expose a direct interface to the Package.
+
+
+Items That are Not Considered Part of a Modified Version 
+
+(9) Works (including, but not limited to, modules and scripts) that
+merely extend or make use of the Package, do not, by themselves, cause
+the Package to be a Modified Version.  In addition, such works are not
+considered parts of the Package itself, and are not subject to the
+terms of this license.
+
+
+General Provisions
+
+(10)  Any use, modification, and distribution of the Standard or
+Modified Versions is governed by this Artistic License. By using,
+modifying or distributing the Package, you accept this license. Do not
+use, modify, or distribute the Package, if you do not accept this
+license.
+
+(11)  If your Modified Version has been derived from a Modified
+Version made by someone other than you, you are nevertheless required
+to ensure that your Modified Version complies with the requirements of
+this license.
+
+(12)  This license does not grant you the right to use any trademark,
+service mark, tradename, or logo of the Copyright Holder.
+
+(13)  This license includes the non-exclusive, worldwide,
+free-of-charge patent license to make, have made, use, offer to sell,
+sell, import and otherwise transfer the Package with respect to any
+patent claims licensable by the Copyright Holder that are necessarily
+infringed by the Package. If you institute patent litigation
+(including a cross-claim or counterclaim) against any party alleging
+that the Package constitutes direct or contributory patent
+infringement, then this Artistic License to you shall terminate on the
+date that such litigation is filed.
+
+(14)  Disclaimer of Warranty:
+THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS
+IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL
+LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -1,31 +1,15 @@
 Changes
-CPP.pm
 MANIFEST
 MANIFEST.SKIP
 Makefile.PL
 README
 TESTED
-grammar/grammar.pm
-grammar/Makefile.PL
-grammar/t/00pod_coverage.t
-grammar/t/01nherit.t
-grammar/t/02scope.t
-grammar/t/03inline.t
-grammar/t/04const.t
-grammar/t/05virt.t
-grammar/t/06deflt.t
-grammar/t/07static.t
-grammar/t/08anon.t
-grammar/t/09purevt.t
-grammar/t/10struct.t
-grammar/t/11minhrt.t
-grammar/t/12retlst.t
-grammar/t/13vararg.t
-grammar/t/14const.t
-grammar/t/15stvar.t
-grammar/t/16varlst.t
-grammar/t/17memberarray.t
+LICENSE
+inc/ILCPPConfig/OldCompilerGuess.pm
+inc/ILCPPConfig/CompilerGuess.pm
+lib/Inline/CPP.pm
 lib/Inline/CPP.pod
+lib/Inline/CPP/Parser/RecDescent.pm
 lib/Inline/CPP/Config.pm
 t/00load_prereqs.t
 t/01fn_cans.t
@@ -42,6 +26,42 @@ t/11rewrite_config.t
 t/12custom_libs.t
 t/13version_numbers.t
 t/14changes.t
+t/15config_case.t
+t/classes/01empty_ns_is_main.t
+t/classes/02main_ns_is_main.t
+t/classes/03baz_ns_is_baz.t
+t/classes/04invoke_from_non_main.t
+t/classes/05invalid_classes.t
+t/classes/06inherit.t
+t/classes/07conflict_avoid.t
+t/classes/08auto.t
+t/classes/09auto_mixed.t
+t/classes/10auto_inherit.t
+t/grammar/00pod_coverage.t
+t/grammar/01nherit.t
+t/grammar/02scope.t
+t/grammar/03inline.t
+t/grammar/04const.t
+t/grammar/05virt.t
+t/grammar/06deflt.t
+t/grammar/07static.t
+t/grammar/08anon.t
+t/grammar/09purevt.t
+t/grammar/10struct.t
+t/grammar/11minhrt.t
+t/grammar/12retlst.t
+t/grammar/13vararg.t
+t/grammar/14const.t
+t/grammar/15stvar.t
+t/grammar/16varlst.t
+t/grammar/17memberarray.t
+t/grammar/18namespace.t
+t/grammar/19multidimarray.t
+t/namespace/01empty_ns_is_main.t
+t/namespace/02main_ns_is_main.t
+t/namespace/03baz_ns_is_baz.t
+t/namespace/04invoke_from_non_main.t
+t/namespace/05invalid_ns.t
+t/namespace/06inherit.t
 META.yml                            Module YAML meta-data (added by MakeMaker)
 META.json                           Module JSON meta-data (added by MakeMaker)
-
@@ -19,13 +19,13 @@
 ^\.#
 
 # Custom skips.
-^grammar/_Inline\b
 ^_Inline/\b
-^FastSieve\.inl
-^grammar/pm_to_blib
+^_Inline/
 ^pm_to_blib
-^grammar/Makefile$
-^grammar/t/_Inline/
 ^t/_Inline/
+^t/grammar/_Inline/
+^t/namespace/_Inline/
 \.gz$
 MYMETA\b
+^Inline-CPP-\d+\.\d+/
+\.perltidyrc
@@ -4,9 +4,9 @@
       "David Oswald <davido@cpan.org>"
    ],
    "dynamic_config" : 1,
-   "generated_by" : "ExtUtils::MakeMaker version 6.86, CPAN::Meta::Converter version 2.133380",
+   "generated_by" : "ExtUtils::MakeMaker version 7.04, CPAN::Meta::Converter version 2.142690",
    "license" : [
-      "artistic_1"
+      "artistic_2"
    ],
    "meta-spec" : {
       "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec",
@@ -16,6 +16,7 @@
    "no_index" : {
       "directory" : [
          "t",
+         "inc",
          "inc"
       ]
    },
@@ -24,31 +25,53 @@
          "requires" : {
             "Config" : "0",
             "English" : "0",
-            "Test::More" : "0.98"
+            "File::Temp" : "0",
+            "Test::More" : "1.001009"
          }
       },
       "configure" : {
          "requires" : {
             "Config" : "0",
-            "ExtUtils::MakeMaker" : "6.56"
+            "ExtUtils::CppGuess" : "0.07",
+            "ExtUtils::MakeMaker" : "7.04",
+            "FindBin" : "0"
          }
       },
       "runtime" : {
          "requires" : {
             "Carp" : "0",
-            "Inline" : "0.53",
-            "Inline::C" : "0.53",
+            "Inline" : "0.78",
+            "Inline::C" : "0.67",
             "Parse::RecDescent" : "0",
-            "perl" : "5.006001"
+            "perl" : "5.008001"
          }
       }
    },
    "provides" : {
       "Inline::CPP" : {
-         "file" : "CPP.pm",
-         "version" : "0.49"
+         "file" : "lib/Inline/CPP.pm",
+         "version" : "0.69"
+      },
+      "Inline::CPP::Config" : {
+         "file" : "lib/Inline/CPP/Config.pm",
+         "version" : "0.69"
+      },
+      "Inline::CPP::Parser::RecDescent" : {
+         "file" : "lib/Inline/CPP/Parser/RecDescent.pm",
+         "version" : "0.69"
       }
    },
    "release_status" : "stable",
-   "version" : "0.49"
+   "resources" : {
+      "homepage" : "http://github.com/daoswald/Inline-CPP",
+      "license" : [
+         "http://dev.perl.org/licenses/artistic.html"
+      ],
+      "repository" : {
+         "type" : "git",
+         "url" : "http://github.com/daoswald/Inline-CPP.git",
+         "web" : "http://github.com/daoswald/Inline-CPP"
+      }
+   },
+   "version" : "0.69"
 }
@@ -3,31 +3,45 @@ abstract: 'Write Perl subroutines and classes in C++.'
 author:
   - 'David Oswald <davido@cpan.org>'
 build_requires:
-  Config: 0
-  English: 0
-  Test::More: 0.98
+  Config: '0'
+  English: '0'
+  File::Temp: '0'
+  Test::More: '1.001009'
 configure_requires:
-  Config: 0
-  ExtUtils::MakeMaker: 6.56
+  Config: '0'
+  ExtUtils::CppGuess: '0.07'
+  ExtUtils::MakeMaker: '7.04'
+  FindBin: '0'
 dynamic_config: 1
-generated_by: 'ExtUtils::MakeMaker version 6.86, CPAN::Meta::Converter version 2.133380'
-license: artistic
+generated_by: 'ExtUtils::MakeMaker version 7.04, CPAN::Meta::Converter version 2.142690'
+license: artistic_2
 meta-spec:
   url: http://module-build.sourceforge.net/META-spec-v1.4.html
-  version: 1.4
+  version: '1.4'
 name: Inline-CPP
 no_index:
   directory:
     - t
     - inc
+    - inc
 provides:
   Inline::CPP:
-    file: CPP.pm
-    version: 0.49
+    file: lib/Inline/CPP.pm
+    version: '0.69'
+  Inline::CPP::Config:
+    file: lib/Inline/CPP/Config.pm
+    version: '0.69'
+  Inline::CPP::Parser::RecDescent:
+    file: lib/Inline/CPP/Parser/RecDescent.pm
+    version: '0.69'
 requires:
-  Carp: 0
-  Inline: 0.53
-  Inline::C: 0.53
-  Parse::RecDescent: 0
-  perl: 5.006001
-version: 0.49
+  Carp: '0'
+  Inline: '0.78'
+  Inline::C: '0.67'
+  Parse::RecDescent: '0'
+  perl: '5.008001'
+resources:
+  homepage: http://github.com/daoswald/Inline-CPP
+  license: http://dev.perl.org/licenses/artistic.html
+  repository: http://github.com/daoswald/Inline-CPP.git
+version: '0.69'
@@ -1,250 +1,228 @@
 use ExtUtils::MakeMaker;
-use Config;
+use FindBin;
+use lib "$FindBin::Bin/inc";
+use ILCPPConfig::CompilerGuess 'guess_compiler';
 use Fcntl qw( :DEFAULT :flock );
-
 use strict;
+use 5.008001;
 
-# use 5.006000;
 
 # We're using bareword file handles and two arg open for backward
 # compatibility in Makefile.PL.  Here we disable those tests in Perl::Critic.
-
 ## no critic (bareword file handle)
 ## no critic (two-argument open)
 
-my $CPP_Config_path = 'lib/Inline/CPP/Config.pm';
+# The next line is verified via t/13version_numbers.t. Retain single quoting.
 
-my %PREREQ_PM = (
-    'Inline'            => '0.53',
-    'Inline::C'         => '0.53',
-    'Parse::RecDescent' => '0',
-    'Carp'              => '0',
-);
+my $DIST_VERSION    = '0.69';                        # DRY in Makefile.PL.
 
-#============================================================================
-# Makefile.PL will later create this as ilcpptest.cpp to verify that
-# the target system uses <iostream> versus <iostream.h> style headers.
-#============================================================================
+my $CPP_Config_path = 'lib/Inline/CPP/Config.pm';
 
 my $test_cpp_filename = 'ilcpptest';        # '.cpp' appended via open.
 my $test_cpp          = <<'END_TEST_CPP';
 #include <iostream>
-int main(){
-    return 0;
-}
+int main(){ return 0; }
 END_TEST_CPP
 
+my %PREREQ_PM = (
+  'Inline'            => '0.78', # Case insensitivity.
+  'Inline::C'         => '0.67',
+  'Parse::RecDescent' => '0',
+  'Carp'              => '0',
+);
+
+
+check_prereqs( \%PREREQ_PM ) or warn "!!! PREREQUISITES NOT MET !!!";
+
+my( $cc_guess, $libs_guess ) = guess_compiler();
+
+my $cpp_compiler
+  = prompt( "What C++ compiler would you like to use?", $cc_guess );
+  
+my $libs
+  = prompt( "What default libraries would you like to include?", $libs_guess );
+
+configure_distribution( $test_cpp_filename, $cpp_compiler, $libs );
+
+WriteMakefile(
+  NAME           => 'Inline::CPP',
+  AUTHOR         => 'David Oswald <davido@cpan.org>',
+  VERSION_FROM   => 'lib/Inline/CPP.pm',
+  ABSTRACT_FROM  => 'lib/Inline/CPP.pod',
+  LICENSE        => 'artistic_2',
+  PREREQ_PM      => \%PREREQ_PM,
+  BUILD_REQUIRES => {
+    'Test::More' => '1.001009',    # Core. Minimum version.
+    'Config'     => '0',           # Core.
+    'English'    => '0',           # Core.
+    'File::Temp' => '0',           # Core.
+  },
+  CONFIGURE_REQUIRES => {
+    'ExtUtils::CppGuess'  => '0.07',    # Beginning IL::CPP 0.54_001.
+    'ExtUtils::MakeMaker' => '7.04',    # Core.
+    'FindBin'             => '0',       # Core.
+    'Config'              => '0',       # Core.
+  },
+  META_MERGE => {
+    'meta-spec' => {
+      version => 2,
+      url     => 'http://search.cpan.org/perldoc?CPAN::Meta::Spec',
+    },
+    no_index   => { directory => [ 'inc' ], },
+    resources   => {
+      license    => 'http://dev.perl.org/licenses/artistic.html',
+      bugtracker => 'http://github.com/daoswald/Inline-CPP/issues',
+      homepage   => 'http://github.com/daoswald/Inline-CPP',
+      repository => {
+        type => 'git',
+        url  => 'http://github.com/daoswald/Inline-CPP.git',
+        web  => 'http://github.com/daoswald/Inline-CPP',
+      },
+    },
+    provides   => {
+      'Inline::CPP' => {
+        file    => 'lib/Inline/CPP.pm',
+        version => $DIST_VERSION,
+      },
+      'Inline::CPP::Parser::RecDescent' => {
+        file    => 'lib/Inline/CPP/Parser/RecDescent.pm',
+        version => $DIST_VERSION,
+      },
+      'Inline::CPP::Config' => {
+        file    => 'lib/Inline/CPP/Config.pm',
+        version => $DIST_VERSION,
+      },
+    },
+  },
+  MIN_PERL_VERSION => '5.008001',  # Modern Inline versions require 5.8.1.
+  test  => { RECURSIVE_TEST_FILES => 1 },
+  clean => { FILES => '_Inline/ t/_Inline t/classes/_Inline t/grammar/_Inline t/namespace/_Inline Inline-CPP-*/' }, # Paths can be space delimited.
+);
+
 #============================================================================
 # We'll do our own prerequisite checking, since MakeMaker does it
 # in a way that always fails: 'use Inline::C 0.33' will never work.
 #============================================================================
-for ( sort keys %PREREQ_PM ) {
-    ## no critic (eval)
+
+sub check_prereqs {
+  my $prereq_pm_href = shift;
+  my $prereqs_ok = 1;
+
+  for( sort keys %{$prereq_pm_href} ) {
+    ## no critic (eval);
     eval "require $_";
 
     # We eval version numbers to normalize _xxx dev numbering.
     my $have = eval 'no strict q/refs/; ${"${_}::VERSION"}';
+
     use strict q/refs/;
-    my $want = eval $PREREQ_PM{$_};
-    warn "Warning: prerequisite $_ version $PREREQ_PM{$_} not found."
-        if $@
-            or $have < $want;
-}
 
-#============================================================================
-# Make an intelligent guess about what compiler to use
-#============================================================================
-my $cc_guess;
-my $libs_guess;
-
-if ( $Config{osname} eq 'darwin' ) {
-    my $stdlib_query
-        = 'find /usr/lib/gcc -name "libstdc++*" | grep $( uname -p )';
-    my $stdcpp = `$stdlib_query`;
-    +$stdcpp =~ s/^(.*)\/[^\/]+$/$1/;
-    $cc_guess   = 'g++';
-    $libs_guess = "-L$stdcpp -lstdc++";
-}
-elsif ( $Config{osname} ne 'darwin'
-    and $Config{gccversion}
-    and $Config{cc} =~ m#\bgcc\b[^/]*$# )
-{
-    ( $cc_guess = $Config{cc} ) =~ s[\bgcc\b([^/]*)$(?:)][g\+\+$1];
-    $libs_guess = '-lstdc++';
-}
-elsif ( $Config{osname} =~ m/^MSWin/ ) {
-    $cc_guess   = 'cl -TP -EHsc';
-    $libs_guess = 'MSVCIRT.LIB';
-}
-elsif ( $Config{osname} eq 'linux' ) {
-    $cc_guess   = 'g++';
-    $libs_guess = '-lstdc++';
-}
+    my $want = eval $prereq_pm_href->{$_};
 
-# Dragonfly patch is just a hunch... (still doesn't work)
-elsif ( $Config{osname} eq 'netbsd' || $Config{osname} eq 'dragonfly' ) {
-    $cc_guess   = 'g++';
-    $libs_guess = '-lstdc++ -lgcc_s';
-}
-elsif ( $Config{osname} eq 'cygwin' ) {
-    $cc_guess   = 'g++';
-    $libs_guess = '-lstdc++';
-}
-elsif ( $Config{osname} eq 'solaris' or $Config{osname} eq 'SunOS' ) {
-    if ( $Config{cc} eq 'gcc'
-        || ( exists( $Config{gccversion} ) && $Config{gccversion} > 0 ) )
-    {
-        $cc_guess   = 'g++';
-        $libs_guess = '-lstdc++';
-    }
-    else {
-        $cc_guess   = 'CC';
-        $libs_guess = '-lCrun';
+    if( $@  or  $have < $want ) {
+      warn "Warning: prerequisite $_ version $prereq_pm_href->{$_} not found.";
+      $prereqs_ok = 0;
     }
+  }
+  return $prereqs_ok;
 }
 
-# MirBSD: Still problematic.
-elsif ( $Config{osname} eq 'mirbsd' ) {
-    my $stdlib_query
-        = 'find /usr/lib/gcc -name "libstdc++*" | grep $( uname -p ) | head -1';
-    my $stdcpp = `$stdlib_query`;
-    +$stdcpp =~ s/^(.*)\/[^\/]+$/$1/;
-    $cc_guess   = 'g++';
-    $libs_guess = "-L$stdcpp -lstdc++ -lc -lgcc_s";
-}
-
-elsif( $Config{osname} eq 'freebsd' && $Config{osvers} =~ /^(\d+)/ && $1 >= 10 ){
-  $cc_guess = 'clang++';
-  $libs_guess = '-lc++';
-}
-
-# Sane defaults for other (probably unix-like) operating systems
-else {
-    $cc_guess   = 'g++';
-    $libs_guess = '-lstdc++';
-}
-
-print "This will configure and build Inline::C++.\n";
 
-my $cpp_compiler
-    = prompt( "What default C++ compiler would you like to use?", $cc_guess );
+###############################################################################
+# Test for appropriate header style.
+# Configure distribution defaults in Inline::CPP::Config.pm.
+###############################################################################
 
-my $libs = prompt( "What default libraries would you like to include?",
-    $libs_guess );
+sub configure_distribution {
+  my( $test_cpp_filename, $cpp_compiler, $libs ) = @_;
+  
+  # Obtain a sentinel lock. Hold it until file work is done.
 
-#============================================================================
-# Test whether the compiler prefers <iostream> or <iostream.h>.
-#============================================================================
+  sysopen TESTCPP_LOCK, "$test_cpp_filename.cpp.lock", O_WRONLY | O_CREAT
+    or die "Makefile.PL: Couldn't open $test_cpp_filename.cpp.lock " .
+           "as a lock sentinel:\n$!";
+  flock TESTCPP_LOCK, LOCK_EX
+    or die "Makefile.PL: Couldn't flock $test_cpp_filename.cpp.lock:\n$!\n";
+    
+  # Test whether the compiler prefers <iostream> or <iostream.h>.
 
-# Lock-safe open:
-# Used to be:
-  # open TESTCPP, ">$test_cpp_filename.cpp"
-  #    or die "Makefile.PL: Couldn't open $test_cpp_filename for output:\n$!\n";
+  sysopen TESTCPP, "$test_cpp_filename.cpp", O_WRONLY | O_CREAT
+    or die "Makefile.PL: Couldn't open $test_cpp_filename.cpp"
+         . " for output:\n$!\n";
 
-sysopen TESTCPP, "$test_cpp_filename.cpp", O_WRONLY | O_CREAT
-  or die "Makefile.PL: Couldn't open $test_cpp_filename.cpp for output:\n$!\n";
-flock TESTCPP, LOCK_EX
-  or die "Makefile.PL: Couldn't flock $test_cpp_filename.cpp:\n$!\n";
-truncate TESTCPP, 0
-  or die "Makefile.PL: Couldn't truncate $test_cpp_filename.cpp:\n$!\n";
+  truncate TESTCPP, 0
+    or die "Makefile.PL: Couldn't truncate $test_cpp_filename.cpp:\n$!\n";
 
-print TESTCPP $test_cpp;
+  print TESTCPP $test_cpp;
 
-close TESTCPP
+  close TESTCPP
     or die "Makefile.PL: Couldn't close $test_cpp_filename:\n$!\n";
 
-# Compile our test C++ program that includes the <iostream> header.
-my $result;
-if ( $cpp_compiler =~ m/^cl/ ) {
-
+  # Compile our test C++ program that includes the <iostream> header.
+  my $result;
+  if ( $cpp_compiler =~ m/^cl/ ) {
     # MS compilers don't support -o (or -o is deprecated for them).
     $result = system( qq{$cpp_compiler -Fe:$test_cpp_filename.exe }
-            . qq{$test_cpp_filename.cpp} );
-}
-else {
+      . qq{$test_cpp_filename.cpp} );
+  }
+  else {
     $result = system( qq{$cpp_compiler -o $test_cpp_filename.exe }
-            . qq{$test_cpp_filename.cpp} );
-}
-
-my $iostream_fname = 'iostream';
-my $comment        = '';
-if ( $result != 0 ) {
+      . qq{$test_cpp_filename.cpp} );
+  }
 
+  my $iostream_fname = 'iostream';
+  my $comment        = '';
+  if ( $result != 0 ) {
     # Compiling with <iostream> failed, so we'll assume .h headers.
     print "Detected <iostream.h> style headers. ('.h' needed.)\n";
     $iostream_fname = 'iostream.h';
-    $comment        = '//';           # Prepend a comment to a #define.
-}
-else {
-
+    $comment        = '//';                 # Prepend a comment to a #define.
+  }
+  else {
     # Compiling with <iostream> passed, so we'll assume Standard headers.
     print "Detected <iostream> style headers. ('.h' not needed.)\n";
-    unlink "$test_cpp_filename.exe" or warn $!;    # Unlink the executable.
-}
+    unlink "$test_cpp_filename.exe" or warn $!;     # Unlink the executable.
+  }
 
-unlink "$test_cpp_filename.cpp" or warn $!;        # Unlink the test source.
+  unlink "$test_cpp_filename.cpp" or warn $!;         # Unlink the test source.
 
-# Apply the defaults:
-# Lock friendly.  This isn't a race condition because even if the file gets
-# modified between read and write, it will be modified to the same system
-# state, unless human intervention changes defaults, in which case it's
-# virtually impossible for concurrency to be a problem.
+  # Apply the distribution defaults:
 
-open CPP_Config, $CPP_Config_path
-  or die "Makefile.PL: Can't read from $CPP_Config_path for configuration!\n$!";
-flock CPP_Config, LOCK_SH
-  or die "Makefile.PL: Can't flock $CPP_Config_path for input:\n$!\n";
+  open CPP_Config, $CPP_Config_path
+    or die "Makefile.PL: Can't read from $CPP_Config_path"
+         . " for configuration!\n$!";
 
-my @lines = <CPP_Config>;
+  my @lines = <CPP_Config>;
 
-close CPP_Config;
+  close CPP_Config;
 
-for (@lines) {
+  for (@lines) {
     s{ ( our \s* \$compiler    \s* = \s* ['"] ) [^'"]+ } {$1$cpp_compiler}x;
     s{ ( our \s* \$libs        \s* = \s* ['"] ) [^'"]+ } {$1$libs}x;
     s{ ( our \s* \$iostream_fn \s* = \s* ['"] ) [^'"]+ } {$1$iostream_fname}x;
     s{ ^ [^#]* ( \#define \s+ __INLINE_CPP_NAMESPACE_STD    ) } {$comment$1}x;
     s{ ^ [^#]* ( \#define \s+ __INLINE_CPP_STANDARD_HEADERS ) } {$comment$1}x;
-}
+  }
 
 
-# Lock friendly open for output.
-sysopen CPP_Config, $CPP_Config_path, O_WRONLY | O_CREAT
-  or die "Makefile.PL: Can't open $CPP_Config_path to write configuration:\n$!";
+  # Lock friendly open for output.
+  sysopen CPP_Config, $CPP_Config_path, O_WRONLY | O_CREAT
+    or die "Makefile.PL: Can't open $CPP_Config_path "
+         . "to write configuration:\n$!";
 
-truncate CPP_Config, 0
-  or die "Makefile.PL: Can't truncate $CPP_Config_path to write config:\n$!";
+  truncate CPP_Config, 0
+    or die "Makefile.PL: Can't truncate $CPP_Config_path to write config:\n$!";
 
-print CPP_Config @lines
+  print CPP_Config @lines
     or die "Can't write to $CPP_Config_path for configuration!\n$!";
 
-close CPP_Config
+  close CPP_Config
     or die "Can't close $CPP_Config_path after config output!\n$!";
 
-WriteMakefile(
-    NAME           => 'Inline::CPP',
-    AUTHOR         => 'David Oswald <davido@cpan.org>',
-    VERSION_FROM   => 'CPP.pm',
-    ABSTRACT_FROM  => 'lib/Inline/CPP.pod',
-    LICENSE        => 'artistic',
-    PREREQ_PM      => \%PREREQ_PM,
-    BUILD_REQUIRES => {
-        'Test::More' => '0.98',    # Core. Minimum version.
-        'Config'     => '0',       # Core.
-        'English'    => '0',       # Core.
-    },
-    CONFIGURE_REQUIRES => {
-        'ExtUtils::MakeMaker' => '6.56',    # Minimum version.
-        'Config'              => '0',       # Core.
-    },
-    META_MERGE => {
-        provides => {
-            'Inline::CPP' => {
-                file    => 'CPP.pm',
-                version => '0.49'
-            },
-        },
-    },
-    MIN_PERL_VERSION => '5.006001',
-    clean            => { FILES => '_Inline/ grammar/_Inline' },
-);
+  close TESTCPP_LOCK; # Release lock only after test compilation, and output to
+                      # Config.pm.
+
+  unlink "$test_cpp_filename.cpp.lock" or warn $!;  # Unlink the test sentinel.
+
+  return;
+}
@@ -45,16 +45,15 @@ variation for your specific C++ compiler,
 
 If you have the HARNESS_OPTIONS environment variable set to run tests 
 concurrently in multiple processes, the test suite will attempt to invoke
-the C++ compiler multiple times concurrently.  We're finding that this option
-is incompatible with Inline::CPP, and the compilation process is too complex
-to work out why without considerable effort.
+the C++ compiler multiple times concurrently.  Recent versions of Inline and
+Inline::C have made progress on stamping out race conditions, but YMMV for now.
 
-Also, some smoke testers run their testing in parallel, which has a similar
-negative effect, and results in FAIL reports for reasons that will never
+Also, some smoke testers run their testing in parallel, which may also be
+problematic, and may result in FAIL reports for reasons that will never
 occur in the real world.
 
-This module requires Inline::C.pm version 0.53 or higher to be installed.
-It also uses Parse::RecDescent, and a new-ish version of ExtUtils::MakeMaker.
+See Makefile.PL, or the META.* files for lists of dependencies and minimum
+dependency version numbers.  Minimum Perl version is now 5.8.1, same as Inline.
 
 To install Inline::CPP do this:
 
@@ -87,4 +86,4 @@ at https://github.com/daoswald/Inline-CPP
 
 Please send questions and comments to "David Oswald" <DAVIDO@cpan.org>
 
-Copyright (c) 2003 - 2013, Neil Watkiss, David Oswald. All Rights Reserved.
+Copyright (c) 2003 - 2014, Neil Watkiss, David Oswald. All Rights Reserved.
@@ -1,6 +0,0 @@
-use ExtUtils::MakeMaker;
-WriteMakefile(
-          NAME => 'Inline::CPP::grammar',
-          VERSION_FROM => 'grammar.pm',
-          PREREQ_PM => { 'Parse::RecDescent' => 0 },
-         );
@@ -1,518 +0,0 @@
-package Inline::CPP::grammar; ## no critic (Package)
-
-use strict;
-use warnings;
-
-use vars qw($TYPEMAP_KIND $class_part $class_decl $star);
-
-# Dev versions will have a _0xx suffix.
-# We eval the $VERSION to accommodate dev version numbering as described in
-# perldoc perlmodstyle
-our $VERSION = '0.49';
-#$VERSION = eval $VERSION;  ## no critic (eval)
-
-# Parse::RecDescent 1.90 and later have an incompatible change
-# 'The key of an %item entry for a repeated subrule now includes
-# the repetition specifier.'
-# Hence various hash keys may or may not need trailing '(s?)' depending on
-# the version of Parse::RecDescent we are using.
-
-require Parse::RecDescent;
-
-# Deal with Parse::RecDescent's version numbers for development
-# releases (eg, '1.96_000') resulting in a warning about non-numeric in >
-# comparison.
-{   # Lexical scope.
-    # Eval away the underscore.  "1.96_000" => "1.96000".
-    # Use that "stable release" version number as the basis for our numeric
-    # comparison.
-    my $stable_version = eval $Parse::RecDescent::VERSION; ## no critic (eval)
-    ( $class_part, $class_decl, $star ) =
-        map {
-            ( $stable_version > 1.89 )
-            ? "$_(s?)"
-            : $_
-        } qw ( class_part class_decl star );
-} # End lexical scope.
-
-
-
-#============================================================================
-# Regular expressions to match code blocks, numbers, strings, parenthesized
-# expressions, function calls, and macros. The more complex regexes are only
-# implemented in 5.6.0 and above, so they're in eval-blocks.
-#
-# These are all adapted from the output of Damian Conway's excellent
-# Regexp::Common module. In future, Inline::CPP may depend directly on it,
-# but for now I'll just duplicate the code.
-use vars qw( $code_block $string $number $parens $funccall );
-#============================================================================
-
-# $RE{balanced}{-parens=>q|{}()[]"'|}
-eval <<'END'; ## no critic (eval)
-$code_block = qr'(?-xism:(?-xism:(?:[{](?:(?>[^][)(}{]+)|(??{$Inline::CPP::grammar::code_block}))*[}]))|(?-xism:(?-xism:(?:[(](?:(?>[^][)(}{]+)|(??{$Inline::CPP::grammar::code_block}))*[)]))|(?-xism:(?-xism:(?:[[](?:(?>[^][)(}{]+)|(??{$Inline::CPP::grammar::code_block}))*[]]))|(?-xism:(?!)))))';
-END
-$code_block = qr'{[^}]*}' if $@; # For the stragglers: here's a lame regexp.
-
-# $RE{balanced}{-parens=>q|()"'|}
-eval <<'END'; ## no critic (eval)
-$parens = qr'(?-xism:(?-xism:(?:[(](?:(?>[^)(]+)|(??{$Inline::CPP::grammar::parens}))*[)]))|(?-xism:(?!)))';
-END
-$parens = qr'\([^)]*\)' if $@; # For the stragglers: here's another
-
-# $RE{quoted}
-$string = qr'(?:(?:\")(?:[^\\\"]*(?:\\.[^\\\"]*)*)(?:\")|(?:\')(?:[^\\\']*(?:\\.[^\\\']*)*)(?:\')|(?:\`)(?:[^\\\`]*(?:\\.[^\\\`]*)*)(?:\`))';
-
-# $RE{num}{real}|$RE{num}{real}{-base=>16}|$RE{num}{int}
-$number   = qr'(?:(?i)(?:[+-]?)(?:(?=[0123456789]|[.])(?:[0123456789]*)(?:(?:[.])(?:[0123456789]{0,}))?)(?:(?:[E])(?:(?:[+-]?)(?:[0123456789]+))|))|(?:(?i)(?:[+-]?)(?:(?=[0123456789ABCDEF]|[.])(?:[0123456789ABCDEF]*)(?:(?:[.])(?:[0123456789ABCDEF]{0,}))?)(?:(?:[G])(?:(?:[+-]?)(?:[0123456789ABCDEF]+))|))|(?:(?:[+-]?)(?:\d+))';
-$funccall = qr/(?:[_a-zA-Z][_a-zA-Z0-9]*::)*[_a-zA-Z][_a-zA-Z0-9]*(?:$Inline::CPP::grammar::parens)?/;
-
-#============================================================================
-# Inline::CPP's grammar
-#============================================================================
-sub grammar {
-    return <<'END';
-
-{ use Data::Dumper; }
-
-{
-    sub handle_class_def {
-        my ($thisparser, $def) = @_;
-#         print "Found a class: $def->[0]\n";
-        my $class = $def->[0];
-        my @parts;
-        for my $part (@{$def->[1]}) { push @parts, @$_ for @$part }
-        push @{$thisparser->{data}{classes}}, $class
-            unless defined $thisparser->{data}{class}{$class};
-        $thisparser->{data}{class}{$class} = \@parts;
-#   print "Class $class:\n", Dumper \@parts;
-        Inline::CPP::grammar::typemap($thisparser, $class);
-        [$class, \@parts];
-    }
-    sub handle_typedef {
-        my ($thisparser, $t) = @_;
-        my ($name, $type) = @{$t}{qw(name type)};
-#   print "found a typedef: $name => $type\n";
-
-        # XXX: this doesn't handle non-class typedefs that we could handle,
-        # e.g. "typedef int my_int_t"
-
-        if ($thisparser->{data}{class}{$type}
-            && !exists($thisparser->{data}{class}{$name})) {
-            push @{$thisparser->{data}{classes}}, $name;
-            $thisparser->{data}{class}{$name} = $thisparser->{data}{class}{$type};
-            Inline::CPP::grammar::typemap($thisparser, $name);
-        }
-        $t;
-    }
-    sub handle_enum {
-        my ($thisparser, $t) = @_;
-        $t;
-    }
-}
-
-code: part(s) {1}
-
-part: comment
-    | typedef
-      {
-        handle_typedef($thisparser, $item[1]);
-        1;
-      }
-    | enum
-      {
-        my $t = handle_enum($thisparser, $item[1]);
-        push @{$thisparser->{data}{enums}}, $t;
-        1;
-      }
-    | class_def
-      {
-         handle_class_def($thisparser, $item[1]);
-     1;
-      }
-    | function_def
-      {
-#         print "found a function: $item[1]->{name}\n";
-         my $name = $item[1]->{name};
-     my $i=0;
-     for my $arg (@{$item[1]->{args}}) {
-        $arg->{name} = 'dummy' . ++$i unless defined $arg->{name};
-     }
-     Inline::CPP::grammar::strip_ellipsis($thisparser,
-                          $item[1]->{args});
-     push @{$thisparser->{data}{functions}}, $name
-           unless defined $thisparser->{data}{function}{$name};
-     $thisparser->{data}{function}{$name} = $item[1];
-#    print Dumper $item[1];
-     1;
-      }
-    | all
-
-typedef: 'typedef' class IDENTIFIER(?) '{' <commit> class_part(s?) '}' IDENTIFIER ';'
-       {
-     my ($class, $parts);
-         $class = $item[3][0] || 'anon_class'.($thisparser->{data}{anonclass}++);
-         ($class, $parts)= handle_class_def($thisparser, [$class, $item{$Inline::CPP::grammar::class_part}]);
-     { thing => 'typedef', name => $item[8], type => $class, body => $parts }
-       }
-       | 'typedef' IDENTIFIER IDENTIFIER ';'
-       { { thing => 'typedef', name => $item[3], type => $item[2] } }
-       | 'typedef' /[^;]*/ ';'
-       {
-#         dprint "Typedef $item{__DIRECTIVE1__} is too heinous\n";
-         { thing => 'comment'}
-       }
-
-enum: 'enum' IDENTIFIER(?) '{' <leftop: enum_item ',' enum_item> '}' ';'
-       {
-    { thing => 'enum', name => $item{IDENTIFIER}[0],
-          body => $item{__DIRECTIVE1__} }
-       }
-
-enum_item: IDENTIFIER '=' <commit> /[0-9]+/
-         { [$item{IDENTIFIER}, $item{__PATTERN1__}] }
-         | IDENTIFIER
-         { [$item{IDENTIFIER}, undef] }
-
-class_def: class IDENTIFIER '{' <commit> class_part(s?) '}' ';'
-           {
-              [@item{'IDENTIFIER',$Inline::CPP::grammar::class_part}]
-       }
-     | class IDENTIFIER ':' <commit> <leftop: inherit ',' inherit>
-            '{' class_part(s?) '}' ';'
-       {
-          push @{$item{$Inline::CPP::grammar::class_part}}, [$item{__DIRECTIVE2__}];
-          [@item{'IDENTIFIER',$Inline::CPP::grammar::class_part}]
-       }
-
-inherit: scope IDENTIFIER
-    { {thing => 'inherits', name => $item[2], scope => $item[1]} }
-
-class_part: comment { [ {thing => 'comment'} ] }
-      | scope ':' <commit> class_decl(s?)
-            {
-          for my $part (@{$item{$Inline::CPP::grammar::class_decl}}) {
-                  $_->{scope} = $item[1] for @$part;
-          }
-          $item{$Inline::CPP::grammar::class_decl}
-        }
-      | class_decl(s)
-            {
-          for my $part (@{$item[1]}) {
-                  $_->{scope} = $thisparser->{data}{defaultscope}
-            for @$part;
-          }
-          $item[1]
-        }
-
-class_decl: comment { [{thing => 'comment'}] }
-          | typedef { [ handle_typedef($thisparser, $item[1]) ] }
-          | enum { [ handle_enum($thisparser, $item[1]) ] }
-          | class_def
-            {
-               my ($class, $parts) = handle_class_def($thisparser, $item[1]);
-               [{ thing => 'class', name => $class, body => $parts }];
-            }
-          | method_def
-        {
-              $item[1]->{thing} = 'method';
-#         print "class_decl found a method: $item[1]->{name}\n";
-          my $i=0;
-          for my $arg (@{$item[1]->{args}}) {
-        $arg->{name} = 'dummy' . ++$i unless defined $arg->{name};
-          }
-          Inline::CPP::grammar::strip_ellipsis($thisparser,
-                           $item[1]->{args});
-          [$item[1]];
-        }
-          | member_def
-        {
-#         print "class_decl found one or more members:\n", Dumper(\@item);
-              $_->{thing} = 'member' for @{$item[1]};
-          $item[1];
-        }
-
-function_def: operator <commit> ';'
-              {
-                   $item[1]
-              }
-            | operator <commit> smod(?) code_block
-              {
-                  $item[1]
-              }
-            | IDENTIFIER '(' <commit> <leftop: arg ',' arg>(s?) ')' smod(?) code_block
-              {
-                {name => $item{IDENTIFIER}, args => $item{__DIRECTIVE2__}, rtype => '' }
-              }
-            | rtype IDENTIFIER '(' <leftop: arg ',' arg>(s?) ')' ';'
-              {
-                {rtype => $item[1], name => $item[2], args => $item{__DIRECTIVE1__} }
-              }
-            | rtype IDENTIFIER '(' <leftop: arg ',' arg>(s?) ')' smod(?) code_block
-              {
-                {rtype => $item{rtype}, name => $item[2], args => $item{__DIRECTIVE1__} }
-              }
-
-method_def: operator <commit> method_imp
-            {
-#               print "method operator:\n", Dumper $item[1];
-               $item[1];
-            }
-
-          | IDENTIFIER '(' <commit> <leftop: arg ',' arg>(s?) ')' method_imp
-            {
-#         print "con-/de-structor found: $item[1]\n";
-              {name => $item[1], args => $item{__DIRECTIVE2__}, abstract => ${$item{method_imp}} };
-            }
-          | rtype IDENTIFIER '(' <leftop: arg ',' arg>(s?) ')' method_imp
-            {
-#         print "method found: $item[2]\n";
-          $return =
-                {name => $item[2], rtype => $item[1], args => $item[4],
-             abstract => ${$item[6]},
-                 rconst => $thisparser->{data}{smod}{const},
-                };
-          $thisparser->{data}{smod}{const} = 0;
-            }
-
-operator: rtype(?) 'operator' /\(\)|[^()]+/ '(' <leftop: arg ',' arg>(s?) ')'
-          {
-#            print "Found operator: $item[1][0] operator $item[3]\n";
-            {name=> "operator $item[3]", args => $item[5], ret => $item[1][0]}
-          }
-
-# By adding smod, we allow 'const' member functions. This would also bind to
-# incorrect C++ with the word 'static' after the argument list, but we don't
-# care at all because such code would never be compiled successfully.
-
-# By adding init, we allow constructors to initialize references. Again, we'll
-# allow them anywhere, but our goal is not to enforce c++ standards -- that's
-# the compiler's job.
-method_imp: smod(?) ';' { \0 }
-          | smod(?) '=' <commit> '0' ';' { \1 }
-          | smod(?) initlist(?) code_block { \0 }
-          | smod(?) '=' '0' code_block { \0 }
-
-initlist: ':' <leftop: subexpr ',' subexpr>
-
-member_def: anytype <leftop: var ',' var> ';'
-            {
-          my @retval;
-          for my $def (@{$item[2]}) {
-              my $type = join '', $item[1], @{$def->[0]};
-          my $name = $def->[1];
-#             print "member found: type=$type, name=$name\n";
-          push @retval, { name => $name, type => $type };
-          }
-          \@retval;
-            }
-
-var: star(s?) IDENTIFIER '=' expr { [@item[1,2]] }
-   | star(s?) IDENTIFIER '[' expr ']' { [@item[1,2]] }
-   | star(s?) IDENTIFIER          { [@item[1,2]] }
-
-arg: type IDENTIFIER '=' expr
-     {
-#       print "argument $item{IDENTIFIER} found\n";
-#       print "expression: $item{expr}\n";
-    {type => $item[1], name => $item{IDENTIFIER}, optional => 1,
-     offset => $thisoffset}
-     }
-   | type IDENTIFIER
-     {
-#       print "argument $item{IDENTIFIER} found\n";
-       {type => $item[1], name => $item{IDENTIFIER}, offset => $thisoffset}
-     }
-   | type { {type => $item[1]} }
-   | '...'
-     { {name => '...', type => '...', offset => $thisoffset} }
-
-ident_part: /[~_a-z]\w*/i '<' <commit> <leftop: IDENTIFIER ',' IDENTIFIER>(s?) '>'
-        {
-       $item[1].'<'.join('', @{$item[4]}).'>'
-        }
-
-      | /[~_a-z]\w*/i
-        {
-           $item[1]
-        }
-
-IDENTIFIER: <leftop: ident_part '::' ident_part>
-        {
-              my $x = join '::', @{$item[1]};
-#              print "IDENTIFIER: $x\n";
-              $x
-        }
-
-# Parse::RecDescent is retarded in this one case: if a subrule fails, it
-# gives up the entire rule. This is a stupid way to get around that.
-rtype: rtype2 | rtype1
-rtype1: TYPE star(s?)
-        {
-         $return = $item[1];
-         $return .= join '',' ',@{$item[2]} if @{$item[2]};
-#    print "rtype1: $return\n";
-#          return undef
-#            unless(defined$thisparser->{data}{typeconv}{valid_rtypes}{$return});
-        }
-rtype2: modifier(s) TYPE star(s?)
-    {
-         $return = $item[2];
-         $return = join ' ',grep{$_}@{$item[1]},$return
-           if @{$item[1]};
-         $return .= join '',' ',@{$item[3]} if @{$item[3]};
-#    print "rtype2: $return\n";
-#          return undef
-#            unless(defined$thisparser->{data}{typeconv}{valid_rtypes}{$return});
-     $return = 'static ' . $return
-       if $thisparser->{data}{smod}{static};
-         $thisparser->{data}{smod}{static} = 0;
-    }
-
-type: type2 | type1
-type1: TYPE star(s?)
-        {
-         $return = $item[1];
-         $return .= join '',' ',@{$item{$Inline::CPP::grammar::star}} if @{$item{$Inline::CPP::grammar::star}};
-#    print "type1: $return\n";
-#          return undef
-#            unless(defined$thisparser->{data}{typeconv}{valid_types}{$return});
-        }
-type2: modifier(s) TYPE star(s?)
-    {
-         $return = $item{TYPE};
-         $return = join ' ',grep{$_}@{$item[1]},$return if @{$item[1]};
-         $return .= join '',' ',@{$item{$Inline::CPP::grammar::star}} if @{$item{$Inline::CPP::grammar::star}};
-#    print "type2: $return\n";
-#          return undef
-#            unless(defined$thisparser->{data}{typeconv}{valid_types}{$return});
-    }
-
-anytype: anytype2 | anytype1
-anytype1: TYPE star(s?)
-         {
-           $return = $item[1];
-           $return .= join '',' ',@{$item[2]} if @{$item[2]};
-         }
-anytype2: modifier(s) TYPE star(s?)
-         {
-           $return = $item[2];
-           $return = join ' ',grep{$_}@{$item[1]},$return if @{$item[1]};
-           $return .= join '',' ',@{$item[3]} if @{$item[3]};
-         }
-
-comment: m{\s* // [^\n]* \n }x
-       | m{\s* /\* (?:[^*]+|\*(?!/))* \*/  ([ \t]*)? }x
-
-# long and short aren't recognized as modifiers because they break when used
-# as regular types. Another Parse::RecDescent problem is greedy matching; I
-# need tmodifier to "give back" long or short in cases where keeping them would
-# cause the modifier rule to fail. One side-effect is 'long long' can never
-# be parsed correctly here.
-modifier: tmod
-        | smod { ++$thisparser->{data}{smod}{$item[1]}; ''}
-    | nmod { '' }
-tmod: 'unsigned' # | 'long' | 'short'
-smod: 'const' | 'static'
-nmod: 'extern' | 'virtual' | 'mutable' | 'volatile' | 'inline'
-
-scope: 'public' | 'private' | 'protected'
-
-class: 'class' { $thisparser->{data}{defaultscope} = 'private'; $item[1] }
-     | 'struct' { $thisparser->{data}{defaultscope} = 'public'; $item[1] }
-
-star: '*' | '&'
-
-code_block: /$Inline::CPP::grammar::code_block/
-
-# Consume expressions
-expr: <leftop: subexpr OP subexpr> {
-    my $o = join '', @{$item[1]};
-#   print "expr: $o\n";
-    $o;
-}
-subexpr: /$Inline::CPP::grammar::funccall/ # Matches a macro, too
-       | /$Inline::CPP::grammar::string/
-       | /$Inline::CPP::grammar::number/
-       | UOP subexpr
-OP: '+' | '-' | '*' | '/' | '^' | '&' | '|' | '%' | '||' | '&&'
-UOP: '~' | '!' | '-' | '*' | '&'
-
-TYPE: IDENTIFIER
-
-all: /.*/
-
-END
-}
-
-#============================================================================
-# Generate typemap code for the classes and structs we bind to. This allows
-# functions declared after a class to return or accept class objects as
-# parameters.
-#============================================================================
-$TYPEMAP_KIND = 'O_Inline_CPP_Class';
-sub typemap {
-    my ( $parser, $typename ) = @_;
-
-#    print "Inline::CPP::grammar::typemap(): typename=$typename\n";
-
-    my ($TYPEMAP, $INPUT, $OUTPUT);
-    $TYPEMAP = "$typename *\t\t$TYPEMAP_KIND\n";
-    $INPUT = <<"END";
-    if (sv_isobject(\$arg) && (SvTYPE(SvRV(\$arg)) == SVt_PVMG)) {
-        \$var = (\$type)SvIV((SV*)SvRV( \$arg ));
-    }
-    else {
-        warn ( \\"\${Package}::\$func_name() -- \$var is not a blessed reference\\" );
-        XSRETURN_UNDEF;
-    }
-END
-    $OUTPUT = <<"END";
-    sv_setref_pv( \$arg, CLASS, (void*)\$var );
-END
-
-    my $ctypename = $typename . ' *';
-    $parser->{data}{typeconv}{input_expr}{$TYPEMAP_KIND}  ||= $INPUT;
-    $parser->{data}{typeconv}{output_expr}{$TYPEMAP_KIND} ||= $OUTPUT;
-    $parser->{data}{typeconv}{type_kind}{$ctypename}      =   $TYPEMAP_KIND;
-    $parser->{data}{typeconv}{valid_types}{$ctypename}++;
-    $parser->{data}{typeconv}{valid_rtypes}{$ctypename}++;
-    return;
-}
-
-#============================================================================
-# Default action is to strip ellipses from the C++ code. This allows having
-# _only_ a '...' in the code, just like XS. It is the default.
-#============================================================================
-sub strip_ellipsis {
-    my( $parser, $args ) = @_;
-    return if $parser->{ILSM}{PRESERVE_ELLIPSIS};
-    for (  my $i = 0; $i < @$args; $i++  ) {
-        next unless $args->[$i]{name} eq '...';
-        # if it's the first one, just strip it
-        if ($i==0) {
-            substr(
-                $parser->{ILSM}{code},
-                $args->[$i]{offset} - 3,
-                3,
-                '   '
-            );
-        }
-        else {
-            my $prev        = $i - 1;
-            my $prev_offset = $args->[$prev]{offset};
-            my $length      = $args->[$i]{offset} - $prev_offset;
-            substr($parser->{ILSM}{code}, $prev_offset, $length) =~ s/\S/ /g;
-        }
-    }
-    return;
-}
-
-1;
-
-__END__
-=head1 Inline::CPP::grammar
-
-All functions are internal.  No documentation necessary.
-
-=cut
@@ -1,31 +0,0 @@
-use strict;
-use warnings;
-use Test::More;
-
-# Satisfy CPANTS, even though all functions are internal.
-
-eval "use Test::Pod::Coverage 1.00";  ## no critic (eval)
-plan skip_all => "Test::Pod::Coverage 1.00 required for testing POD coverage"
-    if $@;
-
-
-# Test for Inline::grammar.
-
-# There really aren't any functions explicitly called by the user. Everything
-# is for internal use, and doesn't require POD documentation.
-my $trustme = {
-    trustme => [
-        qr/(?:
-              ^_
-            | grammar       # Inline::CPP::grammar internal functions.
-            | handle
-            | strip
-            | typemap
-        )/x
-    ]
-};
-
-pod_coverage_ok( 'Inline::CPP::grammar', $trustme );
-
-
-done_testing();
@@ -1,56 +0,0 @@
-use strict;
-use warnings;
-use Test::More;
-
-# Testing proper handling of inherited object methods.
-
-use Inline CPP => <<'END';
-
-class Foo {
- public:
-   Foo() {
-    secret=0;
-   }
-
-   ~Foo() { }
-
-   int get_secret() { return secret; }
-   void set_secret(int s) { secret = s; }
-
- protected:
-   int secret;
-};
-
-class Bar : public Foo {
- public:
-   Bar(int s) { secret = s; }
-   ~Bar() {  }
-
-   void set_secret(int s) { secret = s * 2; }
-};
-
-END
-
-# If it works, it will print this. Otherwise it won't.
-ok(1);
-
-# Test Foo.
-my $o = new_ok( 'Foo' );
-is( $o->get_secret(), 0, "Foo: Object getter." );
-$o->set_secret(539);
-is( $o->get_secret(), 539, "Foo: Object setter." );
-
-
-# Test Bar.
-
-
-my $p = new_ok( 'Bar', [ 11 ] );
-is(
-    $p->get_secret(), 11,
-    "Bar: Overrides constructor, inherits accessor from Foo."
-);
-
-$p->set_secret( 21 );
-is( $p->get_secret(), 42, "Bar: Overrides setter." );
-
-done_testing();
@@ -1,28 +0,0 @@
-use strict;
-use warnings;
-use Test::More;
-
-# Testing proper handling of class scopes.
-
-use Inline CPP => <<'END';
-
-class Foo {
-   void priv(int a) { q = a; }
-   int q;
-public:
-   Foo() {}
-   ~Foo() {}
-   void zippo(int quack) { printf("Hello, world!\n"); }
-};
-
-END
-
-my $obj = new_ok( 'Foo' );
-
-can_ok( $obj, 'zippo' );
-
-is( $obj->zippo( 10 ), undef, "Execute void public member function." );
-
-ok( ! $obj->can( 'priv' ), "Can't access private member function." );
-
-done_testing();
@@ -1,53 +0,0 @@
-use strict;
-use warnings;
-use Test::More;
-
-# Testing proper handling of functions defined inline within a class.
-
-use Inline 'CPP';
-
-my $obj = new_ok( 'Color' );
-
-
-$obj->set_color(15);
-
-is(
-    $obj->get_color, 15,
-    "Member function defined inline within class."
-);
-
-done_testing();
-
-__END__
-__CPP__
-void prn() {
-    printf("prn() called!\n");
-}
-
-class Color {
- public:
-  Color()
-  {
-    printf("new Color object created...\n");
-  }
-
-  ~Color()
-  {
-    printf("Color object being destroyed...\n");
-  }
-
-  int get_color()
-  {
-    printf("Color::get_color called. Returning %i\n", color);
-    return color;
-  }
-
-  void set_color(int a)
-  {
-    printf("Color::set_color(%i)\n", a);
-    color = a;
-  }
-
- private:
-  int color;
-};
@@ -1,21 +0,0 @@
-use strict;
-use warnings;
-use Test::More;
-
-use Inline CPP => <<'END';
-class Foo {
-  public:
-    Foo()  {}
-    ~Foo() {}
-    const char *data() { return "Hello dolly!\n"; }
-};
-
-END
-
-
-is(
-    Foo->new->data, "Hello dolly!\n",
-    "Instantiate object and invoke member function returning a const char*"
-);
-
-done_testing();
@@ -1,22 +0,0 @@
-use strict;
-use warnings;
-use Test::More;
-
-
-use Inline CPP => <<'END';
-class Foo {
-  public:
-    Foo() { }
-    ~Foo() { }
-
-    virtual const char *get_data_ro() { return "Hello Sally!\n"; }
-};
-END
-
-
-is(
-    Foo->new->get_data_ro, "Hello Sally!\n",
-    "Define and invoke virtual function."
-);
-
-done_testing();
@@ -1,34 +0,0 @@
-use strict;
-use warnings;
-use Test::More;
-
-use Inline CPP => <<'END';
-
-int foo(int a=10) { return a; }
-double pi() { return 3.1415926; }
-
-class Freak {
-  public:
-    Freak() {}
-    ~Freak() {}
-
-    int foo(int a=10, int b=13+4, double c=pi()) { return (a+b)/c; }
-    int foo2(int a, int b=15) { return a^b; }
-    int foo3(int a, int b, int c=0, int d=-5) { return 2*a - b + 2*c - d; }
-    int foo4(int a, char *b="hello") { return a + strlen(b); }
-};
-
-END
-
-
-is(
-    Freak->new->foo, 8,
-    "Instantiate object and call member with default arguments."
-);
-
-is(
-    foo, 10,
-    "Call simple function with default arguments."
-);
-
-done_testing();
@@ -1,19 +0,0 @@
-use strict;
-use warnings;
-use Test::More;
-
-use Inline CPP => <<'END';
-class Foo {
-  public:
-    Foo() {}
-    ~Foo() {}
-    static char *get_string() { return "Hello, world!\n"; }
-};
-END
-
-is(
-    Foo->get_string, "Hello, world!\n",
-    "Static member function becomes a class member function."
-);
-
-done_testing();
@@ -1,24 +0,0 @@
-use strict;
-use warnings;
-use Test::More;
-
-use Inline CPP => <<'END';
-
-class Foo {
-  public:
-    Foo(int, int);
-};
-
-Foo::Foo(int a, int b) {
-}
-
-int add(int, int);
-int add(int a, int b) { return a + b; }
-
-END
-
-new_ok( 'Foo', [ 10, 11 ] );
-
-is( add( 2, 3 ), 5, "Simple function." );
-
-done_testing();
@@ -1,53 +0,0 @@
-use strict;
-use warnings;
-use Test::More;
-
-# Test pure virtual functions (abstract classes).
-use Inline CPP => <<'END';
-
-class Abstract {
-  public:
-        virtual char *text() = 0;
-        virtual int greet(char *name) {
-        printf("# Hello, %s.\n", name);
-        return 17;
-    }
-};
-
-class Impl : public Abstract {
-  public:
-    Impl() {}
-    ~Impl() {}
-    virtual char *text() { return "Hello from Impl!"; }
-};
-
-
-END
-
-my $o = new_ok( 'Impl' );
-is(
-    $o->text, 'Hello from Impl!',
-    "Resolved virtual member function from self."
-);
-
-is(
-    $o->greet('Neil'), 17,
-    "Inherited member function from parent."
-);
-
-my $p;
-eval{ $p = Abstract->new(); };
-if( $@ ) {
-    like(
-        $@,
-        qr/^Can't locate object method "new" via package "[^:]+::Abstract"/,
-        "Classes with pure virtual functions cannot be instantiated."
-    );
-} else {
-    not_ok(
-        "Abstract class with pure virtual function should not instantiate."
-    );
-}
-
-
-done_testing();
@@ -1,30 +0,0 @@
-use strict;
-use warnings;
-use Test::More;
-
-use Inline CPP => <<'END';
-
-struct Fizzle {
-  int q;
-  double foozle;
-  int quack;
-  Fizzle(int Q=0, double Foozle=0, int Quack=0) {
-    q = Q;
-    foozle = Foozle;
-    quack = Quack;
-  }
-  int get_q() { return q; }
-  double get_foozle() { return foozle; }
-  int get_quack() { return quack; }
-};
-
-END
-
-my $o = new_ok( 'Fizzle' );
-
-is(
-    $o->get_q, 0,
-    "Struct with public member function."
-);
-
-done_testing();
@@ -1,303 +0,0 @@
-use Test::More tests => 38;
-
-use strict;
-use warnings;
-
-use Inline CPP => 'DATA';
-
-note( 'Instantiating objects.' );
-my @object_descriptions = (
-    [
-        my $parent1_obj = new_ok( 'Parent1', [], 'Parent1 object born:' ),
-        [ qw/ Parent1      / ],
-        [ qw/ do_something / ]
-    ],
-    [
-        my $parent2_obj = new_ok( 'Parent2', [], 'Parent2 object born:' ),
-        [ qw/ Parent2    /   ],
-        [ qw/ do_another /   ]
-    ],
-    [
-        my $child_obj = new_ok( 'Child',     [], 'Child object born:'   ),
-        [ qw/ Child          Parent1         Parent2    / ],
-        [ qw/ yet_another    do_something    do_another / ]
-    ],
-    [
-        my $child2_obj = new_ok( 'Child2',   [], 'Child2 object born:'  ),
-        [ qw/ Child2        Parent1          Parent2    / ],
-        [ qw/ some_other    do_something     do_another / ]
-    ],
-);
-
-note( 'Testing object lineage.' );
-foreach my $obj_desc ( @object_descriptions ) {
-    foreach my $class ( @{ $obj_desc->[1] } ) {
-        ok(
-            $obj_desc->[0]->isa( $class ),
-            "UNIVERSAL::isa confirms $obj_desc->[1][0] object is a $class."
-        );
-    }
-}
-
-note( 'Testing object method capabilities (inheritance).' );
-foreach my $obj_desc ( @object_descriptions ) {
-    foreach my $func_name ( @{ $obj_desc->[2] } ) {
-        can_ok( $obj_desc->[0], $func_name );
-    }
-}
-
-
-note( 'Testing \@Class::ISA arrays.' );
-is_deeply( \@Parent1::ISA, [ ], "\@Parent1::ISA: No inheritance." );
-is_deeply( \@Parent2::ISA, [ ], "\@Parent2::ISA: No inheritance." );
-TODO: {
-    local $TODO = "Still researching why Child and Child2 inherit via main::";
-    is_deeply(
-        \@Child::ISA,   [ qw/ Parent1   Parent2 / ],
-        "\@Child::ISA: Parent1, Parent2."
-    );
-    is_deeply(
-        \@Child2::ISA,  [ qw/ Parent2   Parent1 / ],
-        "\@Child2::ISA: Parent2, Parent1."
-    );
-}
-
-my @method_tests = (
-    [
-        $parent1_obj,           # Object ref.
-        'Parent1',              # Class name.
-        {
-            do_something => 51  # Method call and expected result.
-        }
-    ],
-    [
-        $parent2_obj,           # Object ref.
-        'Parent2',              # Class name.
-        {
-            do_another   => 17  # Method call and expected result.
-        }
-    ],
-    [
-        $child_obj,             # Object ref.
-        'Child',                # Class name.
-        {
-            yet_another  => 3,  # Method call and expected result.
-            do_something => 51, # Inherited from Parent1: Call and expected.
-            do_another   => 17, # Inherited from Parent2: Call and expected.
-        },
-    ],
-    [
-        $child2_obj,            # Object ref.
-        'Child2',               # Class name.
-        {
-            some_other   => 4,  # Method call and expected result.
-            do_something => 51, # Inherited from Parent1: Call and expected.
-            do_another   => 17  # Inherited from Parent2: Call and expected.
-        }
-    ],
-);
-
-note( 'Testing that object methods return correct values' );
-TODO: {
-    foreach my $obj_task ( @method_tests ) {
-        while( my( $method, $expect ) = each %{ $obj_task->[2] } ) {
-            local $TODO =
-                'Still working on why multiple inheritance is messed up.'
-                if( $obj_task->[1] =~ /Child\d?/ );
-            is(
-                $obj_task->[0]->$method, $expect,
-                "$obj_task->[1] object method $method " .
-                "correctly returns $expect."
-            );
-        }
-    }
-}
-
-
-# These tests are essentially repeats from code above, but with code that is
-# more transparent to illustrate the issue as clearly as possible.
-
-note( "\n\nPainfully simple so we don\'t miss it this time.\n\n" );
-TODO: {
-    is(
-        $child_obj->yet_another, 3,
-        'Child $obj->yet_another() should return 3.'
-    );
-    is(
-        $child_obj->do_something, 51,
-        'Child $obj->do_something() ' .
-        'inherits from Parent1 and should return 51.'
-    );
-    {
-        local $TODO = 'Inheritance foulup: Calling do_another() but getting' .
-                      ' return value from do_something().';
-        is(
-            $child_obj->do_another, 17,
-            'Child $obj->do_another() ' .
-            'inherits from Parent2, and should return 17.'
-        );
-    }
-    is(
-        $child2_obj->some_other, 4,
-        'Child2 $obj->some_other() should return 4.'
-    );
-    {
-        local $TODO = 'Inheritance foulup: Calling do_something but getting' .
-                      ' return value from do_another().';
-        is(
-            $child2_obj->do_something, 51,
-            'Child2 $obj->do_something() ' .
-            'inherited from Parent1 and should return 51.'
-        );
-    }
-    is(
-        $child2_obj->do_another, 17,
-        'Child2 $obj->do_another() ' .
-        'inherited from Parent2 and should return 17.'
-    );
-}
-done_testing();
-
-=cut
-
--------------------- email from Patrick ---------------
-David,
-
-I'm really no C++ expert, but I think the implementation is not viable
-the way it is. If you create a
-small C++ program that simulates Inline::CPP like this:
-
-#include <stdio.h>
-
-/* Your Child/Parent classes here "as is" */
-
-int main(int argv, char **argc){
-       Child *c = new Child() ;
-       printf("%d\n", c->do_something()) ;
-       printf("%d\n", c->do_another()) ;
-
-       void *x = c ;
-       printf("%d\n", ((Parent1 *)x)->do_something()) ;
-       printf("%d\n", ((Parent2 *)x)->do_another()) ;
-}
-
-I gives the same error:
-51
-17
-51
-51
-
-I think the problem is that you can't cast your pointer to either
-Parent1 or Parent2 depending on
-your needs because the bytes are not overlapped in memory. In the
-definition of the Child object,
-the Parent1 stuff is before the Parent2 stuff. To access the Parent2
-stuff you probably need to
-use an offset on the Child Pointer.
-
-What's happening (I think) is that your are calling do_something()
-both times because both methods
-are at the same byte offset in there respective parent object. If you
-add some member variables in
-one of the Parent object before the method definitions you will
-probably get crashes because the method
-offset will no longer line up. I'm not sure if any of this is clear....
-
-I think the correct way to do this is something like:
-
-       printf("%d\n", ((Child *)x)->Parent1::do_something()) ;
-       printf("%d\n", ((Child *)x)->Parent2::do_another()) ;
-
-but that implies that your Parent functions know about Child, which is
-not good...
-
-Anyways, just some stuff to think about, unfortunately I don't have
-any suggestions for you...
-
-
-Patrick
-
---------------------------------
-
-Email response from davido/daoswald:
-
-Your explanation was excellent.
-
-What needs to be happening is that, as Child inherits from Parent1 and
-Parent2, the pointer should be cast as a Child type, like in this
-modification of your test:
-
-int main(int argv, char **argc){
-      Child *c = new Child() ;
-      printf("%d\n", c->do_something()) ;
-      printf("%d\n", c->do_another()) ;
-
-      void *x = c ;
-      printf("%d\n", ((Child *)x)->do_something()) ;
-      printf("%d\n", ((Child *)x)->do_another()) ;
-}
-
-...or in more idiomatic C++:
-
-int main() {
-   using std::cout;
-   using std::endl;
-
-   Child *c = new Child() ;
-   cout << c->do_something() << endl;
-   cout << c->do_another()   << endl;
-
-   void *x = c ;
-   cout <<  static_cast< Child* >(x)->do_something() << endl;
-   cout <<  static_cast< Child* >(x)->do_another()   << endl;
-
-   return 0;
-}
-
-Though I'm not much closer to a solution, at least your message
-reminded me that we're dealing with void pointers to objects.  Maybe I
-need to start looking at how and where the casting is being
-accomplished.
-
-------------------------------------
-
-=cut
-
-__END__
-__CPP__
-
-class Parent1 {
-  public:
-    Parent1() { }
-    ~Parent1() { }
-
-    virtual int do_something() { return 51; }
-};
-
-class Parent2 {
-  public:
-    Parent2();
-    ~Parent2();
-
-    virtual int do_another();
-};
-
-Parent2::Parent2() { }
-Parent2::~Parent2() { }
-int Parent2::do_another() { return 17; }
-
-class Child : public Parent1, public Parent2 {
-  public:
-    Child() { }
-    ~Child() { }
-
-    int yet_another() { return 3; }
-};
-
-class Child2 : public Parent2, public Parent1 {
-  public:
-    Child2() { }
-    ~Child2() { }
-
-    int some_other() { return 4; }
-};
@@ -1,39 +0,0 @@
-use strict;
-use warnings;
-use Test::More;
-
-use Inline 'CPP';
-
-
-is_deeply(
-    [ return_list() ], [ 1, 'Hello?', '15.75' ],
-    "Return on the stack a list containing an int, a string, and a double."
-);
-
-# We used to test ok( $list[2], 15.6 ) with a corresponding value in the
-# CPP function.  But because .6 cannot be represented in a finite number of
-# binary digits we were getting some inequality test failures.
-# 15.75 is the same as 126/8, which can be represented accurately in base 2.
-# The goal of the test is to see if we're able to pass floating point values
-# correctly, not to test the way a given C++ compiler handles floating point
-# math.
-
-is( return_void(), undef, "Void function that returns nothing." );
-
-done_testing();
-
-__END__
-__CPP__
-
-void return_list() {
-    Inline_Stack_Vars;
-    Inline_Stack_Reset;
-    Inline_Stack_Push(sv_2mortal(newSViv(1)));
-    Inline_Stack_Push(sv_2mortal(newSVpv("Hello?",0)));
-    Inline_Stack_Push(sv_2mortal(newSVnv(15.75)));
-    Inline_Stack_Done;
-}
-
-void return_void() {
-    printf("# Hello! from return_void()\n");
-}
@@ -1,28 +0,0 @@
-use strict;
-use warnings;
-use Test::More;
-
-use Inline 'CPP';
-
-is(sum(), 0, "Var-args: 0" );
-is(sum(1), 1, "Var-args: 1" );
-is(sum(1, 2), 3, "Var-args: 2" );
-is(sum(1, 2, 3), 6, "Var-args: 3" );
-is(sum(1, 2, 3, 4), 10, "Var-args: 4" );
-is(sum(1, 2, 3, 4, 5), 15, "Var-args: 5" );
-
-done_testing();
-
-__END__
-__CPP__
-
-int sum(...) {
-    Inline_Stack_Vars;
-    int s = 0;
-    for (int i=0; i<items; i++)
-    {
-    int tmp = SvIV(Inline_Stack_Item(i));
-    s += tmp;
-    }
-    return s;
-}
@@ -1,21 +0,0 @@
-use strict;
-use warnings;
-use Test::More;
-
-use Inline CPP => <<'END';
-class Foo {
-  public:
-    Foo()  {}
-    ~Foo() {}
-    char *data() const { return "Hello dolly!\n"; }
-};
-
-END
-
-
-is(
-    Foo->new->data, "Hello dolly!\n",
-    "Constant member function."
-);
-
-done_testing();
@@ -1,25 +0,0 @@
-use strict;
-use warnings;
-use Test::More;
-# Test static variables
-
-use Inline CPP => <<'END';
-class Foo {
-  public:
-    Foo()  {}
-    ~Foo() {}
-    static int get_thing() { return s_thing; }
-  private:
-    static int s_thing;
-};
-
-int Foo::s_thing = 10;
-
-END
-
-is(
-    Foo->new->get_thing, 10,
-    "Static variables within a class."
-);
-
-done_testing();
@@ -1,50 +0,0 @@
-use strict;
-use warnings;
-use Test::More;
-# Test declarations of multiple variables in a member data list.
-
-use Inline CPP => <<'END';
-
-#define NUMBER 25
-#define FOO()  25
-
-class Foo {
-  public:
-    Foo(double _o) : o(_o) {}
-    ~Foo() {}
-    int test() { return 10; }
-  private:
-    int a, b;
-    char *c, d;
-    char *e, *f;
-    char g, **h;
-    double i, j, *k, **m, n, &o;
-
-    static const int    aa = 10,
-            bb = FOO(),
-            cc = NUMBER,
-            dd = 1.25
-            ;
-};
-
-class Bar {
-  public:
-    Bar() { }
-    ~Bar() { }
-    int test() { return -1; }
-};
-
-END
-
-
-is(
-    Foo->new(1.23)->test, 10,
-    "Declaration of multiple variables in a list."
-);
-
-is(
-    Bar->new->test, -1,
-    "Simple case class following multiple variables class."
-);
-
-done_testing();
@@ -1,25 +0,0 @@
-use strict;
-use warnings;
-use Test::More;
-# Test member array feature (single-dimensional only).
-
-use Inline CPP => 'DATA';
-
-my $obj = new_ok( 'TestMemberArray' );
-is( $obj->get_value_at(1), 101, "Member array accessor gets correct value." );
-
-done_testing();
-
-
-__DATA__
-__CPP__
-
-class TestMemberArray {
-  public:
-    TestMemberArray() { for( size_t i = 0; i < 5; i++ ) member_array[i] = i + 100; }
-    ~TestMemberArray() {}
-    int get_value_at( int i ) { return member_array[i]; }
-  private:
-    int member_array[5];
-};
-
@@ -0,0 +1,51 @@
+package ILCPPConfig::CompilerGuess;
+
+use strict;
+use warnings;
+use ExtUtils::CppGuess;
+use Exporter;
+
+our @ISA       = 'Exporter';
+our @EXPORT_OK = 'guess_compiler';
+our $VERSION   = '0.01';
+
+# Repackage results from ExtUtils::CppGuess into a form that is most useful
+# to Inline::CPP's Makefile.PL.
+
+sub guess_compiler {
+
+  my( $cc_guess, $libs_guess, $guesser, %configuration );
+
+  if( $Config::Config{osname} eq 'freebsd'
+    && $Config::Config{osvers} =~ /^(\d+)/
+    && $1 >= 10
+  ){
+    $cc_guess = 'clang++';
+    $libs_guess = '-lc++';
+  }
+  else {
+    $guesser = ExtUtils::CppGuess->new;
+    %configuration = $guesser->module_build_options;
+    if( $guesser->is_gcc ) {
+      $cc_guess = 'g++';
+    }
+    elsif ( $guesser->is_msvc ) {
+      $cc_guess = 'cl';
+    }
+
+    $cc_guess .= $configuration{extra_compiler_flags};
+    $libs_guess = $configuration{extra_linker_flags};
+
+    ( $cc_guess, $libs_guess )
+      = map { _trim_whitespace($_) } ( $cc_guess, $libs_guess );
+  }
+  return ( $cc_guess, $libs_guess );
+}
+
+sub _trim_whitespace {
+  my $string = shift;
+  $string =~ s/^\s+|\s+$//g;
+  return $string;
+}
+
+1;
@@ -0,0 +1,101 @@
+package ILCPPConfig::OldCompilerGuess;
+
+use strict;
+use warnings;
+use Config;
+use Exporter;
+
+our @ISA       = 'Exporter';
+our @EXPORT_OK = 'guess_compiler';
+our $VERSION   = '0.01';
+
+# This is the logic we used to keep in Makefile.PL that was used to make an
+# educated guess as to what compiler, compiler flags, standard libraries, and
+# linker flags to configure into Inline::CPP.
+
+# Inline::CPP shifted to using ExtUtils::CppGuess instead, but retains this
+# logic for testing purposes, as well as for working toward improving
+# ExtUtils::CppGuess.
+
+# my( $cc_guess, $libs_guess ) = guess_compiler();
+
+
+#============================================================================
+# Make an intelligent guess about what compiler to use
+#============================================================================
+
+sub guess_compiler {
+
+  my( $cc_guess, $libs_guess );
+  
+  if ( $Config{osname} eq 'darwin' ) {
+    my $stdlib_query
+        = 'find /usr/lib/gcc -name "libstdc++*" | grep $( uname -p )';
+    my $stdcpp = `$stdlib_query`;
+    +$stdcpp =~ s/^(.*)\/[^\/]+$/$1/;
+    $cc_guess   = 'g++';
+    $libs_guess = "-L$stdcpp -lstdc++";
+  }
+  elsif ( $Config{osname} ne 'darwin'
+    and $Config{gccversion}
+    and $Config{cc} =~ m#\bgcc\b[^/]*$#
+  ) {
+    ( $cc_guess = $Config{cc} ) =~ s[\bgcc\b([^/]*)$(?:)][g\+\+$1];
+    $libs_guess = '-lstdc++';
+  }
+  elsif ( $Config{osname} =~ m/^MSWin/ ) {
+    $cc_guess   = 'cl -TP -EHsc';
+    $libs_guess = 'MSVCIRT.LIB';
+  }
+  elsif ( $Config{osname} eq 'linux' ) {
+    $cc_guess   = 'g++';
+    $libs_guess = '-lstdc++';
+  }
+# Dragonfly patch is just a hunch... (still doesn't work)
+  elsif ( $Config{osname} eq 'netbsd' || $Config{osname} eq 'dragonfly' ) {
+    $cc_guess   = 'g++';
+    $libs_guess = '-lstdc++ -lgcc_s';
+  }
+  elsif ( $Config{osname} eq 'cygwin' ) {
+    $cc_guess   = 'g++';
+    $libs_guess = '-lstdc++';
+  }
+  elsif ( $Config{osname} eq 'solaris' or $Config{osname} eq 'SunOS' ) {
+    if ( $Config{cc} eq 'gcc'
+      || ( exists( $Config{gccversion} ) && $Config{gccversion} > 0 ) )
+    {
+        $cc_guess   = 'g++';
+        $libs_guess = '-lstdc++';
+    }
+    else {
+        $cc_guess   = 'CC';
+        $libs_guess = '-lCrun';
+    }
+  }
+
+  # MirBSD: Still problematic.
+  elsif ( $Config{osname} eq 'mirbsd' ) {
+    my $stdlib_query
+      = 'find /usr/lib/gcc -name "libstdc++*" | grep $( uname -p ) | head -1';
+    my $stdcpp = `$stdlib_query`;
+    +$stdcpp =~ s/^(.*)\/[^\/]+$/$1/;
+    $cc_guess   = 'g++';
+    $libs_guess = "-L$stdcpp -lstdc++ -lc -lgcc_s";
+  }
+  elsif( $Config{osname} eq 'freebsd'
+    and $Config{osvers} =~ /^(\d+)/
+    and $1 >= 10
+  ){
+    $cc_guess = 'clang++';
+    $libs_guess = '-lc++';
+  }
+  # Sane defaults for other (probably unix-like) operating systems
+  else {
+    $cc_guess   = 'g++';
+    $libs_guess = '-lstdc++';
+  }
+
+  return( $cc_guess, $libs_guess );
+}
+
+1;
@@ -5,13 +5,13 @@ package Inline::CPP::Config;
 use strict;
 use warnings;
 
-our $VERSION = '0.49';
+our $VERSION = '0.69';
 #$VERSION = eval $VERSION; ## no critic (eval)
 
 
 # DO NOT MANUALLY ALTER THE FOLLOWING TWO LINES: Makefile.PL locates them by
 # matching their syntax and identifier names.
-our $compiler = 'g++';
+our $compiler = 'g++ -xc++  -D_FILE_OFFSET_BITS=64';
 our $libs     = '-lstdc++';
 
 
@@ -0,0 +1,548 @@
+use strict; use warnings;
+package Inline::CPP::Parser::RecDescent;
+
+# Dev versions will have a _0xx suffix.
+# We eval the $VERSION to accommodate dev version numbering as described in
+# perldoc perlmodstyle
+our $VERSION = '0.69';
+#$VERSION = eval $VERSION;  ## no critic (eval)
+
+use Carp;
+
+sub register {
+    {
+     extends => [qw(CPP)],
+     overrides => [qw(get_parser)],
+    }
+}
+
+sub get_parser {
+    my $o = shift;
+    return Inline::CPP::Parser::RecDescent::get_parser_recdescent($o);
+}
+
+sub get_parser_recdescent {
+    my $o = shift;
+    eval { require Parse::RecDescent };
+    croak <<END if $@;
+This invocation of Inline requires the Parse::RecDescent module.
+$@
+END
+    no warnings qw/ once /;    ## no critic (warnings)
+    $::RD_HINT = 1;    # Turns on Parse::RecDescent's warnings/diagnostics.
+    my $parser = Parse::RecDescent->new(grammar());
+    $parser->{data}{typeconv} = $o->{ILSM}{typeconv};
+    $parser->{ILSM} = $o->{ILSM};    # give parser access to config options
+    return $parser;
+}
+
+use vars qw($TYPEMAP_KIND $class_part $class_decl $star);
+
+# Parse::RecDescent 1.90 and later have an incompatible change
+# 'The key of an %item entry for a repeated subrule now includes
+# the repetition specifier.'
+# Hence various hash keys may or may not need trailing '(s?)' depending on
+# the version of Parse::RecDescent we are using.
+
+require Parse::RecDescent;
+
+# Deal with Parse::RecDescent's version numbers for development
+# releases (eg, '1.96_000') resulting in a warning about non-numeric in >
+# comparison.
+{    # Lexical scope.
+      # Eval away the underscore.  "1.96_000" => "1.96000".
+      # Use that "stable release" version number as the basis for our numeric
+      # comparison.
+  my $stable_version = eval $Parse::RecDescent::VERSION;    ## no critic (eval)
+  ($class_part, $class_decl, $star)
+    = map { ($stable_version > 1.89) ? "$_(s?)" : $_ }
+    qw ( class_part class_decl star );
+}    # End lexical scope.
+
+
+#============================================================================
+# Regular expressions to match code blocks, numbers, strings, parenthesized
+# expressions, function calls, and macros. The more complex regexes are only
+# implemented in 5.6.0 and above, so they're in eval-blocks.
+#
+# These are all adapted from the output of Damian Conway's excellent
+# Regexp::Common module. In future, Inline::CPP may depend directly on it,
+# but for now I'll just duplicate the code.
+use vars qw( $code_block $string $number $parens $funccall );
+
+#============================================================================
+
+# $RE{balanced}{-parens=>q|{}()[]"'|}
+eval <<'END';    ## no critic (eval)
+$code_block = qr'(?-xism:(?-xism:(?:[{](?:(?>[^][)(}{]+)|(??{$Inline::CPP::Parser::RecDescent::code_block}))*[}]))|(?-xism:(?-xism:(?:[(](?:(?>[^][)(}{]+)|(??{$Inline::CPP::Parser::RecDescent::code_block}))*[)]))|(?-xism:(?-xism:(?:[[](?:(?>[^][)(}{]+)|(??{$Inline::CPP::Parser::RecDescent::code_block}))*[]]))|(?-xism:(?!)))))';
+END
+$code_block = qr'{[^}]*}' if $@;    # For the stragglers: here's a lame regexp.
+
+# $RE{balanced}{-parens=>q|()"'|}
+eval <<'END';                       ## no critic (eval)
+$parens = qr'(?-xism:(?-xism:(?:[(](?:(?>[^)(]+)|(??{$Inline::CPP::Parser::RecDescent::parens}))*[)]))|(?-xism:(?!)))';
+END
+$parens = qr'\([^)]*\)' if $@;      # For the stragglers: here's another
+
+# $RE{quoted}
+$string
+  = qr'(?:(?:\")(?:[^\\\"]*(?:\\.[^\\\"]*)*)(?:\")|(?:\')(?:[^\\\']*(?:\\.[^\\\']*)*)(?:\')|(?:\`)(?:[^\\\`]*(?:\\.[^\\\`]*)*)(?:\`))';
+
+# $RE{num}{real}|$RE{num}{real}{-base=>16}|$RE{num}{int}
+$number
+  = qr'(?:(?i)(?:[+-]?)(?:(?=[0123456789]|[.])(?:[0123456789]*)(?:(?:[.])(?:[0123456789]{0,}))?)(?:(?:[E])(?:(?:[+-]?)(?:[0123456789]+))|))|(?:(?i)(?:[+-]?)(?:(?=[0123456789ABCDEF]|[.])(?:[0123456789ABCDEF]*)(?:(?:[.])(?:[0123456789ABCDEF]{0,}))?)(?:(?:[G])(?:(?:[+-]?)(?:[0123456789ABCDEF]+))|))|(?:(?:[+-]?)(?:\d+))';
+$funccall
+  = qr/(?:[_a-zA-Z][_a-zA-Z0-9]*::)*[_a-zA-Z][_a-zA-Z0-9]*(?:$Inline::CPP::Parser::RecDescent::parens)?/;
+
+#============================================================================
+# Inline::CPP's grammar
+#============================================================================
+sub grammar {
+  return <<'END';
+
+{ use Data::Dumper; }
+
+{
+    sub handle_class_def {
+        my ($thisparser, $def) = @_;
+#         print "Found a class: $def->[0]\n";
+        my $class = $def->[0];
+        my @parts;
+        for my $part (@{$def->[1]}) { push @parts, @$_ for @$part }
+        push @{$thisparser->{data}{classes}}, $class
+            unless defined $thisparser->{data}{class}{$class};
+        $thisparser->{data}{class}{$class} = \@parts;
+#   print "Class $class:\n", Dumper \@parts;
+        Inline::CPP::Parser::RecDescent::typemap($thisparser, $class);
+        [$class, \@parts];
+    }
+    sub handle_typedef {
+        my ($thisparser, $t) = @_;
+        my ($name, $type) = @{$t}{qw(name type)};
+#   print "found a typedef: $name => $type\n";
+
+        # XXX: this doesn't handle non-class typedefs that we could handle,
+        # e.g. "typedef int my_int_t"
+
+        if ($thisparser->{data}{class}{$type}
+            && !exists($thisparser->{data}{class}{$name})) {
+            push @{$thisparser->{data}{classes}}, $name;
+            $thisparser->{data}{class}{$name} = $thisparser->{data}{class}{$type};
+            Inline::CPP::Parser::RecDescent::typemap($thisparser, $name);
+        }
+        $t;
+    }
+    sub handle_enum {
+        my ($thisparser, $t) = @_;
+        $t;
+    }
+}
+
+code: part(s) {1}
+
+part: comment
+    | typedef
+      {
+        handle_typedef($thisparser, $item[1]);
+        1;
+      }
+    | enum
+      {
+        my $t = handle_enum($thisparser, $item[1]);
+        push @{$thisparser->{data}{enums}}, $t;
+        1;
+      }
+    | class_def
+      {
+         handle_class_def($thisparser, $item[1]);
+     1;
+      }
+    | function_def
+      {
+#         print "found a function: $item[1]->{name}\n";
+         my $name = $item[1]->{name};
+     my $i=0;
+     for my $arg (@{$item[1]->{args}}) {
+        $arg->{name} = 'dummy' . ++$i unless defined $arg->{name};
+     }
+     Inline::CPP::Parser::RecDescent::strip_ellipsis($thisparser,
+                          $item[1]->{args});
+     push @{$thisparser->{data}{functions}}, $name
+           unless defined $thisparser->{data}{function}{$name};
+     $thisparser->{data}{function}{$name} = $item[1];
+#    print Dumper $item[1];
+     1;
+      }
+    | all
+
+typedef: 'typedef' class IDENTIFIER(?) '{' <commit> class_part(s?) '}' IDENTIFIER ';'
+       {
+     my ($class, $parts);
+         $class = $item[3][0] || 'anon_class'.($thisparser->{data}{anonclass}++);
+         ($class, $parts)= handle_class_def($thisparser, [$class, $item{$Inline::CPP::Parser::RecDescent::class_part}]);
+     { thing => 'typedef', name => $item[8], type => $class, body => $parts }
+       }
+       | 'typedef' IDENTIFIER IDENTIFIER ';'
+       { { thing => 'typedef', name => $item[3], type => $item[2] } }
+       | 'typedef' /[^;]*/ ';'
+       {
+#         dprint "Typedef $item{__DIRECTIVE1__} is too heinous\n";
+         { thing => 'comment'}
+       }
+
+enum: 'enum' IDENTIFIER(?) '{' <leftop: enum_item ',' enum_item> '}' ';'
+       {
+    { thing => 'enum', name => $item{IDENTIFIER}[0],
+          body => $item{__DIRECTIVE1__} }
+       }
+
+enum_item: IDENTIFIER '=' <commit> /[0-9]+/
+         { [$item{IDENTIFIER}, $item{__PATTERN1__}] }
+         | IDENTIFIER
+         { [$item{IDENTIFIER}, undef] }
+
+class_def: class IDENTIFIER '{' <commit> class_part(s?) '}' ';'
+           {
+              [@item{'IDENTIFIER',$Inline::CPP::Parser::RecDescent::class_part}]
+       }
+     | class IDENTIFIER ':' <commit> <leftop: inherit ',' inherit>
+            '{' class_part(s?) '}' ';'
+       {
+          push @{$item{$Inline::CPP::Parser::RecDescent::class_part}}, [$item{__DIRECTIVE2__}];
+          [@item{'IDENTIFIER',$Inline::CPP::Parser::RecDescent::class_part}]
+       }
+
+inherit: scope IDENTIFIER
+    { {thing => 'inherits', name => $item[2], scope => $item[1]} }
+
+class_part: comment { [ {thing => 'comment'} ] }
+      | scope ':' <commit> class_decl(s?)
+            {
+          for my $part (@{$item{$Inline::CPP::Parser::RecDescent::class_decl}}) {
+                  $_->{scope} = $item[1] for @$part;
+          }
+          $item{$Inline::CPP::Parser::RecDescent::class_decl}
+        }
+      | class_decl(s)
+            {
+          for my $part (@{$item[1]}) {
+                  $_->{scope} = $thisparser->{data}{defaultscope}
+            for @$part;
+          }
+          $item[1]
+        }
+
+class_decl: comment { [{thing => 'comment'}] }
+          | typedef { [ handle_typedef($thisparser, $item[1]) ] }
+          | enum { [ handle_enum($thisparser, $item[1]) ] }
+          | class_def
+            {
+               my ($class, $parts) = handle_class_def($thisparser, $item[1]);
+               [{ thing => 'class', name => $class, body => $parts }];
+            }
+          | method_def
+        {
+              $item[1]->{thing} = 'method';
+#         print "class_decl found a method: $item[1]->{name}\n";
+          my $i=0;
+          for my $arg (@{$item[1]->{args}}) {
+        $arg->{name} = 'dummy' . ++$i unless defined $arg->{name};
+          }
+          Inline::CPP::Parser::RecDescent::strip_ellipsis($thisparser,
+                           $item[1]->{args});
+          [$item[1]];
+        }
+          | member_def
+        {
+#         print "class_decl found one or more members:\n", Dumper(\@item);
+              $_->{thing} = 'member' for @{$item[1]};
+          $item[1];
+        }
+
+function_def: operator <commit> ';'
+              {
+                   $item[1]
+              }
+            | operator <commit> smod(?) code_block
+              {
+                  $item[1]
+              }
+            | IDENTIFIER '(' <commit> <leftop: arg ',' arg>(s?) ')' smod(?) code_block
+              {
+                {name => $item{IDENTIFIER}, args => $item{__DIRECTIVE2__}, rtype => '' }
+              }
+            | rtype IDENTIFIER '(' <leftop: arg ',' arg>(s?) ')' ';'
+              {
+                {rtype => $item[1], name => $item[2], args => $item{__DIRECTIVE1__} }
+              }
+            | rtype IDENTIFIER '(' <leftop: arg ',' arg>(s?) ')' smod(?) code_block
+              {
+                {rtype => $item{rtype}, name => $item[2], args => $item{__DIRECTIVE1__} }
+              }
+
+method_def: operator <commit> method_imp
+            {
+#               print "method operator:\n", Dumper $item[1];
+               $item[1];
+            }
+
+          | IDENTIFIER '(' <commit> <leftop: arg ',' arg>(s?) ')' method_imp
+            {
+#         print "con-/de-structor found: $item[1]\n";
+              {name => $item[1], args => $item{__DIRECTIVE2__}, abstract => ${$item{method_imp}} };
+            }
+          | rtype IDENTIFIER '(' <leftop: arg ',' arg>(s?) ')' method_imp
+            {
+#         print "method found: $item[2]\n";
+          $return =
+                {name => $item[2], rtype => $item[1], args => $item[4],
+             abstract => ${$item[6]},
+                 rconst => $thisparser->{data}{smod}{const},
+                };
+          $thisparser->{data}{smod}{const} = 0;
+            }
+
+operator: rtype(?) 'operator' /\(\)|[^()]+/ '(' <leftop: arg ',' arg>(s?) ')'
+          {
+#            print "Found operator: $item[1][0] operator $item[3]\n";
+            {name=> "operator $item[3]", args => $item[5], ret => $item[1][0]}
+          }
+
+# By adding smod, we allow 'const' member functions. This would also bind to
+# incorrect C++ with the word 'static' after the argument list, but we don't
+# care at all because such code would never be compiled successfully.
+
+# By adding init, we allow constructors to initialize references. Again, we'll
+# allow them anywhere, but our goal is not to enforce c++ standards -- that's
+# the compiler's job.
+method_imp: smod(?) ';' { \0 }
+          | smod(?) '=' <commit> '0' ';' { \1 }
+          | smod(?) initlist(?) code_block { \0 }
+          | smod(?) '=' '0' code_block { \0 }
+
+initlist: ':' <leftop: subexpr ',' subexpr>
+
+member_def: anytype <leftop: var ',' var> ';'
+            {
+          my @retval;
+          for my $def (@{$item[2]}) {
+              my $type = join '', $item[1], @{$def->[0]};
+          my $name = $def->[1];
+#             print "member found: type=$type, name=$name\n";
+          push @retval, { name => $name, type => $type };
+          }
+          \@retval;
+            }
+
+var: star(s?) IDENTIFIER '=' expr { [@item[1,2]] }
+   | star(s?) IDENTIFIER '[' expr ']' { [@item[1,2]] }
+   | star(s?) IDENTIFIER          { [@item[1,2]] }
+
+arg: type IDENTIFIER '=' expr
+     {
+#       print "argument $item{IDENTIFIER} found\n";
+#       print "expression: $item{expr}\n";
+    {type => $item[1], name => $item{IDENTIFIER}, optional => 1,
+     offset => $thisoffset}
+     }
+   | type IDENTIFIER
+     {
+#       print "argument $item{IDENTIFIER} found\n";
+       {type => $item[1], name => $item{IDENTIFIER}, offset => $thisoffset}
+     }
+   | type { {type => $item[1]} }
+   | '...'
+     { {name => '...', type => '...', offset => $thisoffset} }
+
+ident_part: /[~_a-z]\w*/i '<' <commit> <leftop: IDENTIFIER ',' IDENTIFIER>(s?) '>'
+        {
+       $item[1].'<'.join('', @{$item[4]}).'>'
+        }
+
+      | /[~_a-z]\w*/i
+        {
+           $item[1]
+        }
+
+IDENTIFIER: <leftop: ident_part '::' ident_part>
+        {
+              my $x = join '::', @{$item[1]};
+#              print "IDENTIFIER: $x\n";
+              $x
+        }
+
+# Parse::RecDescent is retarded in this one case: if a subrule fails, it
+# gives up the entire rule. This is a stupid way to get around that.
+rtype: rtype2 | rtype1
+rtype1: TYPE star(s?)
+        {
+         $return = $item[1];
+         $return .= join '',' ',@{$item[2]} if @{$item[2]};
+#    print "rtype1: $return\n";
+#          return undef
+#            unless(defined$thisparser->{data}{typeconv}{valid_rtypes}{$return});
+        }
+rtype2: modifier(s) TYPE star(s?)
+    {
+         $return = $item[2];
+         $return = join ' ',grep{$_}@{$item[1]},$return
+           if @{$item[1]};
+         $return .= join '',' ',@{$item[3]} if @{$item[3]};
+#    print "rtype2: $return\n";
+#          return undef
+#            unless(defined$thisparser->{data}{typeconv}{valid_rtypes}{$return});
+     $return = 'static ' . $return
+       if $thisparser->{data}{smod}{static};
+         $thisparser->{data}{smod}{static} = 0;
+    }
+
+type: type2 | type1
+type1: TYPE star(s?)
+        {
+         $return = $item[1];
+         $return .= join '',' ',@{$item{$Inline::CPP::Parser::RecDescent::star}} if @{$item{$Inline::CPP::Parser::RecDescent::star}};
+#    print "type1: $return\n";
+#          return undef
+#            unless(defined$thisparser->{data}{typeconv}{valid_types}{$return});
+        }
+type2: modifier(s) TYPE star(s?)
+    {
+         $return = $item{TYPE};
+         $return = join ' ',grep{$_}@{$item[1]},$return if @{$item[1]};
+         $return .= join '',' ',@{$item{$Inline::CPP::Parser::RecDescent::star}} if @{$item{$Inline::CPP::Parser::RecDescent::star}};
+#    print "type2: $return\n";
+#          return undef
+#            unless(defined$thisparser->{data}{typeconv}{valid_types}{$return});
+    }
+
+anytype: anytype2 | anytype1
+anytype1: TYPE star(s?)
+         {
+           $return = $item[1];
+           $return .= join '',' ',@{$item[2]} if @{$item[2]};
+         }
+anytype2: modifier(s) TYPE star(s?)
+         {
+           $return = $item[2];
+           $return = join ' ',grep{$_}@{$item[1]},$return if @{$item[1]};
+           $return .= join '',' ',@{$item[3]} if @{$item[3]};
+         }
+
+comment: m{\s* // [^\n]* \n }x
+       | m{\s* /\* (?:[^*]+|\*(?!/))* \*/  ([ \t]*)? }x
+
+# long and short aren't recognized as modifiers because they break when used
+# as regular types. Another Parse::RecDescent problem is greedy matching; I
+# need tmodifier to "give back" long or short in cases where keeping them would
+# cause the modifier rule to fail. One side-effect is 'long long' can never
+# be parsed correctly here.
+modifier: tmod
+        | smod { ++$thisparser->{data}{smod}{$item[1]}; ''}
+    | nmod { '' }
+tmod: 'unsigned' # | 'long' | 'short'
+smod: 'const' | 'static'
+nmod: 'extern' | 'virtual' | 'mutable' | 'volatile' | 'inline'
+
+scope: 'public' | 'private' | 'protected'
+
+class: 'class' { $thisparser->{data}{defaultscope} = 'private'; $item[1] }
+     | 'struct' { $thisparser->{data}{defaultscope} = 'public'; $item[1] }
+
+star: '*' | '&'
+
+code_block: /$Inline::CPP::Parser::RecDescent::code_block/
+
+# Consume expressions
+expr: <leftop: subexpr OP subexpr> {
+    my $o = join '', @{$item[1]};
+#   print "expr: $o\n";
+    $o;
+}
+subexpr: /$Inline::CPP::Parser::RecDescent::funccall/ # Matches a macro, too
+       | /$Inline::CPP::Parser::RecDescent::string/
+       | /$Inline::CPP::Parser::RecDescent::number/
+       | UOP subexpr
+OP: '+' | '-' | '*' | '/' | '^' | '&' | '|' | '%' | '||' | '&&'
+UOP: '~' | '!' | '-' | '*' | '&'
+
+TYPE: IDENTIFIER
+
+all: /.*/
+
+END
+}
+
+#============================================================================
+# Generate typemap code for the classes and structs we bind to. This allows
+# functions declared after a class to return or accept class objects as
+# parameters.
+#============================================================================
+$TYPEMAP_KIND = 'O_Inline_CPP_Class';
+
+sub typemap {
+  my ($parser, $typename) = @_;
+
+#    print "Inline::CPP::Parser::RecDescent::typemap(): typename=$typename\n";
+
+  my ($TYPEMAP, $INPUT, $OUTPUT);
+  $TYPEMAP = "$typename *\t\t$TYPEMAP_KIND\n";
+  $INPUT   = <<"END";
+    if (sv_isobject(\$arg) && (SvTYPE(SvRV(\$arg)) == SVt_PVMG)) {
+        \$var = (\$type)SvIV((SV*)SvRV( \$arg ));
+    }
+    else {
+        warn ( \\"\${Package}::\$func_name() -- \$var is not a blessed reference\\" );
+        XSRETURN_UNDEF;
+    }
+END
+  $OUTPUT = <<"END";
+    sv_setref_pv( \$arg, CLASS, (void*)\$var );
+END
+
+  my $ctypename = $typename . ' *';
+  $parser->{data}{typeconv}{input_expr}{$TYPEMAP_KIND}  ||= $INPUT;
+  $parser->{data}{typeconv}{output_expr}{$TYPEMAP_KIND} ||= $OUTPUT;
+  $parser->{data}{typeconv}{type_kind}{$ctypename} = $TYPEMAP_KIND;
+  $parser->{data}{typeconv}{valid_types}{$ctypename}++;
+  $parser->{data}{typeconv}{valid_rtypes}{$ctypename}++;
+  return;
+}
+
+#============================================================================
+# Default action is to strip ellipses from the C++ code. This allows having
+# _only_ a '...' in the code, just like XS. It is the default.
+#============================================================================
+sub strip_ellipsis {
+  my ($parser, $args) = @_;
+  return if $parser->{ILSM}{PRESERVE_ELLIPSIS};
+  for (my $i = 0; $i < @$args; $i++) {
+    next unless $args->[$i]{name} eq '...';
+
+    # if it's the first one, just strip it
+    if ($i == 0) {
+      substr($parser->{ILSM}{code}, $args->[$i]{offset} - 3, 3, '   ');
+    }
+    else {
+      my $prev        = $i - 1;
+      my $prev_offset = $args->[$prev]{offset};
+      my $length      = $args->[$i]{offset} - $prev_offset;
+      substr($parser->{ILSM}{code}, $prev_offset, $length) =~ s/\S/ /g;
+    }
+  }
+  return;
+}
+
+my $hack = sub { # Appease -w using Inline::Files
+    print Parse::RecDescent::IN '';
+    print Parse::RecDescent::IN '';
+    print Parse::RecDescent::TRACE_FILE '';
+    print Parse::RecDescent::TRACE_FILE '';
+};
+
+1;
+
+=head1 Inline::CPP::Parser::RecDescent
+
+All functions are internal.  No documentation necessary.
+
+=cut
@@ -0,0 +1,780 @@
+package Inline::CPP;
+
+use strict;
+use warnings;
+use 5.008001;
+use Fcntl qw( :DEFAULT :flock );
+
+require Inline::C;
+require Inline::CPP::Parser::RecDescent;
+require Inline::CPP::Config;
+
+# Note: Parse::RecDescent 'require'd within get_parser().
+
+use Carp;
+
+# use base doesn't work because Inline::C cannot be "use"d directly.
+our @ISA = qw( Inline::C );    ## no critic (ISA)
+
+# Development releases will have a _0xx version suffix.
+# We eval the version number to accommodate dev. version numbering, as
+# described in perldoc perlmodstyle.
+our $VERSION = '0.69';
+# $VERSION = eval $VERSION; ## no critic (eval)
+
+my $TYPEMAP_KIND;
+{
+  no warnings 'once';          ## no critic (warnings)
+  $TYPEMAP_KIND = $Inline::CPP::Parser::RecDescent::TYPEMAP_KIND;
+}
+
+#============================================================================
+# Register Inline::CPP as an Inline language module
+#============================================================================
+sub register {
+  use Config;
+  return {
+    language => 'CPP',
+    aliases  => ['cpp', 'C++', 'c++', 'Cplusplus', 'cplusplus', 'CXX', 'cxx'],
+    type     => 'compiled',
+    suffix   => $Config{dlext},
+  };
+}    ### Tested.
+
+#============================================================================
+# Validate the C++ config options: Now mostly done in Inline::C
+#============================================================================
+sub validate {
+  my ($o, @config_options) = @_;
+  my ($flavor_defs, $iostream);
+
+  {    # "used only once" warning. We know it's ok.
+    no warnings 'once';    ## no critic (warnings)
+    ## no critic (package variable)
+
+    # Set default compiler and libraries.
+    $o->{ILSM}{MAKEFILE}{CC}   ||= $Inline::CPP::Config::compiler;
+    $o->{ILSM}{MAKEFILE}{LIBS} ||= _make_arrayref($Inline::CPP::Config::libs);
+
+    $flavor_defs = $Inline::CPP::Config::cpp_flavor_defs;  # "Standard"?
+    $iostream    = $Inline::CPP::Config::iostream_fn;      # iostream filename.
+  }
+
+  # I haven't traced it out yet, but $o->{STRUCT} gets set before getting
+  # properly set from Inline::C's validate().
+  $o->{STRUCT} ||= {'.macros' => q{}, '.any' => 0, '.xs' => q{}, '.all' => 0,};
+
+  _build_auto_include($o, $flavor_defs, $iostream);
+
+  $o->{ILSM}{PRESERVE_ELLIPSIS} = 0
+    unless defined $o->{ILSM}{PRESERVE_ELLIPSIS};
+
+  # Filter out the parameters we treat differently than Inline::C,
+  # forwarding unknown requests back up to Inline::C.
+  my @propagate = _handle_config_options($o, @config_options);
+  $o->SUPER::validate(@propagate) if @propagate;
+
+  return;
+}
+
+
+sub _build_auto_include {
+  my ($o, $flavor_defs, $iostream) = @_;
+  my $auto_include = <<'END';
+#define __INLINE_CPP 1
+#ifndef bool
+#include <%iostream%>
+#endif
+extern "C" {
+#include "EXTERN.h"
+#include "perl.h"
+#include "XSUB.h"
+#include "INLINE.h"
+}
+#ifdef bool
+#undef bool
+#include <%iostream%>
+#endif
+
+END
+
+  $o->{ILSM}{AUTO_INCLUDE} ||= $auto_include;
+  $o->{ILSM}{AUTO_INCLUDE} = $flavor_defs . $o->{ILSM}{AUTO_INCLUDE};
+
+  # Replace %iostream% with the correct iostream library
+  $o->{ILSM}{AUTO_INCLUDE} =~ s{%iostream%}{$iostream}xg;
+  return;
+}
+
+
+sub _handle_config_options {
+  my ($o, @config_options) = @_;
+  my @propagate;
+
+  while (@config_options) {
+    my ($key, $value) = (shift @config_options, shift @config_options);
+    $key = uc $key;
+    if ($key eq 'NAMESPACE') {
+      _handle_namespace_cfg_option($o, $value);
+    }
+    elsif ($key eq 'CLASSES') {
+      _handle_classes_cfg_option($o, $value);
+    }
+    elsif ($key eq 'LIBS') {
+      _handle_libs_cfg_option($o, $value);
+    }
+    elsif ($key eq 'ALTLIBS') {
+      _handle_altlibs_cfg_option($o, $value);
+    }
+    elsif ($key eq 'PRESERVE_ELLIPSIS' or $key eq 'STD_IOSTREAM') {
+      croak "Argument to $key must be 0 or 1"
+        unless $value == 0 or $value == 1;
+      $o->{ILSM}{$key} = $value;
+    }
+    else {
+      push @propagate, $key, $value;
+    }
+  }
+  return @propagate;
+}
+
+sub _handle_namespace_cfg_option {
+  my ($o, $value) = @_;
+  $value =~ s/^::|::$//g;
+  
+  # Perl 5.12 indroduced \p{XID_Start} and \p{XID_Continue}. Prior to that
+  # we should downgrade gracefully.
+  my $ident = $] ge '5.0120'
+    ? qr{[\p{XID_Start}_][\p{XID_Continue}_]*}
+    : qr{[\p{Alpha}_][\p{Alpha}\p{Digit}_]*};
+
+  croak "$value is an invalid package name."
+    unless length $value == 0
+     || $value =~ m/
+                    \A
+                    $ident
+                    (?:::$ident)*
+                    \z
+                  /x;
+  $value ||= 'main';
+  $o->{API}{pkg} = $value;
+  return;
+}
+
+
+sub _handle_classes_cfg_option {
+  my ($o, $value) = @_;
+  my $ref_value = ref($value);
+  croak 'CLASSES config option is not a valid code reference or hash '
+    . 'reference of class mappings.'
+    unless (($ref_value eq 'CODE') or ($ref_value eq 'HASH'));
+
+  if ($ref_value eq 'HASH') {
+    foreach my $cpp_class (keys %{$value}) {
+      croak "$cpp_class is not a supported C++ class."
+        unless defined $value->{$cpp_class}
+        && length $cpp_class != 0
+        && $cpp_class =~ m/[a-zA-Z]\w*/x;
+      my $perl_class = $value->{$cpp_class};
+      croak "$perl_class is not a supported Perl class."
+        unless length $perl_class != 0 && $perl_class =~ m/[a-zA-Z]\w*/x;
+    }
+  }
+
+  $o->{API}{classes_override} = $value;
+  return;
+}
+
+
+sub _handle_libs_cfg_option {
+  my ($o, $value) = @_;
+  $value = _make_arrayref($value);
+  _add_libs($o, $value);
+  return;
+}
+
+
+sub _handle_altlibs_cfg_option {
+  my ($o, $value) = @_;
+  $value = _make_arrayref($value);
+  push @{$o->{ILSM}{MAKEFILE}{LIBS}}, q{};
+  _add_libs($o, $value);
+  return;
+}
+
+
+sub _make_arrayref {
+  my $value = shift;
+  $value = [$value] unless ref $value eq 'ARRAY';
+  return $value;
+}
+
+sub _add_libs {
+  my ($o, $libs) = @_;
+  my $num = scalar @{$o->{ILSM}{MAKEFILE}{LIBS}} - 1;
+  $o->{ILSM}{MAKEFILE}{LIBS}[$num] .= q{ } . $_ for @{$libs};
+  return;
+}
+
+
+#============================================================================
+# Print a small report if PRINT_INFO option is set
+#============================================================================
+sub info {
+  my $o    = shift;
+  my $info = q{};
+
+  $o->parse unless $o->{ILSM}{parser};
+  my $data = $o->{ILSM}{parser}{data};
+
+  my (@class, @func);
+  if (defined $data->{classes}) {
+    for my $class (sort @{$data->{classes}}) {
+      my @parents
+        = grep { $_->{thing} eq 'inherits' } @{$data->{class}{$class}};
+      push @class, "\tclass $class";
+      push @class,
+        (' : ' . join(', ', map { $_->{scope} . q{ } . $_->{name} } @parents))
+        if @parents;
+      push @class, " {\n";
+      for my $thing (sort { $a->{name} cmp $b->{name} }
+        @{$data->{class}{$class}})
+      {
+        my ($name, $scope, $type) = @{$thing}{qw(name scope thing)};
+        next unless $scope eq 'public' and $type eq 'method';
+        next
+          unless $o->check_type($thing, $name eq $class, $name eq "~$class",);
+        my $rtype = $thing->{rtype} || q{};
+        push @class, "\t\t$rtype" . ($rtype ? q{ } : q{});
+        push @class, $class . "::$name(";
+        my @args = grep { $_->{name} ne '...' } @{$thing->{args}};
+        my $ellipsis = (scalar @{$thing->{args}} - scalar @args) != 0;
+        push @class, join ', ', (map {"$_->{type} $_->{name}"} @args),
+          $ellipsis ? '...' : ();
+        push @class, ");\n";
+      }
+      push @class, "\t};\n";
+    }
+  }
+  if (defined $data->{functions}) {
+    for my $function (sort @{$data->{functions}}) {
+      my $func = $data->{function}{$function};
+      next if $function =~ m/::/x;
+      next unless $o->check_type($func, 0, 0);
+      push @func, "\t" . $func->{rtype} . q{ };
+      push @func, $func->{name} . '(';
+      my @args = grep { $_->{name} ne '...' } @{$func->{args}};
+      my $ellipsis = (scalar @{$func->{args}} - scalar @args) != 0;
+      push @func, join ', ', (map {"$_->{type} $_->{name}"} @args),
+        $ellipsis ? '...' : ();
+      push @func, ");\n";
+    }
+  }
+
+  # Report:
+  {
+    local $" = q{};
+    $info .= "The following classes have been bound to Perl:\n@class\n"
+      if @class;
+    $info .= "The following functions have been bound to Perl:\n@func\n"
+      if @func;
+  }
+  $info .= Inline::Struct::info($o) if $o->{STRUCT}{'.any'};
+  return $info;
+}
+
+#============================================================================
+# Generate a C++ parser
+#============================================================================
+sub get_parser {
+  my $o = shift;
+  return Inline::CPP::Parser::RecDescent::get_parser_recdescent($o);
+}
+
+#============================================================================
+# Intercept xs_generate and create the typemap file
+#============================================================================
+sub xs_generate {
+  my $o = shift;
+  $o->write_typemap;
+  return $o->SUPER::xs_generate;
+}
+
+#============================================================================
+# Return bindings for functions and classes
+#============================================================================
+sub xs_bindings {
+  my $o = shift;
+
+  # What is modfname, and why are we taking it from a slice but not using it?
+  my ($pkg, $module) = @{$o->{API}}{qw(pkg module)};
+  my $data = $o->{ILSM}{parser}{data};
+  my @XS;
+
+  warn "Warning: No Inline C++ functions or classes bound to Perl\n"
+    . "Check your C++ for Inline compatibility.\n\n"
+    if !defined $data->{classes} && !defined $data->{functions} && $^W;
+  for my $class (@{$data->{classes}}) {
+    my $proper_pkg;
+
+    # Possibly override package and class names
+    if (exists $o->{API}{classes_override}) {
+      my $ref_classes_override = ref($o->{API}{classes_override});
+      if ($ref_classes_override eq 'HASH') {
+        if (exists $o->{API}{classes_override}->{$class})
+        {    # Override class name only
+          $proper_pkg = $pkg . '::' . $o->{API}{classes_override}->{$class};
+        }
+        else {
+          # Do not override package or class names
+          $proper_pkg = $pkg . '::' . $class;
+        }
+      }
+      elsif ($ref_classes_override eq 'CODE')
+      {
+        # Override both package and class names
+        $proper_pkg = &{$o->{API}{classes_override}}($class);
+        if   ($proper_pkg eq '') { $proper_pkg = 'main'; }
+      }
+    }
+    else {        # Do not override package or class names
+      $proper_pkg = $pkg . '::' . $class;
+    }
+
+    # Strip main:: from packages.  There cannot be a package main::Foo!
+    $proper_pkg =~ s/^main::(.+)/$1/;
+
+    # Set up the proper namespace
+    push @XS, _build_namespace($module, $proper_pkg);
+    push @XS, _generate_member_xs_wrappers($o, $pkg, $class, $proper_pkg);
+  }
+
+  push @XS, _remove_xs_prefixes($o, $module, $pkg);
+  push @XS, _generate_nonmember_xs_wrappers($o);
+
+  for (@{$data->{enums}}) {
+
+    # Global enums.
+    $o->{ILSM}{XS}{BOOT} .= make_enum($pkg, @{$_}{qw( name body )});
+  }
+  return join q{}, @XS;
+}
+
+
+# Set up the proper namespace.
+sub _build_namespace {
+  my ($module, $proper_pkg) = @_;
+  return <<"END";
+
+MODULE = $module        PACKAGE = $proper_pkg
+
+PROTOTYPES: DISABLE
+
+END
+}
+
+
+sub _generate_member_xs_wrappers {
+  my ($o, $pkg, $class, $proper_pkg) = @_;
+  my @XS;
+  my $data = $o->{ILSM}{parser}{data};
+  my ($ctor, $dtor, $abstract) = (0, 0, 0);    ## no critic (ambiguous)
+  for my $thing (@{$data->{class}{$class}}) {
+    my ($name, $scope, $type) = @{$thing}{qw| name scope thing |};
+
+    _handle_inheritance($o, $type, $scope, $pkg, $class, $name);
+
+    # Get/set methods will go here:
+    # Cases we skip:
+    $abstract ||= ($type eq 'method' and $thing->{abstract});
+    next if ($type eq 'method' and $thing->{abstract});
+    next if $scope ne 'public';
+    if ($type eq 'enum') {
+      $o->{ILSM}{XS}{BOOT} .= make_enum($proper_pkg, $name, $thing->{body});
+    }
+    elsif ($type eq 'method' and $name !~ m/operator/) {
+
+      # generate an XS wrapper
+      $ctor ||= ($name eq $class);
+      $dtor ||= ($name eq "~$class");
+      push @XS, $o->wrap($thing, $name, $class);
+    }
+  }
+
+  # Provide default constructor and destructor:
+  push @XS, "$class *\n${class}::new()\n\n" unless ($ctor or $abstract);
+
+  push @XS, "void\n${class}::DESTROY()\n\n" unless ($dtor or $abstract);
+  return @XS;
+}
+
+
+# Let Perl handle inheritance.
+sub _handle_inheritance {
+  my ($o, $type, $scope, $pkg, $class, $name) = @_;
+  if ($type eq 'inherits' and $scope eq 'public') {
+    $o->{ILSM}{XS}{BOOT} ||= q{};
+    
+    my $ISA_name;
+    my $parent;
+
+    # Possibly override package and class names
+    if (exists $o->{API}{classes_override}) {
+      my $ref_classes_override = ref($o->{API}{classes_override});
+      if ($ref_classes_override eq 'HASH') {
+        if (exists $o->{API}{classes_override}->{$class})
+        {    # Override class name only
+          $ISA_name = $pkg . '::' . $o->{API}{classes_override}->{$class} . '::ISA';
+          $parent   = $pkg . '::' . $o->{API}{classes_override}->{$name};
+        }
+        else {
+          # Do not override package or class names
+          $ISA_name = $pkg . '::' . $class . '::ISA';
+          $parent = $pkg . '::' . $name;
+        }
+      }
+      elsif ($ref_classes_override eq 'CODE')
+      {
+        # Override both package and class names
+        $ISA_name = &{$o->{API}{classes_override}}($class) . '::ISA';
+        $parent = &{$o->{API}{classes_override}}($name);
+        if   ($ISA_name eq '') { croak 'Have empty string for \$ISA_name, croaking' }
+      }
+    }
+    else {        # Do not override package or class names
+      $ISA_name = $pkg . '::' . $class . '::ISA';
+      $parent = $pkg . '::' . $name;
+    }
+
+    # Strip main:: from packages.  There cannot be a package main::Foo!
+    $ISA_name =~ s/^main::(.+)/$1/;
+    $parent =~ s/^main::(.+)/$1/;
+    
+    $o->{ILSM}{XS}{BOOT} .= <<"END";
+{
+#ifndef get_av
+    AV *isa = perl_get_av("$ISA_name", 1);
+#else
+    AV *isa = get_av("$ISA_name", 1);
+#endif
+    av_push(isa, newSVpv("$parent", 0));
+}
+END
+  }
+  return;
+}
+
+
+sub _generate_nonmember_xs_wrappers {
+  my $o    = shift;
+  my $data = $o->{ILSM}{parser}{data};
+  my @XS;
+  for my $function (@{$data->{functions}}) {
+
+    # lose constructor defs outside class decls (and "implicit int")
+    next if $data->{function}{$function}{rtype} eq q{};
+    next if $data->{function}{$function}{rtype} =~ m/static/;    #specl case
+    next if $function =~ m/::/x;         # skip member functions.
+    next if $function =~ m/operator/;    # and operators.
+    push @XS, $o->wrap($data->{function}{$function}, $function);
+  }
+  return @XS;
+}
+
+
+# Generate XS code to remove prefixes from function names.
+sub _remove_xs_prefixes {
+  my ($o, $module, $pkg) = @_;
+  my $prefix
+    = ($o->{ILSM}{XS}{PREFIX} ? "PREFIX = $o->{ILSM}{XS}{PREFIX}" : q{});
+  return <<"END";
+
+MODULE = $module        PACKAGE = $pkg  $prefix
+
+PROTOTYPES: DISABLE
+
+END
+
+}
+
+
+#============================================================================
+# Generate an XS wrapper around anything: a C++ method or function
+#============================================================================
+sub wrap {
+  my ($o, $thing, $name, $class) = @_;
+  $class ||= q{};
+  my $t = q{ } x 4;    # indents in 4-space increments.
+  my (@XS, @PREINIT, @CODE);
+
+  my ($XS, $ctor, $dtor) = _map_subnames_cpp_to_perl($thing, $name, $class);
+
+  push @XS, $XS;
+
+  return q{} unless $o->check_type($thing, $ctor, $dtor);
+
+  # Filter out optional subroutine arguments
+  my (@args, @opts, $ellipsis, $void);
+
+  $_->{optional} ? push @opts, $_ : push @args, $_ for @{$thing->{args}};
+
+  $ellipsis = pop @args if (@args and $args[-1]{name} eq '...');
+
+  $void = ($thing->{rtype} and $thing->{rtype} eq 'void');
+
+  push @XS, join q{},
+    (
+    '(',
+    join(', ',
+      (map { $_->{name} } @args),
+      (scalar @opts or $ellipsis) ? '...' : ()),
+    ")\n",
+    );
+
+  # Declare the non-optional arguments for XS type-checking
+  push @XS, "\t$_->{type}\t$_->{name}\n" for @args;
+
+  # Wrap "complicated" subs in stack-checking code
+  if ($void or $ellipsis) {
+    push @PREINIT, "\tI32 *\t__temp_markstack_ptr;\n";
+    push @CODE,    "\t__temp_markstack_ptr = PL_markstack_ptr++;\n";
+  }
+
+  if (@opts) {
+    push @PREINIT, "\t$_->{type}\t$_->{name};\n" for @opts;
+    push @CODE, 'switch(items' . ($class ? '-1' : q{}) . ") {\n";
+
+    my $offset = scalar @args;             # which is the first optional?
+    my $total  = $offset + scalar @opts;
+    for my $i ($offset .. $total - 1) {
+      push @CODE, 'case ' . ($i + 1) . ":\n";
+      my @tmp;
+      for my $j ($offset .. $i) {
+        my $targ = $opts[$j - $offset]{name};
+        my $type = $opts[$j - $offset]{type};
+        my $src  = "ST($j)";
+        my $conv = $o->typeconv($targ, $src, $type, 'input_expr');
+        push @CODE, $conv . ";\n";
+        push @tmp,  $targ;
+      }
+      push @CODE, "\tRETVAL = " unless $void;
+      push @CODE,
+        call_or_instantiate($name, $ctor, $dtor, $class, $thing->{rconst},
+        $thing->{rtype}, (map { $_->{name} } @args), @tmp);
+      push @CODE, "\tbreak; /* case " . ($i + 1) . " */\n";
+    }
+    push @CODE, "default:\n";
+    push @CODE, "\tRETVAL = " unless $void;
+    push @CODE,
+      call_or_instantiate($name, $ctor, $dtor, $class, $thing->{rconst},
+      $thing->{rtype}, map { $_->{name} } @args);
+    push @CODE, "} /* switch(items) */ \n";
+  }
+  elsif ($void) {
+    push @CODE, "\t";
+    push @CODE,
+      call_or_instantiate($name, $ctor, $dtor, $class, 0, q{},
+      map { $_->{name} } @args);
+  }
+  elsif ($ellipsis or $thing->{rconst}) {
+    push @CODE, "\t";
+    push @CODE, 'RETVAL = ';
+    push @CODE,
+      call_or_instantiate($name, $ctor, $dtor, $class, $thing->{rconst},
+      $thing->{rtype}, map { $_->{name} } @args);
+  }
+  if ($void) {
+    push @CODE, <<'END';
+        if (PL_markstack_ptr != __temp_markstack_ptr) {
+          /* truly void, because dXSARGS not invoked */
+          PL_markstack_ptr = __temp_markstack_ptr;
+          XSRETURN_EMPTY; /* return empty stack */
+        }
+        /* must have used dXSARGS; list context implied */
+        return; /* assume stack size is correct */
+END
+  }
+  elsif ($ellipsis) {
+    push @CODE, "\tPL_markstack_ptr = __temp_markstack_ptr;\n";
+  }
+
+  # The actual function:
+  local $" = q{};
+  push @XS, "${t}PREINIT:\n@PREINIT" if @PREINIT;
+  push @XS, $t;
+  push @XS, 'PP' if $void and @CODE;
+  push @XS, "CODE:\n@CODE" if @CODE;
+  push @XS, "${t}OUTPUT:\nRETVAL\n" if @CODE and not $void;
+  push @XS, "\n";
+  return "@XS";
+}
+
+
+sub _map_subnames_cpp_to_perl {
+  my ($thing, $name, $class) = @_;
+  my ($XS, $ctor, $dtor) = (q{}, 0, 0);
+
+  if ($name eq $class) {    # ctor
+    $XS   = $class . " *\n" . $class . '::new';
+    $ctor = 1;
+  }
+  elsif ($name eq "~$class") {    # dtor
+    $XS   = "void\n$class" . '::DESTROY';
+    $dtor = 1;
+  }
+  elsif ($class) {                # method
+    $XS = "$thing->{rtype}\n$class" . "::$thing->{name}";
+  }
+  else {                          # function
+    $XS = "$thing->{rtype}\n$thing->{name}";
+  }
+  return ($XS, $ctor, $dtor);
+}
+
+
+sub call_or_instantiate {
+  my ($name, $ctor, $dtor, $class, $const, $type, @args) = @_;
+
+  # Create an rvalue (which might be const-casted later).
+  my $rval = q{};
+  $rval .= 'new '    if $ctor;
+  $rval .= 'delete ' if $dtor;
+  $rval .= 'THIS->'  if ($class and not($ctor or $dtor));
+  $rval .= $name . '(' . join(q{,}, @args) . ')';
+
+  return const_cast($rval, $const, $type) . ";\n";
+}    ### Tested.
+
+sub const_cast {
+  my ($value, $const, $type) = @_;
+  return $value unless $const and $type =~ m/[*&]/x;
+  return "const_cast<$type>($value)";
+}    ### Tested.
+
+sub write_typemap {
+  my $o         = shift;
+  my $filename  = "$o->{API}{build_dir}/CPP.map";
+  my $type_kind = $o->{ILSM}{typeconv}{type_kind};
+  my $typemap   = q{};
+  $typemap .= $_ . "\t" x 2 . $TYPEMAP_KIND . "\n"
+    for grep { $type_kind->{$_} eq $TYPEMAP_KIND } keys %{$type_kind};
+  return unless length $typemap;
+
+  my $tm_output = <<"END";
+TYPEMAP
+$typemap
+OUTPUT
+$TYPEMAP_KIND
+$o->{ILSM}{typeconv}{output_expr}{$TYPEMAP_KIND}
+INPUT
+$TYPEMAP_KIND
+$o->{ILSM}{typeconv}{input_expr}{$TYPEMAP_KIND}
+END
+
+
+  # Open an output file, create if necessary, then lock, then truncate.
+  # This replaces the following, which wasn't lock-safe:
+
+  sysopen(my $TYPEMAP_FH, $filename, O_WRONLY | O_CREAT)
+    or croak "Error: Can't write to $filename: $!";
+
+  # Flock and truncate (truncating to zero length to simulate '>' mode).
+  flock $TYPEMAP_FH, LOCK_EX
+    or croak "Error: Can't obtain lock for $filename: $!";
+  truncate $TYPEMAP_FH, 0 or croak "Error: Can't truncate $filename: $!";
+
+  # End of new lock-safe code.
+
+  print {$TYPEMAP_FH} $tm_output;
+
+  close $TYPEMAP_FH or croak "Error: Can't close $filename after write: $!";
+
+  $o->validate(TYPEMAPS => $filename);
+  return;
+}
+
+# Generate type conversion code: perl2c or c2perl.
+sub typeconv {
+  my ($o, $var, $arg, $type, $dir, $preproc) = @_;
+  my $tkind = $o->{ILSM}{typeconv}{type_kind}{$type};
+  my $ret;
+  {
+    no strict;   ## no critic (strict)
+                 # The conditional avoids uninitialized warnings if user passes
+                 # a C++ function with 'void' as param.
+    if (defined $tkind) {
+
+      # eval of typemap gives "Uninit"
+      no warnings 'uninitialized';    ## no critic (warnings)
+          # Even without the conditional this line must remain.
+      $ret = eval    ## no critic (eval)
+        qq{qq{$o->{ILSM}{typeconv}{$dir}{$tkind}}};
+    }
+    else {
+      $ret = q{};
+    }
+  }
+  chomp $ret;
+  $ret =~ s/\n/\\\n/xg if $preproc;
+  return $ret;
+}
+
+# Verify that the return type and all arguments can be bound to Perl.
+sub check_type {
+  my ($o, $thing, $ctor, $dtor) = @_;
+  my $badtype;
+
+  # strip "useless" modifiers so the type is found in typemap:
+BADTYPE: while (1) {
+    if (!($ctor || $dtor)) {
+      my $t = $thing->{rtype};
+      $t =~ s/^(\s|const|virtual|static)+//xg;
+      if ($t ne 'void' && !$o->typeconv(q{}, q{}, $t, 'output_expr')) {
+        $badtype = $t;
+        last BADTYPE;
+      }
+    }
+    foreach (map { $_->{type} } @{$thing->{args}}) {
+      s/^(?:const|\s)+//xgo;
+      if ($_ ne '...' && !$o->typeconv(q{}, q{}, $_, 'input_expr')) {
+        $badtype = $_;
+        last BADTYPE;
+      }
+    }
+    return 1;
+  }
+
+  # I don't really like this verbosity. This is what 'info' is for. Maybe we
+  # should ask Brian for an Inline=DEBUG option.
+  warn "No typemap for type $badtype. "
+    . "Skipping $thing->{rtype} $thing->{name}("
+    . join(', ', map { $_->{type} } @{$thing->{args}}) . ")\n"
+    if 0;
+  return 0;
+}
+
+# Generate boot-code for enumeration constants:
+sub make_enum {
+  my ($class, $name, $body) = @_;
+  my @enum;
+  push @enum, <<"END";
+\t{
+\t    HV * pkg = gv_stashpv(\"$class\", 1);
+\t    if (pkg == NULL)
+\t        croak("Can't find package '$class'\\n");
+END
+  my $val = 0;
+  foreach (@{$body}) {
+    my ($k, $v) = @{$_};
+    $val = $v if defined $v;
+    push @enum, "\tnewCONSTSUB(pkg, \"$k\", newSViv($val));\n";
+    ++$val;
+  }
+  push @enum, "\t}\n";
+  return join q{}, @enum;
+}
+
+
+1;
+
+__END__
@@ -39,16 +39,14 @@ critical code; but only after that code has been identified>" -- Donald Knuth
 L<Inline::CPP> is about that critical 3%.
 
 Tom "Duff's Device" Duff once wrote the following: "I<The alternative to
-genuflecting before the god of code-bumming is finding a better algorithm.  It
-should be clear that none such was available.  If your code is too slow, you
-must make it faster.  If no better algorithm is available, you must
-trim cycles.>"
+genuflecting before the god of code-bumming is finding a better algorithm...
+...If your code is too slow, you must make it faster.  If no better algorithm
+is available, you must trim cycles.>"
 
-97% of the time Perl is fast enough.  In fact, in many problem domains, 99.7% of
-the time it's fast enough.  But when one comes across a situation where
-performance isn't fast enough, and no better algorithm exists, getting closer
-to the metal is one way to trim cycles, assuming it's done well.  L<Inline::CPP>
-minimizes the pain in binding C++ code to Perl via XS.
+Often, well written Perl is fast enough.  But when one comes across a situation
+where performance isn't fast enough, and no better algorithm exists, getting
+closer to the metal is one way to trim cycles, assuming it's done well.
+L<Inline::CPP> minimizes the pain in binding C++ code to Perl via XS.
 
 Performance can also be evaluated in terms of memory requirements.  Perlish
 datastructures are beautifully simple to use, and quite powerful.  But this
@@ -60,7 +58,7 @@ can be aleviated to some degree by holding the data in a C++ data type.
 This can only go so far.  But the common saying is that if you consider a
 reasonable amount of memory to hold a data structure, double it, and then
 multiply by ten, you'll have a pretty good feel for how much memory Perl needs
-to hold it.  Inline::CPP can facilitate making this transition.
+to hold it.  Inline::CPP can facilitate a leaner alternative.
 
 "I<The standard library saves programmers from having to reinvent the wheel.>"
 -- Bjarne Stroustrup
@@ -86,23 +84,24 @@ take the edge off of it.
 
 =head1 Choosing a C++ Compiler
 
-Inline::CPP just parses your C++ code and creates bindings to it. Like
-Inline::C, you will need a suitable compiler the first time you run the
-script. Choosing a C++ compiler can prove difficult, because Perl is
-written in C, not C++.
+Inline::CPP just parses the subroutine and class signatures within your C++
+code and creates bindings to them. Like Inline::C, you will need a suitable
+compiler the first time you run the script.
 
 If you're one of the fortunate majority, you will accept the defaults as you
-install Inline::CPP.  If you're one of the unfortunate (and shrinking)
-minority, read on.
+install Inline::CPP; the correct C++ compiler and standard libraries will be
+configured for you.  If you're one of the unfortunate (and shrinking) minority,
+read on.
 
-Here's the rule: use any C++ compiler that's compatible with the compiler
+Here's the rule: use a C++ compiler that's compatible with the compiler
 which built C<perl>. For instance, if C<perl> was built with C<gcc>,
 use C<g++>.  If you're on a Sun or an IRIX box and the system C compiler
 C<cc> built C<perl>, then use the system C++ compiler, C<CC>.
 
 Some compilers actually compile both C and C++ with the same compiler.
 Microsoft's C<cl.exe> is one such compiler -- you pass it the <-TP> flag
-to convince it that you want C++ mode.
+to convince it that you want C++ mode.  Hopefully this will be deduced
+by default at install time.
 
 If you're using the GNU C++ compiler, make sure that you have the g++ front
 end installed (some Linux distros don't install it by default, but provide
@@ -111,18 +110,20 @@ it via their package management utilities).
 =head1 Using Inline::CPP
 
 Inline::CPP is very similar to Inline::C, and in most cases can be used in
-place of Inline::C without changing a single line of Perl or C code. It uses a 
-grammar to parse your C++ code, and binds to functions or classes which are
-recognized. If a function is recognized, it will be available from
-Perl space. If the function's signature is not recognized, it will not
-be available from Perl space, but will be available from other
-functions or classes within the C++ code.
+place of Inline::C without changing a single line of Perl or C code. If you
+haven't done so already, you should stop reading right now and read the
+documentation for L<Inline::C>, including the L<Inline::C-Cookbook>.
+
+This module uses a  grammar to parse your C++ code, and binds to functions or
+classes which are recognized. If a function is recognized, it will be available
+from Perl space. If the function's signature is not recognized, it will not
+be available from Perl, but will be available from other functions or classes
+within the C++ code.
 
 For more information about the grammar used to parse C++ code, see the
 section called "Grammar".
 
-The following example shows how C++ snippets map into the Perl
-namespace:
+The following example shows how C++ snippets map to Perl:
 
 Example 1:
 
@@ -148,7 +149,7 @@ Example 1:
 
     END
 
-After running the code above, Perl's namespace would look similar to if
+After running the code above, your Perl runtime would look similar to if
 following code had been run:
 
     sub main::doodle { }
@@ -169,22 +170,15 @@ means that things like this won't work:
     $obj->{extrafield} = 10;
 
 It doesn't work because C<$obj> is not a blessed hash. It's a blessed
-reference to a C++ object (and anyway, C++ wouldn't let you do that either,
-since extrafield wasn't defined).
+reference to a C++ object.
 
 =head1 C++ Compilation Phase
 
 The first time you run a program that uses Inline::CPP, the C++ code will be
 compiled into an C<_Inline/> or C<.Inline/> folder within the working directory.
-The first run will consequently incur a startup penalty.  However, the compiled
-code is cached, and assuming it's not modified, subsequent runs will skip the 
-C++ compilation, and startup time will be fast.
-
-While code is under development the default C<_Inline/> directory arrangement
-is probably fine.  But eventually it's probably best to set up a specific
-C<.Inline> folder.  It's easy to do.  The method is well documented in the 
-L<Inline> POD under the heading 
-L<The Inline DIRECTORY|http://search.cpan.org/perldoc?Inline#The_Inline_DIRECTORY>.
+The first run will incur a startup time penalty associated with compiling C++
+code.  However, the compiled code is cached, and assuming it's not modified,
+subsequent runs will skip the C++ compilation, and startup time will be fast.
 
 =head1 Where to put C++ code
 
@@ -207,8 +201,7 @@ Or....
         // C++ code here.
     END_CPP
     
-Ok, so that takes care of where code can reside within a given file.  But
-structurally where does it belong?  For simple one-off scripts, just put it
+Structurally where does it belong?  For simple one-off scripts, just put it
 anywhere you want.  But in the spirit of code reusability, it's often better to
 simply create a module that houses the functionality build upon C++ code:
 
@@ -226,13 +219,8 @@ Where you place your module's file(s) follows the same rules as plain old Perl,
 which is beyond the scope of this POD, but fortunatly no different from what
 you're used to (assuming you're used to writing Perl modules).
 
-One big advantage to putting the C++ code in a module is that it can be shared
-by multiple scripts while only incurring that compilation startup penalty one
-time, ever.
-
-For this reason, when placing the C++ code in a module, it's usually a good 
-idea to specify where the C<_Inline> directory should reside, and again that's 
-covered in full detail in the L<Inline> POD.
+Of course, modules can be shared by multiple scripts while only incurring that
+compilation startup penalty one time, ever.
 
 =head1 Basing (CPAN) Distributions on Inline::CPP
 
@@ -256,7 +244,12 @@ Perl XS code, fit for distribution without the Inline::CPP dependency.
 L<InlineX::CPP2XS> includes an example/ directory that actually converts
 Math::Prime::FastSieve to pure XS.
 
-=head2 The Perl Namespace Hack
+Some extension authors choose to implement first in Inline::CPP, and then
+manually tweak, then copy and paste the resulting XS file into their own
+distribution, with similar effect (and possibly a little finer-grained control)
+to the CPP2XS approach.
+
+=head2 Perl Namespaces
 
 Let's say you use Inline::CPP like this:
 
@@ -277,26 +270,16 @@ Let's say you use Inline::CPP like this:
     END_CPP
     1;
     
-The unfortunate issue is that the C++ class, "C<Foo>" will be mapped to Perl
-below the C<Some::Foo> namespace, as C<Some::Foo::Foo>, and would need to be
-instantiated like this: C<my $foo = Some::Foo::Foo->new()>.  This probably isn't
-what the user intended. Here's a devious hack (provided by BrowserUk) that
-eliminates the problem:
-
-    package Some::Foo;
-    package Some;        # Now we're using the "Some" namespace, and Inline::CPP
-                         # will create the Foo class as Some::Foo.
-    use Inline CPP => <<'END_CPP';
-
-    // No changes to the C++ code from the previous example.
-
-    END_CPP
+The issue is that the C++ class, "C<Foo>" will be mapped to Perl below the 
+C<Some::Foo> namespace, as C<Some::Foo::Foo>, and would need to be instantiated 
+like this: C<< my $foo = Some::Foo::Foo->new() >>.  This probably isn't what 
+the user intended. Use the L<namespace> configuration option to set your base
+namespace:
 
-    package Some::Foo;
-    return 1 if caller;
+    use Inline CPP => config => namespace => 'Some';
 
 Now, C<Foo> falls under the C<Some> heirarchy: C<Some::Foo>, and can be
-instantiated as C<my $foo = Some::Foo->new()>.  This probably I<is> what the
+instantiated as C<< my $foo = Some::Foo->new() >>.  This probably I<is> what the
 user intended.
 
 =head1 C++ Configuration Options
@@ -307,67 +290,202 @@ available for C/C++. Most of the options correspond either to the MakeMaker
 or XS options of the same name. See L<ExtUtils::MakeMaker> and
 L<perlxs>.
 
-=head2 ALTLIBS
+All configuration options, including the word C<config> are case insensitive.
+C<CPP>, and C<DATA> are not configuration options, and are not insensitive to
+case.
+
+=head2 altlibs
 
 Adds a new entry to the end of the list of alternative libraries to
 bind with. MakeMaker will search through this list and use the first
 entry where all the libraries are found.
 
-    use Inline Config => ALTLIBS => '-L/my/other/lib -lfoo';
+    use Inline CPP => config => altlibs => '-L/my/other/lib -lfoo';
 
-See also the LIBS config option, which appends to the last entry in
+See also the C<libs> config option, which appends to the last entry in
 the list.
 
-=head2 AUTO_INCLUDE
+=head2 auto_include
 
 Specifies extra statements to be automatically included. They will be
 added on to the defaults. A newline char will automatically be added.
 
-    use Inline CPP => Config => AUTO_INCLUDE => '#include "something.h"';
+    use Inline CPP => config => auto_include => '#include "something.h"';
 
-=head2 BOOT
+=head2 boot
 
 Specifies code to be run when your code is loaded. May not contain any
 blank lines. See L<perlxs> for more information.
 
-    use Inline Config => BOOT => 'foo();';
+    use Inline CPP => config => boot => 'foo();';
 
-=head2 CC
+=head2 cc
 
-Specifies which compiler to use.
+Specifies which compiler to use.  In most cases the configuration default is
+adequate.
 
-    use Inline CPP => Config => CC => '/usr/bin/g++-4.6';
+    use Inline CPP => config => cc => '/usr/bin/g++-4.6';
 
-=head2 CCFLAGS
+=head2 ccflags
 
 Specifies extra compiler flags. Corresponds to the MakeMaker option.
 
-    use Inline CPP => Config => CCFLAGS => '-std=gnu++0x';
+    use Inline CPP => config => ccflags => '-std=c++11';
+
+=head2 classes 
+
+    use Inline CPP => config => 
+        classes => { 'CPPFoo' => 'PerlFoo', 'CPPBar' => 'PerlBar' };
+
+    use Inline CPP => config => 
+        namespace => 'Qux' => 
+        classes => { 'CPPFoo' => 'PerlFoo', 'CPPBar' => 'PerlBar' };
+
+    use Inline CPP => config => 
+        classes => sub { 
+            my $cpp_class = shift; 
+            ... 
+            return($perl_package); 
+        };
+
+Override C++ class name.
+
+Under default behavior, a C++ class naming conflict will arise by attempting
+to implement the C++ classes C<Foo::Bar::MyClass> and C<Foo::Qux::MyClass>
+which depend upon one another in some way, because C++ sees both classes as 
+named only C<MyClass>.  We are unable to solve this C++ conflict by using just 
+the C<namespace> config option, because C<namespace> is only applied to the 
+Perl package name, not the C++ class name.
+
+In the future, this issue may be solved via Inline::CPP suport for the native 
+C++ C<namespace> operator and/or C++ class names which contain the C<::>
+double-colon scope token.
+
+For now, this issue is solved by using the C<classes> config option, which
+accepts either a hash reference or a code reference.  When a hash reference
+is provided, each hash key is a C++ class name, and each hash value is a 
+corresponding Perl class name.  This hash reference serves as a C++-to-Perl 
+class name mapping mechanism, and may be used in combination with the 
+C<namespace> config option to exercise full control over class and package 
+naming.
+
+When a code reference is provided, it must accept as its sole argument the C++ 
+class name, and return a single string value containing the generated Perl 
+package name.  When a code reference is provided for the C<classes> config
+option, the value of the C<namespace> config option is ignored.
+
+The hash reference may be considered a manual mapping method, and the code 
+reference an automatic mapping method.
+
+Example file C</tmp/Foo__Bar__MyClass.c>:
+
+    class MyClass {
+      private:
+        int a;
+      public:
+        MyClass() :a(10) {}
+        int fetch () { return a; }
+    };
+
+Example file C</tmp/Foo__Qux__MyClass.c>:
+
+    #include "/tmp/Foo__Bar__MyClass.c"
+    class MyClass {
+      private:
+        int a;
+      public:
+        MyClass() :a(20) {}
+        int fetch () { return a; }
+        int other_fetch () { MyClass mybar; return mybar.fetch(); }
+    };
+
+We encounter the C++ class naming conflict when we
+
+    use Inline CPP => '/tmp/Foo__Qux__MyClass.c' => namespace => 'Foo::Qux';
+
+The C++ compiler sees two C<MyClass> classes and gives a redefinition error:
+
+    _08conflict_encounter_t_9d68.xs:25:7: error: redefinition of ‘class MyClass’
+     class MyClass {
+           ^
+    In file included from _08conflict_encounter_t_9d68.xs:24:0:
+    /tmp/Foo__Bar__MyClass.c:1:7: error: previous definition of ‘class MyClass’
+     class MyClass {
+           ^
+
+The solution is to rename each C<MyClass> to utilize unique class names, such as
+C<Foo__Bar__MyClass> and C<Foo__Qux__MyClass>, and use the C<classes> config option.
+
+Updated example file C</tmp/Foo__Bar__MyClass.c>:
+
+    class Foo__Bar__MyClass {
+      private:
+        int a;
+      public:
+        Foo__Bar__MyClass() :a(10) {}
+        int fetch () { return a; }
+    };
+
+Updated example file C</tmp/Foo__Qux__MyClass.c>:
+
+    #include "/tmp/Foo__Bar__MyClass.c"
+    class Foo__Qux__MyClass {
+      private:
+        int a;
+      public:
+        Foo__Qux__MyClass() :a(20) {}
+        int fetch () { return a; }
+        int other_fetch () { Foo__Bar__MyClass mybar; return mybar.fetch(); }
+    };
+
+First, consider the following updated call to Inline using the hash reference
+method to manually map the namespace and class names.  This example does not 
+give any C++ errors, and runs correctly in both C++ and Perl:
+
+    use Inline  CPP => '/tmp/Foo__Qux__MyClass.c' => 
+                namespace => 'Foo' => 
+                classes => { 'Foo__Bar__MyClass' => 'Bar::MyClass', 
+                             'Foo__Qux__MyClass' => 'Qux::MyClass' };
+
+Next, consider another updated call to Inline using the code reference method
+to automatically map the namespace and class names, which may be deployed across
+more complex codebases.  This example automates the mapping of the '__' double-
+underscore to the '::' double-colon scope token.
+
+    use Inline CPP => config => 
+        classes => sub { join('::', split('__', shift)); };
+
+For more information, please see the runnable examples:
+C<t/classes/07conflict_avoid.t>
+C<t/classes/08auto.t>
+C<t/classes/09auto_mixed.t>
 
-=head2 FILTERS
+=head2 filters
 
 Specifies one (or more, in an array ref) filter which is to be applied to
 the code just prior to parsing. The filters are executed one after another,
 each operating on the output of the previous one. You can pass in a code
 reference or the name of a prepackaged filter.
 
-    use Inline Config => FILTERS => [Strip_POD => \&myfilter];
+    use Inline CPP => config => filters => [Strip_POD => \&myfilter];
+    use Inline CPP => config => filters => 'Preprocess';  # Inline::Filters
 
 The filter may do anything. The code is passed as the first argument, and
-it returns the filtered code.
+it returns the filtered code.  For a set of prefabricated filters, consider
+using L<Inline::Filters>.
 
-=head2 INC
+=head2 inc
 
 Specifies extra include directories. Corresponds to the MakeMaker
 parameter.
 
-    use Inline Config => INC => '-I/my/path';
+    use Inline CPP => config => inc => '-I/my/path';
 
-=head2 LD
+=head2 ld
 
 Specifies the linker to use.
 
-=head2 LDDLFLAGS
+=head2 lddlflags
 
 Specifies which linker flags to use.
 
@@ -375,111 +493,193 @@ NOTE: These flags will completely override the existing flags, instead
 of just adding to them. So if you need to use those too, you must
 respecify them here.
 
-=head2 LIBS
+=head2 libs
 
 Specifies external libraries that should be linked into your
 code. Corresponds to the MakeMaker parameter.
 
-    use Inline Config => LIBS => '-L/your/path -lyourlib';
+    use Inline CPP => config => libs => '-L/your/path -lyourlib';
 
-Unlike the LIBS configuration parameter used in Inline::C, successive
-calls to LIBS append to the previous calls. For example,
+Unlike the C<libs> configuration parameter used in Inline::C, successive
+calls to C<libs> append to the previous calls. For example,
 
-    use Inline Config => LIBS => '-L/my/path', LIBS => '-lyourlib';
+    use Inline CPP => config => libs => '-L/my/path', libs => '-lyourlib';
 
-will work correctly. If you want to add a new element to the list of
-possible libraries to link with, use the Inline::CPP configuration ALTLIBS.
+will work correctly, if correct is for both C<libs> to be in effect. If you
+want to add a new element to the list of possible libraries to link with, use
+the Inline::CPP configuration C<altlibs>.
 
-=head2 MAKE
+=head2 make
 
-Specifies the name of the 'make' utility to use.
+Specifies the name of the 'C<make>' utility to use.
 
-=head2 MYEXTLIB
+=head2 myextlib
 
 Specifies a user compiled object that should be linked in. Corresponds
 to the MakeMaker parameter.
 
-    use Inline Config => MYEXTLIB => '/your/path/something.o';
+    use Inline CPP => config => myextlib => '/your/path/something.o';
+
+=head2 namespace
+
+    use Inline CPP => config => namespace => 'Foo';
+    use Inline CPP => config => namespace => 'main';
+    use Inline CPP => config => namespace => q{};
+
+Override default base namespace.
+
+Under default behavior, a C++ class C<Foo> created by invoking L<Inline::CPP>
+from C<package Bar> will result in the C++ C<Foo> class being accessible from
+Perl as C<Bar::Foo>.  While this default behavior may be desirable in some
+cases, it might be undesirable in others.  An example would be creating a C<Foo>
+class while invoking Inline::CPP from package C<Foo>.  The resulting class will
+bind to Perl as C<Foo::Foo>, which is probably not what was intended.
+
+This default behavior can be overridden by specifying an alternate base
+C<namespace>.  Examples are probably the best way to explain this:
+
+
+    package Foo;
+    use Inline CPP => config => namespace => 'Bar';
+    use Inline CPP => <<'EOCPP';
+
+    class Baz {
+      private:
+        int a;
+      public:
+        Baz() :a(20) {}
+        int fetch () { return a; }
+    };
+    EOCPP
+
+    package main;
+    my $b = Bar::Baz->new();
+    print $b->fetch, "\n"; # 20.
+
+
+As demonstrated here, the namespace in which "Baz" resides can now be made
+independent of the package from which L<Inline::CPP> has been invoked.
+Consider instead the default behavior:
+
+
+    package Foo;
+    use Inline CPP => <<'EOCPP';
+    class Foo {
+      private:
+        int a;
+      public:
+        Baz() :a(20) {}
+        int fetch () { return a; }
+    };
+    EOCPP
+
+    package main;
+    my $b = Foo::Foo->new();
+    print $b->fetch, "\n"; # 20.
+
+
+It is probably, in this case, undesirable for the C++ class C<Foo> to reside in
+the Perl C<Foo::Foo> namespace.  We can fix this by adding our own namespace
+configuration:
+
+
+    package Foo;
+    use Inline CPP => config => namespace => q{};  # Disassociate from
+                                                   # calling package.
+    use Inline CPP => <<'EOCPP';
+
+    class Baz {
+      private:
+        int a;
+      public:
+        Baz() :a(20) {}
+        int fetch () { return a; }
+    };
+    EOCPP
+
+    package main;
+    my $b = Foo->new();
+    print $b->fetch, "\n"; # 20.
 
-=head2 PREFIX
+=head2 prefix
 
 Specifies a prefix that will automatically be stripped from C++
 functions when they are bound to Perl. Less useful than in C, because
 C++ mangles its function names to facilitate function overloading.
 
-    use Inline Config => PREFIX => 'ZLIB_';
+    use Inline CPP config => prefix => 'ZLIB_';
 
 This only affects C++ function names, not C++ class names or methods.
 
-=head2 PRESERVE_ELLIPSIS
+=head2 preserve_ellipsis
 
 By default, Inline::CPP replaces C<...> in bound functions with three
 spaces, since the arguments are always passed on the Perl Stack, not on
 the C stack. This is usually desired, since it allows functions with
 no fixed arguments (most compilers require at least one fixed argument).
 
-    use Inline Config => PRESERVE_ELLIPSIS => 1;
+    use Inline CPP config => preserve_ellipsis => 1;
 or
-    use Inline Config => ENABLE => PRESERVE_ELLIPSIS;
+    use Inline CPP config => enable => 'preserve_ellipsis';
 
-For an example of why PRESERVE_ELLIPSIS is normally not needed, see the
+For an example of why C<preserve_ellipsis> is normally not needed, see the
 examples section, below.
 
-=head2 STD_IOSTREAM
+=head2 std_iostream
 
 By default, Inline::CPP includes the standard iostream header at the top
 of your code.  Inline::CPP will try to make the proper selection between
 C<iostream.h> (for older compilers) and C<iostream> (for newer "Standard
 compliant" compilers).
 
-This option assures that it include C<iostream>, which is the
+This option assures that C<iostream> (with no C<.h>) is included, which is the
 ANSI-compliant version of the header. For most compilers the use of this
-configuration option should no longer be necessary.  It is still included
-to maintain backward compatibility with code that used to need it.
+configuration option should no longer be necessary, as detection is done at
+module install time.  The configuration option is still included only to
+maintain backward compatibility with code that used to need it.
 
-    use Inline CPP => Config => ENABLE => STD_IOSTREAM;
+    use Inline CPP => config => enable => 'std_iostream';
 
-=head2 STRUCTS
+=head2 structs
 
-Specifies whether to bind C structs into Perl using Inline::Struct.
-NOTE: Support for this option is experimental. Inline::CPP already binds
-to structs defined in your code. Structs and classes are treated as the
-same construct, except that a struct's initial scope is public, not
-private. Inline::Struct provides autogenerated get/set methods, an
-overloaded constructor, and several other features not available in
-Inline::CPP.
+Specifies whether to bind C structs into Perl using L<Inline::Struct>.
+NOTE: Support for this option is experimental. L<Inline::CPP> already binds
+to structs defined in your code. In C++, structs and classes are treated the
+same, except that a struct's initial scope is public, not private.
+L<Inline::Struct> provides autogenerated get/set methods, an overloaded
+constructor, and several other features not available in L<Inline::CPP>.
 
-You can invoke STRUCTS in several ways:
+You can invoke C<structs> in several ways:
 
-    use Inline Config => STRUCTS => 'Foo';
+    use Inline CPP config => structs => 'Foo';
 or
-    use Inline Config => STRUCTS => ['Bar', 'Baz'];
+    use Inline CPP config => structs => ['Bar', 'Baz'];
 
 Binds the named structs to Perl. Emits warnings if a struct was requested
 but could not be bound for some reason.
 
-    use Inline Config => ENABLE => 'STRUCTS';
+    use Inline CPP config => enable => 'structs';
 or
-    use Inline Config => STRUCTS => 1;
+    use Inline CPP config => structs => 1;
 
 Enables binding structs to Perl. All structs which can be bound, will. This
 parameter overrides all requests for particular structs.
 
-    use Inline Config => DISABLE => 'STRUCTS';
+    use Inline CPP config => disable => 'structs';
 or
-    use Inline Config => STRUCTS => 0;
+    use Inline CPP config => structs => 0;
 
 Disables binding structs to Perl. Overrides any other settings.
 
 See L<Inline::Struct> for more details about how C<Inline::Struct>
 binds C structs to Perl.
 
-=head2 TYPEMAPS
+=head2 typemaps
 
 Specifies extra typemap files to use. These types will modify the
 behaviour of C++ parsing. Corresponds to the MakeMaker parameter.
 
-    use Inline Config => TYPEMAPS => '/your/path/typemap';
+    use Inline CPP config => typemaps => '/your/path/typemap';
 
 =head1 C++-Perl Bindings
 
@@ -499,14 +699,14 @@ C<Inline::CPP> uses a much simpler approach. It parses the system's
 typemap files and only binds to functions with supported types. You
 can tell C<Inline::CPP> about custom typemap files too.
 
-If you have very complicated data structures in either C++ or Perl,
-you should just pass them as an SV* and do the conversion yourself in
+If you have non-trivial data structures in either C++ or Perl,
+you should probably just pass them as an SV* and do the conversion yourself in
 your C++ function.
 
 In C++, a struct is a class whose default scope is public, not
 private.  Inline::CPP binds to structs with this in mind -- get/set
-methods are not yet auto-generated (although they are scheduled to
-land in an upcoming release).
+methods are not yet auto-generated (although this feature may be added to
+an upcoming release).
 
 If you have a C struct, you can use Inline::Struct to allow Perl
 complete access to the internals of the struct. You can create and
@@ -516,14 +716,14 @@ Inline::Struct does not understand any C++ features, so constructors
 and member functions are not supported. See L<Inline::Struct> for more
 details.
 
-=head1 <iostream>, Standard Headers, Namespaces, and Portability Solutions
+=head1 <iostream>, Standard Headers, C++ Namespaces, and Portability Solutions
 
-As mentioned earlier, Inline::CPP automatically includes <iostream>, or
-<iostream.h>, depending on the preference of the target compiler.  This
-distinction illustrates a potential problem when trying to write portable code
-in C++.  Legacy C++ (pre-ANSI-Standard) used headers named, for example,
-<iostream.h>.  As legacy C++ didn't support namespaces, these standard
-tools were not segregated into a separate namespace.
+Inline::CPP automatically includes <iostream>, or <iostream.h>, depending on the
+preference of the target compiler.  This distinction illustrates a potential
+problem when trying to write portable code in C++.  Legacy C++
+(pre-ANSI-Standard) used headers named, for example, <iostream.h>.  As legacy
+C++ didn't support namespaces, these standard tools were not segregated into a
+separate namespace.
 
 ANSI Standard C++ changed that.  Headers were renamed without the '.h' suffix,
 and standard tools were placed in the 'C<std>' namespace.  The
@@ -564,12 +764,12 @@ Modern "ANSI Standard C++" compilers would require code like this:
        return 0;
    }
 
-Obviously the first snippet is going to be completely incompabible with the
-second, third or fourth snippets.  This is no problem for a C++ developer who
-knows his target compiler.  But Perl runs just about everywhere.  If similar
-portability (including backward compatibility) is a design goal, Inline::CPP
-helps by providing two C<#define> constants that may be checked to ascertain
-which style of headers are being used.  The constants are:
+The first snippet is going to be completely incompabible with the second, third
+or fourth snippets.  This is no problem for a C++ developer who knows his target
+compiler.  But Perl runs just about everywhere.  If similar portability
+(including backward compatibility) is a design goal, Inline::CPP helps by
+providing two C<#define> constants that may be checked to ascertain which style
+of headers are being used.  The constants are:
 
    __INLINE_CPP_STANDARD_HEADERS
    __INLINE_CPP_NAMESPACE_STD
@@ -612,8 +812,8 @@ But if you do care (maybe you're basing a CPAN module on Inline::CPP), use these
 preprocessor definitions as a tool in building a widely portable solution.
 
 If you wish, you may C<#undef> either of those defs.  The definitions are
-defined before any C<AUTO_INCLUDE>s -- even <iostream>.  Consequently, you may
-even list C<#undef __INLINE_CPP_....> within an C<AUTO_INCLUDE> configuration
+defined before any C<auto_include>s -- even <iostream>.  Consequently, you may
+even list C<#undef __INLINE_CPP_....> within an C<auto_include> configuration
 directive.  I'm not sure why it would be necessary, but could be useful in
 testing.
 
@@ -691,7 +891,7 @@ destructor, meaning you cannot instantiate an C<Object>.
 The C<Airplane> is a fully-bound class which can be created and
 manipulated from Perl.
 
-   use Inline CPP;
+   use Inline 'CPP';
 
    my $plane = new Airplane;
    $plane->print;
@@ -764,7 +964,7 @@ Here's the same function written in C:
 
 Here's a benchmark program that tests which is faster:
 
-    use Inline CPP;
+    use Inline 'CPP';
     my @numbers = map { rand } (1 .. 10000);
     my ($a, $stop);
     $stop = 200;
@@ -800,16 +1000,7 @@ Here's a benchmark program that tests which is faster:
        return avg;
     }
 
-Comparing the relative speed of the Perl versus the C++ solution, the C++
-solution benchmarks about 10x faster.
-
-Mind you, those both include the time taken to initialize the array with
-random numbers. And by varying the number of elements in the array and the
-number of repetitions of the function, we can change this number a lot.
-
-What's the point? Of B<course> C or C++ is faster than Perl. Well..., actually,
-that wasn't really the point; that was an aside. Look at the function
-declaration:
+Look at the function declaration:
 
     double avg(...)
 
@@ -832,15 +1023,15 @@ ellipsis in the code for the compiler to whine about. :)
 
 =head2 Example 4 - Stacks and Queues
 
-Everyone who learns C++ writes a stack and queue class sooner or
-later. I might as well try it from Inline. But why reinvent the wheel?
+Everyone who learns to program with C++ writes a stack and queue class sooner
+or later. I might as well try it from Inline. But why reinvent the wheel?
 Perl has a perfectly good Array type, which can easily implement both
 a Queue and a Stack.
 
 This example implements a Queue and a Stack class, and shows off just
 a few more new features of Inline::CPP: default values to arguments,
 
-    use Inline CPP;
+    use Inline 'CPP';
 
     my $q = new Queue;
     $q->q(50);
@@ -950,36 +1141,37 @@ applied to calling template-generated code as well.
 
 =head1 Minimum Perl version requirements
 
-As L<Inline> currently requires Perl 5.6.0 or later. Since L<Inline::CPP>
-depends on L<Inline>, Perl 5.6.0 is also required for L<Inline::CPP>.  It's
-hard to imagine anyone still using a Perl older than 5.6.0 wanting to
+As L<Inline> currently requires Perl 5.8.1 or later. Since L<Inline::CPP>
+depends on L<Inline>, Perl 5.8.1 is also required for L<Inline::CPP>.  It's
+hard to imagine anyone still using a Perl older than 5.8.1 wanting to
 interface with C++, but if you're in that camp, you'll need to roll back
 L<Inline> and L<Inline::CPP> to older versions through the magic of backpan.
 L<Inline::CPP> version 0.25 was still compatible with Perl 5.005_03.  Review
 the Changes file from the L<Inline> distribution to decide which L<Inline>
-version is appropriate for your pre-5.6.0 Perl.
+version is appropriate for your pre-5.8.1 Perl.
 
 
 =head1 C++11 Standard
 
-Occasionally I'm asked if Inline::CPP is ready for the C++11 standard.  The
-short answer is mostly, to the extent that your compiler is C++11 standard
-compliant.  There are two issues to consider.  First, what is your compiler
+Is Inline::CPP is ready for the C++11 standard?  The short answer to that
+question is "Mostly, to the extent that your compiler is C++11 standard
+compliant."  There are two issues to consider.  First, what is your compiler
 capable of (and how to you enable those capabilities), and second, what does
 Perl need to care about.
 
-Taking the first question first (because it's the easiest): Use the CCFLAGS
+Taking the first question first (because it's the easiest): Use the C<ccflags>
 option shown above to pass the proper flag to your compiler to enable C++11
-features.  Most of what your compiler will support, Inline::CPP will deal with.
+features.  Most of what your compiler will support, C<Inline::CPP> will deal
+with.
 
-You may also need to use the CC flag to specify a newer version of the compiler,
-if you happen to have more than one installed -- one that handles C++11 and one
-that doesn't.
+You also may need to use the C<cc> flag to specify a newer version of the
+compiler, if you happen to have more than one installed -- one that handles
+C++11 and one that doesn't.
 
-Now for the question of what Perl needs to care about:  Inline::CPP doesn't look
-inside of functions or methods.  That code is treated as a black box that passes
-directly through to your compiler.  So inside of your functions and methods,
-feel free to use whatever C++11 features you want.
+Now for the question of what Perl needs to care about:  L<Inline::CPP> doesn't
+look inside of functions or methods.  That code is treated as a black box that
+passes directly through to your compiler.  So inside of your functions and
+methods, feel free to use whatever C++11 features you want.
 
 The critical areas are function headers, class definitions, and code that falls
 outside of functions or classes.  Take Enums for example:
@@ -992,28 +1184,28 @@ of scope to enums:
     enum class Colors { RED, GREEN, BLUE };
 
 How this should bind to Perl becomes even more difficult.  The fact is that
-Inline::CPP won't bind either to Perl.  And you're probably better off with that
-approach than suddenly having $Colors::RED = 0; showing up in your Perl code.
-Do keep in mind, however, the construct is passed directly through to your
-C++ compiler, so feel free to use it within the C++ code.  It just won't leak
-out into your Perl namespaces.
+L<Inline::CPP> won't bind either to Perl.  And you're probably better off with
+that approach than suddenly having $Colors::RED = 0; showing up in your Perl
+code. Do keep in mind, however, the construct is passed directly through to
+your C++ compiler, so feel free to use it within the C++ code.  It just won't
+leak out into your Perl namespaces.
 
-At the moment the most glaring omission from Inline::CPP of valid C++11 syntax
-is the new "late return type" syntax.  C++11 introduced the following legal
-syntax:
+At the moment the most glaring omission from L<Inline::CPP> of valid C++11
+syntax is the new "late return type" syntax.  C++11 introduced the following
+legal syntax:
 
     auto add ( int x, int y ) -> int { return x + y; }
 
 This omission is only going to be a factor for functions that you want to bind
 to Perl.  If you don't need the function to bind to Perl, the syntax is fine;
-Inline::CPP just ignores the function.  It's important to note that the most
-common uses of this syntax involve templates (don't make sense to Inline::CPP
-anyway), and lambdas (which are still fine, because they take place inside
-of functions, so Inline::CPP doesn't see them anyway).  For now, just don't use
-it in the header of functions that need to bind to Perl.  This may get fixed
-in the future.
+L<Inline::CPP> just ignores the function.  It's important to note that the most
+common uses of this syntax involve templates and lambdas.  Templates don't make
+sense to L<Inline::CPP> anyway. And lambdas are still fine, because they take
+place inside of functions, so L<Inline::CPP> doesn't see them anyway.  For now,
+just don't use the late return type syntax in the header of functions that need
+to bind to Perl.  This may get fixed in future revisions to the grammar.
 
-Now for another, C<constexpr>:
+Another issue is C<constexpr>:
 
     constexpr int multiply ( int x, int y ) { return x * y; }
 
@@ -1026,7 +1218,7 @@ to your compiler, so they I<will> work I<within> your C++ code).
 
 And finally, I<Rvalue references>:
 
-Inline::CPP doesn't (yet) understand this:
+L<Inline::CPP> doesn't (yet) understand this:
 
     int x = 100;
      
@@ -1056,17 +1248,21 @@ will "just work", assuming your C++ compiler understands them.
 
 =head1 BUGS AND DEFICIENCIES
 
-There are bound to be other bugs in code this uncivilized.  If you find one,
-please file a bug report.
+There are bound to be bugs in code this uncivilized.  If you find one, please
+file a bug report.  Patches are even better.  Patches accompanied by tests are
+like the holy grail.
 
 When reporting a bug, please do the following:
 
  - If possible, create a brief stand-alone snippet of code that
    demonstrates the issue.
- - Use rt.cpan.org's bug reporting facility:
-   L<https://rt.cpan.org/Public/Dist/Display.html?Name=Inline-CPP>
+ - Use  L<Github Issues|https://github.com/daoswald/Inline-CPP/issues> to file
+   your bug report.
  - Patches are always welcome, as are tests that tickle a newfound bug.
 
+ - Pull requests should avoid touching irrelevant sections of code/POD, and 
+   tests are required before they can be considered for merge.
+
 ...or...
 
  - Put "use Inline REPORTBUG;" at the top of your code, or
@@ -1075,20 +1271,20 @@ When reporting a bug, please do the following:
  - Follow the printed instructions.
 
 B<Get involved!>  Module development is being tracked on a github
-repository: L<https://github.com/daoswald/Inline-CPP>
+repository: L<https://github.com/daoswald/Inline-CPP>.
 
-The master branch will always hold the latest stable CPAN release.
-(Stable releases have version numbers in the following format: 'x.xx'.)
+The master branch should always be buildable and usable.
 
-The dev branch will hold a combination of minor commits and CPAN
-"Developer" releases (these will have a version number formatted as:
-'x.xx_xxx').
+Official releases have version numbers in the following format: 'x.xx', and
+are usually tagged with the CPAN release number.
 
-Other 'topic' branches will come and go as needed.
+Various development branches will hold a combination of minor commits and CPAN
+"Developer" releases (these may have a version number formatted as:
+'x.xx_xxx' to designate a developer-only CPAN release).
 
 Most discussion relating to this module (user or developer) occurs on
-the Inline mailing list, inline.perl.org.  See
-L<http://lists.perl.org/list/inline.html> for details on subscribing.
+the Inline mailing list, inline.perl.org, and in C<#inline> on C<irc.perl.org>.
+See L<http://lists.perl.org/list/inline.html> for details on subscribing.
 
 Here are some things to watch out for:
 
@@ -1146,14 +1342,9 @@ with gracefully, re-throw back to Perl using C<croak>.
 
 =back
 
-Other grammar problems will probably be noticed quickly.  This is Perl, C++, and
+Other grammar problems will probably be discovered.  This is Perl, C++, and
 XS all sealed into one can of worms.  But it can be fun, which is a description
-never applied to raw XS.
-
-There are a number of smoke test FAILS that will only reasonably occur in a
-testing environment.  Most of these are a result of the module being tested
-in parallel.  It is unlikely that in a real-world environment compilation will
-ever take place in parallel.
+never applicable to raw XS.
 
 =head1 SEE ALSO
 
@@ -1191,21 +1382,35 @@ helpful, although its discussion is focused on Inline::C.
 Neil Watkiss <NEILW@cpan.org> was the original author.
 
 David Oswald <DAVIDO@cpan.org> is the current maintainer.
-David Oswald's Inline::CPP githug repo is:
+David Oswald's Inline::CPP GitHub repo is:
 L<https://github.com/daoswald/Inline-CPP>
 
-Ingy döt Net <INGY@cpan.org> is the author of C<Inline>,
-C<Inline::C> and C<Inline::CPR>. He is known in the innermost Inline
-circles as "Batman". ;)
+Ingy döt Net <INGY@cpan.org> is the author of C<Inline>, and C<Inline::C>.
+
+=head1 CONTRIBUTING
+
+Issues are tracked, and may be reported at the distribution's
+L<GitHub issue tracker|https://github.com/daoswald/Inline-CPP/issues>.
+
+Contributors may also fork the repo and issue a pull requests.  Tests
+should accompany pull requests, and effort should be made to minimize the
+scope of any single pull request.  
+
+Pull requests should not add author names. Non-trivial contributions 
+generally warrant attribution in the log maintained in the C<Changes> 
+file, though the decision to do at the discretion of the maintainers.
+
+Please refer to the Artistic 2.0 license, contained in the C<LICENSE> file,
+included with this distribution for further explanation.
 
 =head1 LICENSE AND COPYRIGHT
 
 Copyright (c) 2000 - 2003 Neil Watkiss.
-Copyright (c) 2011 - 2012 David Oswald.
+Copyright (c) 2011 - 2014 David Oswald.
 
-All Rights Reserved. This module is free software. It may be used,
-redistributed and/or modified under the same terms as Perl itself.
+All Rights Reserved. This module is free software, licensed under
+the Artistic license, version 2.0.
 
-See http://www.perl.com/perl/misc/Artistic.html
+See http://www.perlfoundation.org/artistic_license_2_0
 
 =cut
@@ -7,12 +7,12 @@ use Test::More tests => 4;
 
 ok(1);
 
-use Inline CPP => DATA => PREFIX => 'Foo_';
+use Inline CPP => DATA => prefix => 'Foo_';
 
-is(identity( 100 ), 100, "PREFIX resolved." );
-is(identity(identity( 200 )), 200, "PREFIX resolved in nested calls." );
+is(identity( 100 ), 100, "prefix resolved." );
+is(identity(identity( 200 )), 200, "prefix resolved in nested calls." );
 
-is(Foo->new->dummy, "10", "PREFIXed object resolves." );
+is(Foo->new->dummy, "10", "prefixed object resolves." );
 
 done_testing();
 
@@ -8,7 +8,7 @@ require Inline::CPP;
 
 {
     no warnings 'once';  ## no critic (warnings)
-    ok(defined($Inline::CPP::grammar::TYPEMAP_KIND), 'TYPEMAP_KIND defined.');
+    ok(defined($Inline::CPP::Parser::RecDescent::TYPEMAP_KIND), 'TYPEMAP_KIND defined.');
 }
 
 # Test Inline::CPP::register().
@@ -1,166 +1,33 @@
-use Config;
 use strict;
 use warnings;
 use Test::More tests => 2;
-use English qw( -no_match_vars );
-
-my $eucg_found = 1; # True.
-eval { require ExtUtils::CppGuess; };
-if ( $EVAL_ERROR ) {
-    diag( "ExtUtils::CppGuess not installed.  This set of tests and " .
-          "diagnostics\n" .
-          "is more thorough when ExtUtils::CppGuess can be loaded.\n"
-    );
-    $eucg_found = 0; # False.
-}
+#use English qw( -no_match_vars );
+use FindBin;
+use lib "$FindBin::Bin/../inc";
 
+use ILCPPConfig::CompilerGuess    ();
+use ILCPPConfig::OldCompilerGuess ();
 
-my $old_makefile_config = ilcpp_results();
-my $eu_cppguess_config  = eucppg_results();
+my( $old_compiler, $old_libs )
+  = ILCPPConfig::OldCompilerGuess::guess_compiler();
+my( $compiler,     $libs     )
+  = ILCPPConfig::CompilerGuess::guess_compiler();
 
 TODO: {
-    local $TODO = "Probably will fail: These tests document differences in " .
-                  "config detection methods.";
-        SKIP: {
-            skip
-                "ExtUtils::CppGuess required to compare detection methods.", 2
-                    unless $eucg_found;
-            is(
-                $eu_cppguess_config->{compiler},
-                $old_makefile_config->{compiler},
-                "Compiler / flags for EU::CG versus Makefile.PL guess method."
-            );
-            is(
-                $eu_cppguess_config->{libraries},
-                $old_makefile_config->{libraries},
-                "Libraries for EU::CG versus Makefile.PL guess method."
-            );
-        };
-};
-
-if( $eucg_found ) {
-    diag "\nCompiler guesses:\n" .
-         "\tEU::CppGuess:    [$eu_cppguess_config->{compiler}],\n" .
-         "\tMakefile.PL: [$old_makefile_config->{compiler}].\n";
-
-    diag "Linker guesses:\n"     .
-         "\tEU::CppGuess:    [$eu_cppguess_config->{libraries}],\n" .
-         "\tMakefile.PL: [$old_makefile_config->{libraries}].";
+  local $TODO = "Probably will fail: These tests document differences in " .
+                "config detection methods.";
+  is( $compiler, $old_compiler,
+    "Compiler / flags for EU::CG versus Makefile.PL guess method." );
+  is( $libs, $old_libs,
+    "Libraries for EU::CG versus Makefile.PL guess method." );
 }
-else {
-    diag "\nCompiler guess:\n" .
-         "\tMakefile.PL approach: [$old_makefile_config->{compiler}].\n";
-    diag "\nLinker guess:\n"   .
-         "\tMakefile.PL approach: [$old_makefile_config->{libraries}].\n";
-}
-
-done_testing();
 
+diag "\nCompiler guesses:\n" .
+     "\tEU::CppGuess:    [$compiler],\n" .
+     "\tOld Makefile.PL: [$old_compiler].\n";
 
-# Results obtained from Inline::CPP's old Makefile.PL logic.
-sub ilcpp_results {
-    my $cc_guess;
-    my $libs_guess;
-    # darwin: Compiler g++, Libs: -Llibstdc++, -lstdc++.
-    if ($Config{osname} eq 'darwin'){
-        diag( "Detected darwin\n" );
-        my $stdlib_query =
-            'find /usr/lib/gcc -name "libstdc++*" | grep $( uname -p )';
-        my $stdcpp =
-            `$stdlib_query`; + $stdcpp =~ s/^(.*)\/[^\/]+$/$1/;
-        $cc_guess   = 'g++';
-        $libs_guess = "-L$stdcpp -lstdc++";
-    }
-    elsif ( # Basic default - g++ (Strawberry uses this). Libs: -lstdc++.
-        $Config{osname} ne 'darwin' and
-        $Config{gccversion} and
-        $Config{cc} =~ m#\bgcc\b[^/]*$#
-    ) {
-        diag ( "Detected basic defaults (Strawberry, etc.).\n" );
-        ($cc_guess  = $Config{cc}) =~ s[\bgcc\b([^/]*)$(?:)][g\+\+$1];
-        $libs_guess = '-lstdc++';
-    }
-    elsif ($Config{osname} =~ m/^MSWin/) { # Windows: cl -TP -EHsc
-        diag( "Detected MSWin (probably ActiveState).\n" );
-        $cc_guess   = 'cl -TP -EHsc';      # MSVCIRT.LIB
-        $libs_guess = 'MSVCIRT.LIB';
-    }
-    elsif ($Config{osname} eq 'linux') {    # Linux: g++ with -lstdc++
-        diag( "Detected Linux." );
-        $cc_guess   = 'g++';
-        $libs_guess = '-lstdc++';
-    }
-    elsif( $Config{osname} eq 'netbsd' || $Config{osname} eq 'dragonfly' ) {
-        # netbsd: g++.  Added dragonfly to 0.38_004.
-        diag( "Detected netbsd or dragonfly." );
-        $cc_guess   = 'g++';                # -lstdc++ -lgcc_s
-        $libs_guess = '-lstdc++ -lgcc_s';
-    }
-    elsif ($Config{osname} eq 'cygwin') {   # cygwin: g++
-        diag( "Detected cygwin.\n" );
-        $cc_guess   = 'g++';                # lstdc++
-        $libs_guess = '-lstdc++';
-    }
-    elsif ($Config{osname} eq 'solaris' or $Config{osname} eq 'SunOS') {
-        diag( "Detected solaris or SunOS.\n" );
-        if (                # Solaris/SunOS with gcc: g++ with libs -lstdc++
-            $Config{cc} eq 'gcc' ||
-            ( exists( $Config{gccversion} ) && $Config{gccversion} > 0 )
-        ) {
-            diag( "Solaris/SunOS with GNU compiler.\n" );
-            $cc_guess   = 'g++';
-            $libs_guess = '-lstdc++';
-        }
-        else {                  # Solaris/SunOS with CC: CC with libs -lCrun
-            diag( "Solaris/SunOS with CC compiler.\n" );
-            $cc_guess   = 'CC'; # Seems wrong.
-            $libs_guess ='-lCrun';
-        }
-    }
-    elsif ($Config{osname} eq 'mirbsd') {   # mirbsd: g++
-        diag( "Detected mirbsd.\n" );
-        my $stdlib_query =                  # -Llibstdc++ -lstdc++ -lc -lgcc_s
-            'find /usr/lib/gcc -name "libstdc++*" | grep $( uname -p ) | head -1';
-        my $stdcpp =
-            `$stdlib_query`; + $stdcpp =~ s/^(.*)\/[^\/]+$/$1/;
-        $cc_guess   = 'g++';
-        $libs_guess = "-L$stdcpp -lstdc++ -lc -lgcc_s";
-    }
-    # Sane defaults for other (probably unix-like) operating systems
-    else {                                  # g++
-        diag( "Fell through to final default: g++ with -lstdc++\n" );
-        $cc_guess   = 'g++';                # -lstdc++
-        $libs_guess = '-lstdc++';
-    }
+diag "Linker guesses:\n"     .
+     "\tEU::CppGuess:    [$libs],\n" .
+     "\tOld Makefile.PL: [$old_libs].";
 
-    my $cpp_compiler = $cc_guess;
-    my $libs         = $libs_guess;
-    return { compiler => $cpp_compiler, libraries => $libs };
-}
-
-
-# Results obtained by new ExtUtils::CppGuess dependency.
-sub eucppg_results {
-    my( $cc_guess, $libs_guess    );
-    my( $guesser,  %configuration );
-
-    eval {  # ExtUtils::CppGuess may not be available.
-        $guesser = ExtUtils::CppGuess->new();
-        %configuration = $guesser->module_build_options();
-
-        if( $guesser->is_gcc() ) {
-            $cc_guess = 'g++';
-        }
-        elsif ( $guesser->is_msvc() )
-        {
-            $cc_guess = 'cl';
-        }
-    };
-    return if $EVAL_ERROR; # Skip if EU::CG isn't loaded.
-    $cc_guess .= $configuration{extra_compiler_flags};
-    $libs_guess = $configuration{extra_linker_flags};
-
-    my $cpp_compiler = $cc_guess;
-    my $libs         = $libs_guess;
-    return { compiler => $cpp_compiler, libraries => $libs };
-}
+done_testing();
@@ -11,7 +11,7 @@ BEGIN {
     use Test::More;
     if ( $ENV{RELEASE_TESTING} ) {
         # Set up release testing environment.
-        use Inline CPP => Config => REWRITE_CONFIG_FILE => 1;
+        use Inline CPP => config => rewrite_config_file => 1;
     }
     else {
         my $msg =
@@ -9,7 +9,7 @@ use Inline CPP => 'DATA';
 
 # We're verifying that libs are getting wrapped in an array ref as required.
 
-use Inline CPP => Config => LIBS => '-lstdc++';
+use Inline CPP => config => libs => '-lstdc++';
 
 is( add( 1, 1, 1 ), 3, 'LIBS directive is OK.' );
 
@@ -19,19 +19,19 @@ BEGIN {
 };
 
 require Inline::CPP;
-require Inline::CPP::grammar;
+require Inline::CPP::Parser::RecDescent;
 require Inline::CPP::Config;
 
 use FindBin;
 
 # Eval version numbers to eliminate underscore ambiguity in dev dists.
 my $TARGET_VERSION = eval $Inline::CPP::VERSION;
-my $grammar_version = eval $Inline::CPP::grammar::VERSION;
+my $grammar_version = eval $Inline::CPP::Parser::RecDescent::VERSION;
 my $config_version  = eval $Inline::CPP::Config::VERSION;
 
 
 is( $grammar_version, $TARGET_VERSION, 
-    'Inline::CPP and Inline::CPP::grammar version numbers match.' );
+    'Inline::CPP and Inline::CPP::Parser::RecDescent version numbers match.' );
 
 
 
@@ -40,16 +40,14 @@ is( $config_version, $TARGET_VERSION,
 
 
 
-
+# Makefile.PL's dist version, for META_MERGE.
 my $makefile_pl = slurp_file( '../Makefile.PL' );
-ok( $makefile_pl =~ m/Inline::CPP'?\s*=>\s*\{[^}]*version\s*=>\s*'?([\d._]+)/,
-    'Found an Inline::CPP version number in META_MERGE data from Makefile.PL' );
-
+ok( $makefile_pl =~ m/^\s*my\s*\$DIST_VERSION\s*=\s*'([\d._]+)'\s*;/m,
+    'Found a distribution version number in Makefile.PL' );
 my $makefile_pl_version = eval $1;
 is( $makefile_pl_version, $TARGET_VERSION, 
     'Makefile.PL version matches target.'  );
 
-
 my $changes = slurp_file( '../Changes' );
 ok( $changes =~ m/^([\d._]+)\s/m,
     'Found Inline::CPP version number in Changes' );
@@ -0,0 +1,18 @@
+use strict;
+use warnings;
+use Test::More tests => 1;
+
+# Case insensitive Inline::CPP-specific config options verified in tests for
+# namespace keyword.  Here, we will test pass through of an insensitive Inline
+# option.  See t/namespace/06inherit.t for testing of insensitive Inline::CPP
+# handled options.
+
+use Inline CPP => config => prefix => 'test_';
+
+use Inline CPP => <<'EOCPP';
+
+  int test_add ( int a, int b ) { return a + b; }
+
+EOCPP
+
+is add(2,2), 4, 'Case insensitive Inline::C-handled config option: prefix.';
@@ -0,0 +1,49 @@
+package main; ## no critic (package)
+
+use strict;
+use warnings;
+
+use Inline CPP => config =>
+  namespace => '',
+  classes   => { 'Fuu' => 'MyFuu', 'Bur' => 'MyBur'};
+
+use Inline CPP => <<'EOCPP';
+
+  class Fuu {
+    private:
+      int a;
+    public:
+      Fuu() :a(10) {}
+      int fetch () { return a; }
+  };
+EOCPP
+
+use Inline CPP => <<'EOCPP';
+
+  class Bur {
+    private:
+      int a;
+    public:
+      Bur() :a(20) {}
+      int fetch () { return a; }
+  };
+EOCPP
+
+package main;
+use Test::More;
+
+can_ok 'MyFuu', 'new';
+can_ok 'main::MyFuu', 'new';
+can_ok 'MyFuu', 'fetch';
+can_ok 'main::MyFuu', 'fetch';
+my $f = new_ok 'MyFuu';
+is ref($f), 'MyFuu', 'Our "Fuu" is a "MyFuu"';
+
+can_ok 'MyBur', 'new';
+my $fb = MyBur->new;
+is ref($fb), 'MyBur', 'Our "Bur" is a "MyBur"';
+
+is $f->fetch, 10, 'Proper object method association from MyFuu.';
+is $fb->fetch, 20, 'Proper object method association from MyBur.';
+
+done_testing();
@@ -0,0 +1,48 @@
+package main; ## no critic (package)
+
+use strict;
+use warnings;
+
+use Inline CPP => config =>
+  namespace => 'main',
+  classes   => { 'Fuu' => 'MyFuu', 'Bur' => 'MyBur'};
+
+use Inline CPP => <<'EOCPP';
+
+  class Fuu {
+    private:
+      int a;
+    public:
+      Fuu() :a(10) {}
+      int fetch () { return a; }
+  };
+EOCPP
+
+use Inline CPP => <<'EOCPP';
+
+  class Bur {
+    private:
+      int a;
+    public:
+      Bur() :a(20) {}
+      int fetch () { return a; }
+  };
+EOCPP
+
+package main;
+use Test::More;
+
+can_ok 'MyFuu', 'new';
+can_ok 'main::MyFuu', 'new';
+my $f = new_ok 'MyFuu';
+is ref($f), 'MyFuu', 'Our "Fuu" is a "MyFuu"';
+
+can_ok 'MyBur', 'new';
+can_ok 'main::MyBur', 'new';
+my $fb = new_ok 'MyBur';
+is ref($fb), 'MyBur', 'Our "Bur" is a "MyBur"';
+
+is $f->fetch, 10, 'Proper object method association from main::MyFuu.';
+is $fb->fetch, 20, 'Proper object method association from main::MyBur.';
+
+done_testing();
@@ -0,0 +1,46 @@
+package Ball; ## no critic (package)
+
+use strict;
+use warnings;
+
+use Inline CPP => config =>
+  namespace => 'Buz',
+  classes   => { 'Fuu' => 'MyFuu', 'Bur' => 'MyBur'};
+
+use Inline CPP => <<'EOCPP';
+
+  class Fuu {
+    private:
+      int a;
+    public:
+      Fuu() :a(10) {}
+      int fetch () { return a; }
+  };
+EOCPP
+
+use Inline CPP => <<'EOCPP';
+
+  class Bur {
+    private:
+      int a;
+    public:
+      Bur() :a(20) {}
+      int fetch () { return a; }
+  };
+EOCPP
+
+package main;
+use Test::More;
+
+can_ok 'Buz::MyFuu', 'new';
+my $f = new_ok 'Buz::MyFuu';
+is ref($f), 'Buz::MyFuu', 'Our "Fuu" is a "Buz::MyFuu"';
+
+can_ok 'Buz::MyBur', 'new';
+my $fb = new_ok 'Buz::MyBur';
+is ref($fb), 'Buz::MyBur', 'Our "Bur" is a "Buz::MyBur"';
+
+is $f->fetch, 10, 'Proper object method association from Buz::MyFuu.';
+is $fb->fetch, 20, 'Proper object method association from Buz::MyBur.';
+
+done_testing();
@@ -0,0 +1,35 @@
+package Bur; ## no critic (package)
+
+use strict;
+use warnings;
+
+use Inline CPP => config => namespace => '' => classes => { 'Fuu' => 'MyFuu'};
+
+use Inline CPP => <<'EOCPP';
+
+class Fuu {
+  private:
+    int a;
+  public:
+    Fuu() :a(10) {}
+    int fetch () { return a; }
+};
+EOCPP
+
+package Buz;
+
+use Test::More;
+
+is __PACKAGE__, 'Buz', "Instantiating from package Buz.";
+
+can_ok 'MyFuu', 'new';
+can_ok 'main::MyFuu', 'new';
+can_ok 'MyFuu', 'fetch';
+can_ok 'main::MyFuu', 'fetch';
+my $f = new_ok 'MyFuu';
+is ref($f), 'MyFuu', 'Our "Fuu" is a "MyFuu"';
+is $f->fetch, 10, 'Proper object method association from MyFuu.';
+
+done_testing();
+
+package main;
@@ -0,0 +1,78 @@
+package Fuu; ## no critic (package)
+
+## no critic (eval)
+
+use Test::More;
+
+use strict;
+use warnings;
+
+my $res0 = eval q[
+
+  use Inline CPP => config => namespace => 'BurBat' => classes => 'MyFuu';
+
+  use Inline CPP => <<'EOCPP';
+    class Fuu {
+      private:
+        int a;
+      public:
+        Fuu() :a(10) {}
+        int fetch () { return a; }
+    };
+
+EOCPP
+
+  1;
+
+]; # End of eval.
+
+ok !$res0, 'Invalid classes croaks.';
+like $@,
+  qr/is not a valid code reference or hash reference of class mappings\./,
+  'Correct message.';
+
+my $res1 = eval q[
+
+  use Inline CPP => config =>
+    namespace => 'BurBat',
+    classes   => { '!@#$' => 'MyFuu'};
+    
+  use Inline CPP => <<'EOCPP';
+    class Fuu {
+      private:
+        int a;
+      public:
+        Fuu() :a(10) {}
+        int fetch () { return a; }
+    };
+EOCPP
+
+  1;
+
+]; # End of eval.
+
+ok !$res1, 'Invalid C++ CLASS croaks.';
+like $@, qr/is not a supported C\+\+ class\./, 'Correct message.';
+
+my $res2 = eval q[
+  use Inline CPP => config =>
+    namespace => 'BurBat',
+    classes   => { 'Fuu' => '!@#$'};
+    
+  use Inline CPP => <<'EOCPP';
+    class Fuu {
+      private:
+        int a;
+      public:
+        Fuu() :a(10) {}
+        int fetch () { return a; }
+    };
+EOCPP
+  1;
+
+]; # End of eval.
+
+ok !$res2, 'Invalid Perl CLASS croaks.';
+like $@, qr/is not a supported Perl class\./, 'Correct message.';
+
+done_testing();
@@ -0,0 +1,48 @@
+## no critic (package)
+
+package Fuu;
+
+use strict;
+use warnings;
+
+use Inline CPP => config => namespace => q{} => classes => { 'Fuu' => 'MyFuu'};
+
+use Inline CPP => <<'EOCPP';
+
+  class Fuu {
+    private:
+      int a;
+    public:
+      Fuu() :a(10) {}
+      int fetch () { return a; }
+  };
+
+EOCPP
+
+1;
+
+package Bur;
+
+our @ISA = ('MyFuu');
+sub myfetch { my $self = shift; $self->fetch(); }
+
+
+package main;
+use Test::More;
+
+can_ok 'MyFuu', 'new';
+my $f = new_ok 'MyFuu';
+is ref($f), 'MyFuu', 'Our "Fuu" is a "MyFuu".';
+is $f->fetch, '10', 'Accessor properly associated.';
+
+
+can_ok 'Bur', 'new';
+my $bf = new_ok 'Bur';
+is ref($bf), 'Bur', 'Our "Bur" is a "Bur"';
+is $bf->fetch, 10, 
+   'Inheritance and object method association from Bur.';
+is $bf->myfetch, 10, 'Method resolution for subclass.';
+
+
+
+done_testing();
@@ -0,0 +1,90 @@
+## no critic (eval)
+package Ball;    ## no critic (package)
+
+use strict;
+use warnings;
+use File::Temp 'tempdir';
+
+my $tdir = tempdir( CLEANUP => 1 );
+
+my $foo__bar__myclass = <<'EOCPP';
+
+  class Foo__Bar__MyClass {
+    private:
+      int a;
+    public:
+      Foo__Bar__MyClass() :a(10) {}
+      int fetch () { return a; }
+  };
+
+EOCPP
+
+
+my $foo__qux__myclass = <<"EOCPP";
+
+#include "$tdir/Foo__Bar__MyClass.c"
+
+  class Foo__Qux__MyClass {
+    private:
+      int a;
+    public:
+      Foo__Qux__MyClass() :a(20) {}
+      int fetch () { return a; }
+      int other_fetch () { Foo__Bar__MyClass mybar; return mybar.fetch(); }
+  };
+
+EOCPP
+
+
+open my $fha, '>', "$tdir/Foo__Bar__MyClass.c"
+  or die "Can't open file '$tdir/Foo__Bar__MyClass.c' for writing $!";
+print $fha $foo__bar__myclass;
+close $fha;
+
+open my $fhb, '>', "$tdir/Foo__Qux__MyClass.c"
+  or die "Can't open file '$tdir/Foo__Qux__MyClass.c' for writing $!";
+print $fhb $foo__qux__myclass;
+close $fhb;
+
+eval qq[
+  use Inline CPP =>
+    "$tdir/Foo__Qux__MyClass.c", 
+    filters   => 'Preprocess', 
+    namespace => 'Foo', 
+    classes   => {
+      'Foo__Bar__MyClass' => 'Bar::MyClass',
+      'Foo__Qux__MyClass' => 'Qux::MyClass'
+    };
+];
+
+unlink "$tdir/Foo__Bar__MyClass.c", "$tdir/Foo__Qux__MyClass.c";
+
+package main;
+
+use Test::More;
+
+plan skip_all => "Inline::Filters required for conflict avoidance testing."
+  unless eval q{ require Inline::Filters; 1; };
+
+
+
+can_ok 'Foo::Bar::MyClass', 'new';
+
+my $fb = new_ok 'Foo::Bar::MyClass';
+
+is ref($fb), 'Foo::Bar::MyClass', 'Our "MyClass" is a "Foo::Bar::MyClass"';
+
+can_ok 'Foo::Qux::MyClass', 'new';
+
+my $fq = new_ok 'Foo::Qux::MyClass';
+
+is ref($fq), 'Foo::Qux::MyClass', 'Our "MyClass" is a "Foo::Qux::MyClass"';
+
+is $fb->fetch,  10, 'Proper object method association from Foo::Bar::MyClass.';
+
+is $fq->fetch, 20, 'Proper object method association from Foo::Qux::MyClass.';
+
+is $fq->other_fetch, 10,
+  'Proper cross-class method association from Foo::Qux::MyClass.';
+
+done_testing();
@@ -0,0 +1,56 @@
+package Ball;    ## no critic (package)
+
+use strict;
+use warnings;
+
+use Inline CPP => config => classes => sub { join('::', split('__', shift)); };
+
+use Inline CPP => <<'EOCPP';
+  class MyClass {
+    private:
+      int a;  
+    public:
+      MyClass() :a(5) {}
+      int fetch () { return a; }
+  };
+  class Foo__Bar__MyClass {
+    private:
+      int a;
+    public:
+      Foo__Bar__MyClass() :a(10) {}
+      int fetch () { return a; }
+  };
+  class Foo__Qux__MyClass {
+    private:
+      int a;
+    public:
+      Foo__Qux__MyClass() :a(20) {}
+      int fetch () { return a; }
+      int other_fetch () { Foo__Bar__MyClass mybar; return mybar.fetch(); }
+  };
+EOCPP
+
+package main;
+use Test::More;
+
+can_ok 'MyClass', 'new';
+my $m = new_ok 'MyClass';
+is ref($m), 'MyClass', 'Our "MyClass" is a "MyClass"';
+
+can_ok 'Foo::Bar::MyClass', 'new';
+my $fb = new_ok 'Foo::Bar::MyClass';
+is ref($fb), 'Foo::Bar::MyClass',
+  'Our "Foo__Bar__MyClass" is a "Foo::Bar::MyClass"';
+
+can_ok 'Foo::Qux::MyClass', 'new';
+my $fq = new_ok 'Foo::Qux::MyClass';
+is ref($fq), 'Foo::Qux::MyClass',
+  'Our "Foo__Qux__MyClass" is a "Foo::Qux::MyClass"';
+
+is $m->fetch,  5, 'Proper object method association from MyClass.';
+is $fb->fetch,  10, 'Proper object method association from Foo::Bar::MyClass.';
+is $fq->fetch, 20, 'Proper object method association from Foo::Qux::MyClass.';
+is $fq->other_fetch, 10,
+  'Proper cross-class method association from Foo::Qux::MyClass.';
+
+done_testing();
@@ -0,0 +1,28 @@
+# mix procedural subroutine and object-oriented method
+use strict;
+use warnings;
+use Test::More tests => 5;
+
+use Inline (CPP => 'DATA', classes => sub { join('::', split('__', shift)); } );  # AUTOMATIC
+#use Inline (CPP => 'DATA', classes => { 'Inline__Test__Inline_CPP_Debug' => 'Inline::Test::Inline_CPP_Debug'} );  # MANUAL
+
+can_ok 'Inline::Test::Inline_CPP_Debug', 'new';
+my $my_object = new_ok 'Inline::Test::Inline_CPP_Debug';
+is ref($my_object), 'Inline::Test::Inline_CPP_Debug', 'Our "Inline__Test__Inline_CPP_Debug" is a "Inline::Test::Inline_CPP_Debug"';
+is $my_object->my_method(), 'RETVAL FROM my_subroutine()', 'Proper object method association from Inline::Test::Inline_CPP_Debug.';
+is my_subroutine(), 'RETVAL FROM my_subroutine()', 'Proper subroutine association.';
+
+done_testing();
+
+__DATA__
+__CPP__
+
+SV* my_subroutine() { return(newSVpv("RETVAL FROM my_subroutine()", 27)); }
+
+class Inline__Test__Inline_CPP_Debug
+{
+public:
+    SV* my_method() { return my_subroutine(); }
+    Inline__Test__Inline_CPP_Debug() {}
+    ~Inline__Test__Inline_CPP_Debug() {}
+};
@@ -0,0 +1,74 @@
+use strict;
+use warnings;
+use Test::More tests => 28;
+
+use Inline (CPP => 'DATA', classes => sub { join('::', split('__', shift)); } );
+
+can_ok 'Inline::Test::Parent', 'new';
+my $parent_object = new_ok 'Inline::Test::Parent';
+is ref($parent_object), 'Inline::Test::Parent', 'Our "Inline__Test__Parent" is a "Inline::Test::Parent"';
+can_ok 'Inline::Test::Parent', 'parent_method';
+is $parent_object->parent_method(), 'RETVAL FROM parent_method()', 'Proper object method association from Inline::Test::Parent.';
+
+can_ok 'Inline::Test::Child1', 'new';
+my $child1_object = new_ok 'Inline::Test::Child1';
+is ref($child1_object), 'Inline::Test::Child1', 'Our "Inline__Test__Child1" is a "Inline::Test::Child1"';
+can_ok 'Inline::Test::Child1', 'child1_method';
+is $child1_object->child1_method(), 'RETVAL FROM child1_method()', 'Proper object method association from Inline::Test::Child1.';
+can_ok 'Inline::Test::Child1', 'parent_method';
+is $child1_object->parent_method(), 'RETVAL FROM parent_method()', 'Proper Inline::Test::Child1 object method inheritance from Inline::Test::Parent.';
+
+can_ok 'Inline::Test::Child2', 'new';
+my $child2_object = new_ok 'Inline::Test::Child2';
+is ref($child2_object), 'Inline::Test::Child2', 'Our "Inline__Test__Child2" is a "Inline::Test::Child2"';
+can_ok 'Inline::Test::Child2', 'child2_method';
+is $child2_object->child2_method(), 'RETVAL FROM child2_method()', 'Proper object method association from Inline::Test::Child2.';
+can_ok 'Inline::Test::Child2', 'parent_method';
+is $child2_object->parent_method(), 'RETVAL FROM parent_method()', 'Proper Inline::Test::Child2 object method inheritance from Inline::Test::Parent.';
+
+can_ok 'Inline::Test::Grandchild', 'new';
+my $grandchild_object = new_ok 'Inline::Test::Grandchild';
+is ref($grandchild_object), 'Inline::Test::Grandchild', 'Our "Inline__Test__Grandchild" is a "Inline::Test::Grandchild"';
+can_ok 'Inline::Test::Grandchild', 'grandchild_method';
+is $grandchild_object->grandchild_method(), 'RETVAL FROM grandchild_method()', 'Proper object method association from Inline::Test::Grandchild.';
+can_ok 'Inline::Test::Grandchild', 'child1_method';
+is $grandchild_object->child1_method(), 'RETVAL FROM child1_method()', 'Proper Inline::Test::Grandchild object method inheritance from Inline::Test::Child1.';
+can_ok 'Inline::Test::Grandchild', 'parent_method';
+is $grandchild_object->parent_method(), 'RETVAL FROM parent_method()', 'Proper Inline::Test::Grandchild object method inheritance from Inline::Test::Parent.';
+
+done_testing();
+
+__DATA__
+__CPP__
+
+class Inline__Test__Parent
+{
+public:
+    SV* parent_method() { return(newSVpv("RETVAL FROM parent_method()", 27)); }
+    Inline__Test__Parent() {}
+    ~Inline__Test__Parent() {}
+};
+
+class Inline__Test__Child1: public Inline__Test__Parent
+{
+public:
+    SV* child1_method() { return(newSVpv("RETVAL FROM child1_method()", 27)); }
+    Inline__Test__Child1() {}
+    ~Inline__Test__Child1() {}
+};
+
+class Inline__Test__Child2: public Inline__Test__Parent
+{
+public:
+    SV* child2_method() { return(newSVpv("RETVAL FROM child2_method()", 27)); }
+    Inline__Test__Child2() {}
+    ~Inline__Test__Child2() {}
+};
+
+class Inline__Test__Grandchild: public Inline__Test__Child1
+{
+public:
+    SV* grandchild_method() { return(newSVpv("RETVAL FROM grandchild_method()", 31)); }
+    Inline__Test__Grandchild() {}
+    ~Inline__Test__Grandchild() {}
+};
@@ -0,0 +1,31 @@
+use strict;
+use warnings;
+use Test::More;
+
+# Satisfy CPANTS, even though all functions are internal.
+
+eval "use Test::Pod::Coverage 1.00";  ## no critic (eval)
+plan skip_all => "Test::Pod::Coverage 1.00 required for testing POD coverage"
+    if $@;
+
+
+# Test for Inline::grammar.
+
+# There really aren't any functions explicitly called by the user. Everything
+# is for internal use, and doesn't require POD documentation.
+my $trustme = {
+    trustme => [
+        qr/(?:
+              ^_
+            | grammar       # Inline::CPP::grammar internal functions.
+            | handle
+            | strip
+            | typemap
+        )/x
+    ]
+};
+
+pod_coverage_ok( 'Inline::CPP::Grammar', $trustme );
+
+
+done_testing();
@@ -0,0 +1,56 @@
+use strict;
+use warnings;
+use Test::More;
+
+# Testing proper handling of inherited object methods.
+
+use Inline CPP => <<'END';
+
+class Foo {
+ public:
+   Foo() {
+    secret=0;
+   }
+
+   ~Foo() { }
+
+   int get_secret() { return secret; }
+   void set_secret(int s) { secret = s; }
+
+ protected:
+   int secret;
+};
+
+class Bar : public Foo {
+ public:
+   Bar(int s) { secret = s; }
+   ~Bar() {  }
+
+   void set_secret(int s) { secret = s * 2; }
+};
+
+END
+
+# If it works, it will print this. Otherwise it won't.
+ok(1);
+
+# Test Foo.
+my $o = new_ok( 'Foo' );
+is( $o->get_secret(), 0, "Foo: Object getter." );
+$o->set_secret(539);
+is( $o->get_secret(), 539, "Foo: Object setter." );
+
+
+# Test Bar.
+
+
+my $p = new_ok( 'Bar', [ 11 ] );
+is(
+    $p->get_secret(), 11,
+    "Bar: Overrides constructor, inherits accessor from Foo."
+);
+
+$p->set_secret( 21 );
+is( $p->get_secret(), 42, "Bar: Overrides setter." );
+
+done_testing();
@@ -0,0 +1,28 @@
+use strict;
+use warnings;
+use Test::More;
+
+# Testing proper handling of class scopes.
+
+use Inline CPP => <<'END';
+
+class Foo {
+   void priv(int a) { q = a; }
+   int q;
+public:
+   Foo() {}
+   ~Foo() {}
+   void zippo(int quack) { printf("Hello, world!\n"); }
+};
+
+END
+
+my $obj = new_ok( 'Foo' );
+
+can_ok( $obj, 'zippo' );
+
+is( $obj->zippo( 10 ), undef, "Execute void public member function." );
+
+ok( ! $obj->can( 'priv' ), "Can't access private member function." );
+
+done_testing();
@@ -0,0 +1,53 @@
+use strict;
+use warnings;
+use Test::More;
+
+# Testing proper handling of functions defined inline within a class.
+
+use Inline 'CPP';
+
+my $obj = new_ok( 'Color' );
+
+
+$obj->set_color(15);
+
+is(
+    $obj->get_color, 15,
+    "Member function defined inline within class."
+);
+
+done_testing();
+
+__END__
+__CPP__
+void prn() {
+    printf("prn() called!\n");
+}
+
+class Color {
+ public:
+  Color()
+  {
+    printf("new Color object created...\n");
+  }
+
+  ~Color()
+  {
+    printf("Color object being destroyed...\n");
+  }
+
+  int get_color()
+  {
+    printf("Color::get_color called. Returning %i\n", color);
+    return color;
+  }
+
+  void set_color(int a)
+  {
+    printf("Color::set_color(%i)\n", a);
+    color = a;
+  }
+
+ private:
+  int color;
+};
@@ -0,0 +1,21 @@
+use strict;
+use warnings;
+use Test::More;
+
+use Inline CPP => <<'END';
+class Foo {
+  public:
+    Foo()  {}
+    ~Foo() {}
+    const char *data() { return "Hello dolly!\n"; }
+};
+
+END
+
+
+is(
+    Foo->new->data, "Hello dolly!\n",
+    "Instantiate object and invoke member function returning a const char*"
+);
+
+done_testing();
@@ -0,0 +1,22 @@
+use strict;
+use warnings;
+use Test::More;
+
+
+use Inline CPP => <<'END';
+class Foo {
+  public:
+    Foo() { }
+    ~Foo() { }
+
+    virtual const char *get_data_ro() { return "Hello Sally!\n"; }
+};
+END
+
+
+is(
+    Foo->new->get_data_ro, "Hello Sally!\n",
+    "Define and invoke virtual function."
+);
+
+done_testing();
@@ -0,0 +1,34 @@
+use strict;
+use warnings;
+use Test::More;
+
+use Inline CPP => <<'END';
+
+int foo(int a=10) { return a; }
+double pi() { return 3.1415926; }
+
+class Freak {
+  public:
+    Freak() {}
+    ~Freak() {}
+
+    int foo(int a=10, int b=13+4, double c=pi()) { return (a+b)/c; }
+    int foo2(int a, int b=15) { return a^b; }
+    int foo3(int a, int b, int c=0, int d=-5) { return 2*a - b + 2*c - d; }
+    int foo4(int a, char *b="hello") { return a + strlen(b); }
+};
+
+END
+
+
+is(
+    Freak->new->foo, 8,
+    "Instantiate object and call member with default arguments."
+);
+
+is(
+    foo, 10,
+    "Call simple function with default arguments."
+);
+
+done_testing();
@@ -0,0 +1,19 @@
+use strict;
+use warnings;
+use Test::More;
+
+use Inline CPP => <<'END';
+class Foo {
+  public:
+    Foo() {}
+    ~Foo() {}
+    static char *get_string() { return "Hello, world!\n"; }
+};
+END
+
+is(
+    Foo->get_string, "Hello, world!\n",
+    "Static member function becomes a class member function."
+);
+
+done_testing();
@@ -0,0 +1,24 @@
+use strict;
+use warnings;
+use Test::More;
+
+use Inline CPP => <<'END';
+
+class Foo {
+  public:
+    Foo(int, int);
+};
+
+Foo::Foo(int a, int b) {
+}
+
+int add(int, int);
+int add(int a, int b) { return a + b; }
+
+END
+
+new_ok( 'Foo', [ 10, 11 ] );
+
+is( add( 2, 3 ), 5, "Simple function." );
+
+done_testing();
@@ -0,0 +1,53 @@
+use strict;
+use warnings;
+use Test::More;
+
+# Test pure virtual functions (abstract classes).
+use Inline CPP => <<'END';
+
+class Abstract {
+  public:
+        virtual char *text() = 0;
+        virtual int greet(char *name) {
+        printf("# Hello, %s.\n", name);
+        return 17;
+    }
+};
+
+class Impl : public Abstract {
+  public:
+    Impl() {}
+    ~Impl() {}
+    virtual char *text() { return "Hello from Impl!"; }
+};
+
+
+END
+
+my $o = new_ok( 'Impl' );
+is(
+    $o->text, 'Hello from Impl!',
+    "Resolved virtual member function from self."
+);
+
+is(
+    $o->greet('Neil'), 17,
+    "Inherited member function from parent."
+);
+
+my $p;
+eval{ $p = Abstract->new(); };
+if( $@ ) {
+    like(
+        $@,
+        qr/^Can't locate object method "new" via package "([^:]+::)*Abstract"/,
+        "Classes with pure virtual functions cannot be instantiated."
+    );
+} else {
+    not_ok(
+        "Abstract class with pure virtual function should not instantiate."
+    );
+}
+
+
+done_testing();
@@ -0,0 +1,30 @@
+use strict;
+use warnings;
+use Test::More;
+
+use Inline CPP => <<'END';
+
+struct Fizzle {
+  int q;
+  double foozle;
+  int quack;
+  Fizzle(int Q=0, double Foozle=0, int Quack=0) {
+    q = Q;
+    foozle = Foozle;
+    quack = Quack;
+  }
+  int get_q() { return q; }
+  double get_foozle() { return foozle; }
+  int get_quack() { return quack; }
+};
+
+END
+
+my $o = new_ok( 'Fizzle' );
+
+is(
+    $o->get_q, 0,
+    "Struct with public member function."
+);
+
+done_testing();
@@ -0,0 +1,303 @@
+use Test::More tests => 38;
+
+use strict;
+use warnings;
+
+use Inline CPP => 'DATA';
+
+note( 'Instantiating objects.' );
+my @object_descriptions = (
+    [
+        my $parent1_obj = new_ok( 'Parent1', [], 'Parent1 object born:' ),
+        [ qw/ Parent1      / ],
+        [ qw/ do_something / ]
+    ],
+    [
+        my $parent2_obj = new_ok( 'Parent2', [], 'Parent2 object born:' ),
+        [ qw/ Parent2    /   ],
+        [ qw/ do_another /   ]
+    ],
+    [
+        my $child_obj = new_ok( 'Child',     [], 'Child object born:'   ),
+        [ qw/ Child          Parent1         Parent2    / ],
+        [ qw/ yet_another    do_something    do_another / ]
+    ],
+    [
+        my $child2_obj = new_ok( 'Child2',   [], 'Child2 object born:'  ),
+        [ qw/ Child2        Parent1          Parent2    / ],
+        [ qw/ some_other    do_something     do_another / ]
+    ],
+);
+
+note( 'Testing object lineage.' );
+foreach my $obj_desc ( @object_descriptions ) {
+    foreach my $class ( @{ $obj_desc->[1] } ) {
+        ok(
+            $obj_desc->[0]->isa( $class ),
+            "UNIVERSAL::isa confirms $obj_desc->[1][0] object is a $class."
+        );
+    }
+}
+
+note( 'Testing object method capabilities (inheritance).' );
+foreach my $obj_desc ( @object_descriptions ) {
+    foreach my $func_name ( @{ $obj_desc->[2] } ) {
+        can_ok( $obj_desc->[0], $func_name );
+    }
+}
+
+
+note( 'Testing \@Class::ISA arrays.' );
+is_deeply( \@Parent1::ISA, [ ], "\@Parent1::ISA: No inheritance." );
+is_deeply( \@Parent2::ISA, [ ], "\@Parent2::ISA: No inheritance." );
+TODO: {
+    local $TODO = "Still researching why Child and Child2 inherit via main::";
+    is_deeply(
+        \@Child::ISA,   [ qw/ Parent1   Parent2 / ],
+        "\@Child::ISA: Parent1, Parent2."
+    );
+    is_deeply(
+        \@Child2::ISA,  [ qw/ Parent2   Parent1 / ],
+        "\@Child2::ISA: Parent2, Parent1."
+    );
+}
+
+my @method_tests = (
+    [
+        $parent1_obj,           # Object ref.
+        'Parent1',              # Class name.
+        {
+            do_something => 51  # Method call and expected result.
+        }
+    ],
+    [
+        $parent2_obj,           # Object ref.
+        'Parent2',              # Class name.
+        {
+            do_another   => 17  # Method call and expected result.
+        }
+    ],
+    [
+        $child_obj,             # Object ref.
+        'Child',                # Class name.
+        {
+            yet_another  => 3,  # Method call and expected result.
+            do_something => 51, # Inherited from Parent1: Call and expected.
+            do_another   => 17, # Inherited from Parent2: Call and expected.
+        },
+    ],
+    [
+        $child2_obj,            # Object ref.
+        'Child2',               # Class name.
+        {
+            some_other   => 4,  # Method call and expected result.
+            do_something => 51, # Inherited from Parent1: Call and expected.
+            do_another   => 17  # Inherited from Parent2: Call and expected.
+        }
+    ],
+);
+
+note( 'Testing that object methods return correct values' );
+TODO: {
+    foreach my $obj_task ( @method_tests ) {
+        while( my( $method, $expect ) = each %{ $obj_task->[2] } ) {
+            local $TODO =
+                'Still working on why multiple inheritance is messed up.'
+                if( $obj_task->[1] =~ /Child\d?/ );
+            is(
+                $obj_task->[0]->$method, $expect,
+                "$obj_task->[1] object method $method " .
+                "correctly returns $expect."
+            );
+        }
+    }
+}
+
+
+# These tests are essentially repeats from code above, but with code that is
+# more transparent to illustrate the issue as clearly as possible.
+
+note( "\n\nPainfully simple so we don\'t miss it this time.\n\n" );
+TODO: {
+    is(
+        $child_obj->yet_another, 3,
+        'Child $obj->yet_another() should return 3.'
+    );
+    is(
+        $child_obj->do_something, 51,
+        'Child $obj->do_something() ' .
+        'inherits from Parent1 and should return 51.'
+    );
+    {
+        local $TODO = 'Inheritance foulup: Calling do_another() but getting' .
+                      ' return value from do_something().';
+        is(
+            $child_obj->do_another, 17,
+            'Child $obj->do_another() ' .
+            'inherits from Parent2, and should return 17.'
+        );
+    }
+    is(
+        $child2_obj->some_other, 4,
+        'Child2 $obj->some_other() should return 4.'
+    );
+    {
+        local $TODO = 'Inheritance foulup: Calling do_something but getting' .
+                      ' return value from do_another().';
+        is(
+            $child2_obj->do_something, 51,
+            'Child2 $obj->do_something() ' .
+            'inherited from Parent1 and should return 51.'
+        );
+    }
+    is(
+        $child2_obj->do_another, 17,
+        'Child2 $obj->do_another() ' .
+        'inherited from Parent2 and should return 17.'
+    );
+}
+done_testing();
+
+=cut
+
+-------------------- email from Patrick ---------------
+David,
+
+I'm really no C++ expert, but I think the implementation is not viable
+the way it is. If you create a
+small C++ program that simulates Inline::CPP like this:
+
+#include <stdio.h>
+
+/* Your Child/Parent classes here "as is" */
+
+int main(int argv, char **argc){
+       Child *c = new Child() ;
+       printf("%d\n", c->do_something()) ;
+       printf("%d\n", c->do_another()) ;
+
+       void *x = c ;
+       printf("%d\n", ((Parent1 *)x)->do_something()) ;
+       printf("%d\n", ((Parent2 *)x)->do_another()) ;
+}
+
+I gives the same error:
+51
+17
+51
+51
+
+I think the problem is that you can't cast your pointer to either
+Parent1 or Parent2 depending on
+your needs because the bytes are not overlapped in memory. In the
+definition of the Child object,
+the Parent1 stuff is before the Parent2 stuff. To access the Parent2
+stuff you probably need to
+use an offset on the Child Pointer.
+
+What's happening (I think) is that your are calling do_something()
+both times because both methods
+are at the same byte offset in there respective parent object. If you
+add some member variables in
+one of the Parent object before the method definitions you will
+probably get crashes because the method
+offset will no longer line up. I'm not sure if any of this is clear....
+
+I think the correct way to do this is something like:
+
+       printf("%d\n", ((Child *)x)->Parent1::do_something()) ;
+       printf("%d\n", ((Child *)x)->Parent2::do_another()) ;
+
+but that implies that your Parent functions know about Child, which is
+not good...
+
+Anyways, just some stuff to think about, unfortunately I don't have
+any suggestions for you...
+
+
+Patrick
+
+--------------------------------
+
+Email response from davido/daoswald:
+
+Your explanation was excellent.
+
+What needs to be happening is that, as Child inherits from Parent1 and
+Parent2, the pointer should be cast as a Child type, like in this
+modification of your test:
+
+int main(int argv, char **argc){
+      Child *c = new Child() ;
+      printf("%d\n", c->do_something()) ;
+      printf("%d\n", c->do_another()) ;
+
+      void *x = c ;
+      printf("%d\n", ((Child *)x)->do_something()) ;
+      printf("%d\n", ((Child *)x)->do_another()) ;
+}
+
+...or in more idiomatic C++:
+
+int main() {
+   using std::cout;
+   using std::endl;
+
+   Child *c = new Child() ;
+   cout << c->do_something() << endl;
+   cout << c->do_another()   << endl;
+
+   void *x = c ;
+   cout <<  static_cast< Child* >(x)->do_something() << endl;
+   cout <<  static_cast< Child* >(x)->do_another()   << endl;
+
+   return 0;
+}
+
+Though I'm not much closer to a solution, at least your message
+reminded me that we're dealing with void pointers to objects.  Maybe I
+need to start looking at how and where the casting is being
+accomplished.
+
+------------------------------------
+
+=cut
+
+__END__
+__CPP__
+
+class Parent1 {
+  public:
+    Parent1() { }
+    ~Parent1() { }
+
+    virtual int do_something() { return 51; }
+};
+
+class Parent2 {
+  public:
+    Parent2();
+    ~Parent2();
+
+    virtual int do_another();
+};
+
+Parent2::Parent2() { }
+Parent2::~Parent2() { }
+int Parent2::do_another() { return 17; }
+
+class Child : public Parent1, public Parent2 {
+  public:
+    Child() { }
+    ~Child() { }
+
+    int yet_another() { return 3; }
+};
+
+class Child2 : public Parent2, public Parent1 {
+  public:
+    Child2() { }
+    ~Child2() { }
+
+    int some_other() { return 4; }
+};
@@ -0,0 +1,39 @@
+use strict;
+use warnings;
+use Test::More;
+
+use Inline 'CPP';
+
+
+is_deeply(
+    [ return_list() ], [ 1, 'Hello?', '15.75' ],
+    "Return on the stack a list containing an int, a string, and a double."
+);
+
+# We used to test ok( $list[2], 15.6 ) with a corresponding value in the
+# CPP function.  But because .6 cannot be represented in a finite number of
+# binary digits we were getting some inequality test failures.
+# 15.75 is the same as 126/8, which can be represented accurately in base 2.
+# The goal of the test is to see if we're able to pass floating point values
+# correctly, not to test the way a given C++ compiler handles floating point
+# math.
+
+is( return_void(), undef, "Void function that returns nothing." );
+
+done_testing();
+
+__END__
+__CPP__
+
+void return_list() {
+    Inline_Stack_Vars;
+    Inline_Stack_Reset;
+    Inline_Stack_Push(sv_2mortal(newSViv(1)));
+    Inline_Stack_Push(sv_2mortal(newSVpv("Hello?",0)));
+    Inline_Stack_Push(sv_2mortal(newSVnv(15.75)));
+    Inline_Stack_Done;
+}
+
+void return_void() {
+    printf("# Hello! from return_void()\n");
+}
@@ -0,0 +1,28 @@
+use strict;
+use warnings;
+use Test::More;
+
+use Inline 'CPP';
+
+is(sum(), 0, "Var-args: 0" );
+is(sum(1), 1, "Var-args: 1" );
+is(sum(1, 2), 3, "Var-args: 2" );
+is(sum(1, 2, 3), 6, "Var-args: 3" );
+is(sum(1, 2, 3, 4), 10, "Var-args: 4" );
+is(sum(1, 2, 3, 4, 5), 15, "Var-args: 5" );
+
+done_testing();
+
+__END__
+__CPP__
+
+int sum(...) {
+    Inline_Stack_Vars;
+    int s = 0;
+    for (int i=0; i<items; i++)
+    {
+    int tmp = SvIV(Inline_Stack_Item(i));
+    s += tmp;
+    }
+    return s;
+}
@@ -0,0 +1,21 @@
+use strict;
+use warnings;
+use Test::More;
+
+use Inline CPP => <<'END';
+class Foo {
+  public:
+    Foo()  {}
+    ~Foo() {}
+    char *data() const { return "Hello dolly!\n"; }
+};
+
+END
+
+
+is(
+    Foo->new->data, "Hello dolly!\n",
+    "Constant member function."
+);
+
+done_testing();
@@ -0,0 +1,25 @@
+use strict;
+use warnings;
+use Test::More;
+# Test static variables
+
+use Inline CPP => <<'END';
+class Foo {
+  public:
+    Foo()  {}
+    ~Foo() {}
+    static int get_thing() { return s_thing; }
+  private:
+    static int s_thing;
+};
+
+int Foo::s_thing = 10;
+
+END
+
+is(
+    Foo->new->get_thing, 10,
+    "Static variables within a class."
+);
+
+done_testing();
@@ -0,0 +1,50 @@
+use strict;
+use warnings;
+use Test::More;
+# Test declarations of multiple variables in a member data list.
+
+use Inline CPP => <<'END';
+
+#define NUMBER 25
+#define FOO()  25
+
+class Foo {
+  public:
+    Foo(double _o) : o(_o) {}
+    ~Foo() {}
+    int test() { return 10; }
+  private:
+    int a, b;
+    char *c, d;
+    char *e, *f;
+    char g, **h;
+    double i, j, *k, **m, n, &o;
+
+    static const int    aa = 10,
+            bb = FOO(),
+            cc = NUMBER,
+            dd = 1.25
+            ;
+};
+
+class Bar {
+  public:
+    Bar() { }
+    ~Bar() { }
+    int test() { return -1; }
+};
+
+END
+
+
+is(
+    Foo->new(1.23)->test, 10,
+    "Declaration of multiple variables in a list."
+);
+
+is(
+    Bar->new->test, -1,
+    "Simple case class following multiple variables class."
+);
+
+done_testing();
@@ -0,0 +1,25 @@
+use strict;
+use warnings;
+use Test::More;
+# Test member array feature (single-dimensional only).
+
+use Inline CPP => 'DATA';
+
+my $obj = new_ok( 'TestMemberArray' );
+is( $obj->get_value_at(1), 101, "Member array accessor gets correct value." );
+
+done_testing();
+
+
+__DATA__
+__CPP__
+
+class TestMemberArray {
+  public:
+    TestMemberArray() { for( size_t i = 0; i < 5; i++ ) member_array[i] = i + 100; }
+    ~TestMemberArray() {}
+    int get_value_at( int i ) { return member_array[i]; }
+  private:
+    int member_array[5];
+};
+
@@ -0,0 +1,37 @@
+use strict;
+use warnings;
+use Test::More;
+
+## no critic (eval)
+
+# Test implementation of C++ namespaces.
+
+my $rv = eval <<'EOILCPP';
+  use Inline CPP => q[
+    namespace Bar {
+      class Foo {
+        public:
+          Foo() : a(10) { }
+          int fetch() { return a; }
+        private:
+          int a;
+      };
+    }
+  ];
+  1;
+EOILCPP
+
+
+TODO: {
+  local $TODO = 'C++ namespace feature not yet implemented.';
+
+  is( $rv, 1, 'Compilation succeeded.' );
+  can_ok( 'Bar::Foo', qw( new fetch ) );
+
+  my $bf = new_ok( 'Bar::Foo' );
+  my $val = eval { $bf->fetch };
+  ok( defined($val) && $val == 10, 'Bar::Foo->fetch obtained correct value.' );
+
+};
+
+done_testing();
@@ -0,0 +1,42 @@
+use strict;
+use warnings;
+use Test::More;
+
+## no critic (eval)
+
+# Test multidimensional arrays as member data.
+
+my $rv = eval <<'EOILCPP';
+  use Inline CPP => q/
+    class Foo {
+      public:
+        Foo()  { a[0][0] = 00; a[9][0] = 90; a[0][9] = 9; a[9][9] = 99; }
+        int tl() { return a[0][0]; }
+        int bl() { return a[9][0]; }
+        int tr() { return a[0][9]; }
+        int br() { return a[9][9]; }
+      private:
+        int a[10][10];
+    };
+  /;
+  1;
+EOILCPP
+
+TODO: {
+  local $TODO = 'C++ multi-dimensional arrays as member data not supported.';
+
+  is( $rv, 1, 'Compilation completed without exception.' );
+
+  my $f = new_ok( 'Foo' );
+  can_ok( 'Foo', qw( new tl bl tr br ) );
+
+  my( $tl, $bl, $tr, $br ) = eval { ( $f->tl, $f->bl, $f->tr, $f->br ) };
+
+  ok( defined($tl) && $tl == 0, 'tl() fetches proper element.' );
+  ok( defined($bl) && $bl == 0, 'bl() fetches proper element.' );
+  ok( defined($tr) && $tr == 0, 'tr() fetches proper element.' );
+  ok( defined($br) && $br == 0, 'br() fetches proper element.' );
+
+};
+
+done_testing();
@@ -0,0 +1,47 @@
+package main; ## no critic (package)
+
+use strict;
+use warnings;
+
+use Inline CPP => config => namespace => '';
+
+use Inline CPP => <<'EOCPP';
+
+class Foo {
+  private:
+    int a;
+  public:
+    Foo() :a(10) {}
+    int fetch () { return a; }
+};
+EOCPP
+
+use Inline CPP => <<'EOCPP';
+
+class Bar {
+  private:
+    int a;
+  public:
+    Bar() :a(20) {}
+    int fetch () { return a; }
+};
+EOCPP
+
+package main;
+use Test::More;
+
+can_ok 'Foo', 'new';
+can_ok 'main::Foo', 'new';
+can_ok 'Foo', 'fetch';
+can_ok 'main::Foo', 'fetch';
+my $f = new_ok 'Foo';
+ok( ( ref($f) eq 'Foo' || ref($f) eq 'main::Foo' ), 'Our "Foo" is a "Foo"');
+
+can_ok 'Bar', 'new';
+my $fb = Bar->new;
+ok( ( ref($fb) eq 'Bar' || ref($fb) eq 'main::Bar' ), 'Our "Bar" is a "Bar"');
+
+is $f->fetch, 10, 'Proper object method association from Foo.';
+is $fb->fetch, 20, 'Proper object method association from Bar.';
+
+done_testing();
@@ -0,0 +1,46 @@
+package main; ## no critic (package)
+
+use strict;
+use warnings;
+
+use Inline CPP => config => namespace => 'main';
+
+use Inline CPP => <<'EOCPP';
+
+class Foo {
+  private:
+    int a;
+  public:
+    Foo() :a(10) {}
+    int fetch () { return a; }
+};
+EOCPP
+
+use Inline CPP => <<'EOCPP';
+
+class Bar {
+  private:
+    int a;
+  public:
+    Bar() :a(20) {}
+    int fetch () { return a; }
+};
+EOCPP
+
+package main;
+use Test::More;
+
+can_ok 'Foo', 'new';
+can_ok 'main::Foo', 'new';
+my $f = new_ok 'Foo';
+ok( (ref($f) eq 'Foo' || ref($f) eq 'main::Foo'), 'Our "Foo" is a "Foo"');
+
+can_ok 'Bar', 'new';
+can_ok 'main::Bar', 'new';
+my $fb = new_ok 'Bar';
+ok( (ref($fb) eq 'Bar' || ref($fb) eq 'main::Bar' ), 'Our "Bar" is a "Bar"');
+
+is $f->fetch, 10, 'Proper object method association from Foo.';
+is $fb->fetch, 20, 'Proper object method association from Bar.';
+
+done_testing();
@@ -0,0 +1,44 @@
+package Ball; ## no critic (package)
+
+use strict;
+use warnings;
+
+use Inline CPP => config => namespace         => 'Baz';
+
+use Inline CPP => <<'EOCPP';
+
+class Foo {
+  private:
+    int a;
+  public:
+    Foo() :a(10) {}
+    int fetch () { return a; }
+};
+EOCPP
+
+use Inline CPP => <<'EOCPP';
+
+class Bar {
+  private:
+    int a;
+  public:
+    Bar() :a(20) {}
+    int fetch () { return a; }
+};
+EOCPP
+
+package main;
+use Test::More;
+
+can_ok 'Baz::Foo', 'new';
+my $f = new_ok 'Baz::Foo';
+is ref($f), 'Baz::Foo', 'Our "Foo" is a "Baz::Foo"';
+
+can_ok 'Baz::Bar', 'new';
+my $fb = new_ok 'Baz::Bar';
+is ref($fb), 'Baz::Bar', 'Our "Bar" is a "Baz::Bar"';
+
+is $f->fetch, 10, 'Proper object method association from Baz::Foo.';
+is $fb->fetch, 20, 'Proper object method association from Baz::Bar.';
+
+done_testing();
@@ -0,0 +1,35 @@
+package Bar; ## no critic (package)
+
+use strict;
+use warnings;
+
+use Inline CPP => config => namespace => '';
+
+use Inline CPP => <<'EOCPP';
+
+class Foo {
+  private:
+    int a;
+  public:
+    Foo() :a(10) {}
+    int fetch () { return a; }
+};
+EOCPP
+
+package Baz;
+
+use Test::More;
+
+is __PACKAGE__, 'Baz', "Instantiating from package Baz.";
+
+can_ok 'Foo', 'new';
+can_ok 'main::Foo', 'new';
+can_ok 'Foo', 'fetch';
+can_ok 'main::Foo', 'fetch';
+my $f = new_ok 'Foo';
+ok( (ref($f) eq 'Foo' || ref($f) eq 'main::Foo'), 'Our "Foo" is a "Foo"');
+is $f->fetch, 10, 'Proper object method association from Foo.';
+
+done_testing();
+
+package main;
@@ -0,0 +1,27 @@
+package Foo; ## no critic (package)
+
+## no critic (eval)
+
+use Test::More;
+
+use strict;
+use warnings;
+
+use Inline CPP => config => namespace => '!@#$';
+my $res = eval q[
+  use Inline CPP => <<'EOCPP';
+  class Foo {
+    private:
+      int a;
+    public:
+      Foo() :a(10) {}
+      int fetch () { return a; }
+  };
+EOCPP
+  1;
+];
+
+ok !$res, 'Invalid namespace croaks.';
+like $@, qr/is an invalid package name\./, 'Correct message.';
+
+done_testing();
@@ -0,0 +1,47 @@
+## no critic (package)
+
+package Foo;
+
+use strict;
+use warnings;
+
+# Notice, case insensitive 'config'. Let's keep it that way in support of
+# t/15config_case.t
+use Inline CPP => config => namespace => '';
+
+use Inline CPP => <<'EOCPP';
+
+class Foo {
+  private:
+    int a;
+  public:
+    Foo() :a(10) {}
+    int fetch () { return a; }
+};
+EOCPP
+
+1;
+
+package Bar;
+
+our @ISA = ('Foo');
+sub myfetch { my $self = shift; $self->fetch(); }
+
+
+package main;
+use Test::More;
+
+can_ok 'Foo', 'new';
+my $f = new_ok 'Foo';
+is ref($f), 'Foo', 'Our "Foo" is a "Foo".';
+is $f->fetch, '10', 'Accessor properly associated.';
+
+
+
+can_ok 'Bar', 'new';
+my $bf = new_ok 'Bar';
+is ref($bf), 'Bar', 'Our "Bar" is a "Bar"';
+is $bf->fetch, 10, 
+   'Inheritance and object method association from Bar.';
+is $bf->myfetch, 10, 'Method resolution for subclass.';
+done_testing();