about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2023-01-08 05:03:26 +0000
committerEric Wong <e@80x24.org>2023-01-08 05:05:01 +0000
commitb5ab9be6686aa778a4cfd7622c598736b9c42321 (patch)
treea967297606a1f91f8359e287d5a85ad018e185e3
parent4356beb8237a92b3902b17f55cfe93d347b593d5 (diff)
parent2c25edb01139365f4754985c1e3494765dd1e5a7 (diff)
downloadmwrap-b5ab9be6686aa778a4cfd7622c598736b9c42321.tar.gz
This contains many changes from https://80x24.org/mwrap-perl.git
commit

* Built-in RCU-friendly version of dlmalloc, no more fragile dlsym(3m)
  resolution of malloc-family functions in the constructor

* Allocations are now backed by O_TMPFILE on $TMPDIR on modern Linux.
  Since mwrap increases memory usage greatly and I needed to use it
  on a system where I needed more VM space but lacked the ability
  to add swap.

* Configurable C backtrace level via MWRAP=bt:$DEPTH where $DEPTH
  is a non-negative integer.  Be careful about increasing it, even
  a depth of 3-4 can be orders-of-magnitude more expensive in
  time and space.  This can be changed dynamically at runtime via
  local HTTP (see below).

* Embedded per-process local-socket-only HTTP server obsoletes
  MwrapRack when combined with mwrap-rproxy from the Perl dist
  (set `MWRAP=socket_dir:/dir/of/sockets')
  See https://80x24.org/mwrap-perl/20221210015518.272576-4-e@80x24.org/
  for more info.

  It now supports downloading CSV (suitable for importing into sqlite 3.32.0+)

* License switched to GPL-3+ to be compatible with GNU binutils
  since we may take code from addr2line in the future.

* libxxhash supported if XXH3_64bits is available.
-rw-r--r--.document3
-rw-r--r--.gitignore19
-rw-r--r--.olddoc.yml10
-rw-r--r--INSTALL44
-rw-r--r--MANIFEST39
-rw-r--r--Makefile.PL139
-rw-r--r--Mwrap.xs309
-rw-r--r--README101
-rw-r--r--Rakefile52
-rwxr-xr-xVERSION-GEN36
-rwxr-xr-xbin/mwrap55
-rw-r--r--examples/mwrap.psgi14
-rwxr-xr-xexe.sh8
-rw-r--r--ext/mwrap/check.h (renamed from check.h)0
-rw-r--r--ext/mwrap/dlmalloc_c.h (renamed from dlmalloc_c.h)0
-rw-r--r--ext/mwrap/extconf.rb31
-rw-r--r--ext/mwrap/gcc.h (renamed from gcc.h)0
-rw-r--r--ext/mwrap/httpd.h (renamed from httpd.h)2
-rw-r--r--ext/mwrap/jhash.h (renamed from jhash.h)0
-rw-r--r--ext/mwrap/mwrap.c396
-rw-r--r--ext/mwrap/mwrap_core.h (renamed from mwrap_core.h)161
-rw-r--r--ext/mwrap/mymalloc.h (renamed from mymalloc.h)2
-rw-r--r--ext/mwrap/picohttpparser.h (renamed from picohttpparser.h)0
-rw-r--r--ext/mwrap/picohttpparser_c.h (renamed from picohttpparser_c.h)0
-rw-r--r--lib/Devel/Mwrap.pm21
-rw-r--r--lib/Devel/Mwrap/PSGI.pm190
-rw-r--r--lib/Devel/Mwrap/Rproxy.pm220
-rw-r--r--lib/mwrap/.gitignore1
-rw-r--r--lib/mwrap_rack.rb126
-rw-r--r--mwrap.gemspec35
-rw-r--r--ppport.h8214
-rw-r--r--script/mwrap-perl97
-rw-r--r--script/mwrap-rproxy115
-rw-r--r--t/httpd-unit.t116
-rw-r--r--t/httpd.t42
-rw-r--r--t/mwrap.t177
-rw-r--r--t/source_location.perl9
-rw-r--r--t/test_common.perl20
-rw-r--r--test/test_mwrap.rb292
-rw-r--r--typemap5
40 files changed, 1277 insertions, 9824 deletions
diff --git a/.document b/.document
new file mode 100644
index 0000000..4385cfe
--- /dev/null
+++ b/.document
@@ -0,0 +1,3 @@
+ext/mwrap/mwrap.c
+lib/mwrap_rack.rb
+README
diff --git a/.gitignore b/.gitignore
index a89b4a0..f670b62 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,14 +1,9 @@
+/tmp
 *.o
 *.so
-/MYMETA.
-/MYMETA.*
-/MANIFEST.gen
-/Makefile.old
-/Makefile
-/Mwrap.bs
-/Mwrap.c
-/blib
-/pm_to_blib
-/config.mak
-/_Inline
-/build.env
+/pkg
+/*.gem
+/doc
+/NEWS
+/NEWS.atom.xml
+/LATEST
diff --git a/.olddoc.yml b/.olddoc.yml
new file mode 100644
index 0000000..bfecbaf
--- /dev/null
+++ b/.olddoc.yml
@@ -0,0 +1,10 @@
+---
+cgit_url: https://80x24.org/mwrap.git
+git_url: https://80x24.org/mwrap.git
+rdoc_url: https://80x24.org/mwrap/
+ml_url: https://80x24.org/mwrap-public/
+public_email: mwrap-public@80x24.org
+nntp_url:
+- nntps://news.public-inbox.org/inbox.comp.lang.ruby.mwrap
+imap_url:
+- imaps://;AUTH=ANONYMOUS@80x24.org/inbox.comp.lang.ruby.mwrap.0
diff --git a/INSTALL b/INSTALL
deleted file mode 100644
index 80ff748..0000000
--- a/INSTALL
+++ /dev/null
@@ -1,44 +0,0 @@
-Dependencies: liburcu (Userspace RCU) is required at runtime.
-
-`pkg-config', GNU make, and standard Perl build tools are also required.
-
-             FreeBSD:        pkg install pkg-config liburcu
-Debian-based systems:        apt-get install pkg-config liburcu-dev
-
-
-Newer versions of xxhash can unlock a small bit of performance:
-
-        pkg install xxhash
-        apt-get install libxxhash-dev
-
-
-If using mwrap-rproxy, Plack is also required:
-
-        pkg install p5-Plack p5-Plack-Middleware-Deflater
-        apt-get install libplack-perl libplack-middleware-deflater-perl
-
-symlink-install
----------------
-
-For users who lack permissions and/or wish to minimize their
-installation footprint, the "symlink-install" target is available.
-The following commands installs symlinks to $HOME/bin
-pointing to the source tree:
-
-        perl Makefile.PL
-        make symlink-install prefix=$HOME
-
-standard MakeMaker installation (Perl)
---------------------------------------
-
-To use MakeMaker, you need to ensure ExtUtils::MakeMaker is available.
-This is typically installed with Perl, but RPM-based systems will likely
-need to install the `perl-ExtUtils-MakeMaker' package.
-
-Once the dependencies are installed, you should be able to build and
-install the system (into /usr/local) with:
-
-        perl Makefile.PL
-        make
-        make check
-        make install # root permissions may be needed
diff --git a/MANIFEST b/MANIFEST
index 096cec9..e8ace8b 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -1,30 +1,17 @@
+.document
 .gitignore
+.olddoc.yml
 COPYING
-INSTALL
 MANIFEST
-Makefile.PL
-Mwrap.xs
 README
-check.h
-dlmalloc_c.h
-examples/mwrap.psgi
-exe.sh
-gcc.h
-httpd.h
-jhash.h
-lib/Devel/Mwrap.pm
-lib/Devel/Mwrap/PSGI.pm
-lib/Devel/Mwrap/Rproxy.pm
-mwrap_core.h
-mymalloc.h
-picohttpparser.h
-picohttpparser_c.h
-ppport.h
-script/mwrap-perl
-script/mwrap-rproxy
-t/httpd-unit.t
-t/httpd.t
-t/mwrap.t
-t/source_location.perl
-t/test_common.perl
-typemap
+Rakefile
+VERSION-GEN
+bin/mwrap
+ext/mwrap/extconf.rb
+ext/mwrap/jhash.h
+ext/mwrap/mwrap.c
+lib/mwrap/.gitignore
+lib/mwrap_rack.rb
+mwrap.gemspec
+test/test_mwrap.rb
+lib/mwrap/version.rb
diff --git a/Makefile.PL b/Makefile.PL
deleted file mode 100644
index dadf80b..0000000
--- a/Makefile.PL
+++ /dev/null
@@ -1,139 +0,0 @@
-# Copyright (C) all contributors <mwrap-perl@80x24.org>
-# License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt>
-use v5.12;
-use ExtUtils::MakeMaker;
-use Config;
-my $pkg_config = $ENV{PKG_CONFIG} // 'pkg-config';
-my $LIBS = `$pkg_config --libs liburcu-cds liburcu-bp`;
-if ($?) {
-        print STDERR <<END;
-`$pkg_config --libs liburcu-cds` failed (\$?=$?)
-
-You need to install pkg-config and liburcu <https://liburcu.org/>
-before you can build Devel::Mwrap.
-
-On Debian:
-
-        apt-get install pkg-config liburcu-dev
-END
-        # tell CPAN testing to indicate missing deps
-        exit 0;
-}
-
-chomp($LIBS);
-if ($Config{usemymalloc} eq 'y') {
-        print STDERR <<END;
-Devel::Mwrap requires `usemymalloc=n'.  malloc and related functions
-must be dynamically-linked for Devel::Mwrap to work.
-END
-        exit 0;
-}
-
-# may be empty
-chomp(my $INC = `$pkg_config --cflags liburcu-cds liburcu-bp`);
-my @writemakefile_args = ();
-my $ccflags = '';
-
-print '# checking libxxhash... ';
-chomp(my $xxhash_inc = `$pkg_config --cflags libxxhash`);
-if ($? == 0) {
-        $INC .= " $xxhash_inc";
-        $ccflags .= ' -DHAVE_XXHASH';
-        say 'yes';
-} else {
-        say 'no';
-}
-
-use IO::Handle;
-STDOUT->autoflush(1);
-require ExtUtils::CBuilder;
-require File::Temp;
-my $cb = ExtUtils::CBuilder->new(quiet => $ENV{V} ? 0 : 1);
-my $d = File::Temp->newdir('mwrap-perl-build-XXXX');
-my $olderr;
-print '# checking for -lexecinfo... ';
-{
-        use autodie;
-        open my $fh, '>', "$d/execinfo.c";
-        print $fh <<EOM;
-#include <execinfo.h>
-int main(void) { return backtrace_symbols_fmt ? 1 : 0; }
-EOM
-        close $fh;
-        open $olderr, '+>&', *STDERR{IO};
-        open STDERR, '>', "$d/err.log";
-}
-eval {
-        my $obj = $cb->compile(source => "$d/execinfo.c");
-        $cb->link(objects => $obj, extra_linker_flags => '-lexecinfo');
-        $LIBS .= ' -lexecinfo';
-        say " yes on $^O";
-};
-say " no on $^O" if $@;
-{
-        use autodie;
-        open STDERR, '+>&', $olderr or die "dup stderr: $!";
-}
-
-# See lib/ExtUtils/MakeMaker.pm for details of how to influence
-# the contents of the Makefile that is written.
-push @writemakefile_args, (
-        NAME => 'Devel::Mwrap',
-        VERSION_FROM => 'lib/Devel/Mwrap.pm',
-        CCFLAGS => "$Config{ccflags} $ccflags",
-        PREREQ_PM => {},
-        ABSTRACT_FROM => 'lib/Devel/Mwrap.pm',
-        EXE_FILES => [qw(script/mwrap-perl script/mwrap-rproxy)],
-        AUTHOR => 'mwrap hackers <mwrap-perl@80x24.org>',
-        LIBS => $LIBS, # e.g. -lurcu-cds
-        LICENSE => 'gpl_2', # GPL-3.0+, CPAN::Meta::Spec limitation
-        MIN_PERL_VERSION => '5.12.0',
-        BUILD_REQUIRES => {},
-        INC => $INC,
-        depend => {
-                Makefile => 'lib/Devel/Mwrap.pm',
-        },
-        META_MERGE => {
-                resources => {
-                        repository => 'https://80x24.org/mwrap-perl.git',
-                        homepage => 'https://80x24.org/mwrap-perl.git/about',
-                        bugtracker => 'https://80x24.org/mwrap-public/',
-                },
-        },
-);
-
-WriteMakefile(@writemakefile_args);
-
-my $tflags = $ccflags;
-$tflags .= ' -DHAS_SOCKADDR_SA_LEN ' if $Config{d_sockaddr_sa_len};
-sub MY::postamble {
-        <<EOF;
-N = \$\$(( \$\$(nproc 2>/dev/null || gnproc 2>/dev/null || echo 2) + 1 ))
--include config.mak
-
-check-manifest :: MANIFEST
-        if git ls-files >\$?.gen 2>&1; then diff -u \$? \$?.gen; fi
-
-build.env :: Makefile
-        echo >\$\@+ extra_linker_flags=$LIBS -lpthread
-        echo >>\$\@+ extra_compiler_flags=-I. $INC $Config{ccflags} $tflags
-        mv \$\@+ \$\@
-
-pure_all :: build.env
-
-check:: all check-manifest
-        prove -bvw -j\$(N)
-
-# Install symlinks to ~/bin (which is hopefuly in PATH) which point to
-# this source tree.
-# prefix + bindir matches git.git Makefile:
-prefix = \$(HOME)
-bindir = \$(prefix)/bin
-symlink-install : all
-        mkdir -p \$(bindir)
-        exe=\$\$(realpath exe.sh) && cd \$(bindir) && \\
-        for x in \$(EXE_FILES); do \\
-                ln -sf "\$\$exe" \$\$(basename "\$\$x"); \\
-        done
-EOF
-}
diff --git a/Mwrap.xs b/Mwrap.xs
deleted file mode 100644
index 4d4c996..0000000
--- a/Mwrap.xs
+++ /dev/null
@@ -1,309 +0,0 @@
-/*
- * Copyright (C) mwrap hackers <mwrap-perl@80x24.org>
- * License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt>
- * Disclaimer: I don't really know my way around XS or Perl internals well
- */
-#define MWRAP_PERL 1
-#include "mwrap_core.h"
-
-/*
- * I hate typedefs, especially when they're hiding the fact that there's
- * a pointer, but XS needs this, apparently, and it does s/__/::/g
- */
-typedef struct src_loc * Devel__Mwrap__SrcLoc;
-
-/* keep this consistent with httpd.h write_loc_name */
-static SV *location_string(struct src_loc *l)
-{
-        SV *ret = newSV(0);
-
-        if (l->f) {
-                sv_catpv(ret, l->f->fn);
-                if (l->lineno == U24_MAX)
-                        sv_catpvs(ret, ":-");
-                else
-                        sv_catpvf(ret, ":%u", l->lineno);
-        }
-        if (l->bt_len) {
-                AUTO_FREE char **s = bt_syms(l->bt, l->bt_len);
-                if (s) {
-                        if (l->f)
-                                sv_catpvs(ret, "\n");
-                        sv_catpv(ret, s[0]);
-                        for (uint32_t i = 1; i < l->bt_len; ++i)
-                                sv_catpvf(ret, "\n%s", s[i]);
-                }
-        }
-        return ret;
-}
-
-MODULE = Devel::Mwrap        PACKAGE = Devel::Mwrap        PREFIX = mwrap_
-
-BOOT:
-#ifndef PERL_IMPLICIT_CONTEXT
-        root_locating = &locating;
-#endif
-
-PROTOTYPES: ENABLE
-
-size_t
-mwrap_quiet(int on_off)
-CODE:
-        RETVAL = on_off ? locating++ : locating--;
-OUTPUT:
-        RETVAL
-
-size_t
-mwrap_current_age()
-CODE:
-        RETVAL = uatomic_read(&total_bytes_inc);
-OUTPUT:
-        RETVAL
-
-size_t
-mwrap_total_bytes_allocated()
-CODE:
-        RETVAL = uatomic_read(&total_bytes_inc);
-OUTPUT:
-        RETVAL
-
-size_t
-mwrap_total_bytes_freed()
-CODE:
-        RETVAL = uatomic_read(&total_bytes_dec);
-OUTPUT:
-        RETVAL
-
-void
-mwrap_each(min, cb, arg = &PL_sv_undef)
-        size_t min;
-        SV *cb;
-        SV *arg;
-PREINIT:
-        struct cds_lfht *t;
-        struct cds_lfht_iter iter;
-        struct src_loc *l;
-CODE:
-        ++locating;
-        rcu_read_lock();
-        t = CMM_LOAD_SHARED(totals);
-        if (t) {
-                bool err = false;
-
-                cds_lfht_for_each_entry(t, &iter, l, hnode) {
-                        size_t total = uatomic_read(&l->total);
-
-                        if (total > min) {
-                                SV *loc;
-                                dSP;
-                                ENTER;
-                                SAVETMPS;
-
-                                PUSHMARK(SP);
-                                loc = sv_newmortal();
-                                sv_setref_pv(loc, "Devel::Mwrap::SrcLoc", l);
-                                XPUSHs(arg);
-                                XPUSHs(loc);
-                                PUTBACK;
-
-                                call_sv(cb, G_DISCARD|G_EVAL);
-
-                                SPAGAIN;
-                                if (SvTRUE(ERRSV))
-                                        err = true;
-
-                                FREETMPS;
-                                LEAVE;
-                        }
-                        if (err)
-                                break;
-                        mwrap_assert(rcu_read_ongoing());
-                }
-        }
-        if (SvTRUE(ERRSV))
-                croak(NULL);
-CLEANUP:
-        rcu_read_unlock();
-        --locating;
-
-
-void
-mwrap_reset()
-CODE:
-        mwrap_reset();
-
-unsigned
-mwrap_bt_depth(arg = &PL_sv_undef)
-        SV *arg;
-CODE:
-        if (SvOK(arg)) {
-                UV n = SvUVx(arg);
-                if (n > MWRAP_BT_MAX)
-                        n = MWRAP_BT_MAX;
-                CMM_STORE_SHARED(bt_req_depth, (uint32_t)n);
-                RETVAL = n;
-        } else {
-                RETVAL = CMM_LOAD_SHARED(bt_req_depth);
-        }
-OUTPUT:
-        RETVAL
-
-Devel::Mwrap::SrcLoc
-mwrap_get(loc)
-        SV *loc;
-PREINIT:
-        STRLEN len;
-        const char *str;
-        struct src_loc *l;
-CODE:
-        ++locating;
-        if (!SvPOK(loc))
-                XSRETURN_UNDEF;
-        str = SvPV(loc, len);
-        l = mwrap_get(str, len);
-        if (!l)
-                XSRETURN_UNDEF;
-        RETVAL = l;
-OUTPUT:
-        RETVAL
-CLEANUP:
-        --locating;
-
-MODULE = Devel::Mwrap        PACKAGE = Devel::Mwrap::SrcLoc        PREFIX = src_loc_
-
-PROTOTYPES: ENABLE
-
-size_t
-src_loc_frees(self)
-        Devel::Mwrap::SrcLoc self
-PREINIT:
-CODE:
-        ++locating;
-        RETVAL = uatomic_read(&self->frees);
-OUTPUT:
-        RETVAL
-CLEANUP:
-        --locating;
-
-size_t
-src_loc_freed_bytes(self)
-        Devel::Mwrap::SrcLoc self
-PREINIT:
-CODE:
-        ++locating;
-        RETVAL = uatomic_read(&self->freed_bytes);
-OUTPUT:
-        RETVAL
-CLEANUP:
-        --locating;
-
-size_t
-src_loc_allocations(self)
-        Devel::Mwrap::SrcLoc self
-PREINIT:
-CODE:
-        ++locating;
-        RETVAL = uatomic_read(&self->allocations);
-OUTPUT:
-        RETVAL
-CLEANUP:
-        --locating;
-
-size_t
-src_loc_total(self)
-        Devel::Mwrap::SrcLoc self
-PREINIT:
-CODE:
-        ++locating;
-        RETVAL = uatomic_read(&self->total);
-OUTPUT:
-        RETVAL
-CLEANUP:
-        --locating;
-
-double
-src_loc_mean_lifespan(self)
-        Devel::Mwrap::SrcLoc self
-PREINIT:
-        size_t tot, frees;
-CODE:
-        ++locating;
-        frees = uatomic_read(&self->frees);
-        tot = uatomic_read(&self->age_total);
-        RETVAL = frees ? ((double)tot/(double)frees) : HUGE_VAL;
-OUTPUT:
-        RETVAL
-CLEANUP:
-        --locating;
-
-double
-src_loc_max_lifespan(self)
-        Devel::Mwrap::SrcLoc self
-CODE:
-        ++locating;
-        RETVAL = uatomic_read(&self->max_lifespan);
-OUTPUT:
-        RETVAL
-CLEANUP:
-        --locating;
-
-SV *
-src_loc_name(self)
-        Devel::Mwrap::SrcLoc self
-CODE:
-        ++locating;
-        RETVAL = location_string(self);
-OUTPUT:
-        RETVAL
-CLEANUP:
-        --locating;
-
-void
-src_loc_each(self, min, cb, arg = &PL_sv_undef)
-        Devel::Mwrap::SrcLoc self;
-        size_t min;
-        SV *cb;
-        SV *arg;
-PREINIT:
-        struct alloc_hdr *h;
-        bool err = false;
-CODE:
-        ++locating;
-        rcu_read_lock();
-        cds_list_for_each_entry_rcu(h, &self->allocs, anode) {
-                size_t size = uatomic_read(&h->size);
-                if (size > min) {
-                        dSP;
-                        ENTER;
-                        SAVETMPS;
-
-                        PUSHMARK(SP);
-
-                        /*
-                         * note: we MUST NOT expose alloc_hdr to Perl code
-                         * since that opens us up to use-after-free
-                         */
-                        XPUSHs(arg);
-                        XPUSHs(sv_2mortal(newSVuv(size)));
-                        XPUSHs(sv_2mortal(newSVuv(h->as.live.gen)));
-                        XPUSHs(sv_2mortal(newSVuv((uintptr_t)h->real)));
-                        PUTBACK;
-
-                        call_sv(cb, G_DISCARD|G_EVAL);
-
-                        SPAGAIN;
-                        if (SvTRUE(ERRSV))
-                                err = true;
-
-                        FREETMPS;
-                        LEAVE;
-                        if (err)
-                                break;
-                        mwrap_assert(rcu_read_ongoing());
-                }
-        }
-        if (SvTRUE(ERRSV))
-                croak(NULL);
-CLEANUP:
-        rcu_read_unlock();
-        --locating;
diff --git a/README b/README
index f8a1d1b..382c5a0 100644
--- a/README
+++ b/README
@@ -1,92 +1,97 @@
-Devel::Mwrap - LD_PRELOAD malloc wrapper + malloc line stats for Perl
+= mwrap - LD_PRELOAD malloc wrapper + line stats for Ruby
 
-Devel::Mwrap is designed to answer the question:
+mwrap is designed to answer the question:
 
-   Which lines of Perl are hitting malloc the most?
+   Which lines of Ruby are hitting malloc the most?
 
-Devel::Mwrap wraps all malloc-family calls to trace the Perl source
-location of such calls and bytes allocated at each callsite.  It
-can also function as a leak detector and show live allocations
-at every call site.  Depending on your application and workload,
-the overhead is roughly a 50%-100% increase memory and runtime.
+mwrap wraps all malloc-family calls to trace the Ruby source
+location of such calls and bytes allocated at each callsite.
+As of mwrap 2.0.0, it can also function as a leak detector
+and show live allocations at every call site.  Depending on
+your application and workload, the overhead is roughly a 50%
+increase memory and runtime.
 
-It is thread-safe and requires the concurrent lock-free hash table
-from the Userspace RCU project: https://liburcu.org/
+It works best for allocations under GVL, but tries to track
+numeric caller addresses for allocations made without GVL so you
+can get an idea of how much memory usage certain extensions and
+native libraries use.
 
-It relies on dynamic linking to a malloc(3) implementation.  If
-you got Perl from your OS distribution, this typically does not
-require rebuilding Perl.
+It requires the concurrent lock-free hash table from the
+Userspace RCU project: https://liburcu.org/
 
-Tested on the `perl' package distributed with:
+It does not require recompiling or rebuilding Ruby, but only
+supports Ruby 2.7.0 or later on a few platforms:
 
-* Debian GNU/Linux 10 and 11
-
-* FreeBSD 12.x
+* GNU/Linux
+* FreeBSD
 
 It may work on NetBSD, OpenBSD and DragonFly BSD.
 
 == Install
 
-See `INSTALL' document
+        # FreeBSD: pkg install liburcu
+
+        # Debian-based systems: apt-get liburcu-dev
+
+        # Install mwrap via RubyGems.org
+        gem install mwrap
 
 == Usage
 
-Devel::Mwrap works as an LD_PRELOAD and supplies a mwrap-perl script to
+mwrap works as an LD_PRELOAD and supplies a mwrap RubyGem executable to
 improve ease-of-use.  You can set dump_path: in the MWRAP environment
 variable to append the results to a log file:
 
-        MWRAP=dump_path:/path/to/log mwrap-perl PERL_COMMAND
+        MWRAP=dump_path:/path/to/log mwrap RUBY_COMMAND
 
         # And to display the locations with the most allocations:
         sort -k1,1rn </path/to/log | $PAGER
 
-You may also `use Devel::Mwrap' in your Perl code and use
-Devel::Mwrap->dump, Devel::Mwrap->reset, Devel::Mwrap->each, etc.
+You may also `require "mwrap"' in your Ruby code and use
+Mwrap.dump, Mwrap.reset, Mwrap.each, etc.
 
-However, Devel::Mwrap MUST be loaded via LD_PRELOAD to have any
+However, mwrap MUST be loaded via LD_PRELOAD to have any
 effect in tracking malloc use.  However, it is safe to keep
-"use Devel::Mwrap" in performance-critical deployments,
+"require 'mwrap'" in performance-critical deployments,
 as overhead is only incurred when used as an LD_PRELOAD.
 
-The output of the Devel::Mwrap->dump is a text file with 3 columns:
+The output of the mwrap dump is a text file with 3 columns:
 
         total_bytes        call_count        location
 
-Where location is a Perl source location or an address retrieved
-by backtrace_symbols(3).  It is recommended to use the sort(1)
-command on either of the first two columns to find the hottest
-malloc locations.
+Where location is a Ruby source location (if made under GVL)
+or an address retrieved by backtrace_symbols(3).  It is
+recommended to use the sort(1) command on either of the
+first two columns to find the hottest malloc locations.
 
-== Known problems
+mwrap 2.0.0+ also supports a Rack application endpoint,
+it is documented at:
 
-* 32-bit machines are prone to overflow (WONTFIX)
+https://80x24.org/mwrap/MwrapRack.html
 
-* signalfd(2)-reliant code will need latest URCU with commit
-  ea3a28a3f71dd02f (Disable signals in URCU background threads, 2022-09-23)
+== Known problems
 
-* Perl source files over 16.7 million lines long are not supported :P
+* 32-bit machines are prone to overflow (WONTFIX)
 
-== Public mail archives (HTTP, Atom feeds, IMAP mailbox, NNTP group):
+== Public mail archives and contact info:
 
-        https://80x24.org/mwrap-perl/
-        imaps://80x24.org/inbox.comp.lang.perl.mwrap.0
-        nntps://80x24.org/inbox.comp.lang.perl.mwrap
+* https://80x24.org/mwrap-public/
+* nntps://80x24.org/inbox.comp.lang.ruby.mwrap
+* imaps://;AUTH=ANONYMOUS@80x24.org/inbox.comp.lang.ruby.mwrap.0
+* https://80x24.org/mwrap-public/_/text/help/#pop3
 
-No subscription nor real identities will ever be required to
-obtain support.  Memory usage reductions start with you; only send
-plain-text mail to us and do not top-post.  HTML mail and top-posting
-costs everybody memory and bandwidth.
+No subscription will ever be required to post, but HTML mail
+will be rejected:
 
-                mwrap-perl@80x24.org
+                mwrap-public@80x24.org
 
 == Hacking
 
-        git clone https://80x24.org/mwrap-perl.git
+        git clone https://80x24.org/mwrap.git
 
-Send all patches ("git format-patch" + "git send-email") and
-pull requests (use "git request-pull" to format) via email
-to mwrap-perl@80x24.org.  We do not and will not use
-proprietary messaging systems.
+Send all patches and pull requests (use "git request-pull" to format) to
+mwrap-public@80x24.org.  We do not use centralized or proprietary messaging
+systems.
 
 == License
 
diff --git a/Rakefile b/Rakefile
new file mode 100644
index 0000000..cf4311e
--- /dev/null
+++ b/Rakefile
@@ -0,0 +1,52 @@
+# Copyright (C) mwrap hackers <mwrap-public@80x24.org>
+# License: GPL-2.0+ <https://www.gnu.org/licenses/gpl-2.0.txt>
+require 'rake/testtask'
+begin
+  require 'rake/extensiontask'
+  Rake::ExtensionTask.new('mwrap')
+rescue LoadError
+  warn 'rake-compiler not available, cross compiling disabled'
+end
+
+Rake::TestTask.new(:test)
+task 'test-ruby' => :compile
+task :default => :compile
+
+task 'test-httpd': 'lib/mwrap.so' do
+  require 'rbconfig'
+  ENV['RUBY'] = RbConfig.ruby
+  sh "#{ENV['PROVE'] || 'prove'} -v"
+end
+
+task test: %w(test-ruby test-httpd)
+
+c_files = File.readlines('MANIFEST').grep(%r{ext/.*\.[ch]$}).map!(&:chomp!)
+task 'compile:mwrap' => c_files
+
+olddoc = ENV['OLDDOC'] || 'olddoc'
+rdoc = ENV['RDOC'] || 'rdoc'
+task :rsync_docs do
+  require 'fileutils'
+  top = %w(README COPYING LATEST NEWS NEWS.atom.xml)
+  system("git", "set-file-times")
+  dest = ENV["RSYNC_DEST"] || "80x24.org:/srv/80x24/mwrap/"
+  FileUtils.rm_rf('doc')
+  sh "#{olddoc} prepare"
+  sh "#{rdoc} -f dark216" # dark216 requires olddoc 1.7+
+  File.unlink('doc/created.rid') rescue nil
+  File.unlink('doc/index.html') rescue nil
+  FileUtils.cp(top, 'doc')
+  sh "#{olddoc} merge"
+
+  Dir['doc/**/*'].each do |txt|
+    st = File.stat(txt)
+    if st.file?
+      gz = "#{txt}.gz"
+      tmp = "#{gz}.#$$"
+      sh("gzip --rsyncable -9 <#{txt} >#{tmp}")
+      File.utime(st.atime, st.mtime, tmp) # make nginx gzip_static happy
+      File.rename(tmp, gz)
+    end
+  end
+  sh("rsync --chmod=Fugo=r #{ENV['RSYNC_OPT']} -av doc/ #{dest}/")
+end
diff --git a/VERSION-GEN b/VERSION-GEN
new file mode 100755
index 0000000..ae66e94
--- /dev/null
+++ b/VERSION-GEN
@@ -0,0 +1,36 @@
+#!/bin/sh
+VF=lib/mwrap/version.rb
+DEF_VER=v2.3.0
+VN=$(git describe HEAD 2>/dev/null)
+if test $? -eq 0
+then
+        case "$VN" in
+        v[0-9]*)
+                set -e
+                git update-index -q --refresh
+                set +e
+                git diff-index --quiet HEAD -- || VN="$VN-dirty"
+                set -e
+                VN=$(echo $VN | tr '-' '.')
+                ;;
+        esac
+fi
+set -e
+
+case $VN in
+'') VN="$DEF_VER" ;;
+esac
+
+VN=$(expr "$VN" : v*'\(.*\)')
+VC=unset
+if test -r $VF
+then
+        VC="$(cat $VF)"
+fi
+
+new="module Mwrap; VERSION = '$VN'.freeze; end"
+if test x"$new" != x"$VC"
+then
+        echo "$new" >$VF
+fi
+echo $VN
diff --git a/bin/mwrap b/bin/mwrap
new file mode 100755
index 0000000..054b3a3
--- /dev/null
+++ b/bin/mwrap
@@ -0,0 +1,55 @@
+#!/usr/bin/ruby
+# frozen_string_literal: true
+# Copyright (C) mwrap hackers <mwrap-public@80x24.org>
+# License: GPL-2.0+ <https://www.gnu.org/licenses/gpl-2.0.txt>
+help = <<EOM
+usage: mwrap COMMAND [ARGS]
+see https://80x24.org/mwrap/README.html for more info
+EOM
+ARGV.empty? and abort help
+ARGV.each do |x|
+  case x
+  when '--version', '-v'
+    require 'mwrap/version'
+    puts "mwrap #{Mwrap::VERSION} - #{RUBY_DESCRIPTION}"
+    exit 0
+  when '--help', '-h'
+    puts help
+    exit 0
+  else # don't intercept --version/--help intended for commands we wrap
+    break
+  end
+end
+
+require 'mwrap'
+mwrap_so = $".grep(%r{/mwrap\.so\z})[0] or abort "mwrap.so not loaded"
+cur = ENV['LD_PRELOAD']
+if cur
+  cur = cur.split(/[:\s]+/)
+  if !cur.include?(mwrap_so)
+    # drop old versions
+    cur.delete_if { |path| path.end_with?('/mwrap.so') }
+    cur.unshift(mwrap_so)
+    ENV['LD_PRELOAD'] = cur.join(':')
+  end
+else
+  ENV['LD_PRELOAD'] = mwrap_so
+end
+
+# work around close-on-exec by default behavior in Ruby:
+opts = {}
+if ENV['MWRAP'] =~ /dump_fd:(\d+)/
+  dump_fd = $1.to_i
+  if dump_fd > 2
+    dump_io = IO.new(dump_fd)
+    opts[dump_fd] = dump_io
+  end
+end
+
+# allow inheriting FDs from systemd
+n = ENV['LISTEN_FDS']
+if n && ENV['LISTEN_PID'].to_i == $$
+  n = 3 + n.to_i
+  (3...n).each { |fd| opts[fd] = IO.new(fd) }
+end
+exec *ARGV, opts
diff --git a/examples/mwrap.psgi b/examples/mwrap.psgi
deleted file mode 100644
index b4fcafb..0000000
--- a/examples/mwrap.psgi
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright (C) all contributors <mwrap-perl@80x24.org>
-# License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt>
-# A startup command for development:
-#        plackup -I ./blib/lib -I ./blib/arch -o 127.0.0.1 examples/mwrap.psgi
-use v5.12;
-use Devel::Mwrap::PSGI;
-use Plack::Builder;
-my $mw = Devel::Mwrap::PSGI->new;
-delete $ENV{LD_PRELOAD}; # don't impose in subprocesses
-
-builder {
-        enable 'Head';
-        sub { $mw->call($_[0]) };
-}
diff --git a/exe.sh b/exe.sh
deleted file mode 100755
index c3ee2d3..0000000
--- a/exe.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/sh -e
-# symlink this file to a directory in PATH to run anything in script/*
-# without needing perms to install globally.  Used by "make symlink-install"
-p=$(realpath "$0" || readlink "$0") # neither is POSIX, but common
-p=$(dirname "$p") c=$(basename "$0") # both are POSIX
-exec ${PERL-perl} -w -I"$p"/blib/lib -I"$p"/blib/arch \
-        "$p"/script/"${c%.sh}" "$@"
-: this script is too short to copyright
diff --git a/check.h b/ext/mwrap/check.h
index f4f4ac5..f4f4ac5 100644
--- a/check.h
+++ b/ext/mwrap/check.h
diff --git a/dlmalloc_c.h b/ext/mwrap/dlmalloc_c.h
index 38a0846..38a0846 100644
--- a/dlmalloc_c.h
+++ b/ext/mwrap/dlmalloc_c.h
diff --git a/ext/mwrap/extconf.rb b/ext/mwrap/extconf.rb
new file mode 100644
index 0000000..3336548
--- /dev/null
+++ b/ext/mwrap/extconf.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+# Copyright (C) mwrap hackers <mwrap-public@80x24.org>
+# License: GPL-2.0+ <https://www.gnu.org/licenses/gpl-2.0.txt>
+require 'mkmf'
+
+have_func 'mempcpy'
+have_library 'urcu-cds' or abort 'userspace RCU not installed'
+have_header 'urcu/rculfhash.h' or abort 'rculfhash.h not found'
+have_library 'urcu-bp' or abort 'liburcu-bp not found'
+have_library 'dl'
+have_library 'c'
+have_library 'execinfo' # FreeBSD
+$defs << '-DHAVE_XXHASH' if have_header('xxhash.h')
+
+have_struct_member('struct sockaddr_un', 'sun_len', %w(sys/socket sys/un.h))
+
+if try_link(<<EOC)
+int main(void) { return __builtin_add_overflow_p(0,0,(int)1); }
+EOC
+  $defs << '-DHAVE_BUILTIN_ADD_OVERFLOW_P'
+end
+
+if try_link(<<EOC)
+int main(int a) { return __builtin_add_overflow(0,0,&a); }
+EOC
+  $defs << '-DHAVE_BUILTIN_ADD_OVERFLOW_P'
+else
+  abort 'missing __builtin_add_overflow'
+end
+
+create_makefile 'mwrap'
diff --git a/gcc.h b/ext/mwrap/gcc.h
index 2312aa9..2312aa9 100644
--- a/gcc.h
+++ b/ext/mwrap/gcc.h
diff --git a/httpd.h b/ext/mwrap/httpd.h
index 36e487d..03aef9f 100644
--- a/httpd.h
+++ b/ext/mwrap/httpd.h
@@ -1145,7 +1145,7 @@ static void h1d_unlink(struct mw_h1d *h1d, bool do_close)
 static int h1d_init(struct mw_h1d *h1d, const char *menv)
 {
         union mw_sockaddr sa = { .un = { .sun_family = AF_UNIX } };
-#ifdef HAS_SOCKADDR_SA_LEN
+#if defined(HAS_SOCKADDR_SA_LEN) || defined(HAVE_STRUCT_SOCKADDR_UN_SUN_LEN)
         sa.un.sun_len = (unsigned char)sizeof(struct sockaddr_un);
 #endif
         const char *env = strstr(menv, "socket_dir:");
diff --git a/jhash.h b/ext/mwrap/jhash.h
index 69666f3..69666f3 100644
--- a/jhash.h
+++ b/ext/mwrap/jhash.h
diff --git a/ext/mwrap/mwrap.c b/ext/mwrap/mwrap.c
new file mode 100644
index 0000000..d88fee6
--- /dev/null
+++ b/ext/mwrap/mwrap.c
@@ -0,0 +1,396 @@
+/*
+ * Copyright (C) mwrap hackers <mwrap-public@80x24.org>
+ * License: GPL-2.0+ <https://www.gnu.org/licenses/gpl-2.0.txt>
+ */
+#define MWRAP_RUBY 1
+#include "mwrap_core.h"
+
+static ID id_uminus;
+extern VALUE __attribute__((weak)) rb_cObject;
+extern VALUE __attribute__((weak)) rb_eTypeError;
+extern VALUE __attribute__((weak)) rb_yield(VALUE);
+
+/*
+ * call-seq:
+ *
+ *        Mwrap.dump([[io] [, min]] -> nil
+ *
+ * Dumps the current totals to +io+ which must be an IO object
+ * (StringIO and similar are not supported).  Total sizes smaller
+ * than or equal to +min+ are skipped.
+ *
+ * The output is space-delimited by 3 columns:
+ *
+ * total_size      call_count      location
+ */
+static VALUE mwrap_dump(int argc, VALUE *argv, VALUE mod)
+{
+        VALUE io, min;
+        struct dump_arg a;
+        rb_io_t *fptr;
+
+        rb_scan_args(argc, argv, "02", &io, &min);
+
+        if (NIL_P(io))
+                /* library may be linked w/o Ruby */
+                io = *((VALUE *)dlsym(RTLD_DEFAULT, "rb_stderr"));
+
+        a.min = NIL_P(min) ? 0 : NUM2SIZET(min);
+        io = rb_io_get_io(io);
+        io = rb_io_get_write_io(io);
+        GetOpenFile(io, fptr);
+        a.fp = rb_io_stdio_file(fptr);
+
+        rb_thread_call_without_gvl((void *(*)(void *))dump_to_file, &a, 0, 0);
+        RB_GC_GUARD(io);
+        return Qnil;
+}
+
+/* The whole operation is not remotely atomic... */
+static void *totals_reset(void *ign)
+{
+        mwrap_reset();
+        return NULL;
+}
+
+/*
+ * call-seq:
+ *
+ *        Mwrap.reset -> nil
+ *
+ * Resets the the total tables by zero-ing all counters.
+ * This resets all statistics.  This is not an atomic operation
+ * as other threads (outside of GVL) may increment counters.
+ */
+static VALUE reset_m(VALUE mod)
+{
+        rb_thread_call_without_gvl(totals_reset, 0, 0, 0);
+        return Qnil;
+}
+
+static VALUE rcu_unlock_ensure(VALUE ignored)
+{
+        rcu_read_unlock();
+        --locating;
+        return Qfalse;
+}
+
+static VALUE location_string(const struct src_loc *l)
+{
+        VALUE tmp = rb_str_new(NULL, 0);
+
+        if (l->f) {
+                rb_str_cat(tmp, l->f->fn, l->f->fn_len);
+                if (l->lineno == U24_MAX)
+                        rb_str_cat_cstr(tmp, ":-");
+                else
+                        rb_str_catf(tmp, ":%u", l->lineno);
+        }
+        if (l->bt_len) {
+                AUTO_FREE char **s = bt_syms(l->bt, l->bt_len);
+
+                if (s) {
+                        if (l->f)
+                                rb_str_cat_cstr(tmp, "\n");
+                        rb_str_cat_cstr(tmp, s[0]);
+                        for (uint32_t i = 1; i < l->bt_len; ++i)
+                                rb_str_catf(tmp, "\n%s", s[i]);
+                }
+        }
+
+        /* deduplicate and try to free up some memory */
+        VALUE ret = rb_funcall(tmp, id_uminus, 0);
+        if (!OBJ_FROZEN_RAW(tmp))
+                rb_str_resize(tmp, 0);
+
+        return ret;
+}
+
+static VALUE dump_each_rcu(VALUE x)
+{
+        struct dump_arg *a = (struct dump_arg *)x;
+        struct cds_lfht *t;
+        struct cds_lfht_iter iter;
+        struct src_loc *l;
+
+        t = CMM_LOAD_SHARED(totals);
+        cds_lfht_for_each_entry(t, &iter, l, hnode) {
+                VALUE v[6];
+                if (l->total <= a->min) continue;
+
+                v[0] = location_string(l);
+                v[1] = SIZET2NUM(l->total);
+                v[2] = SIZET2NUM(l->allocations);
+                v[3] = SIZET2NUM(l->frees);
+                v[4] = SIZET2NUM(l->age_total);
+                v[5] = SIZET2NUM(l->max_lifespan);
+
+                rb_yield_values2(6, v);
+                assert(rcu_read_ongoing());
+        }
+        return Qnil;
+}
+
+/*
+ * call-seq:
+ *
+ *        Mwrap.each([min]) do |location,total,allocations,frees,age_total,max_lifespan|
+ *          ...
+ *        end
+ *
+ * Yields each entry of the of the table to a caller-supplied block.
+ * +min+ may be specified to filter out lines with +total+ bytes
+ * equal-to-or-smaller-than the supplied minimum.
+ */
+static VALUE mwrap_each(int argc, VALUE * argv, VALUE mod)
+{
+        VALUE min;
+        struct dump_arg a;
+
+        rb_scan_args(argc, argv, "01", &min);
+        a.min = NIL_P(min) ? 0 : NUM2SIZET(min);
+
+        ++locating;
+        rcu_read_lock();
+
+        return rb_ensure(dump_each_rcu, (VALUE)&a, rcu_unlock_ensure, 0);
+}
+
+static size_t
+src_loc_memsize(const void *p)
+{
+        return sizeof(struct src_loc);
+}
+
+static const rb_data_type_t src_loc_type = {
+        "source_location",
+        /* no marking, no freeing */
+        { 0, 0, src_loc_memsize, /* reserved */ },
+        /* parent, data, [ flags ] */
+};
+
+static VALUE cSrcLoc;
+
+/*
+ * call-seq:
+ *        Mwrap[location] -> Mwrap::SourceLocation
+ *
+ * Returns the associated Mwrap::SourceLocation given the +location+
+ * String.  +location+ is either a Ruby source location path:line
+ * (e.g. "/path/to/foo.rb:5") or a hexadecimal memory address with
+ * square-braces part yielded by Mwrap.dump (e.g. "[0xdeadbeef]")
+ */
+static VALUE mwrap_aref(VALUE mod, VALUE loc)
+{
+        const char *str = StringValueCStr(loc);
+        long len = RSTRING_LEN(loc);
+        assert(len >= 0);
+        struct src_loc *l = mwrap_get(str, (size_t)len);
+
+        return l ? TypedData_Wrap_Struct(cSrcLoc, &src_loc_type, l) : Qnil;
+}
+
+static VALUE src_loc_each_i(VALUE p)
+{
+        struct alloc_hdr *h;
+        struct src_loc *l = (struct src_loc *)p;
+
+        cds_list_for_each_entry_rcu(h, &l->allocs, anode) {
+                size_t gen = uatomic_read(&h->as.live.gen);
+                size_t size = uatomic_read(&h->size);
+
+                if (size) {
+                        VALUE v[2];
+                        v[0] = SIZET2NUM(size);
+                        v[1] = SIZET2NUM(gen);
+
+                        rb_yield_values2(2, v);
+                }
+        }
+
+        return Qfalse;
+}
+
+static struct src_loc *src_loc_of(VALUE self)
+{
+        struct src_loc *l;
+        TypedData_Get_Struct(self, struct src_loc, &src_loc_type, l);
+        assert(l);
+        return l;
+}
+
+/*
+ * call-seq:
+ *        loc = Mwrap[location]
+ *        loc.each { |size,generation| ... }
+ *
+ * Iterates through live allocations for a given Mwrap::SourceLocation,
+ * yielding the +size+ (in bytes) and +generation+ of each allocation.
+ * The +generation+ is the value of the GC.count method at the time
+ * the allocation was made.
+ *
+ * This functionality is only available in mwrap 2.0.0+
+ */
+static VALUE src_loc_each(VALUE self)
+{
+        struct src_loc *l = src_loc_of(self);
+
+        assert(locating == 0 && "forgot to clear locating");
+        ++locating;
+        rcu_read_lock();
+        rb_ensure(src_loc_each_i, (VALUE)l, rcu_unlock_ensure, 0);
+        return self;
+}
+
+/*
+ * The the mean lifespan (in GC generations) of allocations made from this
+ * location.  This does not account for live allocations.
+ */
+static VALUE src_loc_mean_lifespan(VALUE self)
+{
+        struct src_loc *l = src_loc_of(self);
+        size_t tot, frees;
+
+        frees = uatomic_read(&l->frees);
+        tot = uatomic_read(&l->age_total);
+        return DBL2NUM(frees ? ((double)tot/(double)frees) : HUGE_VAL);
+}
+
+/* The number of frees made from this location */
+static VALUE src_loc_frees(VALUE self)
+{
+        return SIZET2NUM(uatomic_read(&src_loc_of(self)->frees));
+}
+
+/* The number of allocations made from this location */
+static VALUE src_loc_allocations(VALUE self)
+{
+        return SIZET2NUM(uatomic_read(&src_loc_of(self)->allocations));
+}
+
+/* The total number of bytes allocated from this location */
+static VALUE src_loc_total(VALUE self)
+{
+        return SIZET2NUM(uatomic_read(&src_loc_of(self)->total));
+}
+
+/*
+ * The maximum age (in GC generations) of an allocation before it was freed.
+ * This does not account for live allocations.
+ */
+static VALUE src_loc_max_lifespan(VALUE self)
+{
+        return SIZET2NUM(uatomic_read(&src_loc_of(self)->max_lifespan));
+}
+
+/*
+ * Returns a frozen String location of the given SourceLocation object.
+ */
+static VALUE src_loc_name(VALUE self)
+{
+        struct src_loc *l = src_loc_of(self);
+        VALUE ret;
+
+        ++locating;
+        ret = location_string(l);
+        --locating;
+        return ret;
+}
+
+static VALUE reset_locating(VALUE ign) { --locating; return Qfalse; }
+
+/*
+ * call-seq:
+ *
+ *        Mwrap.quiet do |depth|
+ *          # expensive sort/calculate/emitting results of Mwrap.each
+ *          # affecting statistics of the rest of the app
+ *        end
+ *
+ * Stops allocation tracking inside the block.  This is useful for
+ * monitoring code which calls other Mwrap (or ObjectSpace/GC)
+ * functions which unavoidably allocate memory.
+ *
+ * This feature was added in mwrap 2.0.0+
+ */
+static VALUE mwrap_quiet(VALUE mod)
+{
+        size_t cur = ++locating;
+        return rb_ensure(rb_yield, SIZET2NUM(cur), reset_locating, 0);
+}
+
+/*
+ * total bytes allocated as tracked by mwrap
+ */
+static VALUE total_inc(VALUE mod)
+{
+        return SIZET2NUM(total_bytes_inc);
+}
+
+/*
+ * total bytes freed as tracked by mwrap
+ */
+static VALUE total_dec(VALUE mod)
+{
+        return SIZET2NUM(total_bytes_dec);
+}
+
+/*
+ * Document-module: Mwrap
+ *
+ *   require 'mwrap'
+ *
+ * Mwrap has a dual function as both a Ruby C extension and LD_PRELOAD
+ * wrapper.  As a Ruby C extension, it exposes a limited Ruby API.
+ * To be effective at gathering status, mwrap must be loaded as a
+ * LD_PRELOAD (using the mwrap(1) executable makes it easy)
+ *
+ * ENVIRONMENT
+ *
+ * The "MWRAP" environment variable contains a comma-delimited list
+ * of key:value options for automatically dumping at program exit.
+ *
+ * * dump_fd: a writable FD to dump to
+ * * dump_path: a path to dump to, the file is opened in O_APPEND mode
+ * * dump_min: the minimum allocation size (total) to dump
+ *
+ * If both `dump_fd' and `dump_path' are specified, dump_path takes
+ * precedence.
+ */
+void Init_mwrap(void)
+{
+        VALUE mod;
+
+        ++locating;
+        mod = rb_define_module("Mwrap");
+        id_uminus = rb_intern("-@");
+
+        /*
+         * Represents a location in source code or library
+         * address which calls a memory allocation.  It is
+         * updated automatically as allocations are made, so
+         * there is no need to reload or reread it from Mwrap#[].
+         * This class is only available since mwrap 2.0.0+.
+         */
+        cSrcLoc = rb_define_class_under(mod, "SourceLocation", rb_cObject);
+        rb_undef_alloc_func(cSrcLoc);
+        rb_define_singleton_method(mod, "dump", mwrap_dump, -1);
+        rb_define_singleton_method(mod, "reset", reset_m, 0);
+        rb_define_singleton_method(mod, "clear", reset_m, 0);
+        rb_define_singleton_method(mod, "each", mwrap_each, -1);
+        rb_define_singleton_method(mod, "[]", mwrap_aref, 1);
+        rb_define_singleton_method(mod, "quiet", mwrap_quiet, 0);
+        rb_define_singleton_method(mod, "total_bytes_allocated", total_inc, 0);
+        rb_define_singleton_method(mod, "total_bytes_freed", total_dec, 0);
+
+
+        rb_define_method(cSrcLoc, "each", src_loc_each, 0);
+        rb_define_method(cSrcLoc, "frees", src_loc_frees, 0);
+        rb_define_method(cSrcLoc, "allocations", src_loc_allocations, 0);
+        rb_define_method(cSrcLoc, "total", src_loc_total, 0);
+        rb_define_method(cSrcLoc, "mean_lifespan", src_loc_mean_lifespan, 0);
+        rb_define_method(cSrcLoc, "max_lifespan", src_loc_max_lifespan, 0);
+        rb_define_method(cSrcLoc, "name", src_loc_name, 0);
+
+        --locating;
+}
diff --git a/mwrap_core.h b/ext/mwrap/mwrap_core.h
index 02b60f3..c0eea2f 100644
--- a/mwrap_core.h
+++ b/ext/mwrap/mwrap_core.h
@@ -4,13 +4,14 @@
  * Disclaimer: I don't really know my way around XS or Perl internals well
  */
 #define _LGPL_SOURCE /* allows URCU to inline some stuff */
+#define _GNU_SOURCE
 #include "mymalloc.h" /* includes dlmalloc_c.h */
 #ifndef MWRAP_PERL
 #        define MWRAP_PERL 0
 #endif
 
-#if !MWRAP_PERL
-typedef void COP;
+#ifndef MWRAP_RUBY
+#        define MWRAP_RUBY 0
 #endif
 
 /* set a sensible max to avoid stack overflows */
@@ -18,15 +19,9 @@ typedef void COP;
 #        define        MWRAP_BT_MAX 32
 #endif
 
-
-#if MWRAP_PERL
-#        include "EXTERN.h"
-#        include "perl.h"
-#        include "XSUB.h"
-#        include "embed.h"
-#        include "ppport.h"
+#ifndef _GNU_SOURCE
+#        define _GNU_SOURCE
 #endif
-
 #include <execinfo.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -44,6 +39,21 @@ typedef void COP;
 #include <urcu/rculist.h>
 #include <limits.h>
 
+#if MWRAP_PERL
+#        include "EXTERN.h"
+#        include "perl.h"
+#        include "XSUB.h"
+#        include "embed.h"
+#        include "ppport.h"
+#endif
+
+#if MWRAP_RUBY
+#        undef _GNU_SOURCE /* ruby.h redefines it */
+#        include <ruby.h> /* defines HAVE_RUBY_RACTOR_H on 3.0+ */
+#        include <ruby/thread.h>
+#        include <ruby/io.h>
+#endif
+
 /*
  * XXH3 (truncated to 32-bits) seems to provide a ~2% speedup.
  * XXH32 doesn't show improvements over jhash despite rculfhash
@@ -75,12 +85,56 @@ static uint32_t bt_req_depth;
 #if MWRAP_PERL
 extern pthread_key_t __attribute__((weak)) PL_thr_key;
 extern const char __attribute__((weak)) PL_memory_wrap[]; /* needed for -O0 */
-#endif
+#        if !defined(PERL_IMPLICIT_CONTEXT)
+static size_t *root_locating; /* determines if PL_curcop is our thread */
+#        endif
+#endif /* MWRAP_PERL */
+
+#if MWRAP_RUBY
+const char *rb_source_location_cstr(int *line); /* requires 2.6.0dev or later */
+
+#        ifdef HAVE_RUBY_RACTOR_H /* Ruby 3.0+ */
+extern MWRAP_TSD void * __attribute__((weak)) ruby_current_ec;
+#        else /* Ruby 2.6-2.7 */
+extern void * __attribute__((weak)) ruby_current_execution_context_ptr;
+#                define ruby_current_ec ruby_current_execution_context_ptr
+#        endif /* HAVE_RUBY_RACTOR_H */
+
+extern void * __attribute__((weak)) ruby_current_vm_ptr; /* for rb_gc_count */
+extern size_t __attribute__((weak)) rb_gc_count(void);
+int __attribute__((weak)) ruby_thread_has_gvl_p(void);
+
+/*
+ * rb_source_location_cstr relies on GET_EC(), and it's possible
+ * to have a native thread but no EC during the early and late
+ * (teardown) phases of the Ruby process
+ */
+static int has_ec_p(void)
+{
+        return ruby_thread_has_gvl_p && ruby_thread_has_gvl_p() &&
+                ruby_current_vm_ptr && ruby_current_ec;
+}
 
+static void set_generation(size_t *gen, size_t size)
+{
+        if (rb_gc_count) {
+                uatomic_add_return(&total_bytes_inc, size);
+                if (has_ec_p())
+                        *gen = rb_gc_count();
+        } else {
+                *gen = uatomic_add_return(&total_bytes_inc, size);
+        }
+}
+#        define SET_GENERATION(gen, size) set_generation(gen, size)
+#endif /* MWRAP_RUBY */
+
+#ifndef SET_GENERATION
+#        define SET_GENERATION(gen, size) \
+                *gen = uatomic_add_return(&total_bytes_inc, size)
+#endif /* !SET_GENERATION */
+
+/* generic stuff: */
 static MWRAP_TSD size_t locating;
-#if MWRAP_PERL && !defined(PERL_IMPLICIT_CONTEXT)
-static size_t *root_locating; /* determines if PL_curcop is our thread */
-#endif
 static struct cds_lfht *files, *totals;
 union padded_mutex {
         pthread_mutex_t mtx;
@@ -142,6 +196,7 @@ static void *my_mempcpy(void *dest, const void *src, size_t n)
 
 /*
  * only for interpreted sources (Perl/Ruby/etc), not backtrace_symbols* files
+ * Allocated via real_malloc / real_free
  */
 struct src_file {
         struct cds_lfht_node nd; /* <=> files table */
@@ -179,7 +234,7 @@ struct alloc_hdr {
         struct cds_list_head anode; /* <=> src_loc.allocs */
         union {
                 struct {
-                        size_t gen; /* global age */
+                        size_t gen; /* global age || rb_gc_count() */
                         struct src_loc *loc;
                 } live;
                 struct rcu_head dead;
@@ -319,20 +374,6 @@ again:
         return l;
 }
 
-static const COP *mwp_curcop(void)
-{
-#if MWRAP_PERL
-        if (&PL_thr_key) { /* are we even in a Perl process? */
-#        ifdef PERL_IMPLICIT_CONTEXT
-                if (aTHX) return PL_curcop;
-#        else /* !PERL_IMPLICIT_CONTEXT */
-                if (&locating == root_locating) return PL_curcop;
-#        endif /* PERL_IMPLICIT_CONTEXT */
-        }
-#endif /* MWRAP_PERL */
-        return NULL;
-}
-
 static uint32_t do_hash(const void *p, size_t len)
 {
 #if defined(XXH3_64bits)
@@ -372,18 +413,50 @@ static struct src_file *src_file_get(struct cds_lfht *t, struct src_file *k,
         return cur ? caa_container_of(cur, struct src_file, nd) : NULL;
 }
 
-#if !MWRAP_PERL
-#        define CopFILE(cop) NULL
-#        define CopLINE(cop) 0
-#endif
-static struct src_loc *assign_line(size_t size, const COP *cop,
-                                struct src_loc *sl)
+#if MWRAP_PERL
+static const COP *mwp_curcop(void)
 {
-        /* avoid vsnprintf or anything which could call malloc here: */
+        if (&PL_thr_key) { /* are we even in a Perl process? */
+#        ifdef PERL_IMPLICIT_CONTEXT
+                if (aTHX) return PL_curcop;
+#        else /* !PERL_IMPLICIT_CONTEXT */
+                if (&locating == root_locating) return PL_curcop;
+#        endif /* PERL_IMPLICIT_CONTEXT */
+        }
+        return NULL;
+}
+
+static const char *mw_perl_src_file_cstr(unsigned *lineno)
+{
+        const COP *cop = mwp_curcop();
         if (!cop) return NULL;
         const char *fn = CopFILE(cop);
         if (!fn) return NULL;
-        unsigned lineno = CopLINE(cop);
+        *lineno = CopLINE(cop);
+        return fn;
+}
+#        define SRC_FILE_CSTR(lineno) mw_perl_src_file_cstr(lineno)
+#endif /* MWRAP_PERL */
+
+#if MWRAP_RUBY
+static const char *mw_ruby_src_file_cstr(unsigned *lineno)
+{
+        if (!has_ec_p()) return NULL;
+        int line;
+        const char *fn = rb_source_location_cstr(&line);
+        *lineno = line < 0 ? UINT_MAX : (unsigned)line;
+        return fn;
+}
+#        define SRC_FILE_CSTR(lineno) mw_ruby_src_file_cstr(lineno)
+#endif /* MWRAP_RUBY */
+
+#ifndef SRC_FILE_CSTR /* for C-only compilation */
+#        define SRC_FILE_CSTR(lineno)        (NULL)
+#endif /* !SRC_FILE_CSTR */
+
+static struct src_loc *assign_line(size_t size, struct src_loc *sl,
+                                const char *fn, unsigned lineno)
+{
         struct src_file *f;
         union stk_sf sf;
         struct cds_lfht_node *cur;
@@ -430,7 +503,7 @@ again:
 }
 
 static struct src_loc *
-update_stats_rcu_lock(size_t *generation, size_t size, struct src_loc *sl)
+update_stats_rcu_lock(size_t *gen, size_t size, struct src_loc *sl)
 {
         struct cds_lfht *t = CMM_LOAD_SHARED(totals);
         struct src_loc *ret = NULL;
@@ -438,11 +511,15 @@ update_stats_rcu_lock(size_t *generation, size_t size, struct src_loc *sl)
         if (caa_unlikely(!t)) return 0; /* not initialized */
         if (locating++) goto out; /* do not recurse into another *alloc */
 
-        *generation = uatomic_add_return(&total_bytes_inc, size);
-        const COP *cop = mwp_curcop();
+        SET_GENERATION(gen, size);
+
+        unsigned lineno;
+        const char *fn = SRC_FILE_CSTR(&lineno);
+
         rcu_read_lock();
-        ret = assign_line(size, cop, sl);
-        if (!ret) { /* no associated Perl code, just C/C++ */
+        if (fn)
+                ret = assign_line(size, sl, fn, lineno);
+        if (!ret) { /* no associated Perl|Ruby code, just C/C++ */
                 sl->total = size;
                 sl->f = NULL;
                 sl->lineno = 0;
diff --git a/mymalloc.h b/ext/mwrap/mymalloc.h
index 6b5a22d..196ccc0 100644
--- a/mymalloc.h
+++ b/ext/mwrap/mymalloc.h
@@ -100,6 +100,8 @@ static void *my_mmap(size_t size)
 #endif
 #include "dlmalloc_c.h"
 #undef ABORT /* conflicts with Perl */
+#undef NOINLINE /* conflicts with Ruby, defined by dlmalloc_c.h */
+#undef HAVE_MREMAP /* conflicts with Ruby 3.2 */
 
 static MWRAP_TSD mstate ms_tsd;
 
diff --git a/picohttpparser.h b/ext/mwrap/picohttpparser.h
index 0927985..0927985 100644
--- a/picohttpparser.h
+++ b/ext/mwrap/picohttpparser.h
diff --git a/picohttpparser_c.h b/ext/mwrap/picohttpparser_c.h
index c5e345d..c5e345d 100644
--- a/picohttpparser_c.h
+++ b/ext/mwrap/picohttpparser_c.h
diff --git a/lib/Devel/Mwrap.pm b/lib/Devel/Mwrap.pm
deleted file mode 100644
index 2691802..0000000
--- a/lib/Devel/Mwrap.pm
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright (C) all contributors <mwrap-perl@80x24.org>
-# License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt>
-package Devel::Mwrap;
-use v5.12;
-our $VERSION = '0.0.0';
-use XSLoader;
-XSLoader::load(__PACKAGE__, $VERSION);
-
-# allow using via the "-d:Mwrap" switch on the command-line:
-package # hide the package from the PAUSE indexer
-        DB;
-
-sub DB {} # noop, just keeps "-d:Mwrap" happy
-
-1;
-__END__
-=pod
-
-=head1 NAME
-
-Devel::Mwrap - LD_PRELOAD malloc wrapper + line stats for Perl
diff --git a/lib/Devel/Mwrap/PSGI.pm b/lib/Devel/Mwrap/PSGI.pm
deleted file mode 100644
index 3a3a29b..0000000
--- a/lib/Devel/Mwrap/PSGI.pm
+++ /dev/null
@@ -1,190 +0,0 @@
-# Copyright (C) all contributors <mwrap@80x24.org>
-# License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt>
-#
-# Note: this is deprecated, use httpd.h instead
-package Devel::Mwrap::PSGI;
-use v5.12; # strict
-use warnings;
-use Devel::Mwrap;
-use Fcntl qw(SEEK_SET);
-
-sub new {
-        my ($class) = @_;
-        bless {}, $class;
-}
-
-my %HTML_ESC = (
-        '&' => '&amp;',
-        '>' => '&gt;',
-        '<' => '&lt;',
-        '"' => '&quot;',
-        "'" => '&#39;'
-);
-
-sub encode_html {
-        my ($str) = @_;
-        $str =~ s/[&><"']/$HTML_ESC{$1}/sge;
-        $str;
-}
-
-my %URI_ESC;
-for (0..255) { $URI_ESC{chr($_)} = sprintf('%%%02X', $_) }
-sub uri_escape {
-        my ($str) = @_;
-        $str =~ s/([^A-Za-z0-9\-\._~])/$URI_ESC{$1}/sge;
-        $str;
-}
-
-sub uri_unescape {
-        my ($str) = @_;
-        $str =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/sge;
-        $str;
-}
-
-my @FIELDS = qw(bytes allocations frees live
-                mean_life max_life location);
-my $HDR = '<tr><th>' . join('</th><th>', @FIELDS) . '</th></tr>';
-
-sub accumulate_i { # callback for Devel::Mwrap::each
-        my ($all, $src_loc) = @_;
-        my $alloc = $src_loc->allocations;
-        my $frees = $src_loc->frees;
-        push @$all, [ $src_loc->total - $src_loc->freed_bytes,
-                        $alloc, $frees, $alloc - $frees,
-                        $src_loc->mean_lifespan, $src_loc->max_lifespan,
-                        $src_loc->name ];
-}
-
-sub fh_response {
-        my ($fh) = @_;
-        $fh->flush or die "flush: $!";
-        seek($fh, 0, SEEK_SET) or die "seek: $!";
-        [ 200, [
-                'Expires' => 'Fri, 01 Jan 1980 00:00:00 GMT',
-                'Pragma' => 'no-cache',
-                'Cache-Control' => 'no-cache, max-age=0, must-revalidate',
-                'Content-Type' => 'text/html; charset=UTF-8',
-                'Content-Length' => -s $fh
-        ], $fh];
-}
-
-sub each_gt {
-        my ($env, $min) = @_;
-        my ($sort) = ($env->{QUERY_STRING} =~ /\bsort=(\w+)\b/a);
-        open my $fh, '+>', undef or die "open: $!";
-        $sort //= 'bytes';
-        my $sn = $env->{SCRIPT_NAME};
-        my $t = "Devel::Mwrap::each($min)";
-        my $all = [];
-        my @f = @FIELDS;
-        my $sc = 0;
-        for (my $i = 0; $i <= $#FIELDS; $i++) {
-                if ($FIELDS[$i] eq $sort) {
-                        $sc = $i;
-                        last;
-                }
-        }
-        $f[$sc] = "<b>$f[$sc]</b>";
-        @f = (join('</th><th>', map {;
-                if (substr($_, 0, 1) eq '<') {
-                        $_;
-                } else {
-                        qq(<a\nhref="$sn/each/$min?sort=$_">$_</a>);
-                }
-        } @f));
-        my @all;
-        Devel::Mwrap::each($min, \&accumulate_i, \@all);
-        if ($sc eq $#FIELDS) { # locations are sorted alphabetically
-                @all = sort { $a->[$sc] cmp $b->[$sc] } @all;
-        } else { # everything else is numeric
-                @all = sort { $b->[$sc] <=> $a->[$sc] } @all;
-        }
-        my $age = Devel::Mwrap::current_age();
-        my $live = $age - Devel::Mwrap::total_bytes_freed();
-        print $fh <<EOM;
-<html><head><title>$t</title></head><body><p>$t
-<p>Current age: $age (live: $live)
-<table><tr><th>@f</th></tr>
-EOM
-        while (my $cols = shift @all) {
-                # cols: [ bytes , allocations, frees, mean_lifespan,
-                #   max_lifespan, name ]
-                my $loc_name = pop @$cols;
-                $cols->[4] = sprintf('%0.3f', $cols->[4]); # mean_life
-                my $href = "$sn/at/".uri_escape($loc_name);
-                print $fh '<tr><td>', join('</td><td>', @$cols),
-                        qq(<td><a\nhref="),
-                                encode_html($href),
-                        qq(">), encode_html($loc_name),
-                        "</a></td></tr>\n";
-        }
-        print $fh "</table></body></html>\n";
-        fh_response($fh);
-}
-
-sub each_at_i {
-        my ($fh, $size, $gen, $addr) = @_;
-        print $fh "<tr><td>$size</td><td>$gen</td><td>";
-        printf $fh "0x%lx</td></tr>\n", $addr;
-}
-
-sub each_at {
-        my ($env, $src_loc) = @_;
-        my $t = encode_html($src_loc->name);
-        open my $fh, '+>', undef or die "open: $!";
-        my $age = Devel::Mwrap::current_age();
-        my $live = $age - Devel::Mwrap::total_bytes_freed();
-        print $fh <<EOM;
-<html><head><title>$t</title></head><body><p>live allocations at $t
-<p>Current age: $age (live: $live)\n<table>
-<tr><th>size</th><th>generation</th><th>address</th></tr>
-EOM
-        $src_loc->each(0, \&each_at_i, $fh);
-        print $fh "</table></body></html>\n";
-        fh_response($fh);
-}
-
-sub r404 {
-        my $t404 = "Not Found\n";
-        [ 404, [ qw(Content-Type text/plain
-                Content-Length), length($t404) ], [ $t404 ] ];
-}
-
-my $default_min = 2000;
-my $url = 'https://80x24.org/mwrap-perl.git/about';
-chomp(my $root = <<EOM);
-<html><head><title>Mwrap demo</title></head><body><p><a
-href="each/$default_min">allocations &gt;$default_min bytes</a><p><a
-href="$url">$url</a></body></html>
-EOM
-
-sub call { # PSGI entry point
-        Devel::Mwrap::quiet(1);
-        my (undef, $env) = @_;
-        my $ret;
-        my $path_info = $env->{PATH_INFO};
-        if ($env->{REQUEST_METHOD} eq 'GET') {
-                if ($path_info =~ m!\A/each/([0-9]+)\z!) {
-                        $ret = each_gt($env, $1 + 0);
-                } elsif ($path_info =~ m!\A/at/(.*)\z!) {
-                        my $src_loc = Devel::Mwrap::get(uri_unescape($1));
-                        $ret = $src_loc ? each_at($env, $src_loc) : r404();
-                } elsif ($path_info eq '/') {
-                        $ret = [ 200, [ qw(Content-Type text/html
-                                        Content-Length), length($root) ],
-                                [ $root ] ]
-                }
-        } elsif ($env->{REQUEST_METHOD} eq 'POST') {
-                if ($path_info eq '/reset') {
-                        Devel::Mwrap::reset();
-                        $ret = [ 200, [ qw(Content-Type text/html
-                                        Content-Length 5) ],
-                                [ "done\n" ] ];
-                }
-        }
-        $ret //= r404();
-        Devel::Mwrap::quiet(0);
-        $ret;
-}
-
-1;
diff --git a/lib/Devel/Mwrap/Rproxy.pm b/lib/Devel/Mwrap/Rproxy.pm
deleted file mode 100644
index d5a9d9d..0000000
--- a/lib/Devel/Mwrap/Rproxy.pm
+++ /dev/null
@@ -1,220 +0,0 @@
-# Copyright (C) mwrap hackers <mwrap-perl@80x24.org>
-# License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt>
-
-# minimal reverse proxy to expose the embedded httpd.h UNIX sockets
-# via PSGI (and thus TCP HTTP/1.x).  This does not have a hard dependency
-# on Mwrap.so.
-#
-# Warning: this has a synchronous wait dependency, so isn't suited for
-# non-blocking async HTTP servers.
-package Devel::Mwrap::Rproxy;
-use v5.12; # strict
-use Fcntl qw(SEEK_SET);
-use IO::Socket::UNIX;
-use Plack::Util;
-
-sub new { bless { socket_dir => $_[1]}, $_[0] }
-
-sub r {
-        [ $_[0], [
-                'Expires' => 'Fri, 01 Jan 1980 00:00:00 GMT',
-                'Pragma' => 'no-cache',
-                'Cache-Control' => 'no-cache, max-age=0, must-revalidate',
-                'Content-Type' => 'text/html; charset=UTF-8',
-                'Content-Length' => length($_[1]),
-        ], [ $_[1] ] ];
-}
-
-my $valid_pid = $^O eq 'linux' ? sub {
-        my ($pid) = @_;
-        if (open(my $fh, '<', "/proc/$pid/cmdline")) {
-                local $/;
-                my $str = <$fh> // return;
-                $str =~ tr/\0/ /;
-                Plack::Util::encode_html($str);
-        }
-} : sub { kill(0, $_[0]) ? "PID: $_[0]" : undef };
-
-sub list {
-        my ($self, $env) = @_;
-        state $t = 'mwrap reverse proxy endpoints';
-        open(my $fh, '+>', \(my $str)) or die "open: $!";
-        print $fh '<html><head><title>', $t, '</title></head><body><pre>', $t,
-                "\n\n";
-        my $dir = $self->{socket_dir};
-        opendir(my $dh, $dir) or return r(500, "socket_dir: $!");
-        my @socks = grep(/\A[0-9]+\.sock\z/, readdir($dh));
-        my %o = (Type => SOCK_STREAM, Peer => undef);
-        for (@socks) {
-                $o{Peer} = "$dir/$_";
-                substr($_, -5, 5, ''); # chop off .sock
-                my $cmd = $valid_pid->($_) // next;
-                my $c = IO::Socket::UNIX->new(%o) // next;
-                print $fh qq(<a\nhref="./$_/">$_</a>/);
-                $_ .= '/each/2000';
-                say $fh qq(<a\nhref="./), $_, qq(">each/2000</a>\t), $cmd;
-        }
-        print $fh '</pre></body></html>';
-        r(200, $str);
-}
-
-our %addr2line; # { exe|lib => Devel::Mwrap::Rproxy::A2L }
-my %cache; # "$exe\0$addr$st_ctime$st_size" => $line
-my $cache_exp = 0;
-my $cache_time = 1800;
-
-sub resolve_exe ($$) {
-        my ($exe, $st) = @_;
-        # n.b. this assumes PATH is identical across the rproxy and
-        # mwrap-httpd process, which may not always be the case:
-        if (index($exe, '/') < 0 && !-r $exe) {
-                for my $p (split(/:/, $ENV{PATH})) {
-                        $p .= "/$exe";
-                        if (-x $p) {
-                                $exe = $p;
-                                last;
-                        }
-                }
-        }
-        my $fh;
-        if (-T $exe && open($fh, '<', $exe)) { # is it text? use shebang
-                my $l = readline($fh);
-                $exe = ($l =~ /\A\#\![ \t]*(\S+)/) ? $1 : $^X;
-        }
-        return unless -e $exe;
-        my @st = stat(_);
-
-        # Debian `perl-debug' is special:
-        if ($exe eq '/usr/bin/perl' && -x '/usr/bin/debugperl') {
-                @st = stat(_);
-                $exe = '/usr/bin/debugperl';
-        }
-        $$st = pack('dd', $st[10], $st[7]); # ctime + size
-        $exe;
-}
-
-# addr2line bidirectional pipe wrapper
-sub a2l {
-        my ($exe, $addr) = @_;
-        $exe = resolve_exe($exe, \(my $st)) // return "$exe($addr)";
-        $cache{"$addr\0$exe$st"} //= do {
-                my $a2l = $addr2line{$exe} //=
-                        Devel::Mwrap::Rproxy::A2L->new($exe);
-
-                $a2l ? do {
-                        chomp(my $line = $a2l->lookup($addr));
-                        $line =~ s/\Q?? at ??:0\E//; # FreeBSD
-                        $line = Plack::Util::encode_html($line);
-                        $line =~ /\?\?/ ? "$line $exe($addr)" :
-                                ($line =~ /\S/ ? $line : "$exe($addr)");
-                } : "$exe($addr)"
-        }
-}
-
-sub call { # PSGI entry point
-        my ($self, $env) = @_;
-        my $uri = $env->{REQUEST_URI};
-        $uri =~ s!\A\Q$env->{SCRIPT_NAME}\E!!;
-        my $method = $env->{REQUEST_METHOD};
-        return list(@_) if $uri eq '/' && $method eq 'GET';
-
-        # must have /$PID/ prefix to map socket
-        $uri =~ m!\A/([0-9]+)/! or return r(404, 'not found');
-        my $s = "$self->{socket_dir}/$1.sock";
-        my %o = (Peer => $s, Type => SOCK_STREAM);
-        my $c = IO::Socket::UNIX->new(%o) or return r(500, "connect: $!");
-        my $h = "$method $uri HTTP/1.0\n\n";
-        $s = send($c, $h, MSG_NOSIGNAL) // return r(500, "send: $!");
-        $s == length($h) or return r(500, "send $s <".length($h));
-        # this only expects httpd.h output, so no continuation lines:
-        $h = do { local $/ = "\r\n\r\n"; <$c> } // return r(500, "read: $!");
-        my ($code, @hdr) = split(/\r\n/, $h);
-        @hdr = grep(!/^Content-Length:/i, @hdr); # addr2line changes length
-        my $csv = grep(m!^Content-Type: text/csv!i, @hdr);
-        (undef, $code, undef) = split(/ /, $code);
-        @hdr = map { split(/: /, $_, 2) } @hdr;
-        sub {
-                my ($wcb) = @_;
-                my $http_out = $wcb->([$code, \@hdr]);
-                my $now = time;
-                if ($now > $cache_exp) {
-                        undef %cache;
-                        $cache_exp = $now + $cache_time;
-                }
-
-                # GNU addr2line is slow with high bt:, and FreeBSD addr2line
-                # seems less capable.  And we can't see addr2line in this
-                # anyways since we kill them at the end of this scope.
-                # So just disable MWRAP, here:
-                delete local $ENV{MWRAP};
-                delete local $ENV{LD_PRELOAD};
-                eval {
-                        local %addr2line;
-                        # extract executable|library(address)
-                        if ($csv) {
-                                while (<$c>) {
-                                        s/\\n/\0\0/g;
-                                        s!(["\0])
-                                                ([^\("\0]+) # exe
-                                                \(([^\)"\0]+)\) # addr
-                                                (["\0])!
-                                                $1.a2l($2,$3).$4!gex;
-                                        s/\0\0/\\n/g;
-                                        $http_out->write($_);
-                                }
-                        } else {
-                                while (<$c>) {
-                                        s!>
-                                                ([^\(<]+) # exe
-                                                \(([^\)<]+)\) # addr
-                                                <!
-                                                '>'.a2l($1,$2).'<'!gex;
-                                        $http_out->write($_);
-                                }
-                        }
-                        close $c;
-                };
-                warn "E: $@" if $@;
-                $http_out->close;
-        }
-}
-
-# requires GNU addr2line for stdin/stdout support
-package Devel::Mwrap::Rproxy::A2L;
-use v5.12;
-
-sub new {
-        my ($cls, $exe) = @_;
-        pipe(my ($rd, $_wr)) or die "pipe: $!";
-        pipe(my ($_rd, $wr)) or die "pipe: $!";
-        # -f/--functions needs -p/--pretty-print to go with it
-        my $addr2line = $ENV{ADDR2LINE} // 'addr2line -i -p -f';
-        my @addr2line = split(/\s+/, $addr2line);
-        my $pid = fork // die "fork: $!";
-        if ($pid == 0) {
-                close $rd;
-                close $wr;
-                open STDIN, '<&', $_rd or die "STDIN: $!";
-                open STDOUT, '>&', $_wr or die "STDOUT: $!";
-                exec @addr2line, '-e', $exe;
-                die "exec @addr2line -e $exe: $!";
-        }
-        $_rd = $_wr = undef;
-        $wr->autoflush(1);
-        bless { rd => $rd, wr => $wr, pid => $pid }, __PACKAGE__;
-}
-
-sub lookup {
-        my ($self, $addr) = @_;
-        $addr =~ s/\A\+//;
-        say { $self->{wr} } $addr;
-        readline($self->{rd});
-}
-
-sub DESTROY {
-        my ($self) = @_;
-        close($_) for (delete @$self{qw(wr rd)});
-        waitpid(delete $self->{pid}, 0);
-}
-
-1;
diff --git a/lib/mwrap/.gitignore b/lib/mwrap/.gitignore
new file mode 100644
index 0000000..07c0394
--- /dev/null
+++ b/lib/mwrap/.gitignore
@@ -0,0 +1 @@
+version.rb
diff --git a/lib/mwrap_rack.rb b/lib/mwrap_rack.rb
new file mode 100644
index 0000000..6cc6d31
--- /dev/null
+++ b/lib/mwrap_rack.rb
@@ -0,0 +1,126 @@
+# Copyright (C) all contributors <mwrap-public@80x24.org>
+# License: GPL-2.0+ <https://www.gnu.org/licenses/gpl-2.0.txt>
+# frozen_string_literal: true
+require 'mwrap'
+require 'rack'
+require 'cgi'
+
+# MwrapRack is an obsolete standalone Rack application which can be
+# mounted to run within your application process.
+#
+# The embedded mwrap-httpd for Unix sockets and mwrap-rproxy for TCP
+# from the Perl version <https://80x24.org/mwrap-perl.git/> replaces
+# this in a non-obtrusive way for code which can't handle Ruby-level
+# threads.
+#
+# The remaining documentation remains for historical purposes:
+#
+# Using the Rack::Builder API in config.ru, you can map it to
+# the "/MWRAP/" endpoint.  As with the rest of the Mwrap API,
+# your Rack server needs to be spawned with the mwrap(1)
+# wrapper to enable the LD_PRELOAD.
+#
+#     require 'mwrap_rack'
+#     map('/MWRAP') { run(MwrapRack.new) }
+#     map('/') { run(your_normal_app) }
+#
+# This module is only available in mwrap 2.0.0+
+class MwrapRack
+  module HtmlResponse # :nodoc:
+    def response
+      [ 200, {
+          'expires' => 'Fri, 01 Jan 1980 00:00:00 GMT',
+          'pragma' => 'no-cache',
+          'cache-control' => 'no-cache, max-age=0, must-revalidate',
+          'content-type' => 'text/html; charset=UTF-8',
+        }, self ]
+    end
+  end
+
+  class Each < Struct.new(:script_name, :min, :sort) # :nodoc:
+    include HtmlResponse
+    HEADER = '<tr><th>' + %w(total allocations frees mean_life max_life
+                location).join('</th><th>') + '</th></tr>'
+    FIELDS = %w(total allocations frees mean_life max_life location)
+    def each
+      Mwrap.quiet do
+        t = -"Mwrap.each(#{min})"
+        sn = script_name
+        all = []
+        f = FIELDS.dup
+        sc = FIELDS.index(sort || 'total') || 0
+        f[sc] = -"<b>#{f[sc]}</b>"
+        f.map! do |hdr|
+          if hdr.start_with?('<b>')
+            hdr
+          else
+            -%Q(<a\nhref="#{sn}/each/#{min}?sort=#{hdr}">#{hdr}</a>)
+          end
+        end
+        Mwrap.each(min) do |loc, total, allocations, frees, age_sum, max_life|
+          mean_life = frees == 0 ? Float::INFINITY : age_sum/frees.to_f
+          all << [total,allocations,frees,mean_life,max_life,loc]
+        end
+        all.sort_by! { |cols| -cols[sc] }
+
+        yield(-"<html><head><title>#{t}</title></head>" \
+               "<body><h1>#{t}</h1>\n" \
+               "<h2>Current generation: #{GC.count}</h2>\n<table>\n" \
+               "<tr><th>#{f.join('</th><th>')}</th></tr>\n")
+        all.each do |cols|
+          loc = cols.pop
+          cols[3] = sprintf('%0.3f', cols[3]) # mean_life
+          href = -(+"#{sn}/at/#{CGI.escape(loc)}").encode!(xml: :attr)
+          yield(%Q(<tr><td>#{cols.join('</td><td>')}<td><a\nhref=#{
+                  href}>#{-loc.encode(xml: :text)}</a></td></tr>\n))
+          cols.clear
+        end.clear
+        yield "</table></body></html>\n"
+      end
+    end
+  end
+
+  class EachAt < Struct.new(:loc) # :nodoc:
+    include HtmlResponse
+    HEADER = '<tr><th>size</th><th>generation</th></tr>'
+
+    def each
+      t = loc.name.encode(xml: :text)
+      yield(-"<html><head><title>#{t}</title></head>" \
+             "<body><h1>live allocations at #{t}</h1>" \
+             "<h2>Current generation: #{GC.count}</h2>\n<table>#{HEADER}")
+      loc.each do |size, generation|
+        yield("<tr><td>#{size}</td><td>#{generation}</td></tr>\n")
+      end
+      yield "</table></body></html>\n"
+    end
+  end
+
+  def r404 # :nodoc:
+    [404,{'content-type'=>'text/plain'},["Not found\n"]]
+  end
+
+  # The standard Rack application endpoint for MwrapRack
+  def call(env)
+    case env['PATH_INFO']
+    when %r{\A/each/(\d+)\z}
+      min = $1.to_i
+      m = env['QUERY_STRING'].match(/\bsort=(\w+)/)
+      Each.new(env['SCRIPT_NAME'], min, m ? m[1] : nil).response
+    when %r{\A/at/(.*)\z}
+      loc = -CGI.unescape($1)
+      loc = Mwrap[loc] or return r404
+      EachAt.new(loc).response
+    when '/'
+      n = 2000
+      u = 'https://80x24.org/mwrap/README.html'
+      b = -('<html><head><title>Mwrap demo</title></head>' \
+          "<body><p><a href=\"each/#{n}\">allocations &gt;#{n} bytes</a>" \
+          "<p><a href=\"#{u}\">#{u}</a>" \
+          "</body></html>\n")
+      [ 200, {'content-type'=>'text/html','content-length'=>-b.size.to_s},[b]]
+    else
+      r404
+    end
+  end
+end
diff --git a/mwrap.gemspec b/mwrap.gemspec
new file mode 100644
index 0000000..dc99924
--- /dev/null
+++ b/mwrap.gemspec
@@ -0,0 +1,35 @@
+git_manifest = `git ls-files 2>/dev/null`.split("\n")
+git_ok = $?.success?
+git_manifest << 'lib/mwrap/version.rb'.freeze # generated by ./VERSION-GEN
+manifest = File.exist?('MANIFEST') ?
+  File.readlines('MANIFEST').map!(&:chomp).delete_if(&:empty?) : git_manifest
+if git_ok && manifest != git_manifest
+  tmp = "MANIFEST.#$$.tmp"
+  File.open(tmp, 'w') { |fp| fp.puts(git_manifest.join("\n")) }
+  File.rename(tmp, 'MANIFEST')
+  system('git add MANIFEST')
+end
+
+version = `./VERSION-GEN`.chomp
+$?.success? or abort './VERSION-GEN failed'
+
+Gem::Specification.new do |s|
+  s.name = 'mwrap'
+  s.version = version
+  s.homepage = 'https://80x24.org/mwrap/'
+  s.authors = ["mwrap hackers"]
+  s.summary = 'LD_PRELOAD malloc wrapper for Ruby'
+  s.executables = %w(mwrap)
+  s.files = manifest
+  s.description = <<~EOF
+mwrap wraps all malloc, calloc, and realloc calls to trace the Ruby
+source location of such calls and bytes allocated at each callsite.
+  EOF
+  s.email = %q{e@80x24.org}
+  s.test_files = Dir['test/test_*.rb']
+  s.extensions = %w(ext/mwrap/extconf.rb)
+
+  s.add_development_dependency('test-unit', '~> 3.0')
+  s.add_development_dependency('rake-compiler', '~> 1.0')
+  s.licenses = %w(GPL-3.0+)
+end
diff --git a/ppport.h b/ppport.h
deleted file mode 100644
index 208fb41..0000000
--- a/ppport.h
+++ /dev/null
@@ -1,8214 +0,0 @@
-#if 0
-<<'SKIP';
-#endif
-/*
-----------------------------------------------------------------------
-
-    ppport.h -- Perl/Pollution/Portability Version 3.40
-
-    Automatically created by Devel::PPPort running under perl 5.028001.
-
-    Do NOT edit this file directly! -- Edit PPPort_pm.PL and the
-    includes in parts/inc/ instead.
-
-    Use 'perldoc ppport.h' to view the documentation below.
-
-----------------------------------------------------------------------
-
-SKIP
-
-=pod
-
-=head1 NAME
-
-ppport.h - Perl/Pollution/Portability version 3.40
-
-=head1 SYNOPSIS
-
-  perl ppport.h [options] [source files]
-
-  Searches current directory for files if no [source files] are given
-
-  --help                      show short help
-
-  --version                   show version
-
-  --patch=file                write one patch file with changes
-  --copy=suffix               write changed copies with suffix
-  --diff=program              use diff program and options
-
-  --compat-version=version    provide compatibility with Perl version
-  --cplusplus                 accept C++ comments
-
-  --quiet                     don't output anything except fatal errors
-  --nodiag                    don't show diagnostics
-  --nohints                   don't show hints
-  --nochanges                 don't suggest changes
-  --nofilter                  don't filter input files
-
-  --strip                     strip all script and doc functionality
-                              from ppport.h
-
-  --list-provided             list provided API
-  --list-unsupported          list unsupported API
-  --api-info=name             show Perl API portability information
-
-=head1 COMPATIBILITY
-
-This version of F<ppport.h> is designed to support operation with Perl
-installations back to 5.003, and has been tested up to 5.20.
-
-=head1 OPTIONS
-
-=head2 --help
-
-Display a brief usage summary.
-
-=head2 --version
-
-Display the version of F<ppport.h>.
-
-=head2 --patch=I<file>
-
-If this option is given, a single patch file will be created if
-any changes are suggested. This requires a working diff program
-to be installed on your system.
-
-=head2 --copy=I<suffix>
-
-If this option is given, a copy of each file will be saved with
-the given suffix that contains the suggested changes. This does
-not require any external programs. Note that this does not
-automagically add a dot between the original filename and the
-suffix. If you want the dot, you have to include it in the option
-argument.
-
-If neither C<--patch> or C<--copy> are given, the default is to
-simply print the diffs for each file. This requires either
-C<Text::Diff> or a C<diff> program to be installed.
-
-=head2 --diff=I<program>
-
-Manually set the diff program and options to use. The default
-is to use C<Text::Diff>, when installed, and output unified
-context diffs.
-
-=head2 --compat-version=I<version>
-
-Tell F<ppport.h> to check for compatibility with the given
-Perl version. The default is to check for compatibility with Perl
-version 5.003. You can use this option to reduce the output
-of F<ppport.h> if you intend to be backward compatible only
-down to a certain Perl version.
-
-=head2 --cplusplus
-
-Usually, F<ppport.h> will detect C++ style comments and
-replace them with C style comments for portability reasons.
-Using this option instructs F<ppport.h> to leave C++
-comments untouched.
-
-=head2 --quiet
-
-Be quiet. Don't print anything except fatal errors.
-
-=head2 --nodiag
-
-Don't output any diagnostic messages. Only portability
-alerts will be printed.
-
-=head2 --nohints
-
-Don't output any hints. Hints often contain useful portability
-notes. Warnings will still be displayed.
-
-=head2 --nochanges
-
-Don't suggest any changes. Only give diagnostic output and hints
-unless these are also deactivated.
-
-=head2 --nofilter
-
-Don't filter the list of input files. By default, files not looking
-like source code (i.e. not *.xs, *.c, *.cc, *.cpp or *.h) are skipped.
-
-=head2 --strip
-
-Strip all script and documentation functionality from F<ppport.h>.
-This reduces the size of F<ppport.h> dramatically and may be useful
-if you want to include F<ppport.h> in smaller modules without
-increasing their distribution size too much.
-
-The stripped F<ppport.h> will have a C<--unstrip> option that allows
-you to undo the stripping, but only if an appropriate C<Devel::PPPort>
-module is installed.
-
-=head2 --list-provided
-
-Lists the API elements for which compatibility is provided by
-F<ppport.h>. Also lists if it must be explicitly requested,
-if it has dependencies, and if there are hints or warnings for it.
-
-=head2 --list-unsupported
-
-Lists the API elements that are known not to be supported by
-F<ppport.h> and below which version of Perl they probably
-won't be available or work.
-
-=head2 --api-info=I<name>
-
-Show portability information for API elements matching I<name>.
-If I<name> is surrounded by slashes, it is interpreted as a regular
-expression.
-
-=head1 DESCRIPTION
-
-In order for a Perl extension (XS) module to be as portable as possible
-across differing versions of Perl itself, certain steps need to be taken.
-
-=over 4
-
-=item *
-
-Including this header is the first major one. This alone will give you
-access to a large part of the Perl API that hasn't been available in
-earlier Perl releases. Use
-
-    perl ppport.h --list-provided
-
-to see which API elements are provided by ppport.h.
-
-=item *
-
-You should avoid using deprecated parts of the API. For example, using
-global Perl variables without the C<PL_> prefix is deprecated. Also,
-some API functions used to have a C<perl_> prefix. Using this form is
-also deprecated. You can safely use the supported API, as F<ppport.h>
-will provide wrappers for older Perl versions.
-
-=item *
-
-If you use one of a few functions or variables that were not present in
-earlier versions of Perl, and that can't be provided using a macro, you
-have to explicitly request support for these functions by adding one or
-more C<#define>s in your source code before the inclusion of F<ppport.h>.
-
-These functions or variables will be marked C<explicit> in the list shown
-by C<--list-provided>.
-
-Depending on whether you module has a single or multiple files that
-use such functions or variables, you want either C<static> or global
-variants.
-
-For a C<static> function or variable (used only in a single source
-file), use:
-
-    #define NEED_function
-    #define NEED_variable
-
-For a global function or variable (used in multiple source files),
-use:
-
-    #define NEED_function_GLOBAL
-    #define NEED_variable_GLOBAL
-
-Note that you mustn't have more than one global request for the
-same function or variable in your project.
-
-    Function / Variable       Static Request               Global Request
-    -----------------------------------------------------------------------------------------
-    PL_parser                 NEED_PL_parser               NEED_PL_parser_GLOBAL
-    PL_signals                NEED_PL_signals              NEED_PL_signals_GLOBAL
-    SvRX()                    NEED_SvRX                    NEED_SvRX_GLOBAL
-    caller_cx()               NEED_caller_cx               NEED_caller_cx_GLOBAL
-    croak_xs_usage()          NEED_croak_xs_usage          NEED_croak_xs_usage_GLOBAL
-    die_sv()                  NEED_die_sv                  NEED_die_sv_GLOBAL
-    eval_pv()                 NEED_eval_pv                 NEED_eval_pv_GLOBAL
-    grok_bin()                NEED_grok_bin                NEED_grok_bin_GLOBAL
-    grok_hex()                NEED_grok_hex                NEED_grok_hex_GLOBAL
-    grok_number()             NEED_grok_number             NEED_grok_number_GLOBAL
-    grok_numeric_radix()      NEED_grok_numeric_radix      NEED_grok_numeric_radix_GLOBAL
-    grok_oct()                NEED_grok_oct                NEED_grok_oct_GLOBAL
-    gv_fetchpvn_flags()       NEED_gv_fetchpvn_flags       NEED_gv_fetchpvn_flags_GLOBAL
-    load_module()             NEED_load_module             NEED_load_module_GLOBAL
-    mess()                    NEED_mess                    NEED_mess_GLOBAL
-    mess_nocontext()          NEED_mess_nocontext          NEED_mess_nocontext_GLOBAL
-    mess_sv()                 NEED_mess_sv                 NEED_mess_sv_GLOBAL
-    mg_findext()              NEED_mg_findext              NEED_mg_findext_GLOBAL
-    my_snprintf()             NEED_my_snprintf             NEED_my_snprintf_GLOBAL
-    my_sprintf()              NEED_my_sprintf              NEED_my_sprintf_GLOBAL
-    my_strlcat()              NEED_my_strlcat              NEED_my_strlcat_GLOBAL
-    my_strlcpy()              NEED_my_strlcpy              NEED_my_strlcpy_GLOBAL
-    newCONSTSUB()             NEED_newCONSTSUB             NEED_newCONSTSUB_GLOBAL
-    newRV_noinc()             NEED_newRV_noinc             NEED_newRV_noinc_GLOBAL
-    newSV_type()              NEED_newSV_type              NEED_newSV_type_GLOBAL
-    newSVpvn_flags()          NEED_newSVpvn_flags          NEED_newSVpvn_flags_GLOBAL
-    newSVpvn_share()          NEED_newSVpvn_share          NEED_newSVpvn_share_GLOBAL
-    pv_display()              NEED_pv_display              NEED_pv_display_GLOBAL
-    pv_escape()               NEED_pv_escape               NEED_pv_escape_GLOBAL
-    pv_pretty()               NEED_pv_pretty               NEED_pv_pretty_GLOBAL
-    sv_2pv_flags()            NEED_sv_2pv_flags            NEED_sv_2pv_flags_GLOBAL
-    sv_2pvbyte()              NEED_sv_2pvbyte              NEED_sv_2pvbyte_GLOBAL
-    sv_catpvf_mg()            NEED_sv_catpvf_mg            NEED_sv_catpvf_mg_GLOBAL
-    sv_catpvf_mg_nocontext()  NEED_sv_catpvf_mg_nocontext  NEED_sv_catpvf_mg_nocontext_GLOBAL
-    sv_pvn_force_flags()      NEED_sv_pvn_force_flags      NEED_sv_pvn_force_flags_GLOBAL
-    sv_setpvf_mg()            NEED_sv_setpvf_mg            NEED_sv_setpvf_mg_GLOBAL
-    sv_setpvf_mg_nocontext()  NEED_sv_setpvf_mg_nocontext  NEED_sv_setpvf_mg_nocontext_GLOBAL
-    sv_unmagicext()           NEED_sv_unmagicext           NEED_sv_unmagicext_GLOBAL
-    vload_module()            NEED_vload_module            NEED_vload_module_GLOBAL
-    vmess()                   NEED_vmess                   NEED_vmess_GLOBAL
-    vnewSVpvf()               NEED_vnewSVpvf               NEED_vnewSVpvf_GLOBAL
-    warner()                  NEED_warner                  NEED_warner_GLOBAL
-
-To avoid namespace conflicts, you can change the namespace of the
-explicitly exported functions / variables using the C<DPPP_NAMESPACE>
-macro. Just C<#define> the macro before including C<ppport.h>:
-
-    #define DPPP_NAMESPACE MyOwnNamespace_
-    #include "ppport.h"
-
-The default namespace is C<DPPP_>.
-
-=back
-
-The good thing is that most of the above can be checked by running
-F<ppport.h> on your source code. See the next section for
-details.
-
-=head1 EXAMPLES
-
-To verify whether F<ppport.h> is needed for your module, whether you
-should make any changes to your code, and whether any special defines
-should be used, F<ppport.h> can be run as a Perl script to check your
-source code. Simply say:
-
-    perl ppport.h
-
-The result will usually be a list of patches suggesting changes
-that should at least be acceptable, if not necessarily the most
-efficient solution, or a fix for all possible problems.
-
-If you know that your XS module uses features only available in
-newer Perl releases, if you're aware that it uses C++ comments,
-and if you want all suggestions as a single patch file, you could
-use something like this:
-
-    perl ppport.h --compat-version=5.6.0 --cplusplus --patch=test.diff
-
-If you only want your code to be scanned without any suggestions
-for changes, use:
-
-    perl ppport.h --nochanges
-
-You can specify a different C<diff> program or options, using
-the C<--diff> option:
-
-    perl ppport.h --diff='diff -C 10'
-
-This would output context diffs with 10 lines of context.
-
-If you want to create patched copies of your files instead, use:
-
-    perl ppport.h --copy=.new
-
-To display portability information for the C<newSVpvn> function,
-use:
-
-    perl ppport.h --api-info=newSVpvn
-
-Since the argument to C<--api-info> can be a regular expression,
-you can use
-
-    perl ppport.h --api-info=/_nomg$/
-
-to display portability information for all C<_nomg> functions or
-
-    perl ppport.h --api-info=/./
-
-to display information for all known API elements.
-
-=head1 BUGS
-
-If this version of F<ppport.h> is causing failure during
-the compilation of this module, please check if newer versions
-of either this module or C<Devel::PPPort> are available on CPAN
-before sending a bug report.
-
-If F<ppport.h> was generated using the latest version of
-C<Devel::PPPort> and is causing failure of this module, please
-send a bug report to L<perlbug@perl.org|mailto:perlbug@perl.org>.
-
-Please include the following information:
-
-=over 4
-
-=item 1.
-
-The complete output from running "perl -V"
-
-=item 2.
-
-This file.
-
-=item 3.
-
-The name and version of the module you were trying to build.
-
-=item 4.
-
-A full log of the build that failed.
-
-=item 5.
-
-Any other information that you think could be relevant.
-
-=back
-
-For the latest version of this code, please get the C<Devel::PPPort>
-module from CPAN.
-
-=head1 COPYRIGHT
-
-Version 3.x, Copyright (c) 2004-2013, Marcus Holland-Moritz.
-
-Version 2.x, Copyright (C) 2001, Paul Marquess.
-
-Version 1.x, Copyright (C) 1999, Kenneth Albanowski.
-
-This program is free software; you can redistribute it and/or
-modify it under the same terms as Perl itself.
-
-=head1 SEE ALSO
-
-See L<Devel::PPPort>.
-
-=cut
-
-use strict;
-
-# Disable broken TRIE-optimization
-BEGIN { eval '${^RE_TRIE_MAXBUF} = -1' if $] >= 5.009004 && $] <= 5.009005 }
-
-my $VERSION = 3.40;
-
-my %opt = (
-  quiet     => 0,
-  diag      => 1,
-  hints     => 1,
-  changes   => 1,
-  cplusplus => 0,
-  filter    => 1,
-  strip     => 0,
-  version   => 0,
-);
-
-my($ppport) = $0 =~ /([\w.]+)$/;
-my $LF = '(?:\r\n|[\r\n])';   # line feed
-my $HS = "[ \t]";             # horizontal whitespace
-
-# Never use C comments in this file!
-my $ccs  = '/'.'*';
-my $cce  = '*'.'/';
-my $rccs = quotemeta $ccs;
-my $rcce = quotemeta $cce;
-
-eval {
-  require Getopt::Long;
-  Getopt::Long::GetOptions(\%opt, qw(
-    help quiet diag! filter! hints! changes! cplusplus strip version
-    patch=s copy=s diff=s compat-version=s
-    list-provided list-unsupported api-info=s
-  )) or usage();
-};
-
-if ($@ and grep /^-/, @ARGV) {
-  usage() if "@ARGV" =~ /^--?h(?:elp)?$/;
-  die "Getopt::Long not found. Please don't use any options.\n";
-}
-
-if ($opt{version}) {
-  print "This is $0 $VERSION.\n";
-  exit 0;
-}
-
-usage() if $opt{help};
-strip() if $opt{strip};
-
-if (exists $opt{'compat-version'}) {
-  my($r,$v,$s) = eval { parse_version($opt{'compat-version'}) };
-  if ($@) {
-    die "Invalid version number format: '$opt{'compat-version'}'\n";
-  }
-  die "Only Perl 5 is supported\n" if $r != 5;
-  die "Invalid version number: $opt{'compat-version'}\n" if $v >= 1000 || $s >= 1000;
-  $opt{'compat-version'} = sprintf "%d.%03d%03d", $r, $v, $s;
-}
-else {
-  $opt{'compat-version'} = 5;
-}
-
-my %API = map { /^(\w+)\|([^|]*)\|([^|]*)\|(\w*)$/
-                ? ( $1 => {
-                      ($2                  ? ( base     => $2 ) : ()),
-                      ($3                  ? ( todo     => $3 ) : ()),
-                      (index($4, 'v') >= 0 ? ( varargs  => 1  ) : ()),
-                      (index($4, 'p') >= 0 ? ( provided => 1  ) : ()),
-                      (index($4, 'n') >= 0 ? ( nothxarg => 1  ) : ()),
-                    } )
-                : die "invalid spec: $_" } qw(
-ASCII_TO_NEED||5.007001|n
-AvFILLp|5.004050||p
-AvFILL|||
-BhkDISABLE||5.024000|
-BhkENABLE||5.024000|
-BhkENTRY_set||5.024000|
-BhkENTRY|||
-BhkFLAGS|||
-CALL_BLOCK_HOOKS|||
-CLASS|||n
-CPERLscope|5.005000||p
-CX_CURPAD_SAVE|||
-CX_CURPAD_SV|||
-C_ARRAY_END|5.013002||p
-C_ARRAY_LENGTH|5.008001||p
-CopFILEAV|5.006000||p
-CopFILEGV_set|5.006000||p
-CopFILEGV|5.006000||p
-CopFILESV|5.006000||p
-CopFILE_set|5.006000||p
-CopFILE|5.006000||p
-CopSTASHPV_set|5.006000||p
-CopSTASHPV|5.006000||p
-CopSTASH_eq|5.006000||p
-CopSTASH_set|5.006000||p
-CopSTASH|5.006000||p
-CopyD|5.009002|5.004050|p
-Copy|||
-CvPADLIST||5.008001|
-CvSTASH|||
-CvWEAKOUTSIDE|||
-DECLARATION_FOR_LC_NUMERIC_MANIPULATION||5.021010|n
-DEFSV_set|5.010001||p
-DEFSV|5.004050||p
-DO_UTF8||5.006000|
-END_EXTERN_C|5.005000||p
-ENTER|||
-ERRSV|5.004050||p
-EXTEND|||
-EXTERN_C|5.005000||p
-F0convert|||n
-FREETMPS|||
-GIMME_V||5.004000|n
-GIMME|||n
-GROK_NUMERIC_RADIX|5.007002||p
-G_ARRAY|||
-G_DISCARD|||
-G_EVAL|||
-G_METHOD|5.006001||p
-G_NOARGS|||
-G_SCALAR|||
-G_VOID||5.004000|
-GetVars|||
-GvAV|||
-GvCV|||
-GvHV|||
-GvSV|||
-Gv_AMupdate||5.011000|
-HEf_SVKEY|5.003070||p
-HeHASH||5.003070|
-HeKEY||5.003070|
-HeKLEN||5.003070|
-HePV||5.004000|
-HeSVKEY_force||5.003070|
-HeSVKEY_set||5.004000|
-HeSVKEY||5.003070|
-HeUTF8|5.010001|5.008000|p
-HeVAL||5.003070|
-HvENAMELEN||5.015004|
-HvENAMEUTF8||5.015004|
-HvENAME||5.013007|
-HvNAMELEN_get|5.009003||p
-HvNAMELEN||5.015004|
-HvNAMEUTF8||5.015004|
-HvNAME_get|5.009003||p
-HvNAME|||
-INT2PTR|5.006000||p
-IN_LOCALE_COMPILETIME|5.007002||p
-IN_LOCALE_RUNTIME|5.007002||p
-IN_LOCALE|5.007002||p
-IN_PERL_COMPILETIME|5.008001||p
-IS_NUMBER_GREATER_THAN_UV_MAX|5.007002||p
-IS_NUMBER_INFINITY|5.007002||p
-IS_NUMBER_IN_UV|5.007002||p
-IS_NUMBER_NAN|5.007003||p
-IS_NUMBER_NEG|5.007002||p
-IS_NUMBER_NOT_INT|5.007002||p
-IVSIZE|5.006000||p
-IVTYPE|5.006000||p
-IVdf|5.006000||p
-LEAVE|||
-LINKLIST||5.013006|
-LVRET|||
-MARK|||
-MULTICALL||5.024000|
-MUTABLE_PTR|5.010001||p
-MUTABLE_SV|5.010001||p
-MY_CXT_CLONE|5.009002||p
-MY_CXT_INIT|5.007003||p
-MY_CXT|5.007003||p
-MoveD|5.009002|5.004050|p
-Move|||
-NATIVE_TO_NEED||5.007001|n
-NOOP|5.005000||p
-NUM2PTR|5.006000||p
-NVTYPE|5.006000||p
-NVef|5.006001||p
-NVff|5.006001||p
-NVgf|5.006001||p
-Newxc|5.009003||p
-Newxz|5.009003||p
-Newx|5.009003||p
-Nullav|||
-Nullch|||
-Nullcv|||
-Nullhv|||
-Nullsv|||
-OP_CLASS||5.013007|
-OP_DESC||5.007003|
-OP_NAME||5.007003|
-OP_TYPE_IS_OR_WAS||5.019010|
-OP_TYPE_IS||5.019007|
-ORIGMARK|||
-OpHAS_SIBLING|5.021007||p
-OpLASTSIB_set|5.021011||p
-OpMAYBESIB_set|5.021011||p
-OpMORESIB_set|5.021011||p
-OpSIBLING|5.021007||p
-PAD_BASE_SV|||
-PAD_CLONE_VARS|||
-PAD_COMPNAME_FLAGS|||
-PAD_COMPNAME_GEN_set|||
-PAD_COMPNAME_GEN|||
-PAD_COMPNAME_OURSTASH|||
-PAD_COMPNAME_PV|||
-PAD_COMPNAME_TYPE|||
-PAD_RESTORE_LOCAL|||
-PAD_SAVE_LOCAL|||
-PAD_SAVE_SETNULLPAD|||
-PAD_SETSV|||
-PAD_SET_CUR_NOSAVE|||
-PAD_SET_CUR|||
-PAD_SVl|||
-PAD_SV|||
-PERLIO_FUNCS_CAST|5.009003||p
-PERLIO_FUNCS_DECL|5.009003||p
-PERL_ABS|5.008001||p
-PERL_ARGS_ASSERT_CROAK_XS_USAGE|||p
-PERL_BCDVERSION|5.024000||p
-PERL_GCC_BRACE_GROUPS_FORBIDDEN|5.008001||p
-PERL_HASH|5.003070||p
-PERL_INT_MAX|5.003070||p
-PERL_INT_MIN|5.003070||p
-PERL_LONG_MAX|5.003070||p
-PERL_LONG_MIN|5.003070||p
-PERL_MAGIC_arylen|5.007002||p
-PERL_MAGIC_backref|5.007002||p
-PERL_MAGIC_bm|5.007002||p
-PERL_MAGIC_collxfrm|5.007002||p
-PERL_MAGIC_dbfile|5.007002||p
-PERL_MAGIC_dbline|5.007002||p
-PERL_MAGIC_defelem|5.007002||p
-PERL_MAGIC_envelem|5.007002||p
-PERL_MAGIC_env|5.007002||p
-PERL_MAGIC_ext|5.007002||p
-PERL_MAGIC_fm|5.007002||p
-PERL_MAGIC_glob|5.024000||p
-PERL_MAGIC_isaelem|5.007002||p
-PERL_MAGIC_isa|5.007002||p
-PERL_MAGIC_mutex|5.024000||p
-PERL_MAGIC_nkeys|5.007002||p
-PERL_MAGIC_overload_elem|5.024000||p
-PERL_MAGIC_overload_table|5.007002||p
-PERL_MAGIC_overload|5.024000||p
-PERL_MAGIC_pos|5.007002||p
-PERL_MAGIC_qr|5.007002||p
-PERL_MAGIC_regdata|5.007002||p
-PERL_MAGIC_regdatum|5.007002||p
-PERL_MAGIC_regex_global|5.007002||p
-PERL_MAGIC_shared_scalar|5.007003||p
-PERL_MAGIC_shared|5.007003||p
-PERL_MAGIC_sigelem|5.007002||p
-PERL_MAGIC_sig|5.007002||p
-PERL_MAGIC_substr|5.007002||p
-PERL_MAGIC_sv|5.007002||p
-PERL_MAGIC_taint|5.007002||p
-PERL_MAGIC_tiedelem|5.007002||p
-PERL_MAGIC_tiedscalar|5.007002||p
-PERL_MAGIC_tied|5.007002||p
-PERL_MAGIC_utf8|5.008001||p
-PERL_MAGIC_uvar_elem|5.007003||p
-PERL_MAGIC_uvar|5.007002||p
-PERL_MAGIC_vec|5.007002||p
-PERL_MAGIC_vstring|5.008001||p
-PERL_PV_ESCAPE_ALL|5.009004||p
-PERL_PV_ESCAPE_FIRSTCHAR|5.009004||p
-PERL_PV_ESCAPE_NOBACKSLASH|5.009004||p
-PERL_PV_ESCAPE_NOCLEAR|5.009004||p
-PERL_PV_ESCAPE_QUOTE|5.009004||p
-PERL_PV_ESCAPE_RE|5.009005||p
-PERL_PV_ESCAPE_UNI_DETECT|5.009004||p
-PERL_PV_ESCAPE_UNI|5.009004||p
-PERL_PV_PRETTY_DUMP|5.009004||p
-PERL_PV_PRETTY_ELLIPSES|5.010000||p
-PERL_PV_PRETTY_LTGT|5.009004||p
-PERL_PV_PRETTY_NOCLEAR|5.010000||p
-PERL_PV_PRETTY_QUOTE|5.009004||p
-PERL_PV_PRETTY_REGPROP|5.009004||p
-PERL_QUAD_MAX|5.003070||p
-PERL_QUAD_MIN|5.003070||p
-PERL_REVISION|5.006000||p
-PERL_SCAN_ALLOW_UNDERSCORES|5.007003||p
-PERL_SCAN_DISALLOW_PREFIX|5.007003||p
-PERL_SCAN_GREATER_THAN_UV_MAX|5.007003||p
-PERL_SCAN_SILENT_ILLDIGIT|5.008001||p
-PERL_SHORT_MAX|5.003070||p
-PERL_SHORT_MIN|5.003070||p
-PERL_SIGNALS_UNSAFE_FLAG|5.008001||p
-PERL_SUBVERSION|5.006000||p
-PERL_SYS_INIT3||5.006000|
-PERL_SYS_INIT|||
-PERL_SYS_TERM||5.024000|
-PERL_UCHAR_MAX|5.003070||p
-PERL_UCHAR_MIN|5.003070||p
-PERL_UINT_MAX|5.003070||p
-PERL_UINT_MIN|5.003070||p
-PERL_ULONG_MAX|5.003070||p
-PERL_ULONG_MIN|5.003070||p
-PERL_UNUSED_ARG|5.009003||p
-PERL_UNUSED_CONTEXT|5.009004||p
-PERL_UNUSED_DECL|5.007002||p
-PERL_UNUSED_RESULT|5.021001||p
-PERL_UNUSED_VAR|5.007002||p
-PERL_UQUAD_MAX|5.003070||p
-PERL_UQUAD_MIN|5.003070||p
-PERL_USE_GCC_BRACE_GROUPS|5.009004||p
-PERL_USHORT_MAX|5.003070||p
-PERL_USHORT_MIN|5.003070||p
-PERL_VERSION|5.006000||p
-PL_DBsignal|5.005000||p
-PL_DBsingle|||pn
-PL_DBsub|||pn
-PL_DBtrace|||pn
-PL_Sv|5.005000||p
-PL_bufend|5.024000||p
-PL_bufptr|5.024000||p
-PL_check||5.006000|
-PL_compiling|5.004050||p
-PL_comppad_name||5.017004|
-PL_comppad||5.008001|
-PL_copline|5.024000||p
-PL_curcop|5.004050||p
-PL_curpad||5.005000|
-PL_curstash|5.004050||p
-PL_debstash|5.004050||p
-PL_defgv|5.004050||p
-PL_diehook|5.004050||p
-PL_dirty|5.004050||p
-PL_dowarn|||pn
-PL_errgv|5.004050||p
-PL_error_count|5.024000||p
-PL_expect|5.024000||p
-PL_hexdigit|5.005000||p
-PL_hints|5.005000||p
-PL_in_my_stash|5.024000||p
-PL_in_my|5.024000||p
-PL_keyword_plugin||5.011002|
-PL_last_in_gv|||n
-PL_laststatval|5.005000||p
-PL_lex_state|5.024000||p
-PL_lex_stuff|5.024000||p
-PL_linestr|5.024000||p
-PL_modglobal||5.005000|n
-PL_na|5.004050||pn
-PL_no_modify|5.006000||p
-PL_ofsgv|||n
-PL_opfreehook||5.011000|n
-PL_parser|5.009005||p
-PL_peepp||5.007003|n
-PL_perl_destruct_level|5.004050||p
-PL_perldb|5.004050||p
-PL_ppaddr|5.006000||p
-PL_rpeepp||5.013005|n
-PL_rsfp_filters|5.024000||p
-PL_rsfp|5.024000||p
-PL_rs|||n
-PL_signals|5.008001||p
-PL_stack_base|5.004050||p
-PL_stack_sp|5.004050||p
-PL_statcache|5.005000||p
-PL_stdingv|5.004050||p
-PL_sv_arenaroot|5.004050||p
-PL_sv_no|5.004050||pn
-PL_sv_undef|5.004050||pn
-PL_sv_yes|5.004050||pn
-PL_tainted|5.004050||p
-PL_tainting|5.004050||p
-PL_tokenbuf|5.024000||p
-POP_MULTICALL||5.024000|
-POPi|||n
-POPl|||n
-POPn|||n
-POPpbytex||5.007001|n
-POPpx||5.005030|n
-POPp|||n
-POPs|||n
-POPul||5.006000|n
-POPu||5.004000|n
-PTR2IV|5.006000||p
-PTR2NV|5.006000||p
-PTR2UV|5.006000||p
-PTR2nat|5.009003||p
-PTR2ul|5.007001||p
-PTRV|5.006000||p
-PUSHMARK|||
-PUSH_MULTICALL||5.024000|
-PUSHi|||
-PUSHmortal|5.009002||p
-PUSHn|||
-PUSHp|||
-PUSHs|||
-PUSHu|5.004000||p
-PUTBACK|||
-PadARRAY||5.024000|
-PadMAX||5.024000|
-PadlistARRAY||5.024000|
-PadlistMAX||5.024000|
-PadlistNAMESARRAY||5.024000|
-PadlistNAMESMAX||5.024000|
-PadlistNAMES||5.024000|
-PadlistREFCNT||5.017004|
-PadnameIsOUR|||
-PadnameIsSTATE|||
-PadnameLEN||5.024000|
-PadnameOURSTASH|||
-PadnameOUTER|||
-PadnamePV||5.024000|
-PadnameREFCNT_dec||5.024000|
-PadnameREFCNT||5.024000|
-PadnameSV||5.024000|
-PadnameTYPE|||
-PadnameUTF8||5.021007|
-PadnamelistARRAY||5.024000|
-PadnamelistMAX||5.024000|
-PadnamelistREFCNT_dec||5.024000|
-PadnamelistREFCNT||5.024000|
-PerlIO_clearerr||5.007003|
-PerlIO_close||5.007003|
-PerlIO_context_layers||5.009004|
-PerlIO_eof||5.007003|
-PerlIO_error||5.007003|
-PerlIO_fileno||5.007003|
-PerlIO_fill||5.007003|
-PerlIO_flush||5.007003|
-PerlIO_get_base||5.007003|
-PerlIO_get_bufsiz||5.007003|
-PerlIO_get_cnt||5.007003|
-PerlIO_get_ptr||5.007003|
-PerlIO_read||5.007003|
-PerlIO_restore_errno|||
-PerlIO_save_errno|||
-PerlIO_seek||5.007003|
-PerlIO_set_cnt||5.007003|
-PerlIO_set_ptrcnt||5.007003|
-PerlIO_setlinebuf||5.007003|
-PerlIO_stderr||5.007003|
-PerlIO_stdin||5.007003|
-PerlIO_stdout||5.007003|
-PerlIO_tell||5.007003|
-PerlIO_unread||5.007003|
-PerlIO_write||5.007003|
-Perl_signbit||5.009005|n
-PoisonFree|5.009004||p
-PoisonNew|5.009004||p
-PoisonWith|5.009004||p
-Poison|5.008000||p
-READ_XDIGIT||5.017006|
-RESTORE_LC_NUMERIC||5.024000|
-RETVAL|||n
-Renewc|||
-Renew|||
-SAVECLEARSV|||
-SAVECOMPPAD|||
-SAVEPADSV|||
-SAVETMPS|||
-SAVE_DEFSV|5.004050||p
-SPAGAIN|||
-SP|||
-START_EXTERN_C|5.005000||p
-START_MY_CXT|5.007003||p
-STMT_END|||p
-STMT_START|||p
-STORE_LC_NUMERIC_FORCE_TO_UNDERLYING||5.024000|
-STORE_LC_NUMERIC_SET_TO_NEEDED||5.024000|
-STR_WITH_LEN|5.009003||p
-ST|||
-SV_CONST_RETURN|5.009003||p
-SV_COW_DROP_PV|5.008001||p
-SV_COW_SHARED_HASH_KEYS|5.009005||p
-SV_GMAGIC|5.007002||p
-SV_HAS_TRAILING_NUL|5.009004||p
-SV_IMMEDIATE_UNREF|5.007001||p
-SV_MUTABLE_RETURN|5.009003||p
-SV_NOSTEAL|5.009002||p
-SV_SMAGIC|5.009003||p
-SV_UTF8_NO_ENCODING|5.008001||p
-SVfARG|5.009005||p
-SVf_UTF8|5.006000||p
-SVf|5.006000||p
-SVt_INVLIST||5.019002|
-SVt_IV|||
-SVt_NULL|||
-SVt_NV|||
-SVt_PVAV|||
-SVt_PVCV|||
-SVt_PVFM|||
-SVt_PVGV|||
-SVt_PVHV|||
-SVt_PVIO|||
-SVt_PVIV|||
-SVt_PVLV|||
-SVt_PVMG|||
-SVt_PVNV|||
-SVt_PV|||
-SVt_REGEXP||5.011000|
-Safefree|||
-Slab_Alloc|||
-Slab_Free|||
-Slab_to_ro|||
-Slab_to_rw|||
-StructCopy|||
-SvCUR_set|||
-SvCUR|||
-SvEND|||
-SvGAMAGIC||5.006001|
-SvGETMAGIC|5.004050||p
-SvGROW|||
-SvIOK_UV||5.006000|
-SvIOK_notUV||5.006000|
-SvIOK_off|||
-SvIOK_only_UV||5.006000|
-SvIOK_only|||
-SvIOK_on|||
-SvIOKp|||
-SvIOK|||
-SvIVX|||
-SvIV_nomg|5.009001||p
-SvIV_set|||
-SvIVx|||
-SvIV|||
-SvIsCOW_shared_hash||5.008003|
-SvIsCOW||5.008003|
-SvLEN_set|||
-SvLEN|||
-SvLOCK||5.007003|
-SvMAGIC_set|5.009003||p
-SvNIOK_off|||
-SvNIOKp|||
-SvNIOK|||
-SvNOK_off|||
-SvNOK_only|||
-SvNOK_on|||
-SvNOKp|||
-SvNOK|||
-SvNVX|||
-SvNV_nomg||5.013002|
-SvNV_set|||
-SvNVx|||
-SvNV|||
-SvOK|||
-SvOOK_offset||5.011000|
-SvOOK|||
-SvPOK_off|||
-SvPOK_only_UTF8||5.006000|
-SvPOK_only|||
-SvPOK_on|||
-SvPOKp|||
-SvPOK|||
-SvPVX_const|5.009003||p
-SvPVX_mutable|5.009003||p
-SvPVX|||
-SvPV_const|5.009003||p
-SvPV_flags_const_nolen|5.009003||p
-SvPV_flags_const|5.009003||p
-SvPV_flags_mutable|5.009003||p
-SvPV_flags|5.007002||p
-SvPV_force_flags_mutable|5.009003||p
-SvPV_force_flags_nolen|5.009003||p
-SvPV_force_flags|5.007002||p
-SvPV_force_mutable|5.009003||p
-SvPV_force_nolen|5.009003||p
-SvPV_force_nomg_nolen|5.009003||p
-SvPV_force_nomg|5.007002||p
-SvPV_force|||p
-SvPV_mutable|5.009003||p
-SvPV_nolen_const|5.009003||p
-SvPV_nolen|5.006000||p
-SvPV_nomg_const_nolen|5.009003||p
-SvPV_nomg_const|5.009003||p
-SvPV_nomg_nolen|5.013007||p
-SvPV_nomg|5.007002||p
-SvPV_renew|5.009003||p
-SvPV_set|||
-SvPVbyte_force||5.009002|
-SvPVbyte_nolen||5.006000|
-SvPVbytex_force||5.006000|
-SvPVbytex||5.006000|
-SvPVbyte|5.006000||p
-SvPVutf8_force||5.006000|
-SvPVutf8_nolen||5.006000|
-SvPVutf8x_force||5.006000|
-SvPVutf8x||5.006000|
-SvPVutf8||5.006000|
-SvPVx|||
-SvPV|||
-SvREFCNT_dec_NN||5.017007|
-SvREFCNT_dec|||
-SvREFCNT_inc_NN|5.009004||p
-SvREFCNT_inc_simple_NN|5.009004||p
-SvREFCNT_inc_simple_void_NN|5.009004||p
-SvREFCNT_inc_simple_void|5.009004||p
-SvREFCNT_inc_simple|5.009004||p
-SvREFCNT_inc_void_NN|5.009004||p
-SvREFCNT_inc_void|5.009004||p
-SvREFCNT_inc|||p
-SvREFCNT|||
-SvROK_off|||
-SvROK_on|||
-SvROK|||
-SvRV_set|5.009003||p
-SvRV|||
-SvRXOK|5.009005||p
-SvRX|5.009005||p
-SvSETMAGIC|||
-SvSHARED_HASH|5.009003||p
-SvSHARE||5.007003|
-SvSTASH_set|5.009003||p
-SvSTASH|||
-SvSetMagicSV_nosteal||5.004000|
-SvSetMagicSV||5.004000|
-SvSetSV_nosteal||5.004000|
-SvSetSV|||
-SvTAINTED_off||5.004000|
-SvTAINTED_on||5.004000|
-SvTAINTED||5.004000|
-SvTAINT|||
-SvTHINKFIRST|||
-SvTRUE_nomg||5.013006|
-SvTRUE|||
-SvTYPE|||
-SvUNLOCK||5.007003|
-SvUOK|5.007001|5.006000|p
-SvUPGRADE|||
-SvUTF8_off||5.006000|
-SvUTF8_on||5.006000|
-SvUTF8||5.006000|
-SvUVXx|5.004000||p
-SvUVX|5.004000||p
-SvUV_nomg|5.009001||p
-SvUV_set|5.009003||p
-SvUVx|5.004000||p
-SvUV|5.004000||p
-SvVOK||5.008001|
-SvVSTRING_mg|5.009004||p
-THIS|||n
-UNDERBAR|5.009002||p
-UTF8SKIP||5.006000|
-UTF8_MAXBYTES|5.009002||p
-UVCHR_SKIP||5.022000|
-UVSIZE|5.006000||p
-UVTYPE|5.006000||p
-UVXf|5.007001||p
-UVof|5.006000||p
-UVuf|5.006000||p
-UVxf|5.006000||p
-WARN_ALL|5.006000||p
-WARN_AMBIGUOUS|5.006000||p
-WARN_ASSERTIONS|5.024000||p
-WARN_BAREWORD|5.006000||p
-WARN_CLOSED|5.006000||p
-WARN_CLOSURE|5.006000||p
-WARN_DEBUGGING|5.006000||p
-WARN_DEPRECATED|5.006000||p
-WARN_DIGIT|5.006000||p
-WARN_EXEC|5.006000||p
-WARN_EXITING|5.006000||p
-WARN_GLOB|5.006000||p
-WARN_INPLACE|5.006000||p
-WARN_INTERNAL|5.006000||p
-WARN_IO|5.006000||p
-WARN_LAYER|5.008000||p
-WARN_MALLOC|5.006000||p
-WARN_MISC|5.006000||p
-WARN_NEWLINE|5.006000||p
-WARN_NUMERIC|5.006000||p
-WARN_ONCE|5.006000||p
-WARN_OVERFLOW|5.006000||p
-WARN_PACK|5.006000||p
-WARN_PARENTHESIS|5.006000||p
-WARN_PIPE|5.006000||p
-WARN_PORTABLE|5.006000||p
-WARN_PRECEDENCE|5.006000||p
-WARN_PRINTF|5.006000||p
-WARN_PROTOTYPE|5.006000||p
-WARN_QW|5.006000||p
-WARN_RECURSION|5.006000||p
-WARN_REDEFINE|5.006000||p
-WARN_REGEXP|5.006000||p
-WARN_RESERVED|5.006000||p
-WARN_SEMICOLON|5.006000||p
-WARN_SEVERE|5.006000||p
-WARN_SIGNAL|5.006000||p
-WARN_SUBSTR|5.006000||p
-WARN_SYNTAX|5.006000||p
-WARN_TAINT|5.006000||p
-WARN_THREADS|5.008000||p
-WARN_UNINITIALIZED|5.006000||p
-WARN_UNOPENED|5.006000||p
-WARN_UNPACK|5.006000||p
-WARN_UNTIE|5.006000||p
-WARN_UTF8|5.006000||p
-WARN_VOID|5.006000||p
-WIDEST_UTYPE|5.015004||p
-XCPT_CATCH|5.009002||p
-XCPT_RETHROW|5.009002||p
-XCPT_TRY_END|5.009002||p
-XCPT_TRY_START|5.009002||p
-XPUSHi|||
-XPUSHmortal|5.009002||p
-XPUSHn|||
-XPUSHp|||
-XPUSHs|||
-XPUSHu|5.004000||p
-XSPROTO|5.010000||p
-XSRETURN_EMPTY|||
-XSRETURN_IV|||
-XSRETURN_NO|||
-XSRETURN_NV|||
-XSRETURN_PV|||
-XSRETURN_UNDEF|||
-XSRETURN_UV|5.008001||p
-XSRETURN_YES|||
-XSRETURN|||p
-XST_mIV|||
-XST_mNO|||
-XST_mNV|||
-XST_mPV|||
-XST_mUNDEF|||
-XST_mUV|5.008001||p
-XST_mYES|||
-XS_APIVERSION_BOOTCHECK||5.024000|
-XS_EXTERNAL||5.024000|
-XS_INTERNAL||5.024000|
-XS_VERSION_BOOTCHECK||5.024000|
-XS_VERSION|||
-XSprePUSH|5.006000||p
-XS|||
-XopDISABLE||5.024000|
-XopENABLE||5.024000|
-XopENTRYCUSTOM||5.024000|
-XopENTRY_set||5.024000|
-XopENTRY||5.024000|
-XopFLAGS||5.013007|
-ZeroD|5.009002||p
-Zero|||
-_aMY_CXT|5.007003||p
-_add_range_to_invlist|||
-_append_range_to_invlist|||
-_core_swash_init|||
-_get_encoding|||
-_get_regclass_nonbitmap_data|||
-_get_swash_invlist|||
-_invlistEQ|||
-_invlist_array_init|||n
-_invlist_contains_cp|||n
-_invlist_dump|||
-_invlist_intersection_maybe_complement_2nd|||
-_invlist_intersection|||
-_invlist_invert|||
-_invlist_len|||n
-_invlist_populate_swatch|||n
-_invlist_search|||n
-_invlist_subtract|||
-_invlist_union_maybe_complement_2nd|||
-_invlist_union|||
-_is_cur_LC_category_utf8|||
-_is_in_locale_category||5.021001|
-_is_uni_FOO||5.017008|
-_is_uni_perl_idcont||5.017008|
-_is_uni_perl_idstart||5.017007|
-_is_utf8_FOO||5.017008|
-_is_utf8_char_slow||5.021001|n
-_is_utf8_idcont||5.021001|
-_is_utf8_idstart||5.021001|
-_is_utf8_mark||5.017008|
-_is_utf8_perl_idcont||5.017008|
-_is_utf8_perl_idstart||5.017007|
-_is_utf8_xidcont||5.021001|
-_is_utf8_xidstart||5.021001|
-_load_PL_utf8_foldclosures|||
-_make_exactf_invlist|||
-_new_invlist_C_array|||
-_new_invlist|||
-_pMY_CXT|5.007003||p
-_setlocale_debug_string|||n
-_setup_canned_invlist|||
-_swash_inversion_hash|||
-_swash_to_invlist|||
-_to_fold_latin1|||
-_to_uni_fold_flags||5.014000|
-_to_upper_title_latin1|||
-_to_utf8_case|||
-_to_utf8_fold_flags||5.019009|
-_to_utf8_lower_flags||5.019009|
-_to_utf8_title_flags||5.019009|
-_to_utf8_upper_flags||5.019009|
-_warn_problematic_locale|||n
-aMY_CXT_|5.007003||p
-aMY_CXT|5.007003||p
-aTHXR_|5.024000||p
-aTHXR|5.024000||p
-aTHX_|5.006000||p
-aTHX|5.006000||p
-add_above_Latin1_folds|||
-add_cp_to_invlist|||
-add_data|||n
-add_multi_match|||
-add_utf16_textfilter|||
-adjust_size_and_find_bucket|||n
-advance_one_LB|||
-advance_one_SB|||
-advance_one_WB|||
-alloc_maybe_populate_EXACT|||
-alloccopstash|||
-allocmy|||
-amagic_call|||
-amagic_cmp_locale|||
-amagic_cmp|||
-amagic_deref_call||5.013007|
-amagic_i_ncmp|||
-amagic_is_enabled|||
-amagic_ncmp|||
-anonymise_cv_maybe|||
-any_dup|||
-ao|||
-append_utf8_from_native_byte||5.019004|n
-apply_attrs_my|||
-apply_attrs_string||5.006001|
-apply_attrs|||
-apply|||
-assert_uft8_cache_coherent|||
-assignment_type|||
-atfork_lock||5.007003|n
-atfork_unlock||5.007003|n
-av_arylen_p||5.009003|
-av_clear|||
-av_create_and_push||5.009005|
-av_create_and_unshift_one||5.009005|
-av_delete||5.006000|
-av_exists||5.006000|
-av_extend_guts|||
-av_extend|||
-av_fetch|||
-av_fill|||
-av_iter_p||5.011000|
-av_len|||
-av_make|||
-av_pop|||
-av_push|||
-av_reify|||
-av_shift|||
-av_store|||
-av_tindex||5.017009|
-av_top_index||5.017009|
-av_undef|||
-av_unshift|||
-ax|||n
-backup_one_LB|||
-backup_one_SB|||
-backup_one_WB|||
-bad_type_gv|||
-bad_type_pv|||
-bind_match|||
-block_end||5.004000|
-block_gimme||5.004000|
-block_start||5.004000|
-blockhook_register||5.013003|
-boolSV|5.004000||p
-boot_core_PerlIO|||
-boot_core_UNIVERSAL|||
-boot_core_mro|||
-bytes_cmp_utf8||5.013007|
-bytes_from_utf8||5.007001|
-bytes_to_utf8||5.006001|
-cBOOL|5.013000||p
-call_argv|5.006000||p
-call_atexit||5.006000|
-call_list||5.004000|
-call_method|5.006000||p
-call_pv|5.006000||p
-call_sv|5.006000||p
-caller_cx|5.013005|5.006000|p
-calloc||5.007002|n
-cando|||
-cast_i32||5.006000|n
-cast_iv||5.006000|n
-cast_ulong||5.006000|n
-cast_uv||5.006000|n
-check_locale_boundary_crossing|||
-check_type_and_open|||
-check_uni|||
-check_utf8_print|||
-checkcomma|||
-ckWARN|5.006000||p
-ck_entersub_args_core|||
-ck_entersub_args_list||5.013006|
-ck_entersub_args_proto_or_list||5.013006|
-ck_entersub_args_proto||5.013006|
-ck_warner_d||5.011001|v
-ck_warner||5.011001|v
-ckwarn_common|||
-ckwarn_d||5.009003|
-ckwarn||5.009003|
-clear_defarray||5.023008|
-clear_placeholders|||
-clear_special_blocks|||
-clone_params_del|||n
-clone_params_new|||n
-closest_cop|||
-cntrl_to_mnemonic|||n
-compute_EXACTish|||n
-construct_ahocorasick_from_trie|||
-cop_fetch_label||5.015001|
-cop_free|||
-cop_hints_2hv||5.013007|
-cop_hints_fetch_pvn||5.013007|
-cop_hints_fetch_pvs||5.013007|
-cop_hints_fetch_pv||5.013007|
-cop_hints_fetch_sv||5.013007|
-cop_store_label||5.015001|
-cophh_2hv||5.013007|
-cophh_copy||5.013007|
-cophh_delete_pvn||5.013007|
-cophh_delete_pvs||5.013007|
-cophh_delete_pv||5.013007|
-cophh_delete_sv||5.013007|
-cophh_fetch_pvn||5.013007|
-cophh_fetch_pvs||5.013007|
-cophh_fetch_pv||5.013007|
-cophh_fetch_sv||5.013007|
-cophh_free||5.013007|
-cophh_new_empty||5.024000|
-cophh_store_pvn||5.013007|
-cophh_store_pvs||5.013007|
-cophh_store_pv||5.013007|
-cophh_store_sv||5.013007|
-core_prototype|||
-coresub_op|||
-cr_textfilter|||
-create_eval_scope|||
-croak_memory_wrap|5.019003||pn
-croak_no_mem|||n
-croak_no_modify|5.013003||pn
-croak_nocontext|||pvn
-croak_popstack|||n
-croak_sv|5.013001||p
-croak_xs_usage|5.010001||pn
-croak|||v
-csighandler||5.009003|n
-current_re_engine|||
-curse|||
-custom_op_desc||5.007003|
-custom_op_get_field|||
-custom_op_name||5.007003|
-custom_op_register||5.013007|
-custom_op_xop||5.013007|
-cv_ckproto_len_flags|||
-cv_clone_into|||
-cv_clone|||
-cv_const_sv_or_av|||n
-cv_const_sv||5.003070|n
-cv_dump|||
-cv_forget_slab|||
-cv_get_call_checker||5.013006|
-cv_name||5.021005|
-cv_set_call_checker_flags||5.021004|
-cv_set_call_checker||5.013006|
-cv_undef_flags|||
-cv_undef|||
-cvgv_from_hek|||
-cvgv_set|||
-cvstash_set|||
-cx_dump||5.005000|
-cx_dup|||
-cx_popblock||5.023008|
-cx_popeval||5.023008|
-cx_popformat||5.023008|
-cx_popgiven||5.023008|
-cx_poploop||5.023008|
-cx_popsub_args||5.023008|
-cx_popsub_common||5.023008|
-cx_popsub||5.023008|
-cx_popwhen||5.023008|
-cx_pushblock||5.023008|
-cx_pusheval||5.023008|
-cx_pushformat||5.023008|
-cx_pushgiven||5.023008|
-cx_pushloop_for||5.023008|
-cx_pushloop_plain||5.023008|
-cx_pushsub||5.023008|
-cx_pushwhen||5.023008|
-cx_topblock||5.023008|
-cxinc|||
-dAXMARK|5.009003||p
-dAX|5.007002||p
-dITEMS|5.007002||p
-dMARK|||
-dMULTICALL||5.009003|
-dMY_CXT_SV|5.007003||p
-dMY_CXT|5.007003||p
-dNOOP|5.006000||p
-dORIGMARK|||
-dSP|||
-dTHR|5.004050||p
-dTHXR|5.024000||p
-dTHXa|5.006000||p
-dTHXoa|5.006000||p
-dTHX|5.006000||p
-dUNDERBAR|5.009002||p
-dVAR|5.009003||p
-dXCPT|5.009002||p
-dXSARGS|||
-dXSI32|||
-dXSTARG|5.006000||p
-deb_curcv|||
-deb_nocontext|||vn
-deb_stack_all|||
-deb_stack_n|||
-debop||5.005000|
-debprofdump||5.005000|
-debprof|||
-debstackptrs||5.007003|
-debstack||5.007003|
-debug_start_match|||
-deb||5.007003|v
-defelem_target|||
-del_sv|||
-delete_eval_scope|||
-delimcpy||5.004000|n
-deprecate_commaless_var_list|||
-despatch_signals||5.007001|
-destroy_matcher|||
-die_nocontext|||vn
-die_sv|5.013001||p
-die_unwind|||
-die|||v
-dirp_dup|||
-div128|||
-djSP|||
-do_aexec5|||
-do_aexec|||
-do_aspawn|||
-do_binmode||5.004050|
-do_chomp|||
-do_close|||
-do_delete_local|||
-do_dump_pad|||
-do_eof|||
-do_exec3|||
-do_execfree|||
-do_exec|||
-do_gv_dump||5.006000|
-do_gvgv_dump||5.006000|
-do_hv_dump||5.006000|
-do_ipcctl|||
-do_ipcget|||
-do_join|||
-do_magic_dump||5.006000|
-do_msgrcv|||
-do_msgsnd|||
-do_ncmp|||
-do_oddball|||
-do_op_dump||5.006000|
-do_open6|||
-do_open9||5.006000|
-do_open_raw|||
-do_openn||5.007001|
-do_open||5.003070|
-do_pmop_dump||5.006000|
-do_print|||
-do_readline|||
-do_seek|||
-do_semop|||
-do_shmio|||
-do_smartmatch|||
-do_spawn_nowait|||
-do_spawn|||
-do_sprintf|||
-do_sv_dump||5.006000|
-do_sysseek|||
-do_tell|||
-do_trans_complex_utf8|||
-do_trans_complex|||
-do_trans_count_utf8|||
-do_trans_count|||
-do_trans_simple_utf8|||
-do_trans_simple|||
-do_trans|||
-do_vecget|||
-do_vecset|||
-do_vop|||
-docatch|||
-doeval_compile|||
-dofile|||
-dofindlabel|||
-doform|||
-doing_taint||5.008001|n
-dooneliner|||
-doopen_pm|||
-doparseform|||
-dopoptoeval|||
-dopoptogivenfor|||
-dopoptolabel|||
-dopoptoloop|||
-dopoptosub_at|||
-dopoptowhen|||
-doref||5.009003|
-dounwind|||
-dowantarray|||
-drand48_init_r|||n
-drand48_r|||n
-dtrace_probe_call|||
-dtrace_probe_load|||
-dtrace_probe_op|||
-dtrace_probe_phase|||
-dump_all_perl|||
-dump_all||5.006000|
-dump_c_backtrace|||
-dump_eval||5.006000|
-dump_exec_pos|||
-dump_form||5.006000|
-dump_indent||5.006000|v
-dump_mstats|||
-dump_packsubs_perl|||
-dump_packsubs||5.006000|
-dump_sub_perl|||
-dump_sub||5.006000|
-dump_sv_child|||
-dump_trie_interim_list|||
-dump_trie_interim_table|||
-dump_trie|||
-dump_vindent||5.006000|
-dumpuntil|||
-dup_attrlist|||
-edit_distance|||n
-emulate_cop_io|||
-eval_pv|5.006000||p
-eval_sv|5.006000||p
-exec_failed|||
-expect_number|||
-fbm_compile||5.005000|
-fbm_instr||5.005000|
-feature_is_enabled|||
-filter_add|||
-filter_del|||
-filter_gets|||
-filter_read|||
-finalize_optree|||
-finalize_op|||
-find_and_forget_pmops|||
-find_array_subscript|||
-find_beginning|||
-find_byclass|||
-find_default_stash|||
-find_hash_subscript|||
-find_in_my_stash|||
-find_lexical_cv|||
-find_runcv_where|||
-find_runcv||5.008001|
-find_rundefsvoffset||5.009002|
-find_rundefsv||5.013002|
-find_script|||
-find_uninit_var|||
-first_symbol|||n
-fixup_errno_string|||
-foldEQ_latin1||5.013008|n
-foldEQ_locale||5.013002|n
-foldEQ_utf8_flags||5.013010|
-foldEQ_utf8||5.013002|
-foldEQ||5.013002|n
-fold_constants|||
-forbid_setid|||
-force_ident_maybe_lex|||
-force_ident|||
-force_list|||
-force_next|||
-force_strict_version|||
-force_version|||
-force_word|||
-forget_pmop|||
-form_nocontext|||vn
-form_short_octal_warning|||
-form||5.004000|v
-fp_dup|||
-fprintf_nocontext|||vn
-free_c_backtrace|||
-free_global_struct|||
-free_tied_hv_pool|||
-free_tmps|||
-gen_constant_list|||
-get_ANYOF_cp_list_for_ssc|||
-get_and_check_backslash_N_name|||
-get_aux_mg|||
-get_av|5.006000||p
-get_c_backtrace_dump|||
-get_c_backtrace|||
-get_context||5.006000|n
-get_cvn_flags|||
-get_cvs|5.011000||p
-get_cv|5.006000||p
-get_db_sub|||
-get_debug_opts|||
-get_hash_seed|||
-get_hv|5.006000||p
-get_invlist_iter_addr|||n
-get_invlist_offset_addr|||n
-get_invlist_previous_index_addr|||n
-get_mstats|||
-get_no_modify|||
-get_num|||
-get_op_descs||5.005000|
-get_op_names||5.005000|
-get_opargs|||
-get_ppaddr||5.006000|
-get_re_arg|||
-get_sv|5.006000||p
-get_vtbl||5.005030|
-getcwd_sv||5.007002|
-getenv_len|||
-glob_2number|||
-glob_assign_glob|||
-gp_dup|||
-gp_free|||
-gp_ref|||
-grok_atoUV|||n
-grok_bin|5.007003||p
-grok_bslash_N|||
-grok_bslash_c|||
-grok_bslash_o|||
-grok_bslash_x|||
-grok_hex|5.007003||p
-grok_infnan||5.021004|
-grok_number_flags||5.021002|
-grok_number|5.007002||p
-grok_numeric_radix|5.007002||p
-grok_oct|5.007003||p
-group_end|||
-gv_AVadd|||
-gv_HVadd|||
-gv_IOadd|||
-gv_SVadd|||
-gv_add_by_type||5.011000|
-gv_autoload4||5.004000|
-gv_autoload_pvn||5.015004|
-gv_autoload_pv||5.015004|
-gv_autoload_sv||5.015004|
-gv_check|||
-gv_const_sv||5.009003|
-gv_dump||5.006000|
-gv_efullname3||5.003070|
-gv_efullname4||5.006001|
-gv_efullname|||
-gv_fetchfile_flags||5.009005|
-gv_fetchfile|||
-gv_fetchmeth_autoload||5.007003|
-gv_fetchmeth_internal|||
-gv_fetchmeth_pv_autoload||5.015004|
-gv_fetchmeth_pvn_autoload||5.015004|
-gv_fetchmeth_pvn||5.015004|
-gv_fetchmeth_pv||5.015004|
-gv_fetchmeth_sv_autoload||5.015004|
-gv_fetchmeth_sv||5.015004|
-gv_fetchmethod_autoload||5.004000|
-gv_fetchmethod_pv_flags||5.015004|
-gv_fetchmethod_pvn_flags||5.015004|
-gv_fetchmethod_sv_flags||5.015004|
-gv_fetchmethod|||
-gv_fetchmeth|||
-gv_fetchpvn_flags|5.009002||p
-gv_fetchpvs|5.009004||p
-gv_fetchpv|||
-gv_fetchsv|||
-gv_fullname3||5.003070|
-gv_fullname4||5.006001|
-gv_fullname|||
-gv_handler||5.007001|
-gv_init_pvn|||
-gv_init_pv||5.015004|
-gv_init_svtype|||
-gv_init_sv||5.015004|
-gv_init|||
-gv_is_in_main|||
-gv_magicalize_isa|||
-gv_magicalize|||
-gv_name_set||5.009004|
-gv_override|||
-gv_setref|||
-gv_stashpvn_internal|||
-gv_stashpvn|5.003070||p
-gv_stashpvs|5.009003||p
-gv_stashpv|||
-gv_stashsvpvn_cached|||
-gv_stashsv|||
-gv_try_downgrade|||
-handle_named_backref|||
-handle_possible_posix|||
-handle_regex_sets|||
-he_dup|||
-hek_dup|||
-hfree_next_entry|||
-hsplit|||
-hv_assert|||
-hv_auxinit_internal|||n
-hv_auxinit|||
-hv_backreferences_p|||
-hv_clear_placeholders||5.009001|
-hv_clear|||
-hv_common_key_len||5.010000|
-hv_common||5.010000|
-hv_copy_hints_hv||5.009004|
-hv_delayfree_ent||5.004000|
-hv_delete_common|||
-hv_delete_ent||5.003070|
-hv_delete|||
-hv_eiter_p||5.009003|
-hv_eiter_set||5.009003|
-hv_ename_add|||
-hv_ename_delete|||
-hv_exists_ent||5.003070|
-hv_exists|||
-hv_fetch_ent||5.003070|
-hv_fetchs|5.009003||p
-hv_fetch|||
-hv_fill||5.013002|
-hv_free_ent_ret|||
-hv_free_entries|||
-hv_free_ent||5.004000|
-hv_iterinit|||
-hv_iterkeysv||5.003070|
-hv_iterkey|||
-hv_iternext_flags||5.008000|
-hv_iternextsv|||
-hv_iternext|||
-hv_iterval|||
-hv_kill_backrefs|||
-hv_ksplit||5.003070|
-hv_magic_check|||n
-hv_magic|||
-hv_name_set||5.009003|
-hv_notallowed|||
-hv_placeholders_get||5.009003|
-hv_placeholders_p|||
-hv_placeholders_set||5.009003|
-hv_rand_set||5.018000|
-hv_riter_p||5.009003|
-hv_riter_set||5.009003|
-hv_scalar||5.009001|
-hv_store_ent||5.003070|
-hv_store_flags||5.008000|
-hv_stores|5.009004||p
-hv_store|||
-hv_undef_flags|||
-hv_undef|||
-ibcmp_locale||5.004000|
-ibcmp_utf8||5.007003|
-ibcmp|||
-incline|||
-incpush_if_exists|||
-incpush_use_sep|||
-incpush|||
-ingroup|||
-init_argv_symbols|||
-init_constants|||
-init_dbargs|||
-init_debugger|||
-init_global_struct|||
-init_i18nl10n||5.006000|
-init_i18nl14n||5.006000|
-init_ids|||
-init_interp|||
-init_main_stash|||
-init_perllib|||
-init_postdump_symbols|||
-init_predump_symbols|||
-init_stacks||5.005000|
-init_tm||5.007002|
-inplace_aassign|||
-instr|||n
-intro_my||5.004000|
-intuit_method|||
-intuit_more|||
-invert|||
-invlist_array|||n
-invlist_clear|||
-invlist_clone|||
-invlist_contents|||
-invlist_extend|||
-invlist_highest|||n
-invlist_is_iterating|||n
-invlist_iterfinish|||n
-invlist_iterinit|||n
-invlist_iternext|||n
-invlist_max|||n
-invlist_previous_index|||n
-invlist_replace_list_destroys_src|||
-invlist_set_len|||
-invlist_set_previous_index|||n
-invlist_trim|||n
-invoke_exception_hook|||
-io_close|||
-isALNUMC|5.006000||p
-isALNUM_lazy||5.021001|
-isALPHANUMERIC||5.017008|
-isALPHA|||
-isASCII|5.006000||p
-isBLANK|5.006001||p
-isCNTRL|5.006000||p
-isDIGIT|||
-isFOO_lc|||
-isFOO_utf8_lc|||
-isGCB|||n
-isGRAPH|5.006000||p
-isIDCONT||5.017008|
-isIDFIRST_lazy||5.021001|
-isIDFIRST|||
-isLB|||
-isLOWER|||
-isOCTAL||5.013005|
-isPRINT|5.004000||p
-isPSXSPC|5.006001||p
-isPUNCT|5.006000||p
-isSB|||
-isSPACE|||
-isUPPER|||
-isUTF8_CHAR||5.021001|
-isWB|||
-isWORDCHAR||5.013006|
-isXDIGIT|5.006000||p
-is_an_int|||
-is_ascii_string||5.011000|
-is_handle_constructor|||n
-is_invariant_string||5.021007|n
-is_lvalue_sub||5.007001|
-is_safe_syscall||5.019004|
-is_ssc_worth_it|||n
-is_uni_alnum_lc||5.006000|
-is_uni_alnumc_lc||5.017007|
-is_uni_alnumc||5.017007|
-is_uni_alnum||5.006000|
-is_uni_alpha_lc||5.006000|
-is_uni_alpha||5.006000|
-is_uni_ascii_lc||5.006000|
-is_uni_ascii||5.006000|
-is_uni_blank_lc||5.017002|
-is_uni_blank||5.017002|
-is_uni_cntrl_lc||5.006000|
-is_uni_cntrl||5.006000|
-is_uni_digit_lc||5.006000|
-is_uni_digit||5.006000|
-is_uni_graph_lc||5.006000|
-is_uni_graph||5.006000|
-is_uni_idfirst_lc||5.006000|
-is_uni_idfirst||5.006000|
-is_uni_lower_lc||5.006000|
-is_uni_lower||5.006000|
-is_uni_print_lc||5.006000|
-is_uni_print||5.006000|
-is_uni_punct_lc||5.006000|
-is_uni_punct||5.006000|
-is_uni_space_lc||5.006000|
-is_uni_space||5.006000|
-is_uni_upper_lc||5.006000|
-is_uni_upper||5.006000|
-is_uni_xdigit_lc||5.006000|
-is_uni_xdigit||5.006000|
-is_utf8_alnumc||5.017007|
-is_utf8_alnum||5.006000|
-is_utf8_alpha||5.006000|
-is_utf8_ascii||5.006000|
-is_utf8_blank||5.017002|
-is_utf8_char_buf||5.015008|n
-is_utf8_char||5.006000|n
-is_utf8_cntrl||5.006000|
-is_utf8_common|||
-is_utf8_digit||5.006000|
-is_utf8_graph||5.006000|
-is_utf8_idcont||5.008000|
-is_utf8_idfirst||5.006000|
-is_utf8_lower||5.006000|
-is_utf8_mark||5.006000|
-is_utf8_perl_space||5.011001|
-is_utf8_perl_word||5.011001|
-is_utf8_posix_digit||5.011001|
-is_utf8_print||5.006000|
-is_utf8_punct||5.006000|
-is_utf8_space||5.006000|
-is_utf8_string_loclen||5.009003|n
-is_utf8_string_loc||5.008001|n
-is_utf8_string||5.006001|n
-is_utf8_upper||5.006000|
-is_utf8_xdigit||5.006000|
-is_utf8_xidcont||5.013010|
-is_utf8_xidfirst||5.013010|
-isa_lookup|||
-isinfnansv|||
-isinfnan||5.021004|n
-items|||n
-ix|||n
-jmaybe|||
-join_exact|||
-keyword_plugin_standard|||
-keyword|||
-leave_adjust_stacks||5.023008|
-leave_scope|||
-lex_bufutf8||5.011002|
-lex_discard_to||5.011002|
-lex_grow_linestr||5.011002|
-lex_next_chunk||5.011002|
-lex_peek_unichar||5.011002|
-lex_read_space||5.011002|
-lex_read_to||5.011002|
-lex_read_unichar||5.011002|
-lex_start||5.009005|
-lex_stuff_pvn||5.011002|
-lex_stuff_pvs||5.013005|
-lex_stuff_pv||5.013006|
-lex_stuff_sv||5.011002|
-lex_unstuff||5.011002|
-listkids|||
-list|||
-load_module_nocontext|||vn
-load_module|5.006000||pv
-localize|||
-looks_like_bool|||
-looks_like_number|||
-lop|||
-mPUSHi|5.009002||p
-mPUSHn|5.009002||p
-mPUSHp|5.009002||p
-mPUSHs|5.010001||p
-mPUSHu|5.009002||p
-mXPUSHi|5.009002||p
-mXPUSHn|5.009002||p
-mXPUSHp|5.009002||p
-mXPUSHs|5.010001||p
-mXPUSHu|5.009002||p
-magic_clear_all_env|||
-magic_cleararylen_p|||
-magic_clearenv|||
-magic_clearhints|||
-magic_clearhint|||
-magic_clearisa|||
-magic_clearpack|||
-magic_clearsig|||
-magic_copycallchecker|||
-magic_dump||5.006000|
-magic_existspack|||
-magic_freearylen_p|||
-magic_freeovrld|||
-magic_getarylen|||
-magic_getdebugvar|||
-magic_getdefelem|||
-magic_getnkeys|||
-magic_getpack|||
-magic_getpos|||
-magic_getsig|||
-magic_getsubstr|||
-magic_gettaint|||
-magic_getuvar|||
-magic_getvec|||
-magic_get|||
-magic_killbackrefs|||
-magic_methcall1|||
-magic_methcall|||v
-magic_methpack|||
-magic_nextpack|||
-magic_regdata_cnt|||
-magic_regdatum_get|||
-magic_regdatum_set|||
-magic_scalarpack|||
-magic_set_all_env|||
-magic_setarylen|||
-magic_setcollxfrm|||
-magic_setdbline|||
-magic_setdebugvar|||
-magic_setdefelem|||
-magic_setenv|||
-magic_sethint|||
-magic_setisa|||
-magic_setlvref|||
-magic_setmglob|||
-magic_setnkeys|||
-magic_setpack|||
-magic_setpos|||
-magic_setregexp|||
-magic_setsig|||
-magic_setsubstr|||
-magic_settaint|||
-magic_setutf8|||
-magic_setuvar|||
-magic_setvec|||
-magic_set|||
-magic_sizepack|||
-magic_wipepack|||
-make_matcher|||
-make_trie|||
-malloc_good_size|||n
-malloced_size|||n
-malloc||5.007002|n
-markstack_grow||5.021001|
-matcher_matches_sv|||
-maybe_multimagic_gv|||
-mayberelocate|||
-measure_struct|||
-memEQs|5.009005||p
-memEQ|5.004000||p
-memNEs|5.009005||p
-memNE|5.004000||p
-mem_collxfrm|||
-mem_log_alloc|||n
-mem_log_common|||n
-mem_log_free|||n
-mem_log_realloc|||n
-mess_alloc|||
-mess_nocontext|||pvn
-mess_sv|5.013001||p
-mess|5.006000||pv
-mfree||5.007002|n
-mg_clear|||
-mg_copy|||
-mg_dup|||
-mg_find_mglob|||
-mg_findext|5.013008||pn
-mg_find|||n
-mg_free_type||5.013006|
-mg_free|||
-mg_get|||
-mg_length||5.005000|
-mg_localize|||
-mg_magical|||n
-mg_set|||
-mg_size||5.005000|
-mini_mktime||5.007002|n
-minus_v|||
-missingterm|||
-mode_from_discipline|||
-modkids|||
-more_bodies|||
-more_sv|||
-moreswitches|||
-move_proto_attr|||
-mro_clean_isarev|||
-mro_gather_and_rename|||
-mro_get_from_name||5.010001|
-mro_get_linear_isa_dfs|||
-mro_get_linear_isa||5.009005|
-mro_get_private_data||5.010001|
-mro_isa_changed_in|||
-mro_meta_dup|||
-mro_meta_init|||
-mro_method_changed_in||5.009005|
-mro_package_moved|||
-mro_register||5.010001|
-mro_set_mro||5.010001|
-mro_set_private_data||5.010001|
-mul128|||
-mulexp10|||n
-multideref_stringify|||
-my_atof2||5.007002|
-my_atof||5.006000|
-my_attrs|||
-my_bcopy||5.004050|n
-my_bytes_to_utf8|||n
-my_bzero|||n
-my_chsize|||
-my_clearenv|||
-my_cxt_index|||
-my_cxt_init|||
-my_dirfd||5.009005|n
-my_exit_jump|||
-my_exit|||
-my_failure_exit||5.004000|
-my_fflush_all||5.006000|
-my_fork||5.007003|n
-my_kid|||
-my_lstat_flags|||
-my_lstat||5.024000|
-my_memcmp|||n
-my_memset|||n
-my_pclose||5.003070|
-my_popen_list||5.007001|
-my_popen||5.003070|
-my_setenv|||
-my_setlocale|||
-my_snprintf|5.009004||pvn
-my_socketpair||5.007003|n
-my_sprintf|5.009003||pvn
-my_stat_flags|||
-my_stat||5.024000|
-my_strerror||5.021001|
-my_strftime||5.007002|
-my_strlcat|5.009004||pn
-my_strlcpy|5.009004||pn
-my_unexec|||
-my_vsnprintf||5.009004|n
-need_utf8|||n
-newANONATTRSUB||5.006000|
-newANONHASH|||
-newANONLIST|||
-newANONSUB|||
-newASSIGNOP|||
-newATTRSUB_x|||
-newATTRSUB||5.006000|
-newAVREF|||
-newAV|||
-newBINOP|||
-newCONDOP|||
-newCONSTSUB_flags||5.015006|
-newCONSTSUB|5.004050||p
-newCVREF|||
-newDEFSVOP||5.021006|
-newFORM|||
-newFOROP||5.013007|
-newGIVENOP||5.009003|
-newGIVWHENOP|||
-newGP|||
-newGVOP|||
-newGVREF|||
-newGVgen_flags||5.015004|
-newGVgen|||
-newHVREF|||
-newHVhv||5.005000|
-newHV|||
-newIO|||
-newLISTOP|||
-newLOGOP|||
-newLOOPEX|||
-newLOOPOP|||
-newMETHOP_internal|||
-newMETHOP_named||5.021005|
-newMETHOP||5.021005|
-newMYSUB||5.017004|
-newNULLLIST|||
-newOP|||
-newPADNAMELIST||5.021007|n
-newPADNAMEouter||5.021007|n
-newPADNAMEpvn||5.021007|n
-newPADOP|||
-newPMOP|||
-newPROG|||
-newPVOP|||
-newRANGE|||
-newRV_inc|5.004000||p
-newRV_noinc|5.004000||p
-newRV|||
-newSLICEOP|||
-newSTATEOP|||
-newSTUB|||
-newSUB|||
-newSVOP|||
-newSVREF|||
-newSV_type|5.009005||p
-newSVavdefelem|||
-newSVhek||5.009003|
-newSViv|||
-newSVnv|||
-newSVpadname||5.017004|
-newSVpv_share||5.013006|
-newSVpvf_nocontext|||vn
-newSVpvf||5.004000|v
-newSVpvn_flags|5.010001||p
-newSVpvn_share|5.007001||p
-newSVpvn_utf8|5.010001||p
-newSVpvn|5.004050||p
-newSVpvs_flags|5.010001||p
-newSVpvs_share|5.009003||p
-newSVpvs|5.009003||p
-newSVpv|||
-newSVrv|||
-newSVsv|||
-newSVuv|5.006000||p
-newSV|||
-newUNOP_AUX||5.021007|
-newUNOP|||
-newWHENOP||5.009003|
-newWHILEOP||5.013007|
-newXS_deffile|||
-newXS_flags||5.009004|
-newXS_len_flags|||
-newXSproto||5.006000|
-newXS||5.006000|
-new_collate||5.006000|
-new_constant|||
-new_ctype||5.006000|
-new_he|||
-new_logop|||
-new_numeric||5.006000|
-new_stackinfo||5.005000|
-new_version||5.009000|
-new_warnings_bitfield|||
-next_symbol|||
-nextargv|||
-nextchar|||
-ninstr|||n
-no_bareword_allowed|||
-no_fh_allowed|||
-no_op|||
-noperl_die|||vn
-not_a_number|||
-not_incrementable|||
-nothreadhook||5.008000|
-nuke_stacks|||
-num_overflow|||n
-oopsAV|||
-oopsHV|||
-op_append_elem||5.013006|
-op_append_list||5.013006|
-op_clear|||
-op_contextualize||5.013006|
-op_convert_list||5.021006|
-op_dump||5.006000|
-op_free|||
-op_integerize|||
-op_linklist||5.013006|
-op_lvalue_flags|||
-op_lvalue||5.013007|
-op_null||5.007002|
-op_parent|||n
-op_prepend_elem||5.013006|
-op_refcnt_dec|||
-op_refcnt_inc|||
-op_refcnt_lock||5.009002|
-op_refcnt_unlock||5.009002|
-op_relocate_sv|||
-op_scope||5.013007|
-op_sibling_splice||5.021002|n
-op_std_init|||
-op_unscope|||
-open_script|||
-openn_cleanup|||
-openn_setup|||
-opmethod_stash|||
-opslab_force_free|||
-opslab_free_nopad|||
-opslab_free|||
-output_or_return_posix_warnings|||
-pMY_CXT_|5.007003||p
-pMY_CXT|5.007003||p
-pTHX_|5.006000||p
-pTHX|5.006000||p
-packWARN|5.007003||p
-pack_cat||5.007003|
-pack_rec|||
-package_version|||
-package|||
-packlist||5.008001|
-pad_add_anon||5.008001|
-pad_add_name_pvn||5.015001|
-pad_add_name_pvs||5.015001|
-pad_add_name_pv||5.015001|
-pad_add_name_sv||5.015001|
-pad_add_weakref|||
-pad_alloc_name|||
-pad_alloc|||
-pad_block_start|||
-pad_check_dup|||
-pad_compname_type||5.009003|
-pad_findlex|||
-pad_findmy_pvn||5.015001|
-pad_findmy_pvs||5.015001|
-pad_findmy_pv||5.015001|
-pad_findmy_sv||5.015001|
-pad_fixup_inner_anons|||
-pad_free|||
-pad_leavemy|||
-pad_new||5.008001|
-pad_push|||
-pad_reset|||
-pad_setsv|||
-pad_sv|||
-pad_swipe|||
-pad_tidy||5.008001|
-padlist_dup|||
-padlist_store|||
-padname_dup|||
-padname_free|||
-padnamelist_dup|||
-padnamelist_fetch||5.021007|n
-padnamelist_free|||
-padnamelist_store||5.021007|
-parse_arithexpr||5.013008|
-parse_barestmt||5.013007|
-parse_block||5.013007|
-parse_body|||
-parse_fullexpr||5.013008|
-parse_fullstmt||5.013005|
-parse_gv_stash_name|||
-parse_ident|||
-parse_label||5.013007|
-parse_listexpr||5.013008|
-parse_lparen_question_flags|||
-parse_stmtseq||5.013006|
-parse_subsignature|||
-parse_termexpr||5.013008|
-parse_unicode_opts|||
-parser_dup|||
-parser_free_nexttoke_ops|||
-parser_free|||
-path_is_searchable|||n
-peep|||
-pending_ident|||
-perl_alloc_using|||n
-perl_alloc|||n
-perl_clone_using|||n
-perl_clone|||n
-perl_construct|||n
-perl_destruct||5.007003|n
-perl_free|||n
-perl_parse||5.006000|n
-perl_run|||n
-pidgone|||
-pm_description|||
-pmop_dump||5.006000|
-pmruntime|||
-pmtrans|||
-pop_scope|||
-populate_ANYOF_from_invlist|||
-populate_isa|||v
-pregcomp||5.009005|
-pregexec|||
-pregfree2||5.011000|
-pregfree|||
-prescan_version||5.011004|
-printbuf|||
-printf_nocontext|||vn
-process_special_blocks|||
-ptr_hash|||n
-ptr_table_clear||5.009005|
-ptr_table_fetch||5.009005|
-ptr_table_find|||n
-ptr_table_free||5.009005|
-ptr_table_new||5.009005|
-ptr_table_split||5.009005|
-ptr_table_store||5.009005|
-push_scope|||
-put_charclass_bitmap_innards_common|||
-put_charclass_bitmap_innards_invlist|||
-put_charclass_bitmap_innards|||
-put_code_point|||
-put_range|||
-pv_display|5.006000||p
-pv_escape|5.009004||p
-pv_pretty|5.009004||p
-pv_uni_display||5.007003|
-qerror|||
-qsortsvu|||
-quadmath_format_needed|||n
-quadmath_format_single|||n
-re_compile||5.009005|
-re_croak2|||
-re_dup_guts|||
-re_exec_indentf|||v
-re_indentf|||v
-re_intuit_start||5.019001|
-re_intuit_string||5.006000|
-re_op_compile|||
-re_printf|||v
-realloc||5.007002|n
-reentrant_free||5.024000|
-reentrant_init||5.024000|
-reentrant_retry||5.024000|vn
-reentrant_size||5.024000|
-ref_array_or_hash|||
-refcounted_he_chain_2hv|||
-refcounted_he_fetch_pvn|||
-refcounted_he_fetch_pvs|||
-refcounted_he_fetch_pv|||
-refcounted_he_fetch_sv|||
-refcounted_he_free|||
-refcounted_he_inc|||
-refcounted_he_new_pvn|||
-refcounted_he_new_pvs|||
-refcounted_he_new_pv|||
-refcounted_he_new_sv|||
-refcounted_he_value|||
-refkids|||
-refto|||
-ref||5.024000|
-reg2Lanode|||
-reg_check_named_buff_matched|||n
-reg_named_buff_all||5.009005|
-reg_named_buff_exists||5.009005|
-reg_named_buff_fetch||5.009005|
-reg_named_buff_firstkey||5.009005|
-reg_named_buff_iter|||
-reg_named_buff_nextkey||5.009005|
-reg_named_buff_scalar||5.009005|
-reg_named_buff|||
-reg_node|||
-reg_numbered_buff_fetch|||
-reg_numbered_buff_length|||
-reg_numbered_buff_store|||
-reg_qr_package|||
-reg_recode|||
-reg_scan_name|||
-reg_skipcomment|||n
-reg_temp_copy|||
-reganode|||
-regatom|||
-regbranch|||
-regclass_swash||5.009004|
-regclass|||
-regcppop|||
-regcppush|||
-regcurly|||n
-regdump_extflags|||
-regdump_intflags|||
-regdump||5.005000|
-regdupe_internal|||
-regex_set_precedence|||n
-regexec_flags||5.005000|
-regfree_internal||5.009005|
-reghop3|||n
-reghop4|||n
-reghopmaybe3|||n
-reginclass|||
-reginitcolors||5.006000|
-reginsert|||
-regmatch|||
-regnext||5.005000|
-regnode_guts|||
-regpiece|||
-regprop|||
-regrepeat|||
-regtail_study|||
-regtail|||
-regtry|||
-reg|||
-repeatcpy|||n
-report_evil_fh|||
-report_redefined_cv|||
-report_uninit|||
-report_wrongway_fh|||
-require_pv||5.006000|
-require_tie_mod|||
-restore_magic|||
-rninstr|||n
-rpeep|||
-rsignal_restore|||
-rsignal_save|||
-rsignal_state||5.004000|
-rsignal||5.004000|
-run_body|||
-run_user_filter|||
-runops_debug||5.005000|
-runops_standard||5.005000|
-rv2cv_op_cv||5.013006|
-rvpv_dup|||
-rxres_free|||
-rxres_restore|||
-rxres_save|||
-safesyscalloc||5.006000|n
-safesysfree||5.006000|n
-safesysmalloc||5.006000|n
-safesysrealloc||5.006000|n
-same_dirent|||
-save_I16||5.004000|
-save_I32|||
-save_I8||5.006000|
-save_adelete||5.011000|
-save_aelem_flags||5.011000|
-save_aelem||5.004050|
-save_alloc||5.006000|
-save_aptr|||
-save_ary|||
-save_bool||5.008001|
-save_clearsv|||
-save_delete|||
-save_destructor_x||5.006000|
-save_destructor||5.006000|
-save_freeop|||
-save_freepv|||
-save_freesv|||
-save_generic_pvref||5.006001|
-save_generic_svref||5.005030|
-save_gp||5.004000|
-save_hash|||
-save_hdelete||5.011000|
-save_hek_flags|||n
-save_helem_flags||5.011000|
-save_helem||5.004050|
-save_hints||5.010001|
-save_hptr|||
-save_int|||
-save_item|||
-save_iv||5.005000|
-save_lines|||
-save_list|||
-save_long|||
-save_magic_flags|||
-save_mortalizesv||5.007001|
-save_nogv|||
-save_op||5.005000|
-save_padsv_and_mortalize||5.010001|
-save_pptr|||
-save_pushi32ptr||5.010001|
-save_pushptri32ptr|||
-save_pushptrptr||5.010001|
-save_pushptr||5.010001|
-save_re_context||5.006000|
-save_scalar_at|||
-save_scalar|||
-save_set_svflags||5.009000|
-save_shared_pvref||5.007003|
-save_sptr|||
-save_strlen|||
-save_svref|||
-save_vptr||5.006000|
-savepvn|||
-savepvs||5.009003|
-savepv|||
-savesharedpvn||5.009005|
-savesharedpvs||5.013006|
-savesharedpv||5.007003|
-savesharedsvpv||5.013006|
-savestack_grow_cnt||5.008001|
-savestack_grow|||
-savesvpv||5.009002|
-savetmps||5.023008|
-sawparens|||
-scalar_mod_type|||n
-scalarboolean|||
-scalarkids|||
-scalarseq|||
-scalarvoid|||
-scalar|||
-scan_bin||5.006000|
-scan_commit|||
-scan_const|||
-scan_formline|||
-scan_heredoc|||
-scan_hex|||
-scan_ident|||
-scan_inputsymbol|||
-scan_num||5.007001|
-scan_oct|||
-scan_pat|||
-scan_str|||
-scan_subst|||
-scan_trans|||
-scan_version||5.009001|
-scan_vstring||5.009005|
-scan_word|||
-search_const|||
-seed||5.008001|
-sequence_num|||
-set_ANYOF_arg|||
-set_caret_X|||
-set_context||5.006000|n
-set_numeric_local||5.006000|
-set_numeric_radix||5.006000|
-set_numeric_standard||5.006000|
-set_padlist|||n
-setdefout|||
-share_hek_flags|||
-share_hek||5.004000|
-should_warn_nl|||n
-si_dup|||
-sighandler|||n
-simplify_sort|||
-skip_to_be_ignored_text|||
-skipspace_flags|||
-softref2xv|||
-sortcv_stacked|||
-sortcv_xsub|||
-sortcv|||
-sortsv_flags||5.009003|
-sortsv||5.007003|
-space_join_names_mortal|||
-ss_dup|||
-ssc_add_range|||
-ssc_and|||
-ssc_anything|||
-ssc_clear_locale|||n
-ssc_cp_and|||
-ssc_finalize|||
-ssc_init|||
-ssc_intersection|||
-ssc_is_anything|||n
-ssc_is_cp_posixl_init|||n
-ssc_or|||
-ssc_union|||
-stack_grow|||
-start_glob|||
-start_subparse||5.004000|
-stdize_locale|||
-strEQ|||
-strGE|||
-strGT|||
-strLE|||
-strLT|||
-strNE|||
-str_to_version||5.006000|
-strip_return|||
-strnEQ|||
-strnNE|||
-study_chunk|||
-sub_crush_depth|||
-sublex_done|||
-sublex_push|||
-sublex_start|||
-sv_2bool_flags||5.013006|
-sv_2bool|||
-sv_2cv|||
-sv_2io|||
-sv_2iuv_common|||
-sv_2iuv_non_preserve|||
-sv_2iv_flags||5.009001|
-sv_2iv|||
-sv_2mortal|||
-sv_2num|||
-sv_2nv_flags||5.013001|
-sv_2pv_flags|5.007002||p
-sv_2pv_nolen|5.006000||p
-sv_2pvbyte_nolen|5.006000||p
-sv_2pvbyte|5.006000||p
-sv_2pvutf8_nolen||5.006000|
-sv_2pvutf8||5.006000|
-sv_2pv|||
-sv_2uv_flags||5.009001|
-sv_2uv|5.004000||p
-sv_add_arena|||
-sv_add_backref|||
-sv_backoff|||n
-sv_bless|||
-sv_buf_to_ro|||
-sv_buf_to_rw|||
-sv_cat_decode||5.008001|
-sv_catpv_flags||5.013006|
-sv_catpv_mg|5.004050||p
-sv_catpv_nomg||5.013006|
-sv_catpvf_mg_nocontext|||pvn
-sv_catpvf_mg|5.006000|5.004000|pv
-sv_catpvf_nocontext|||vn
-sv_catpvf||5.004000|v
-sv_catpvn_flags||5.007002|
-sv_catpvn_mg|5.004050||p
-sv_catpvn_nomg|5.007002||p
-sv_catpvn|||
-sv_catpvs_flags||5.013006|
-sv_catpvs_mg||5.013006|
-sv_catpvs_nomg||5.013006|
-sv_catpvs|5.009003||p
-sv_catpv|||
-sv_catsv_flags||5.007002|
-sv_catsv_mg|5.004050||p
-sv_catsv_nomg|5.007002||p
-sv_catsv|||
-sv_chop|||
-sv_clean_all|||
-sv_clean_objs|||
-sv_clear|||
-sv_cmp_flags||5.013006|
-sv_cmp_locale_flags||5.013006|
-sv_cmp_locale||5.004000|
-sv_cmp|||
-sv_collxfrm_flags||5.013006|
-sv_collxfrm|||
-sv_copypv_flags||5.017002|
-sv_copypv_nomg||5.017002|
-sv_copypv|||
-sv_dec_nomg||5.013002|
-sv_dec|||
-sv_del_backref|||
-sv_derived_from_pvn||5.015004|
-sv_derived_from_pv||5.015004|
-sv_derived_from_sv||5.015004|
-sv_derived_from||5.004000|
-sv_destroyable||5.010000|
-sv_display|||
-sv_does_pvn||5.015004|
-sv_does_pv||5.015004|
-sv_does_sv||5.015004|
-sv_does||5.009004|
-sv_dump|||
-sv_dup_common|||
-sv_dup_inc_multiple|||
-sv_dup_inc|||
-sv_dup|||
-sv_eq_flags||5.013006|
-sv_eq|||
-sv_exp_grow|||
-sv_force_normal_flags||5.007001|
-sv_force_normal||5.006000|
-sv_free2|||
-sv_free_arenas|||
-sv_free|||
-sv_get_backrefs||5.021008|n
-sv_gets||5.003070|
-sv_grow|||
-sv_i_ncmp|||
-sv_inc_nomg||5.013002|
-sv_inc|||
-sv_insert_flags||5.010001|
-sv_insert|||
-sv_isa|||
-sv_isobject|||
-sv_iv||5.005000|
-sv_kill_backrefs|||
-sv_len_utf8_nomg|||
-sv_len_utf8||5.006000|
-sv_len|||
-sv_magic_portable|5.024000|5.004000|p
-sv_magicext_mglob|||
-sv_magicext||5.007003|
-sv_magic|||
-sv_mortalcopy_flags|||
-sv_mortalcopy|||
-sv_ncmp|||
-sv_newmortal|||
-sv_newref|||
-sv_nolocking||5.007003|
-sv_nosharing||5.007003|
-sv_nounlocking|||
-sv_nv||5.005000|
-sv_only_taint_gmagic|||n
-sv_or_pv_pos_u2b|||
-sv_peek||5.005000|
-sv_pos_b2u_flags||5.019003|
-sv_pos_b2u_midway|||
-sv_pos_b2u||5.006000|
-sv_pos_u2b_cached|||
-sv_pos_u2b_flags||5.011005|
-sv_pos_u2b_forwards|||n
-sv_pos_u2b_midway|||n
-sv_pos_u2b||5.006000|
-sv_pvbyten_force||5.006000|
-sv_pvbyten||5.006000|
-sv_pvbyte||5.006000|
-sv_pvn_force_flags|5.007002||p
-sv_pvn_force|||
-sv_pvn_nomg|5.007003|5.005000|p
-sv_pvn||5.005000|
-sv_pvutf8n_force||5.006000|
-sv_pvutf8n||5.006000|
-sv_pvutf8||5.006000|
-sv_pv||5.006000|
-sv_recode_to_utf8||5.007003|
-sv_reftype|||
-sv_ref||5.015004|
-sv_replace|||
-sv_report_used|||
-sv_resetpvn|||
-sv_reset|||
-sv_rvweaken||5.006000|
-sv_sethek|||
-sv_setiv_mg|5.004050||p
-sv_setiv|||
-sv_setnv_mg|5.006000||p
-sv_setnv|||
-sv_setpv_mg|5.004050||p
-sv_setpvf_mg_nocontext|||pvn
-sv_setpvf_mg|5.006000|5.004000|pv
-sv_setpvf_nocontext|||vn
-sv_setpvf||5.004000|v
-sv_setpviv_mg||5.008001|
-sv_setpviv||5.008001|
-sv_setpvn_mg|5.004050||p
-sv_setpvn|||
-sv_setpvs_mg||5.013006|
-sv_setpvs|5.009004||p
-sv_setpv|||
-sv_setref_iv|||
-sv_setref_nv|||
-sv_setref_pvn|||
-sv_setref_pvs||5.024000|
-sv_setref_pv|||
-sv_setref_uv||5.007001|
-sv_setsv_cow|||
-sv_setsv_flags||5.007002|
-sv_setsv_mg|5.004050||p
-sv_setsv_nomg|5.007002||p
-sv_setsv|||
-sv_setuv_mg|5.004050||p
-sv_setuv|5.004000||p
-sv_tainted||5.004000|
-sv_taint||5.004000|
-sv_true||5.005000|
-sv_unglob|||
-sv_uni_display||5.007003|
-sv_unmagicext|5.013008||p
-sv_unmagic|||
-sv_unref_flags||5.007001|
-sv_unref|||
-sv_untaint||5.004000|
-sv_upgrade|||
-sv_usepvn_flags||5.009004|
-sv_usepvn_mg|5.004050||p
-sv_usepvn|||
-sv_utf8_decode||5.006000|
-sv_utf8_downgrade||5.006000|
-sv_utf8_encode||5.006000|
-sv_utf8_upgrade_flags_grow||5.011000|
-sv_utf8_upgrade_flags||5.007002|
-sv_utf8_upgrade_nomg||5.007002|
-sv_utf8_upgrade||5.007001|
-sv_uv|5.005000||p
-sv_vcatpvf_mg|5.006000|5.004000|p
-sv_vcatpvfn_flags||5.017002|
-sv_vcatpvfn||5.004000|
-sv_vcatpvf|5.006000|5.004000|p
-sv_vsetpvf_mg|5.006000|5.004000|p
-sv_vsetpvfn||5.004000|
-sv_vsetpvf|5.006000|5.004000|p
-svtype|||
-swallow_bom|||
-swash_fetch||5.007002|
-swash_init||5.006000|
-swash_scan_list_line|||
-swatch_get|||
-sync_locale||5.021004|
-sys_init3||5.010000|n
-sys_init||5.010000|n
-sys_intern_clear|||
-sys_intern_dup|||
-sys_intern_init|||
-sys_term||5.010000|n
-taint_env|||
-taint_proper|||
-tied_method|||v
-tmps_grow_p|||
-toFOLD_utf8||5.019001|
-toFOLD_uvchr||5.023009|
-toFOLD||5.019001|
-toLOWER_L1||5.019001|
-toLOWER_LC||5.004000|
-toLOWER_utf8||5.015007|
-toLOWER_uvchr||5.023009|
-toLOWER|||
-toTITLE_utf8||5.015007|
-toTITLE_uvchr||5.023009|
-toTITLE||5.019001|
-toUPPER_utf8||5.015007|
-toUPPER_uvchr||5.023009|
-toUPPER|||
-to_byte_substr|||
-to_lower_latin1|||n
-to_uni_fold||5.007003|
-to_uni_lower_lc||5.006000|
-to_uni_lower||5.007003|
-to_uni_title_lc||5.006000|
-to_uni_title||5.007003|
-to_uni_upper_lc||5.006000|
-to_uni_upper||5.007003|
-to_utf8_case||5.007003|
-to_utf8_fold||5.015007|
-to_utf8_lower||5.015007|
-to_utf8_substr|||
-to_utf8_title||5.015007|
-to_utf8_upper||5.015007|
-tokenize_use|||
-tokeq|||
-tokereport|||
-too_few_arguments_pv|||
-too_many_arguments_pv|||
-translate_substr_offsets|||n
-try_amagic_bin|||
-try_amagic_un|||
-uiv_2buf|||n
-unlnk|||
-unpack_rec|||
-unpack_str||5.007003|
-unpackstring||5.008001|
-unreferenced_to_tmp_stack|||
-unshare_hek_or_pvn|||
-unshare_hek|||
-unsharepvn||5.003070|
-unwind_handler_stack|||
-update_debugger_info|||
-upg_version||5.009005|
-usage|||
-utf16_textfilter|||
-utf16_to_utf8_reversed||5.006001|
-utf16_to_utf8||5.006001|
-utf8_distance||5.006000|
-utf8_hop||5.006000|n
-utf8_length||5.007001|
-utf8_mg_len_cache_update|||
-utf8_mg_pos_cache_update|||
-utf8_to_bytes||5.006001|
-utf8_to_uvchr_buf||5.015009|
-utf8_to_uvchr||5.007001|
-utf8_to_uvuni_buf||5.015009|
-utf8_to_uvuni||5.007001|
-utf8n_to_uvchr||5.007001|
-utf8n_to_uvuni||5.007001|
-utilize|||
-uvchr_to_utf8_flags||5.007003|
-uvchr_to_utf8||5.007001|
-uvoffuni_to_utf8_flags||5.019004|
-uvuni_to_utf8_flags||5.007003|
-uvuni_to_utf8||5.007001|
-valid_utf8_to_uvchr||5.015009|
-valid_utf8_to_uvuni||5.015009|
-validate_proto|||
-validate_suid|||
-varname|||
-vcmp||5.009000|
-vcroak||5.006000|
-vdeb||5.007003|
-vform||5.006000|
-visit|||
-vivify_defelem|||
-vivify_ref|||
-vload_module|5.006000||p
-vmess|5.006000||p
-vnewSVpvf|5.006000|5.004000|p
-vnormal||5.009002|
-vnumify||5.009000|
-vstringify||5.009000|
-vverify||5.009003|
-vwarner||5.006000|
-vwarn||5.006000|
-wait4pid|||
-warn_nocontext|||pvn
-warn_sv|5.013001||p
-warner_nocontext|||vn
-warner|5.006000|5.004000|pv
-warn|||v
-was_lvalue_sub|||
-watch|||
-whichsig_pvn||5.015004|
-whichsig_pv||5.015004|
-whichsig_sv||5.015004|
-whichsig|||
-win32_croak_not_implemented|||n
-with_queued_errors|||
-wrap_op_checker||5.015008|
-write_to_stderr|||
-xs_boot_epilog|||
-xs_handshake|||vn
-xs_version_bootcheck|||
-yyerror_pvn|||
-yyerror_pv|||
-yyerror|||
-yylex|||
-yyparse|||
-yyunlex|||
-yywarn|||
-);
-
-if (exists $opt{'list-unsupported'}) {
-  my $f;
-  for $f (sort { lc $a cmp lc $b } keys %API) {
-    next unless $API{$f}{todo};
-    print "$f ", '.'x(40-length($f)), " ", format_version($API{$f}{todo}), "\n";
-  }
-  exit 0;
-}
-
-# Scan for possible replacement candidates
-
-my(%replace, %need, %hints, %warnings, %depends);
-my $replace = 0;
-my($hint, $define, $function);
-
-sub find_api
-{
-  my $code = shift;
-  $code =~ s{
-    / (?: \*[^*]*\*+(?:[^$ccs][^*]*\*+)* / | /[^\r\n]*)
-  | "[^"\\]*(?:\\.[^"\\]*)*"
-  | '[^'\\]*(?:\\.[^'\\]*)*' }{}egsx;
-  grep { exists $API{$_} } $code =~ /(\w+)/mg;
-}
-
-while (<DATA>) {
-  if ($hint) {
-    my $h = $hint->[0] eq 'Hint' ? \%hints : \%warnings;
-    if (m{^\s*\*\s(.*?)\s*$}) {
-      for (@{$hint->[1]}) {
-        $h->{$_} ||= '';  # suppress warning with older perls
-        $h->{$_} .= "$1\n";
-      }
-    }
-    else { undef $hint }
-  }
-
-  $hint = [$1, [split /,?\s+/, $2]]
-      if m{^\s*$rccs\s+(Hint|Warning):\s+(\w+(?:,?\s+\w+)*)\s*$};
-
-  if ($define) {
-    if ($define->[1] =~ /\\$/) {
-      $define->[1] .= $_;
-    }
-    else {
-      if (exists $API{$define->[0]} && $define->[1] !~ /^DPPP_\(/) {
-        my @n = find_api($define->[1]);
-        push @{$depends{$define->[0]}}, @n if @n
-      }
-      undef $define;
-    }
-  }
-
-  $define = [$1, $2] if m{^\s*#\s*define\s+(\w+)(?:\([^)]*\))?\s+(.*)};
-
-  if ($function) {
-    if (/^}/) {
-      if (exists $API{$function->[0]}) {
-        my @n = find_api($function->[1]);
-        push @{$depends{$function->[0]}}, @n if @n
-      }
-      undef $function;
-    }
-    else {
-      $function->[1] .= $_;
-    }
-  }
-
-  $function = [$1, ''] if m{^DPPP_\(my_(\w+)\)};
-
-  $replace     = $1 if m{^\s*$rccs\s+Replace:\s+(\d+)\s+$rcce\s*$};
-  $replace{$2} = $1 if $replace and m{^\s*#\s*define\s+(\w+)(?:\([^)]*\))?\s+(\w+)};
-  $replace{$2} = $1 if m{^\s*#\s*define\s+(\w+)(?:\([^)]*\))?\s+(\w+).*$rccs\s+Replace\s+$rcce};
-  $replace{$1} = $2 if m{^\s*$rccs\s+Replace (\w+) with (\w+)\s+$rcce\s*$};
-
-  if (m{^\s*$rccs\s+(\w+(\s*,\s*\w+)*)\s+depends\s+on\s+(\w+(\s*,\s*\w+)*)\s+$rcce\s*$}) {
-    my @deps = map { s/\s+//g; $_ } split /,/, $3;
-    my $d;
-    for $d (map { s/\s+//g; $_ } split /,/, $1) {
-      push @{$depends{$d}}, @deps;
-    }
-  }
-
-  $need{$1} = 1 if m{^#if\s+defined\(NEED_(\w+)(?:_GLOBAL)?\)};
-}
-
-for (values %depends) {
-  my %s;
-  $_ = [sort grep !$s{$_}++, @$_];
-}
-
-if (exists $opt{'api-info'}) {
-  my $f;
-  my $count = 0;
-  my $match = $opt{'api-info'} =~ m!^/(.*)/$! ? $1 : "^\Q$opt{'api-info'}\E\$";
-  for $f (sort { lc $a cmp lc $b } keys %API) {
-    next unless $f =~ /$match/;
-    print "\n=== $f ===\n\n";
-    my $info = 0;
-    if ($API{$f}{base} || $API{$f}{todo}) {
-      my $base = format_version($API{$f}{base} || $API{$f}{todo});
-      print "Supported at least starting from perl-$base.\n";
-      $info++;
-    }
-    if ($API{$f}{provided}) {
-      my $todo = $API{$f}{todo} ? format_version($API{$f}{todo}) : "5.003";
-      print "Support by $ppport provided back to perl-$todo.\n";
-      print "Support needs to be explicitly requested by NEED_$f.\n" if exists $need{$f};
-      print "Depends on: ", join(', ', @{$depends{$f}}), ".\n" if exists $depends{$f};
-      print "\n$hints{$f}" if exists $hints{$f};
-      print "\nWARNING:\n$warnings{$f}" if exists $warnings{$f};
-      $info++;
-    }
-    print "No portability information available.\n" unless $info;
-    $count++;
-  }
-  $count or print "Found no API matching '$opt{'api-info'}'.";
-  print "\n";
-  exit 0;
-}
-
-if (exists $opt{'list-provided'}) {
-  my $f;
-  for $f (sort { lc $a cmp lc $b } keys %API) {
-    next unless $API{$f}{provided};
-    my @flags;
-    push @flags, 'explicit' if exists $need{$f};
-    push @flags, 'depend'   if exists $depends{$f};
-    push @flags, 'hint'     if exists $hints{$f};
-    push @flags, 'warning'  if exists $warnings{$f};
-    my $flags = @flags ? '  ['.join(', ', @flags).']' : '';
-    print "$f$flags\n";
-  }
-  exit 0;
-}
-
-my @files;
-my @srcext = qw( .xs .c .h .cc .cpp -c.inc -xs.inc );
-my $srcext = join '|', map { quotemeta $_ } @srcext;
-
-if (@ARGV) {
-  my %seen;
-  for (@ARGV) {
-    if (-e) {
-      if (-f) {
-        push @files, $_ unless $seen{$_}++;
-      }
-      else { warn "'$_' is not a file.\n" }
-    }
-    else {
-      my @new = grep { -f } glob $_
-          or warn "'$_' does not exist.\n";
-      push @files, grep { !$seen{$_}++ } @new;
-    }
-  }
-}
-else {
-  eval {
-    require File::Find;
-    File::Find::find(sub {
-      $File::Find::name =~ /($srcext)$/i
-          and push @files, $File::Find::name;
-    }, '.');
-  };
-  if ($@) {
-    @files = map { glob "*$_" } @srcext;
-  }
-}
-
-if (!@ARGV || $opt{filter}) {
-  my(@in, @out);
-  my %xsc = map { /(.*)\.xs$/ ? ("$1.c" => 1, "$1.cc" => 1) : () } @files;
-  for (@files) {
-    my $out = exists $xsc{$_} || /\b\Q$ppport\E$/i || !/($srcext)$/i;
-    push @{ $out ? \@out : \@in }, $_;
-  }
-  if (@ARGV && @out) {
-    warning("Skipping the following files (use --nofilter to avoid this):\n| ", join "\n| ", @out);
-  }
-  @files = @in;
-}
-
-die "No input files given!\n" unless @files;
-
-my(%files, %global, %revreplace);
-%revreplace = reverse %replace;
-my $filename;
-my $patch_opened = 0;
-
-for $filename (@files) {
-  unless (open IN, "<$filename") {
-    warn "Unable to read from $filename: $!\n";
-    next;
-  }
-
-  info("Scanning $filename ...");
-
-  my $c = do { local $/; <IN> };
-  close IN;
-
-  my %file = (orig => $c, changes => 0);
-
-  # Temporarily remove C/XS comments and strings from the code
-  my @ccom;
-
-  $c =~ s{
-    ( ^$HS*\#$HS*include\b[^\r\n]+\b(?:\Q$ppport\E|XSUB\.h)\b[^\r\n]*
-    | ^$HS*\#$HS*(?:define|elif|if(?:def)?)\b[^\r\n]* )
-  | ( ^$HS*\#[^\r\n]*
-    | "[^"\\]*(?:\\.[^"\\]*)*"
-    | '[^'\\]*(?:\\.[^'\\]*)*'
-    | / (?: \*[^*]*\*+(?:[^$ccs][^*]*\*+)* / | /[^\r\n]* ) )
-  }{ defined $2 and push @ccom, $2;
-     defined $1 ? $1 : "$ccs$#ccom$cce" }mgsex;
-
-  $file{ccom} = \@ccom;
-  $file{code} = $c;
-  $file{has_inc_ppport} = $c =~ /^$HS*#$HS*include[^\r\n]+\b\Q$ppport\E\b/m;
-
-  my $func;
-
-  for $func (keys %API) {
-    my $match = $func;
-    $match .= "|$revreplace{$func}" if exists $revreplace{$func};
-    if ($c =~ /\b(?:Perl_)?($match)\b/) {
-      $file{uses_replace}{$1}++ if exists $revreplace{$func} && $1 eq $revreplace{$func};
-      $file{uses_Perl}{$func}++ if $c =~ /\bPerl_$func\b/;
-      if (exists $API{$func}{provided}) {
-        $file{uses_provided}{$func}++;
-        if (!exists $API{$func}{base} || $API{$func}{base} > $opt{'compat-version'}) {
-          $file{uses}{$func}++;
-          my @deps = rec_depend($func);
-          if (@deps) {
-            $file{uses_deps}{$func} = \@deps;
-            for (@deps) {
-              $file{uses}{$_} = 0 unless exists $file{uses}{$_};
-            }
-          }
-          for ($func, @deps) {
-            $file{needs}{$_} = 'static' if exists $need{$_};
-          }
-        }
-      }
-      if (exists $API{$func}{todo} && $API{$func}{todo} > $opt{'compat-version'}) {
-        if ($c =~ /\b$func\b/) {
-          $file{uses_todo}{$func}++;
-        }
-      }
-    }
-  }
-
-  while ($c =~ /^$HS*#$HS*define$HS+(NEED_(\w+?)(_GLOBAL)?)\b/mg) {
-    if (exists $need{$2}) {
-      $file{defined $3 ? 'needed_global' : 'needed_static'}{$2}++;
-    }
-    else { warning("Possibly wrong #define $1 in $filename") }
-  }
-
-  for (qw(uses needs uses_todo needed_global needed_static)) {
-    for $func (keys %{$file{$_}}) {
-      push @{$global{$_}{$func}}, $filename;
-    }
-  }
-
-  $files{$filename} = \%file;
-}
-
-# Globally resolve NEED_'s
-my $need;
-for $need (keys %{$global{needs}}) {
-  if (@{$global{needs}{$need}} > 1) {
-    my @targets = @{$global{needs}{$need}};
-    my @t = grep $files{$_}{needed_global}{$need}, @targets;
-    @targets = @t if @t;
-    @t = grep /\.xs$/i, @targets;
-    @targets = @t if @t;
-    my $target = shift @targets;
-    $files{$target}{needs}{$need} = 'global';
-    for (@{$global{needs}{$need}}) {
-      $files{$_}{needs}{$need} = 'extern' if $_ ne $target;
-    }
-  }
-}
-
-for $filename (@files) {
-  exists $files{$filename} or next;
-
-  info("=== Analyzing $filename ===");
-
-  my %file = %{$files{$filename}};
-  my $func;
-  my $c = $file{code};
-  my $warnings = 0;
-
-  for $func (sort keys %{$file{uses_Perl}}) {
-    if ($API{$func}{varargs}) {
-      unless ($API{$func}{nothxarg}) {
-        my $changes = ($c =~ s{\b(Perl_$func\s*\(\s*)(?!aTHX_?)(\)|[^\s)]*\))}
-                              { $1 . ($2 eq ')' ? 'aTHX' : 'aTHX_ ') . $2 }ge);
-        if ($changes) {
-          warning("Doesn't pass interpreter argument aTHX to Perl_$func");
-          $file{changes} += $changes;
-        }
-      }
-    }
-    else {
-      warning("Uses Perl_$func instead of $func");
-      $file{changes} += ($c =~ s{\bPerl_$func(\s*)\((\s*aTHX_?)?\s*}
-                                {$func$1(}g);
-    }
-  }
-
-  for $func (sort keys %{$file{uses_replace}}) {
-    warning("Uses $func instead of $replace{$func}");
-    $file{changes} += ($c =~ s/\b$func\b/$replace{$func}/g);
-  }
-
-  for $func (sort keys %{$file{uses_provided}}) {
-    if ($file{uses}{$func}) {
-      if (exists $file{uses_deps}{$func}) {
-        diag("Uses $func, which depends on ", join(', ', @{$file{uses_deps}{$func}}));
-      }
-      else {
-        diag("Uses $func");
-      }
-    }
-    $warnings += hint($func);
-  }
-
-  unless ($opt{quiet}) {
-    for $func (sort keys %{$file{uses_todo}}) {
-      print "*** WARNING: Uses $func, which may not be portable below perl ",
-            format_version($API{$func}{todo}), ", even with '$ppport'\n";
-      $warnings++;
-    }
-  }
-
-  for $func (sort keys %{$file{needed_static}}) {
-    my $message = '';
-    if (not exists $file{uses}{$func}) {
-      $message = "No need to define NEED_$func if $func is never used";
-    }
-    elsif (exists $file{needs}{$func} && $file{needs}{$func} ne 'static') {
-      $message = "No need to define NEED_$func when already needed globally";
-    }
-    if ($message) {
-      diag($message);
-      $file{changes} += ($c =~ s/^$HS*#$HS*define$HS+NEED_$func\b.*$LF//mg);
-    }
-  }
-
-  for $func (sort keys %{$file{needed_global}}) {
-    my $message = '';
-    if (not exists $global{uses}{$func}) {
-      $message = "No need to define NEED_${func}_GLOBAL if $func is never used";
-    }
-    elsif (exists $file{needs}{$func}) {
-      if ($file{needs}{$func} eq 'extern') {
-        $message = "No need to define NEED_${func}_GLOBAL when already needed globally";
-      }
-      elsif ($file{needs}{$func} eq 'static') {
-        $message = "No need to define NEED_${func}_GLOBAL when only used in this file";
-      }
-    }
-    if ($message) {
-      diag($message);
-      $file{changes} += ($c =~ s/^$HS*#$HS*define$HS+NEED_${func}_GLOBAL\b.*$LF//mg);
-    }
-  }
-
-  $file{needs_inc_ppport} = keys %{$file{uses}};
-
-  if ($file{needs_inc_ppport}) {
-    my $pp = '';
-
-    for $func (sort keys %{$file{needs}}) {
-      my $type = $file{needs}{$func};
-      next if $type eq 'extern';
-      my $suffix = $type eq 'global' ? '_GLOBAL' : '';
-      unless (exists $file{"needed_$type"}{$func}) {
-        if ($type eq 'global') {
-          diag("Files [@{$global{needs}{$func}}] need $func, adding global request");
-        }
-        else {
-          diag("File needs $func, adding static request");
-        }
-        $pp .= "#define NEED_$func$suffix\n";
-      }
-    }
-
-    if ($pp && ($c =~ s/^(?=$HS*#$HS*define$HS+NEED_\w+)/$pp/m)) {
-      $pp = '';
-      $file{changes}++;
-    }
-
-    unless ($file{has_inc_ppport}) {
-      diag("Needs to include '$ppport'");
-      $pp .= qq(#include "$ppport"\n)
-    }
-
-    if ($pp) {
-      $file{changes} += ($c =~ s/^($HS*#$HS*define$HS+NEED_\w+.*?)^/$1$pp/ms)
-                     || ($c =~ s/^(?=$HS*#$HS*include.*\Q$ppport\E)/$pp/m)
-                     || ($c =~ s/^($HS*#$HS*include.*XSUB.*\s*?)^/$1$pp/m)
-                     || ($c =~ s/^/$pp/);
-    }
-  }
-  else {
-    if ($file{has_inc_ppport}) {
-      diag("No need to include '$ppport'");
-      $file{changes} += ($c =~ s/^$HS*?#$HS*include.*\Q$ppport\E.*?$LF//m);
-    }
-  }
-
-  # put back in our C comments
-  my $ix;
-  my $cppc = 0;
-  my @ccom = @{$file{ccom}};
-  for $ix (0 .. $#ccom) {
-    if (!$opt{cplusplus} && $ccom[$ix] =~ s!^//!!) {
-      $cppc++;
-      $file{changes} += $c =~ s/$rccs$ix$rcce/$ccs$ccom[$ix] $cce/;
-    }
-    else {
-      $c =~ s/$rccs$ix$rcce/$ccom[$ix]/;
-    }
-  }
-
-  if ($cppc) {
-    my $s = $cppc != 1 ? 's' : '';
-    warning("Uses $cppc C++ style comment$s, which is not portable");
-  }
-
-  my $s = $warnings != 1 ? 's' : '';
-  my $warn = $warnings ? " ($warnings warning$s)" : '';
-  info("Analysis completed$warn");
-
-  if ($file{changes}) {
-    if (exists $opt{copy}) {
-      my $newfile = "$filename$opt{copy}";
-      if (-e $newfile) {
-        error("'$newfile' already exists, refusing to write copy of '$filename'");
-      }
-      else {
-        local *F;
-        if (open F, ">$newfile") {
-          info("Writing copy of '$filename' with changes to '$newfile'");
-          print F $c;
-          close F;
-        }
-        else {
-          error("Cannot open '$newfile' for writing: $!");
-        }
-      }
-    }
-    elsif (exists $opt{patch} || $opt{changes}) {
-      if (exists $opt{patch}) {
-        unless ($patch_opened) {
-          if (open PATCH, ">$opt{patch}") {
-            $patch_opened = 1;
-          }
-          else {
-            error("Cannot open '$opt{patch}' for writing: $!");
-            delete $opt{patch};
-            $opt{changes} = 1;
-            goto fallback;
-          }
-        }
-        mydiff(\*PATCH, $filename, $c);
-      }
-      else {
-fallback:
-        info("Suggested changes:");
-        mydiff(\*STDOUT, $filename, $c);
-      }
-    }
-    else {
-      my $s = $file{changes} == 1 ? '' : 's';
-      info("$file{changes} potentially required change$s detected");
-    }
-  }
-  else {
-    info("Looks good");
-  }
-}
-
-close PATCH if $patch_opened;
-
-exit 0;
-
-
-sub try_use { eval "use @_;"; return $@ eq '' }
-
-sub mydiff
-{
-  local *F = shift;
-  my($file, $str) = @_;
-  my $diff;
-
-  if (exists $opt{diff}) {
-    $diff = run_diff($opt{diff}, $file, $str);
-  }
-
-  if (!defined $diff and try_use('Text::Diff')) {
-    $diff = Text::Diff::diff($file, \$str, { STYLE => 'Unified' });
-    $diff = <<HEADER . $diff;
---- $file
-+++ $file.patched
-HEADER
-  }
-
-  if (!defined $diff) {
-    $diff = run_diff('diff -u', $file, $str);
-  }
-
-  if (!defined $diff) {
-    $diff = run_diff('diff', $file, $str);
-  }
-
-  if (!defined $diff) {
-    error("Cannot generate a diff. Please install Text::Diff or use --copy.");
-    return;
-  }
-
-  print F $diff;
-}
-
-sub run_diff
-{
-  my($prog, $file, $str) = @_;
-  my $tmp = 'dppptemp';
-  my $suf = 'aaa';
-  my $diff = '';
-  local *F;
-
-  while (-e "$tmp.$suf") { $suf++ }
-  $tmp = "$tmp.$suf";
-
-  if (open F, ">$tmp") {
-    print F $str;
-    close F;
-
-    if (open F, "$prog $file $tmp |") {
-      while (<F>) {
-        s/\Q$tmp\E/$file.patched/;
-        $diff .= $_;
-      }
-      close F;
-      unlink $tmp;
-      return $diff;
-    }
-
-    unlink $tmp;
-  }
-  else {
-    error("Cannot open '$tmp' for writing: $!");
-  }
-
-  return undef;
-}
-
-sub rec_depend
-{
-  my($func, $seen) = @_;
-  return () unless exists $depends{$func};
-  $seen = {%{$seen||{}}};
-  return () if $seen->{$func}++;
-  my %s;
-  grep !$s{$_}++, map { ($_, rec_depend($_, $seen)) } @{$depends{$func}};
-}
-
-sub parse_version
-{
-  my $ver = shift;
-
-  if ($ver =~ /^(\d+)\.(\d+)\.(\d+)$/) {
-    return ($1, $2, $3);
-  }
-  elsif ($ver !~ /^\d+\.[\d_]+$/) {
-    die "cannot parse version '$ver'\n";
-  }
-
-  $ver =~ s/_//g;
-  $ver =~ s/$/000000/;
-
-  my($r,$v,$s) = $ver =~ /(\d+)\.(\d{3})(\d{3})/;
-
-  $v = int $v;
-  $s = int $s;
-
-  if ($r < 5 || ($r == 5 && $v < 6)) {
-    if ($s % 10) {
-      die "cannot parse version '$ver'\n";
-    }
-  }
-
-  return ($r, $v, $s);
-}
-
-sub format_version
-{
-  my $ver = shift;
-
-  $ver =~ s/$/000000/;
-  my($r,$v,$s) = $ver =~ /(\d+)\.(\d{3})(\d{3})/;
-
-  $v = int $v;
-  $s = int $s;
-
-  if ($r < 5 || ($r == 5 && $v < 6)) {
-    if ($s % 10) {
-      die "invalid version '$ver'\n";
-    }
-    $s /= 10;
-
-    $ver = sprintf "%d.%03d", $r, $v;
-    $s > 0 and $ver .= sprintf "_%02d", $s;
-
-    return $ver;
-  }
-
-  return sprintf "%d.%d.%d", $r, $v, $s;
-}
-
-sub info
-{
-  $opt{quiet} and return;
-  print @_, "\n";
-}
-
-sub diag
-{
-  $opt{quiet} and return;
-  $opt{diag} and print @_, "\n";
-}
-
-sub warning
-{
-  $opt{quiet} and return;
-  print "*** ", @_, "\n";
-}
-
-sub error
-{
-  print "*** ERROR: ", @_, "\n";
-}
-
-my %given_hints;
-my %given_warnings;
-sub hint
-{
-  $opt{quiet} and return;
-  my $func = shift;
-  my $rv = 0;
-  if (exists $warnings{$func} && !$given_warnings{$func}++) {
-    my $warn = $warnings{$func};
-    $warn =~ s!^!*** !mg;
-    print "*** WARNING: $func\n", $warn;
-    $rv++;
-  }
-  if ($opt{hints} && exists $hints{$func} && !$given_hints{$func}++) {
-    my $hint = $hints{$func};
-    $hint =~ s/^/   /mg;
-    print "   --- hint for $func ---\n", $hint;
-  }
-  $rv;
-}
-
-sub usage
-{
-  my($usage) = do { local(@ARGV,$/)=($0); <> } =~ /^=head\d$HS+SYNOPSIS\s*^(.*?)\s*^=/ms;
-  my %M = ( 'I' => '*' );
-  $usage =~ s/^\s*perl\s+\S+/$^X $0/;
-  $usage =~ s/([A-Z])<([^>]+)>/$M{$1}$2$M{$1}/g;
-
-  print <<ENDUSAGE;
-
-Usage: $usage
-
-See perldoc $0 for details.
-
-ENDUSAGE
-
-  exit 2;
-}
-
-sub strip
-{
-  my $self = do { local(@ARGV,$/)=($0); <> };
-  my($copy) = $self =~ /^=head\d\s+COPYRIGHT\s*^(.*?)^=\w+/ms;
-  $copy =~ s/^(?=\S+)/    /gms;
-  $self =~ s/^$HS+Do NOT edit.*?(?=^-)/$copy/ms;
-  $self =~ s/^SKIP.*(?=^__DATA__)/SKIP
-if (\@ARGV && \$ARGV[0] eq '--unstrip') {
-  eval { require Devel::PPPort };
-  \$@ and die "Cannot require Devel::PPPort, please install.\\n";
-  if (eval \$Devel::PPPort::VERSION < $VERSION) {
-    die "$0 was originally generated with Devel::PPPort $VERSION.\\n"
-      . "Your Devel::PPPort is only version \$Devel::PPPort::VERSION.\\n"
-      . "Please install a newer version, or --unstrip will not work.\\n";
-  }
-  Devel::PPPort::WriteFile(\$0);
-  exit 0;
-}
-print <<END;
-
-Sorry, but this is a stripped version of \$0.
-
-To be able to use its original script and doc functionality,
-please try to regenerate this file using:
-
-  \$^X \$0 --unstrip
-
-END
-/ms;
-  my($pl, $c) = $self =~ /(.*^__DATA__)(.*)/ms;
-  $c =~ s{
-    / (?: \*[^*]*\*+(?:[^$ccs][^*]*\*+)* / | /[^\r\n]*)
-  | ( "[^"\\]*(?:\\.[^"\\]*)*"
-    | '[^'\\]*(?:\\.[^'\\]*)*' )
-  | ($HS+) }{ defined $2 ? ' ' : ($1 || '') }gsex;
-  $c =~ s!\s+$!!mg;
-  $c =~ s!^$LF!!mg;
-  $c =~ s!^\s*#\s*!#!mg;
-  $c =~ s!^\s+!!mg;
-
-  open OUT, ">$0" or die "cannot strip $0: $!\n";
-  print OUT "$pl$c\n";
-
-  exit 0;
-}
-
-__DATA__
-*/
-
-#ifndef _P_P_PORTABILITY_H_
-#define _P_P_PORTABILITY_H_
-
-#ifndef DPPP_NAMESPACE
-#  define DPPP_NAMESPACE DPPP_
-#endif
-
-#define DPPP_CAT2(x,y) CAT2(x,y)
-#define DPPP_(name) DPPP_CAT2(DPPP_NAMESPACE, name)
-
-#ifndef PERL_REVISION
-#  if !defined(__PATCHLEVEL_H_INCLUDED__) && !(defined(PATCHLEVEL) && defined(SUBVERSION))
-#    define PERL_PATCHLEVEL_H_IMPLICIT
-#    include <patchlevel.h>
-#  endif
-#  if !(defined(PERL_VERSION) || (defined(SUBVERSION) && defined(PATCHLEVEL)))
-#    include <could_not_find_Perl_patchlevel.h>
-#  endif
-#  ifndef PERL_REVISION
-#    define PERL_REVISION       (5)
-     /* Replace: 1 */
-#    define PERL_VERSION        PATCHLEVEL
-#    define PERL_SUBVERSION     SUBVERSION
-     /* Replace PERL_PATCHLEVEL with PERL_VERSION */
-     /* Replace: 0 */
-#  endif
-#endif
-
-#define D_PPP_DEC2BCD(dec) ((((dec)/100)<<8)|((((dec)%100)/10)<<4)|((dec)%10))
-#define PERL_BCDVERSION ((D_PPP_DEC2BCD(PERL_REVISION)<<24)|(D_PPP_DEC2BCD(PERL_VERSION)<<12)|D_PPP_DEC2BCD(PERL_SUBVERSION))
-
-/* It is very unlikely that anyone will try to use this with Perl 6
-   (or greater), but who knows.
- */
-#if PERL_REVISION != 5
-#  error ppport.h only works with Perl version 5
-#endif /* PERL_REVISION != 5 */
-#ifndef dTHR
-#  define dTHR                           dNOOP
-#endif
-#ifndef dTHX
-#  define dTHX                           dNOOP
-#endif
-
-#ifndef dTHXa
-#  define dTHXa(x)                       dNOOP
-#endif
-#ifndef pTHX
-#  define pTHX                           void
-#endif
-
-#ifndef pTHX_
-#  define pTHX_
-#endif
-
-#ifndef aTHX
-#  define aTHX
-#endif
-
-#ifndef aTHX_
-#  define aTHX_
-#endif
-
-#if (PERL_BCDVERSION < 0x5006000)
-#  ifdef USE_THREADS
-#    define aTHXR  thr
-#    define aTHXR_ thr,
-#  else
-#    define aTHXR
-#    define aTHXR_
-#  endif
-#  define dTHXR  dTHR
-#else
-#  define aTHXR  aTHX
-#  define aTHXR_ aTHX_
-#  define dTHXR  dTHX
-#endif
-#ifndef dTHXoa
-#  define dTHXoa(x)                      dTHXa(x)
-#endif
-
-#ifdef I_LIMITS
-#  include <limits.h>
-#endif
-
-#ifndef PERL_UCHAR_MIN
-#  define PERL_UCHAR_MIN ((unsigned char)0)
-#endif
-
-#ifndef PERL_UCHAR_MAX
-#  ifdef UCHAR_MAX
-#    define PERL_UCHAR_MAX ((unsigned char)UCHAR_MAX)
-#  else
-#    ifdef MAXUCHAR
-#      define PERL_UCHAR_MAX ((unsigned char)MAXUCHAR)
-#    else
-#      define PERL_UCHAR_MAX ((unsigned char)~(unsigned)0)
-#    endif
-#  endif
-#endif
-
-#ifndef PERL_USHORT_MIN
-#  define PERL_USHORT_MIN ((unsigned short)0)
-#endif
-
-#ifndef PERL_USHORT_MAX
-#  ifdef USHORT_MAX
-#    define PERL_USHORT_MAX ((unsigned short)USHORT_MAX)
-#  else
-#    ifdef MAXUSHORT
-#      define PERL_USHORT_MAX ((unsigned short)MAXUSHORT)
-#    else
-#      ifdef USHRT_MAX
-#        define PERL_USHORT_MAX ((unsigned short)USHRT_MAX)
-#      else
-#        define PERL_USHORT_MAX ((unsigned short)~(unsigned)0)
-#      endif
-#    endif
-#  endif
-#endif
-
-#ifndef PERL_SHORT_MAX
-#  ifdef SHORT_MAX
-#    define PERL_SHORT_MAX ((short)SHORT_MAX)
-#  else
-#    ifdef MAXSHORT    /* Often used in <values.h> */
-#      define PERL_SHORT_MAX ((short)MAXSHORT)
-#    else
-#      ifdef SHRT_MAX
-#        define PERL_SHORT_MAX ((short)SHRT_MAX)
-#      else
-#        define PERL_SHORT_MAX ((short) (PERL_USHORT_MAX >> 1))
-#      endif
-#    endif
-#  endif
-#endif
-
-#ifndef PERL_SHORT_MIN
-#  ifdef SHORT_MIN
-#    define PERL_SHORT_MIN ((short)SHORT_MIN)
-#  else
-#    ifdef MINSHORT
-#      define PERL_SHORT_MIN ((short)MINSHORT)
-#    else
-#      ifdef SHRT_MIN
-#        define PERL_SHORT_MIN ((short)SHRT_MIN)
-#      else
-#        define PERL_SHORT_MIN (-PERL_SHORT_MAX - ((3 & -1) == 3))
-#      endif
-#    endif
-#  endif
-#endif
-
-#ifndef PERL_UINT_MAX
-#  ifdef UINT_MAX
-#    define PERL_UINT_MAX ((unsigned int)UINT_MAX)
-#  else
-#    ifdef MAXUINT
-#      define PERL_UINT_MAX ((unsigned int)MAXUINT)
-#    else
-#      define PERL_UINT_MAX (~(unsigned int)0)
-#    endif
-#  endif
-#endif
-
-#ifndef PERL_UINT_MIN
-#  define PERL_UINT_MIN ((unsigned int)0)
-#endif
-
-#ifndef PERL_INT_MAX
-#  ifdef INT_MAX
-#    define PERL_INT_MAX ((int)INT_MAX)
-#  else
-#    ifdef MAXINT    /* Often used in <values.h> */
-#      define PERL_INT_MAX ((int)MAXINT)
-#    else
-#      define PERL_INT_MAX ((int)(PERL_UINT_MAX >> 1))
-#    endif
-#  endif
-#endif
-
-#ifndef PERL_INT_MIN
-#  ifdef INT_MIN
-#    define PERL_INT_MIN ((int)INT_MIN)
-#  else
-#    ifdef MININT
-#      define PERL_INT_MIN ((int)MININT)
-#    else
-#      define PERL_INT_MIN (-PERL_INT_MAX - ((3 & -1) == 3))
-#    endif
-#  endif
-#endif
-
-#ifndef PERL_ULONG_MAX
-#  ifdef ULONG_MAX
-#    define PERL_ULONG_MAX ((unsigned long)ULONG_MAX)
-#  else
-#    ifdef MAXULONG
-#      define PERL_ULONG_MAX ((unsigned long)MAXULONG)
-#    else
-#      define PERL_ULONG_MAX (~(unsigned long)0)
-#    endif
-#  endif
-#endif
-
-#ifndef PERL_ULONG_MIN
-#  define PERL_ULONG_MIN ((unsigned long)0L)
-#endif
-
-#ifndef PERL_LONG_MAX
-#  ifdef LONG_MAX
-#    define PERL_LONG_MAX ((long)LONG_MAX)
-#  else
-#    ifdef MAXLONG
-#      define PERL_LONG_MAX ((long)MAXLONG)
-#    else
-#      define PERL_LONG_MAX ((long) (PERL_ULONG_MAX >> 1))
-#    endif
-#  endif
-#endif
-
-#ifndef PERL_LONG_MIN
-#  ifdef LONG_MIN
-#    define PERL_LONG_MIN ((long)LONG_MIN)
-#  else
-#    ifdef MINLONG
-#      define PERL_LONG_MIN ((long)MINLONG)
-#    else
-#      define PERL_LONG_MIN (-PERL_LONG_MAX - ((3 & -1) == 3))
-#    endif
-#  endif
-#endif
-
-#if defined(HAS_QUAD) && (defined(convex) || defined(uts))
-#  ifndef PERL_UQUAD_MAX
-#    ifdef ULONGLONG_MAX
-#      define PERL_UQUAD_MAX ((unsigned long long)ULONGLONG_MAX)
-#    else
-#      ifdef MAXULONGLONG
-#        define PERL_UQUAD_MAX ((unsigned long long)MAXULONGLONG)
-#      else
-#        define PERL_UQUAD_MAX (~(unsigned long long)0)
-#      endif
-#    endif
-#  endif
-
-#  ifndef PERL_UQUAD_MIN
-#    define PERL_UQUAD_MIN ((unsigned long long)0L)
-#  endif
-
-#  ifndef PERL_QUAD_MAX
-#    ifdef LONGLONG_MAX
-#      define PERL_QUAD_MAX ((long long)LONGLONG_MAX)
-#    else
-#      ifdef MAXLONGLONG
-#        define PERL_QUAD_MAX ((long long)MAXLONGLONG)
-#      else
-#        define PERL_QUAD_MAX ((long long) (PERL_UQUAD_MAX >> 1))
-#      endif
-#    endif
-#  endif
-
-#  ifndef PERL_QUAD_MIN
-#    ifdef LONGLONG_MIN
-#      define PERL_QUAD_MIN ((long long)LONGLONG_MIN)
-#    else
-#      ifdef MINLONGLONG
-#        define PERL_QUAD_MIN ((long long)MINLONGLONG)
-#      else
-#        define PERL_QUAD_MIN (-PERL_QUAD_MAX - ((3 & -1) == 3))
-#      endif
-#    endif
-#  endif
-#endif
-
-/* This is based on code from 5.003 perl.h */
-#ifdef HAS_QUAD
-#  ifdef cray
-#ifndef IVTYPE
-#  define IVTYPE                         int
-#endif
-
-#ifndef IV_MIN
-#  define IV_MIN                         PERL_INT_MIN
-#endif
-
-#ifndef IV_MAX
-#  define IV_MAX                         PERL_INT_MAX
-#endif
-
-#ifndef UV_MIN
-#  define UV_MIN                         PERL_UINT_MIN
-#endif
-
-#ifndef UV_MAX
-#  define UV_MAX                         PERL_UINT_MAX
-#endif
-
-#    ifdef INTSIZE
-#ifndef IVSIZE
-#  define IVSIZE                         INTSIZE
-#endif
-
-#    endif
-#  else
-#    if defined(convex) || defined(uts)
-#ifndef IVTYPE
-#  define IVTYPE                         long long
-#endif
-
-#ifndef IV_MIN
-#  define IV_MIN                         PERL_QUAD_MIN
-#endif
-
-#ifndef IV_MAX
-#  define IV_MAX                         PERL_QUAD_MAX
-#endif
-
-#ifndef UV_MIN
-#  define UV_MIN                         PERL_UQUAD_MIN
-#endif
-
-#ifndef UV_MAX
-#  define UV_MAX                         PERL_UQUAD_MAX
-#endif
-
-#      ifdef LONGLONGSIZE
-#ifndef IVSIZE
-#  define IVSIZE                         LONGLONGSIZE
-#endif
-
-#      endif
-#    else
-#ifndef IVTYPE
-#  define IVTYPE                         long
-#endif
-
-#ifndef IV_MIN
-#  define IV_MIN                         PERL_LONG_MIN
-#endif
-
-#ifndef IV_MAX
-#  define IV_MAX                         PERL_LONG_MAX
-#endif
-
-#ifndef UV_MIN
-#  define UV_MIN                         PERL_ULONG_MIN
-#endif
-
-#ifndef UV_MAX
-#  define UV_MAX                         PERL_ULONG_MAX
-#endif
-
-#      ifdef LONGSIZE
-#ifndef IVSIZE
-#  define IVSIZE                         LONGSIZE
-#endif
-
-#      endif
-#    endif
-#  endif
-#ifndef IVSIZE
-#  define IVSIZE                         8
-#endif
-
-#ifndef LONGSIZE
-#  define LONGSIZE                       8
-#endif
-
-#ifndef PERL_QUAD_MIN
-#  define PERL_QUAD_MIN                  IV_MIN
-#endif
-
-#ifndef PERL_QUAD_MAX
-#  define PERL_QUAD_MAX                  IV_MAX
-#endif
-
-#ifndef PERL_UQUAD_MIN
-#  define PERL_UQUAD_MIN                 UV_MIN
-#endif
-
-#ifndef PERL_UQUAD_MAX
-#  define PERL_UQUAD_MAX                 UV_MAX
-#endif
-
-#else
-#ifndef IVTYPE
-#  define IVTYPE                         long
-#endif
-
-#ifndef LONGSIZE
-#  define LONGSIZE                       4
-#endif
-
-#ifndef IV_MIN
-#  define IV_MIN                         PERL_LONG_MIN
-#endif
-
-#ifndef IV_MAX
-#  define IV_MAX                         PERL_LONG_MAX
-#endif
-
-#ifndef UV_MIN
-#  define UV_MIN                         PERL_ULONG_MIN
-#endif
-
-#ifndef UV_MAX
-#  define UV_MAX                         PERL_ULONG_MAX
-#endif
-
-#endif
-
-#ifndef IVSIZE
-#  ifdef LONGSIZE
-#    define IVSIZE LONGSIZE
-#  else
-#    define IVSIZE 4 /* A bold guess, but the best we can make. */
-#  endif
-#endif
-#ifndef UVTYPE
-#  define UVTYPE                         unsigned IVTYPE
-#endif
-
-#ifndef UVSIZE
-#  define UVSIZE                         IVSIZE
-#endif
-#ifndef sv_setuv
-#  define sv_setuv(sv, uv)               \
-               STMT_START {                         \
-                 UV TeMpUv = uv;                    \
-                 if (TeMpUv <= IV_MAX)              \
-                   sv_setiv(sv, TeMpUv);            \
-                 else                               \
-                   sv_setnv(sv, (double)TeMpUv);    \
-               } STMT_END
-#endif
-#ifndef newSVuv
-#  define newSVuv(uv)                    ((uv) <= IV_MAX ? newSViv((IV)uv) : newSVnv((NV)uv))
-#endif
-#ifndef sv_2uv
-#  define sv_2uv(sv)                     ((PL_Sv = (sv)), (UV) (SvNOK(PL_Sv) ? SvNV(PL_Sv) : sv_2nv(PL_Sv)))
-#endif
-
-#ifndef SvUVX
-#  define SvUVX(sv)                      ((UV)SvIVX(sv))
-#endif
-
-#ifndef SvUVXx
-#  define SvUVXx(sv)                     SvUVX(sv)
-#endif
-
-#ifndef SvUV
-#  define SvUV(sv)                       (SvIOK(sv) ? SvUVX(sv) : sv_2uv(sv))
-#endif
-
-#ifndef SvUVx
-#  define SvUVx(sv)                      ((PL_Sv = (sv)), SvUV(PL_Sv))
-#endif
-
-/* Hint: sv_uv
- * Always use the SvUVx() macro instead of sv_uv().
- */
-#ifndef sv_uv
-#  define sv_uv(sv)                      SvUVx(sv)
-#endif
-
-#if !defined(SvUOK) && defined(SvIOK_UV)
-#  define SvUOK(sv) SvIOK_UV(sv)
-#endif
-#ifndef XST_mUV
-#  define XST_mUV(i,v)                   (ST(i) = sv_2mortal(newSVuv(v))  )
-#endif
-
-#ifndef XSRETURN_UV
-#  define XSRETURN_UV(v)                 STMT_START { XST_mUV(0,v);  XSRETURN(1); } STMT_END
-#endif
-#ifndef PUSHu
-#  define PUSHu(u)                       STMT_START { sv_setuv(TARG, (UV)(u)); PUSHTARG;  } STMT_END
-#endif
-
-#ifndef XPUSHu
-#  define XPUSHu(u)                      STMT_START { sv_setuv(TARG, (UV)(u)); XPUSHTARG; } STMT_END
-#endif
-
-#ifdef HAS_MEMCMP
-#ifndef memNE
-#  define memNE(s1,s2,l)                 (memcmp(s1,s2,l))
-#endif
-
-#ifndef memEQ
-#  define memEQ(s1,s2,l)                 (!memcmp(s1,s2,l))
-#endif
-
-#else
-#ifndef memNE
-#  define memNE(s1,s2,l)                 (bcmp(s1,s2,l))
-#endif
-
-#ifndef memEQ
-#  define memEQ(s1,s2,l)                 (!bcmp(s1,s2,l))
-#endif
-
-#endif
-#ifndef memEQs
-#  define memEQs(s1, l, s2)              \
-                   (sizeof(s2)-1 == l && memEQ(s1, (s2 ""), (sizeof(s2)-1)))
-#endif
-
-#ifndef memNEs
-#  define memNEs(s1, l, s2)              !memEQs(s1, l, s2)
-#endif
-#ifndef MoveD
-#  define MoveD(s,d,n,t)                 memmove((char*)(d),(char*)(s), (n) * sizeof(t))
-#endif
-
-#ifndef CopyD
-#  define CopyD(s,d,n,t)                 memcpy((char*)(d),(char*)(s), (n) * sizeof(t))
-#endif
-
-#ifdef HAS_MEMSET
-#ifndef ZeroD
-#  define ZeroD(d,n,t)                   memzero((char*)(d), (n) * sizeof(t))
-#endif
-
-#else
-#ifndef ZeroD
-#  define ZeroD(d,n,t)                   ((void)memzero((char*)(d), (n) * sizeof(t)), d)
-#endif
-
-#endif
-#ifndef PoisonWith
-#  define PoisonWith(d,n,t,b)            (void)memset((char*)(d), (U8)(b), (n) * sizeof(t))
-#endif
-
-#ifndef PoisonNew
-#  define PoisonNew(d,n,t)               PoisonWith(d,n,t,0xAB)
-#endif
-
-#ifndef PoisonFree
-#  define PoisonFree(d,n,t)              PoisonWith(d,n,t,0xEF)
-#endif
-
-#ifndef Poison
-#  define Poison(d,n,t)                  PoisonFree(d,n,t)
-#endif
-#ifndef Newx
-#  define Newx(v,n,t)                    New(0,v,n,t)
-#endif
-
-#ifndef Newxc
-#  define Newxc(v,n,t,c)                 Newc(0,v,n,t,c)
-#endif
-
-#ifndef Newxz
-#  define Newxz(v,n,t)                   Newz(0,v,n,t)
-#endif
-#ifndef SvGETMAGIC
-#  define SvGETMAGIC(x)                  STMT_START { if (SvGMAGICAL(x)) mg_get(x); } STMT_END
-#endif
-
-/* Some random bits for sv_unmagicext. These should probably be pulled in for
-   real and organized at some point */
-#ifndef HEf_SVKEY
-#  define HEf_SVKEY                      -2
-#endif
-
-#ifndef MUTABLE_PTR
-#if defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN)
-#  define MUTABLE_PTR(p) ({ void *_p = (p); _p; })
-#else
-#  define MUTABLE_PTR(p) ((void *) (p))
-#endif
-#endif
-#ifndef MUTABLE_SV
-#  define MUTABLE_SV(p)                  ((SV *)MUTABLE_PTR(p))
-#endif
-
-/* end of random bits */
-#ifndef PERL_MAGIC_sv
-#  define PERL_MAGIC_sv                  '\0'
-#endif
-
-#ifndef PERL_MAGIC_overload
-#  define PERL_MAGIC_overload            'A'
-#endif
-
-#ifndef PERL_MAGIC_overload_elem
-#  define PERL_MAGIC_overload_elem       'a'
-#endif
-
-#ifndef PERL_MAGIC_overload_table
-#  define PERL_MAGIC_overload_table      'c'
-#endif
-
-#ifndef PERL_MAGIC_bm
-#  define PERL_MAGIC_bm                  'B'
-#endif
-
-#ifndef PERL_MAGIC_regdata
-#  define PERL_MAGIC_regdata             'D'
-#endif
-
-#ifndef PERL_MAGIC_regdatum
-#  define PERL_MAGIC_regdatum            'd'
-#endif
-
-#ifndef PERL_MAGIC_env
-#  define PERL_MAGIC_env                 'E'
-#endif
-
-#ifndef PERL_MAGIC_envelem
-#  define PERL_MAGIC_envelem             'e'
-#endif
-
-#ifndef PERL_MAGIC_fm
-#  define PERL_MAGIC_fm                  'f'
-#endif
-
-#ifndef PERL_MAGIC_regex_global
-#  define PERL_MAGIC_regex_global        'g'
-#endif
-
-#ifndef PERL_MAGIC_isa
-#  define PERL_MAGIC_isa                 'I'
-#endif
-
-#ifndef PERL_MAGIC_isaelem
-#  define PERL_MAGIC_isaelem             'i'
-#endif
-
-#ifndef PERL_MAGIC_nkeys
-#  define PERL_MAGIC_nkeys               'k'
-#endif
-
-#ifndef PERL_MAGIC_dbfile
-#  define PERL_MAGIC_dbfile              'L'
-#endif
-
-#ifndef PERL_MAGIC_dbline
-#  define PERL_MAGIC_dbline              'l'
-#endif
-
-#ifndef PERL_MAGIC_mutex
-#  define PERL_MAGIC_mutex               'm'
-#endif
-
-#ifndef PERL_MAGIC_shared
-#  define PERL_MAGIC_shared              'N'
-#endif
-
-#ifndef PERL_MAGIC_shared_scalar
-#  define PERL_MAGIC_shared_scalar       'n'
-#endif
-
-#ifndef PERL_MAGIC_collxfrm
-#  define PERL_MAGIC_collxfrm            'o'
-#endif
-
-#ifndef PERL_MAGIC_tied
-#  define PERL_MAGIC_tied                'P'
-#endif
-
-#ifndef PERL_MAGIC_tiedelem
-#  define PERL_MAGIC_tiedelem            'p'
-#endif
-
-#ifndef PERL_MAGIC_tiedscalar
-#  define PERL_MAGIC_tiedscalar          'q'
-#endif
-
-#ifndef PERL_MAGIC_qr
-#  define PERL_MAGIC_qr                  'r'
-#endif
-
-#ifndef PERL_MAGIC_sig
-#  define PERL_MAGIC_sig                 'S'
-#endif
-
-#ifndef PERL_MAGIC_sigelem
-#  define PERL_MAGIC_sigelem             's'
-#endif
-
-#ifndef PERL_MAGIC_taint
-#  define PERL_MAGIC_taint               't'
-#endif
-
-#ifndef PERL_MAGIC_uvar
-#  define PERL_MAGIC_uvar                'U'
-#endif
-
-#ifndef PERL_MAGIC_uvar_elem
-#  define PERL_MAGIC_uvar_elem           'u'
-#endif
-
-#ifndef PERL_MAGIC_vstring
-#  define PERL_MAGIC_vstring             'V'
-#endif
-
-#ifndef PERL_MAGIC_vec
-#  define PERL_MAGIC_vec                 'v'
-#endif
-
-#ifndef PERL_MAGIC_utf8
-#  define PERL_MAGIC_utf8                'w'
-#endif
-
-#ifndef PERL_MAGIC_substr
-#  define PERL_MAGIC_substr              'x'
-#endif
-
-#ifndef PERL_MAGIC_defelem
-#  define PERL_MAGIC_defelem             'y'
-#endif
-
-#ifndef PERL_MAGIC_glob
-#  define PERL_MAGIC_glob                '*'
-#endif
-
-#ifndef PERL_MAGIC_arylen
-#  define PERL_MAGIC_arylen              '#'
-#endif
-
-#ifndef PERL_MAGIC_pos
-#  define PERL_MAGIC_pos                 '.'
-#endif
-
-#ifndef PERL_MAGIC_backref
-#  define PERL_MAGIC_backref             '<'
-#endif
-
-#ifndef PERL_MAGIC_ext
-#  define PERL_MAGIC_ext                 '~'
-#endif
-
-/* That's the best we can do... */
-#ifndef sv_catpvn_nomg
-#  define sv_catpvn_nomg                 sv_catpvn
-#endif
-
-#ifndef sv_catsv_nomg
-#  define sv_catsv_nomg                  sv_catsv
-#endif
-
-#ifndef sv_setsv_nomg
-#  define sv_setsv_nomg                  sv_setsv
-#endif
-
-#ifndef sv_pvn_nomg
-#  define sv_pvn_nomg                    sv_pvn
-#endif
-
-#ifndef SvIV_nomg
-#  define SvIV_nomg                      SvIV
-#endif
-
-#ifndef SvUV_nomg
-#  define SvUV_nomg                      SvUV
-#endif
-
-#ifndef sv_catpv_mg
-#  define sv_catpv_mg(sv, ptr)          \
-   STMT_START {                         \
-     SV *TeMpSv = sv;                   \
-     sv_catpv(TeMpSv,ptr);              \
-     SvSETMAGIC(TeMpSv);                \
-   } STMT_END
-#endif
-
-#ifndef sv_catpvn_mg
-#  define sv_catpvn_mg(sv, ptr, len)    \
-   STMT_START {                         \
-     SV *TeMpSv = sv;                   \
-     sv_catpvn(TeMpSv,ptr,len);         \
-     SvSETMAGIC(TeMpSv);                \
-   } STMT_END
-#endif
-
-#ifndef sv_catsv_mg
-#  define sv_catsv_mg(dsv, ssv)         \
-   STMT_START {                         \
-     SV *TeMpSv = dsv;                  \
-     sv_catsv(TeMpSv,ssv);              \
-     SvSETMAGIC(TeMpSv);                \
-   } STMT_END
-#endif
-
-#ifndef sv_setiv_mg
-#  define sv_setiv_mg(sv, i)            \
-   STMT_START {                         \
-     SV *TeMpSv = sv;                   \
-     sv_setiv(TeMpSv,i);                \
-     SvSETMAGIC(TeMpSv);                \
-   } STMT_END
-#endif
-
-#ifndef sv_setnv_mg
-#  define sv_setnv_mg(sv, num)          \
-   STMT_START {                         \
-     SV *TeMpSv = sv;                   \
-     sv_setnv(TeMpSv,num);              \
-     SvSETMAGIC(TeMpSv);                \
-   } STMT_END
-#endif
-
-#ifndef sv_setpv_mg
-#  define sv_setpv_mg(sv, ptr)          \
-   STMT_START {                         \
-     SV *TeMpSv = sv;                   \
-     sv_setpv(TeMpSv,ptr);              \
-     SvSETMAGIC(TeMpSv);                \
-   } STMT_END
-#endif
-
-#ifndef sv_setpvn_mg
-#  define sv_setpvn_mg(sv, ptr, len)    \
-   STMT_START {                         \
-     SV *TeMpSv = sv;                   \
-     sv_setpvn(TeMpSv,ptr,len);         \
-     SvSETMAGIC(TeMpSv);                \
-   } STMT_END
-#endif
-
-#ifndef sv_setsv_mg
-#  define sv_setsv_mg(dsv, ssv)         \
-   STMT_START {                         \
-     SV *TeMpSv = dsv;                  \
-     sv_setsv(TeMpSv,ssv);              \
-     SvSETMAGIC(TeMpSv);                \
-   } STMT_END
-#endif
-
-#ifndef sv_setuv_mg
-#  define sv_setuv_mg(sv, i)            \
-   STMT_START {                         \
-     SV *TeMpSv = sv;                   \
-     sv_setuv(TeMpSv,i);                \
-     SvSETMAGIC(TeMpSv);                \
-   } STMT_END
-#endif
-
-#ifndef sv_usepvn_mg
-#  define sv_usepvn_mg(sv, ptr, len)    \
-   STMT_START {                         \
-     SV *TeMpSv = sv;                   \
-     sv_usepvn(TeMpSv,ptr,len);         \
-     SvSETMAGIC(TeMpSv);                \
-   } STMT_END
-#endif
-#ifndef SvVSTRING_mg
-#  define SvVSTRING_mg(sv)               (SvMAGICAL(sv) ? mg_find(sv, PERL_MAGIC_vstring) : NULL)
-#endif
-
-/* Hint: sv_magic_portable
- * This is a compatibility function that is only available with
- * Devel::PPPort. It is NOT in the perl core.
- * Its purpose is to mimic the 5.8.0 behaviour of sv_magic() when
- * it is being passed a name pointer with namlen == 0. In that
- * case, perl 5.8.0 and later store the pointer, not a copy of it.
- * The compatibility can be provided back to perl 5.004. With
- * earlier versions, the code will not compile.
- */
-
-#if (PERL_BCDVERSION < 0x5004000)
-
-  /* code that uses sv_magic_portable will not compile */
-
-#elif (PERL_BCDVERSION < 0x5008000)
-
-#  define sv_magic_portable(sv, obj, how, name, namlen)     \
-   STMT_START {                                             \
-     SV *SvMp_sv = (sv);                                    \
-     char *SvMp_name = (char *) (name);                     \
-     I32 SvMp_namlen = (namlen);                            \
-     if (SvMp_name && SvMp_namlen == 0)                     \
-     {                                                      \
-       MAGIC *mg;                                           \
-       sv_magic(SvMp_sv, obj, how, 0, 0);                   \
-       mg = SvMAGIC(SvMp_sv);                               \
-       mg->mg_len = -42; /* XXX: this is the tricky part */ \
-       mg->mg_ptr = SvMp_name;                              \
-     }                                                      \
-     else                                                   \
-     {                                                      \
-       sv_magic(SvMp_sv, obj, how, SvMp_name, SvMp_namlen); \
-     }                                                      \
-   } STMT_END
-
-#else
-
-#  define sv_magic_portable(a, b, c, d, e)  sv_magic(a, b, c, d, e)
-
-#endif
-
-#if !defined(mg_findext)
-#if defined(NEED_mg_findext)
-static MAGIC * DPPP_(my_mg_findext)(SV * sv, int type, const MGVTBL *vtbl);
-static
-#else
-extern MAGIC * DPPP_(my_mg_findext)(SV * sv, int type, const MGVTBL *vtbl);
-#endif
-
-#if defined(NEED_mg_findext) || defined(NEED_mg_findext_GLOBAL)
-
-#define mg_findext DPPP_(my_mg_findext)
-#define Perl_mg_findext DPPP_(my_mg_findext)
-
-
-MAGIC *
-DPPP_(my_mg_findext)(SV * sv, int type, const MGVTBL *vtbl) {
-    if (sv) {
-        MAGIC *mg;
-
-#ifdef AvPAD_NAMELIST
-        assert(!(SvTYPE(sv) == SVt_PVAV && AvPAD_NAMELIST(sv)));
-#endif
-
-        for (mg = SvMAGIC (sv); mg; mg = mg->mg_moremagic) {
-            if (mg->mg_type == type && mg->mg_virtual == vtbl)
-                return mg;
-        }
-    }
-
-    return NULL;
-}
-
-#endif
-#endif
-
-#if !defined(sv_unmagicext)
-#if defined(NEED_sv_unmagicext)
-static int DPPP_(my_sv_unmagicext)(pTHX_ SV * const sv, const int type, MGVTBL * vtbl);
-static
-#else
-extern int DPPP_(my_sv_unmagicext)(pTHX_ SV * const sv, const int type, MGVTBL * vtbl);
-#endif
-
-#if defined(NEED_sv_unmagicext) || defined(NEED_sv_unmagicext_GLOBAL)
-
-#ifdef sv_unmagicext
-#  undef sv_unmagicext
-#endif
-#define sv_unmagicext(a,b,c) DPPP_(my_sv_unmagicext)(aTHX_ a,b,c)
-#define Perl_sv_unmagicext DPPP_(my_sv_unmagicext)
-
-
-int
-DPPP_(my_sv_unmagicext)(pTHX_ SV *const sv, const int type, MGVTBL *vtbl)
-{
-    MAGIC* mg;
-    MAGIC** mgp;
-
-    if (SvTYPE(sv) < SVt_PVMG || !SvMAGIC(sv))
-        return 0;
-    mgp = &(SvMAGIC(sv));
-    for (mg = *mgp; mg; mg = *mgp) {
-        const MGVTBL* const virt = mg->mg_virtual;
-        if (mg->mg_type == type && virt == vtbl) {
-            *mgp = mg->mg_moremagic;
-            if (virt && virt->svt_free)
-                virt->svt_free(aTHX_ sv, mg);
-            if (mg->mg_ptr && mg->mg_type != PERL_MAGIC_regex_global) {
-                if (mg->mg_len > 0)
-                    Safefree(mg->mg_ptr);
-                else if (mg->mg_len == HEf_SVKEY) /* Questionable on older perls... */
-                    SvREFCNT_dec(MUTABLE_SV(mg->mg_ptr));
-                else if (mg->mg_type == PERL_MAGIC_utf8)
-                    Safefree(mg->mg_ptr);
-            }
-            if (mg->mg_flags & MGf_REFCOUNTED)
-                SvREFCNT_dec(mg->mg_obj);
-            Safefree(mg);
-        }
-        else
-            mgp = &mg->mg_moremagic;
-    }
-    if (SvMAGIC(sv)) {
-        if (SvMAGICAL(sv))        /* if we're under save_magic, wait for restore_magic; */
-            mg_magical(sv);        /*    else fix the flags now */
-    }
-    else {
-        SvMAGICAL_off(sv);
-        SvFLAGS(sv) |= (SvFLAGS(sv) & (SVp_IOK|SVp_NOK|SVp_POK)) >> PRIVSHIFT;
-    }
-    return 0;
-}
-
-#endif
-#endif
-#ifndef cBOOL
-#  define cBOOL(cbool)                   ((cbool) ? (bool)1 : (bool)0)
-#endif
-
-#ifndef OpHAS_SIBLING
-#  define OpHAS_SIBLING(o)               (cBOOL((o)->op_sibling))
-#endif
-
-#ifndef OpSIBLING
-#  define OpSIBLING(o)                   (0 + (o)->op_sibling)
-#endif
-
-#ifndef OpMORESIB_set
-#  define OpMORESIB_set(o, sib)          ((o)->op_sibling = (sib))
-#endif
-
-#ifndef OpLASTSIB_set
-#  define OpLASTSIB_set(o, parent)       ((o)->op_sibling = NULL)
-#endif
-
-#ifndef OpMAYBESIB_set
-#  define OpMAYBESIB_set(o, sib, parent) ((o)->op_sibling = (sib))
-#endif
-
-#ifndef SvRX
-#if defined(NEED_SvRX)
-static void * DPPP_(my_SvRX)(pTHX_ SV *rv);
-static
-#else
-extern void * DPPP_(my_SvRX)(pTHX_ SV *rv);
-#endif
-
-#if defined(NEED_SvRX) || defined(NEED_SvRX_GLOBAL)
-
-#ifdef SvRX
-#  undef SvRX
-#endif
-#define SvRX(a) DPPP_(my_SvRX)(aTHX_ a)
-
-
-void *
-DPPP_(my_SvRX)(pTHX_ SV *rv)
-{
-        if (SvROK(rv)) {
-                SV *sv = SvRV(rv);
-                if (SvMAGICAL(sv)) {
-                        MAGIC *mg = mg_find(sv, PERL_MAGIC_qr);
-                        if (mg && mg->mg_obj) {
-                                return mg->mg_obj;
-                        }
-                }
-        }
-        return 0;
-}
-#endif
-#endif
-#ifndef SvRXOK
-#  define SvRXOK(sv)                     (!!SvRX(sv))
-#endif
-
-#ifndef PERL_UNUSED_DECL
-#  ifdef HASATTRIBUTE
-#    if (defined(__GNUC__) && defined(__cplusplus)) || defined(__INTEL_COMPILER)
-#      define PERL_UNUSED_DECL
-#    else
-#      define PERL_UNUSED_DECL __attribute__((unused))
-#    endif
-#  else
-#    define PERL_UNUSED_DECL
-#  endif
-#endif
-
-#ifndef PERL_UNUSED_ARG
-#  if defined(lint) && defined(S_SPLINT_S) /* www.splint.org */
-#    include <note.h>
-#    define PERL_UNUSED_ARG(x) NOTE(ARGUNUSED(x))
-#  else
-#    define PERL_UNUSED_ARG(x) ((void)x)
-#  endif
-#endif
-
-#ifndef PERL_UNUSED_VAR
-#  define PERL_UNUSED_VAR(x) ((void)x)
-#endif
-
-#ifndef PERL_UNUSED_CONTEXT
-#  ifdef USE_ITHREADS
-#    define PERL_UNUSED_CONTEXT PERL_UNUSED_ARG(my_perl)
-#  else
-#    define PERL_UNUSED_CONTEXT
-#  endif
-#endif
-
-#ifndef PERL_UNUSED_RESULT
-#  if defined(__GNUC__) && defined(HASATTRIBUTE_WARN_UNUSED_RESULT)
-#    define PERL_UNUSED_RESULT(v) STMT_START { __typeof__(v) z = (v); (void)sizeof(z); } STMT_END
-#  else
-#    define PERL_UNUSED_RESULT(v) ((void)(v))
-#  endif
-#endif
-#ifndef NOOP
-#  define NOOP                           /*EMPTY*/(void)0
-#endif
-
-#ifndef dNOOP
-#  define dNOOP                          extern int /*@unused@*/ Perl___notused PERL_UNUSED_DECL
-#endif
-
-#ifndef NVTYPE
-#  if defined(USE_LONG_DOUBLE) && defined(HAS_LONG_DOUBLE)
-#    define NVTYPE long double
-#  else
-#    define NVTYPE double
-#  endif
-typedef NVTYPE NV;
-#endif
-
-#ifndef INT2PTR
-#  if (IVSIZE == PTRSIZE) && (UVSIZE == PTRSIZE)
-#    define PTRV                  UV
-#    define INT2PTR(any,d)        (any)(d)
-#  else
-#    if PTRSIZE == LONGSIZE
-#      define PTRV                unsigned long
-#    else
-#      define PTRV                unsigned
-#    endif
-#    define INT2PTR(any,d)        (any)(PTRV)(d)
-#  endif
-#endif
-
-#ifndef PTR2ul
-#  if PTRSIZE == LONGSIZE
-#    define PTR2ul(p)     (unsigned long)(p)
-#  else
-#    define PTR2ul(p)     INT2PTR(unsigned long,p)
-#  endif
-#endif
-#ifndef PTR2nat
-#  define PTR2nat(p)                     (PTRV)(p)
-#endif
-
-#ifndef NUM2PTR
-#  define NUM2PTR(any,d)                 (any)PTR2nat(d)
-#endif
-
-#ifndef PTR2IV
-#  define PTR2IV(p)                      INT2PTR(IV,p)
-#endif
-
-#ifndef PTR2UV
-#  define PTR2UV(p)                      INT2PTR(UV,p)
-#endif
-
-#ifndef PTR2NV
-#  define PTR2NV(p)                      NUM2PTR(NV,p)
-#endif
-
-#undef START_EXTERN_C
-#undef END_EXTERN_C
-#undef EXTERN_C
-#ifdef __cplusplus
-#  define START_EXTERN_C extern "C" {
-#  define END_EXTERN_C }
-#  define EXTERN_C extern "C"
-#else
-#  define START_EXTERN_C
-#  define END_EXTERN_C
-#  define EXTERN_C extern
-#endif
-
-#if defined(PERL_GCC_PEDANTIC)
-#  ifndef PERL_GCC_BRACE_GROUPS_FORBIDDEN
-#    define PERL_GCC_BRACE_GROUPS_FORBIDDEN
-#  endif
-#endif
-
-#if defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN) && !defined(__cplusplus)
-#  ifndef PERL_USE_GCC_BRACE_GROUPS
-#    define PERL_USE_GCC_BRACE_GROUPS
-#  endif
-#endif
-
-#undef STMT_START
-#undef STMT_END
-#ifdef PERL_USE_GCC_BRACE_GROUPS
-#  define STMT_START    (void)( /* gcc supports ``({ STATEMENTS; })'' */
-#  define STMT_END      )
-#else
-#  if defined(VOIDFLAGS) && (VOIDFLAGS) && (defined(sun) || defined(__sun__)) && !defined(__GNUC__)
-#    define STMT_START  if (1)
-#    define STMT_END    else (void)0
-#  else
-#    define STMT_START  do
-#    define STMT_END    while (0)
-#  endif
-#endif
-#ifndef boolSV
-#  define boolSV(b)                      ((b) ? &PL_sv_yes : &PL_sv_no)
-#endif
-
-/* DEFSV appears first in 5.004_56 */
-#ifndef DEFSV
-#  define DEFSV                          GvSV(PL_defgv)
-#endif
-
-#ifndef SAVE_DEFSV
-#  define SAVE_DEFSV                     SAVESPTR(GvSV(PL_defgv))
-#endif
-
-#ifndef DEFSV_set
-#  define DEFSV_set(sv)                  (DEFSV = (sv))
-#endif
-
-/* Older perls (<=5.003) lack AvFILLp */
-#ifndef AvFILLp
-#  define AvFILLp                        AvFILL
-#endif
-#ifndef ERRSV
-#  define ERRSV                          get_sv("@",FALSE)
-#endif
-
-/* Hint: gv_stashpvn
- * This function's backport doesn't support the length parameter, but
- * rather ignores it. Portability can only be ensured if the length
- * parameter is used for speed reasons, but the length can always be
- * correctly computed from the string argument.
- */
-#ifndef gv_stashpvn
-#  define gv_stashpvn(str,len,create)    gv_stashpv(str,create)
-#endif
-
-/* Replace: 1 */
-#ifndef get_cv
-#  define get_cv                         perl_get_cv
-#endif
-
-#ifndef get_sv
-#  define get_sv                         perl_get_sv
-#endif
-
-#ifndef get_av
-#  define get_av                         perl_get_av
-#endif
-
-#ifndef get_hv
-#  define get_hv                         perl_get_hv
-#endif
-
-/* Replace: 0 */
-#ifndef dUNDERBAR
-#  define dUNDERBAR                      dNOOP
-#endif
-
-#ifndef UNDERBAR
-#  define UNDERBAR                       DEFSV
-#endif
-#ifndef dAX
-#  define dAX                            I32 ax = MARK - PL_stack_base + 1
-#endif
-
-#ifndef dITEMS
-#  define dITEMS                         I32 items = SP - MARK
-#endif
-#ifndef dXSTARG
-#  define dXSTARG                        SV * targ = sv_newmortal()
-#endif
-#ifndef dAXMARK
-#  define dAXMARK                        I32 ax = POPMARK; \
-                               register SV ** const mark = PL_stack_base + ax++
-#endif
-#ifndef XSprePUSH
-#  define XSprePUSH                      (sp = PL_stack_base + ax - 1)
-#endif
-
-#if (PERL_BCDVERSION < 0x5005000)
-#  undef XSRETURN
-#  define XSRETURN(off)                                   \
-      STMT_START {                                        \
-          PL_stack_sp = PL_stack_base + ax + ((off) - 1); \
-          return;                                         \
-      } STMT_END
-#endif
-#ifndef XSPROTO
-#  define XSPROTO(name)                  void name(pTHX_ CV* cv)
-#endif
-
-#ifndef SVfARG
-#  define SVfARG(p)                      ((void*)(p))
-#endif
-#ifndef PERL_ABS
-#  define PERL_ABS(x)                    ((x) < 0 ? -(x) : (x))
-#endif
-#ifndef dVAR
-#  define dVAR                           dNOOP
-#endif
-#ifndef SVf
-#  define SVf                            "_"
-#endif
-#ifndef UTF8_MAXBYTES
-#  define UTF8_MAXBYTES                  UTF8_MAXLEN
-#endif
-#ifndef CPERLscope
-#  define CPERLscope(x)                  x
-#endif
-#ifndef PERL_HASH
-#  define PERL_HASH(hash,str,len)        \
-     STMT_START { \
-        const char *s_PeRlHaSh = str; \
-        I32 i_PeRlHaSh = len; \
-        U32 hash_PeRlHaSh = 0; \
-        while (i_PeRlHaSh--) \
-            hash_PeRlHaSh = hash_PeRlHaSh * 33 + *s_PeRlHaSh++; \
-        (hash) = hash_PeRlHaSh; \
-    } STMT_END
-#endif
-
-#ifndef PERLIO_FUNCS_DECL
-# ifdef PERLIO_FUNCS_CONST
-#  define PERLIO_FUNCS_DECL(funcs) const PerlIO_funcs funcs
-#  define PERLIO_FUNCS_CAST(funcs) (PerlIO_funcs*)(funcs)
-# else
-#  define PERLIO_FUNCS_DECL(funcs) PerlIO_funcs funcs
-#  define PERLIO_FUNCS_CAST(funcs) (funcs)
-# endif
-#endif
-
-/* provide these typedefs for older perls */
-#if (PERL_BCDVERSION < 0x5009003)
-
-# ifdef ARGSproto
-typedef OP* (CPERLscope(*Perl_ppaddr_t))(ARGSproto);
-# else
-typedef OP* (CPERLscope(*Perl_ppaddr_t))(pTHX);
-# endif
-
-typedef OP* (CPERLscope(*Perl_check_t)) (pTHX_ OP*);
-
-#endif
-#ifndef isPSXSPC
-#  define isPSXSPC(c)                    (isSPACE(c) || (c) == '\v')
-#endif
-
-#ifndef isBLANK
-#  define isBLANK(c)                     ((c) == ' ' || (c) == '\t')
-#endif
-
-#ifdef EBCDIC
-#ifndef isALNUMC
-#  define isALNUMC(c)                    isalnum(c)
-#endif
-
-#ifndef isASCII
-#  define isASCII(c)                     isascii(c)
-#endif
-
-#ifndef isCNTRL
-#  define isCNTRL(c)                     iscntrl(c)
-#endif
-
-#ifndef isGRAPH
-#  define isGRAPH(c)                     isgraph(c)
-#endif
-
-#ifndef isPRINT
-#  define isPRINT(c)                     isprint(c)
-#endif
-
-#ifndef isPUNCT
-#  define isPUNCT(c)                     ispunct(c)
-#endif
-
-#ifndef isXDIGIT
-#  define isXDIGIT(c)                    isxdigit(c)
-#endif
-
-#else
-# if (PERL_BCDVERSION < 0x5010000)
-/* Hint: isPRINT
- * The implementation in older perl versions includes all of the
- * isSPACE() characters, which is wrong. The version provided by
- * Devel::PPPort always overrides a present buggy version.
- */
-#  undef isPRINT
-# endif
-
-#ifndef WIDEST_UTYPE
-# ifdef QUADKIND
-#  ifdef U64TYPE
-#   define WIDEST_UTYPE U64TYPE
-#  else
-#   define WIDEST_UTYPE Quad_t
-#  endif
-# else
-#  define WIDEST_UTYPE U32
-# endif
-#endif
-#ifndef isALNUMC
-#  define isALNUMC(c)                    (isALPHA(c) || isDIGIT(c))
-#endif
-
-#ifndef isASCII
-#  define isASCII(c)                     ((WIDEST_UTYPE) (c) <= 127)
-#endif
-
-#ifndef isCNTRL
-#  define isCNTRL(c)                     ((WIDEST_UTYPE) (c) < ' ' || (c) == 127)
-#endif
-
-#ifndef isGRAPH
-#  define isGRAPH(c)                     (isALNUM(c) || isPUNCT(c))
-#endif
-
-#ifndef isPRINT
-#  define isPRINT(c)                     (((c) >= 32 && (c) < 127))
-#endif
-
-#ifndef isPUNCT
-#  define isPUNCT(c)                     (((c) >= 33 && (c) <= 47) || ((c) >= 58 && (c) <= 64)  || ((c) >= 91 && (c) <= 96) || ((c) >= 123 && (c) <= 126))
-#endif
-
-#ifndef isXDIGIT
-#  define isXDIGIT(c)                    (isDIGIT(c) || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F'))
-#endif
-
-#endif
-
-/* Until we figure out how to support this in older perls... */
-#if (PERL_BCDVERSION >= 0x5008000)
-#ifndef HeUTF8
-#  define HeUTF8(he)                     ((HeKLEN(he) == HEf_SVKEY) ?            \
-                                 SvUTF8(HeKEY_sv(he)) :                 \
-                                 (U32)HeKUTF8(he))
-#endif
-
-#endif
-#ifndef C_ARRAY_LENGTH
-#  define C_ARRAY_LENGTH(a)              (sizeof(a)/sizeof((a)[0]))
-#endif
-
-#ifndef C_ARRAY_END
-#  define C_ARRAY_END(a)                 ((a) + C_ARRAY_LENGTH(a))
-#endif
-
-#ifndef IVdf
-#  if IVSIZE == LONGSIZE
-#    define     IVdf      "ld"
-#    define     UVuf      "lu"
-#    define     UVof      "lo"
-#    define     UVxf      "lx"
-#    define     UVXf      "lX"
-#  elif IVSIZE == INTSIZE
-#    define   IVdf      "d"
-#    define   UVuf      "u"
-#    define   UVof      "o"
-#    define   UVxf      "x"
-#    define   UVXf      "X"
-#  else
-#    error "cannot define IV/UV formats"
-#  endif
-#endif
-
-#ifndef NVef
-#  if defined(USE_LONG_DOUBLE) && defined(HAS_LONG_DOUBLE) && \
-      defined(PERL_PRIfldbl) && (PERL_BCDVERSION != 0x5006000)
-            /* Not very likely, but let's try anyway. */
-#    define NVef          PERL_PRIeldbl
-#    define NVff          PERL_PRIfldbl
-#    define NVgf          PERL_PRIgldbl
-#  else
-#    define NVef          "e"
-#    define NVff          "f"
-#    define NVgf          "g"
-#  endif
-#endif
-
-#ifdef NEED_mess_sv
-#define NEED_mess
-#endif
-
-#ifdef NEED_mess
-#define NEED_mess_nocontext
-#define NEED_vmess
-#endif
-
-#ifndef croak_sv
-#if (PERL_BCDVERSION >= 0x5007003) || ( (PERL_BCDVERSION >= 0x5006001) && (PERL_BCDVERSION < 0x5007000) )
-#  if ( (PERL_BCDVERSION >= 0x5008000) && (PERL_BCDVERSION < 0x5008009) ) || ( (PERL_BCDVERSION >= 0x5009000) && (PERL_BCDVERSION < 0x5010001) )
-#    define D_PPP_FIX_UTF8_ERRSV(errsv, sv)                     \
-        STMT_START {                                            \
-            if (sv != ERRSV)                                    \
-                SvFLAGS(ERRSV) = (SvFLAGS(ERRSV) & ~SVf_UTF8) | \
-                                 (SvFLAGS(sv) & SVf_UTF8);      \
-        } STMT_END
-#  else
-#    define D_PPP_FIX_UTF8_ERRSV(errsv, sv) STMT_START {} STMT_END
-#  endif
-#  define croak_sv(sv)                        \
-    STMT_START {                              \
-        if (SvROK(sv)) {                      \
-            sv_setsv(ERRSV, sv);              \
-            croak(NULL);                      \
-        } else {                              \
-            D_PPP_FIX_UTF8_ERRSV(ERRSV, sv);  \
-            croak("%" SVf, SVfARG(sv));       \
-        }                                     \
-    } STMT_END
-#elif (PERL_BCDVERSION >= 0x5004000)
-#  define croak_sv(sv) croak("%" SVf, SVfARG(sv))
-#else
-#  define croak_sv(sv) croak("%s", SvPV_nolen(sv))
-#endif
-#endif
-
-#ifndef die_sv
-#if defined(NEED_die_sv)
-static OP * DPPP_(my_die_sv)(pTHX_ SV *sv);
-static
-#else
-extern OP * DPPP_(my_die_sv)(pTHX_ SV *sv);
-#endif
-
-#if defined(NEED_die_sv) || defined(NEED_die_sv_GLOBAL)
-
-#ifdef die_sv
-#  undef die_sv
-#endif
-#define die_sv(a) DPPP_(my_die_sv)(aTHX_ a)
-#define Perl_die_sv DPPP_(my_die_sv)
-
-OP *
-DPPP_(my_die_sv)(pTHX_ SV *sv)
-{
-    croak_sv(sv);
-    return (OP *)NULL;
-}
-#endif
-#endif
-
-#ifndef warn_sv
-#if (PERL_BCDVERSION >= 0x5004000)
-#  define warn_sv(sv) warn("%" SVf, SVfARG(sv))
-#else
-#  define warn_sv(sv) warn("%s", SvPV_nolen(sv))
-#endif
-#endif
-
-#ifndef vmess
-#if defined(NEED_vmess)
-static SV * DPPP_(my_vmess)(pTHX_ const char * pat, va_list * args);
-static
-#else
-extern SV * DPPP_(my_vmess)(pTHX_ const char * pat, va_list * args);
-#endif
-
-#if defined(NEED_vmess) || defined(NEED_vmess_GLOBAL)
-
-#ifdef vmess
-#  undef vmess
-#endif
-#define vmess(a,b) DPPP_(my_vmess)(aTHX_ a,b)
-#define Perl_vmess DPPP_(my_vmess)
-
-SV*
-DPPP_(my_vmess)(pTHX_ const char* pat, va_list* args)
-{
-    mess(pat, args);
-    return PL_mess_sv;
-}
-#endif
-#endif
-
-#if (PERL_BCDVERSION < 0x5006000)
-#undef mess
-#endif
-
-#if !defined(mess_nocontext) && !defined(Perl_mess_nocontext)
-#if defined(NEED_mess_nocontext)
-static SV * DPPP_(my_mess_nocontext)(const char * pat, ...);
-static
-#else
-extern SV * DPPP_(my_mess_nocontext)(const char * pat, ...);
-#endif
-
-#if defined(NEED_mess_nocontext) || defined(NEED_mess_nocontext_GLOBAL)
-
-#define mess_nocontext DPPP_(my_mess_nocontext)
-#define Perl_mess_nocontext DPPP_(my_mess_nocontext)
-
-SV*
-DPPP_(my_mess_nocontext)(const char* pat, ...)
-{
-    dTHX;
-    SV *sv;
-    va_list args;
-    va_start(args, pat);
-    sv = vmess(pat, &args);
-    va_end(args);
-    return sv;
-}
-#endif
-#endif
-
-#ifndef mess
-#if defined(NEED_mess)
-static SV * DPPP_(my_mess)(pTHX_ const char * pat, ...);
-static
-#else
-extern SV * DPPP_(my_mess)(pTHX_ const char * pat, ...);
-#endif
-
-#if defined(NEED_mess) || defined(NEED_mess_GLOBAL)
-
-#define Perl_mess DPPP_(my_mess)
-
-SV*
-DPPP_(my_mess)(pTHX_ const char* pat, ...)
-{
-    SV *sv;
-    va_list args;
-    va_start(args, pat);
-    sv = vmess(pat, &args);
-    va_end(args);
-    return sv;
-}
-#ifdef mess_nocontext
-#define mess mess_nocontext
-#else
-#define mess Perl_mess_nocontext
-#endif
-#endif
-#endif
-
-#ifndef mess_sv
-#if defined(NEED_mess_sv)
-static SV * DPPP_(my_mess_sv)(pTHX_ SV * basemsg, bool consume);
-static
-#else
-extern SV * DPPP_(my_mess_sv)(pTHX_ SV * basemsg, bool consume);
-#endif
-
-#if defined(NEED_mess_sv) || defined(NEED_mess_sv_GLOBAL)
-
-#ifdef mess_sv
-#  undef mess_sv
-#endif
-#define mess_sv(a,b) DPPP_(my_mess_sv)(aTHX_ a,b)
-#define Perl_mess_sv DPPP_(my_mess_sv)
-
-SV *
-DPPP_(my_mess_sv)(pTHX_ SV *basemsg, bool consume)
-{
-    SV *tmp;
-    SV *ret;
-
-    if (SvPOK(basemsg) && SvCUR(basemsg) && *(SvEND(basemsg)-1) == '\n') {
-        if (consume)
-            return basemsg;
-        ret = mess("");
-        SvSetSV_nosteal(ret, basemsg);
-        return ret;
-    }
-
-    if (consume) {
-        sv_catsv(basemsg, mess(""));
-        return basemsg;
-    }
-
-    ret = mess("");
-    tmp = newSVsv(ret);
-    SvSetSV_nosteal(ret, basemsg);
-    sv_catsv(ret, tmp);
-    sv_dec(tmp);
-    return ret;
-}
-#endif
-#endif
-
-#ifndef warn_nocontext
-#define warn_nocontext warn
-#endif
-
-#ifndef croak_nocontext
-#define croak_nocontext croak
-#endif
-
-#ifndef croak_no_modify
-#define croak_no_modify() croak_nocontext("%s", PL_no_modify)
-#define Perl_croak_no_modify() croak_no_modify()
-#endif
-
-#ifndef croak_memory_wrap
-#if (PERL_BCDVERSION >= 0x5009002) || ( (PERL_BCDVERSION >= 0x5008006) && (PERL_BCDVERSION < 0x5009000) )
-#  define croak_memory_wrap() croak_nocontext("%s", PL_memory_wrap)
-#else
-#  define croak_memory_wrap() croak_nocontext("panic: memory wrap")
-#endif
-#endif
-
-#ifndef croak_xs_usage
-#if defined(NEED_croak_xs_usage)
-static void DPPP_(my_croak_xs_usage)(const CV * const cv, const char * const params);
-static
-#else
-extern void DPPP_(my_croak_xs_usage)(const CV * const cv, const char * const params);
-#endif
-
-#if defined(NEED_croak_xs_usage) || defined(NEED_croak_xs_usage_GLOBAL)
-
-#define croak_xs_usage DPPP_(my_croak_xs_usage)
-#define Perl_croak_xs_usage DPPP_(my_croak_xs_usage)
-
-
-#ifndef PERL_ARGS_ASSERT_CROAK_XS_USAGE
-#define PERL_ARGS_ASSERT_CROAK_XS_USAGE assert(cv); assert(params)
-#endif
-
-void
-DPPP_(my_croak_xs_usage)(const CV *const cv, const char *const params)
-{
-    dTHX;
-    const GV *const gv = CvGV(cv);
-
-    PERL_ARGS_ASSERT_CROAK_XS_USAGE;
-
-    if (gv) {
-        const char *const gvname = GvNAME(gv);
-        const HV *const stash = GvSTASH(gv);
-        const char *const hvname = stash ? HvNAME(stash) : NULL;
-
-        if (hvname)
-            croak("Usage: %s::%s(%s)", hvname, gvname, params);
-        else
-            croak("Usage: %s(%s)", gvname, params);
-    } else {
-        /* Pants. I don't think that it should be possible to get here. */
-        croak("Usage: CODE(0x%" UVxf ")(%s)", PTR2UV(cv), params);
-    }
-}
-#endif
-#endif
-
-#ifndef PERL_SIGNALS_UNSAFE_FLAG
-
-#define PERL_SIGNALS_UNSAFE_FLAG 0x0001
-
-#if (PERL_BCDVERSION < 0x5008000)
-#  define D_PPP_PERL_SIGNALS_INIT   PERL_SIGNALS_UNSAFE_FLAG
-#else
-#  define D_PPP_PERL_SIGNALS_INIT   0
-#endif
-
-#if defined(NEED_PL_signals)
-static U32 DPPP_(my_PL_signals) = D_PPP_PERL_SIGNALS_INIT;
-#elif defined(NEED_PL_signals_GLOBAL)
-U32 DPPP_(my_PL_signals) = D_PPP_PERL_SIGNALS_INIT;
-#else
-extern U32 DPPP_(my_PL_signals);
-#endif
-#define PL_signals DPPP_(my_PL_signals)
-
-#endif
-
-/* Hint: PL_ppaddr
- * Calling an op via PL_ppaddr requires passing a context argument
- * for threaded builds. Since the context argument is different for
- * 5.005 perls, you can use aTHXR (supplied by ppport.h), which will
- * automatically be defined as the correct argument.
- */
-
-#if (PERL_BCDVERSION <= 0x5005005)
-/* Replace: 1 */
-#  define PL_ppaddr                 ppaddr
-#  define PL_no_modify              no_modify
-/* Replace: 0 */
-#endif
-
-#if (PERL_BCDVERSION <= 0x5004005)
-/* Replace: 1 */
-#  define PL_DBsignal               DBsignal
-#  define PL_DBsingle               DBsingle
-#  define PL_DBsub                  DBsub
-#  define PL_DBtrace                DBtrace
-#  define PL_Sv                     Sv
-#  define PL_bufend                 bufend
-#  define PL_bufptr                 bufptr
-#  define PL_compiling              compiling
-#  define PL_copline                copline
-#  define PL_curcop                 curcop
-#  define PL_curstash               curstash
-#  define PL_debstash               debstash
-#  define PL_defgv                  defgv
-#  define PL_diehook                diehook
-#  define PL_dirty                  dirty
-#  define PL_dowarn                 dowarn
-#  define PL_errgv                  errgv
-#  define PL_error_count            error_count
-#  define PL_expect                 expect
-#  define PL_hexdigit               hexdigit
-#  define PL_hints                  hints
-#  define PL_in_my                  in_my
-#  define PL_laststatval            laststatval
-#  define PL_lex_state              lex_state
-#  define PL_lex_stuff              lex_stuff
-#  define PL_linestr                linestr
-#  define PL_na                     na
-#  define PL_perl_destruct_level    perl_destruct_level
-#  define PL_perldb                 perldb
-#  define PL_rsfp_filters           rsfp_filters
-#  define PL_rsfp                   rsfp
-#  define PL_stack_base             stack_base
-#  define PL_stack_sp               stack_sp
-#  define PL_statcache              statcache
-#  define PL_stdingv                stdingv
-#  define PL_sv_arenaroot           sv_arenaroot
-#  define PL_sv_no                  sv_no
-#  define PL_sv_undef               sv_undef
-#  define PL_sv_yes                 sv_yes
-#  define PL_tainted                tainted
-#  define PL_tainting               tainting
-#  define PL_tokenbuf               tokenbuf
-/* Replace: 0 */
-#endif
-
-/* Warning: PL_parser
- * For perl versions earlier than 5.9.5, this is an always
- * non-NULL dummy. Also, it cannot be dereferenced. Don't
- * use it if you can avoid is and unless you absolutely know
- * what you're doing.
- * If you always check that PL_parser is non-NULL, you can
- * define DPPP_PL_parser_NO_DUMMY to avoid the creation of
- * a dummy parser structure.
- */
-
-#if (PERL_BCDVERSION >= 0x5009005)
-# ifdef DPPP_PL_parser_NO_DUMMY
-#  define D_PPP_my_PL_parser_var(var) ((PL_parser ? PL_parser : \
-                (croak("panic: PL_parser == NULL in %s:%d", \
-                       __FILE__, __LINE__), (yy_parser *) NULL))->var)
-# else
-#  ifdef DPPP_PL_parser_NO_DUMMY_WARNING
-#   define D_PPP_parser_dummy_warning(var)
-#  else
-#   define D_PPP_parser_dummy_warning(var) \
-             warn("warning: dummy PL_" #var " used in %s:%d", __FILE__, __LINE__),
-#  endif
-#  define D_PPP_my_PL_parser_var(var) ((PL_parser ? PL_parser : \
-                (D_PPP_parser_dummy_warning(var) &DPPP_(dummy_PL_parser)))->var)
-#if defined(NEED_PL_parser)
-static yy_parser DPPP_(dummy_PL_parser);
-#elif defined(NEED_PL_parser_GLOBAL)
-yy_parser DPPP_(dummy_PL_parser);
-#else
-extern yy_parser DPPP_(dummy_PL_parser);
-#endif
-
-# endif
-
-/* PL_expect, PL_copline, PL_rsfp, PL_rsfp_filters, PL_linestr, PL_bufptr, PL_bufend, PL_lex_state, PL_lex_stuff, PL_tokenbuf depends on PL_parser */
-/* Warning: PL_expect, PL_copline, PL_rsfp, PL_rsfp_filters, PL_linestr, PL_bufptr, PL_bufend, PL_lex_state, PL_lex_stuff, PL_tokenbuf
- * Do not use this variable unless you know exactly what you're
- * doing. It is internal to the perl parser and may change or even
- * be removed in the future. As of perl 5.9.5, you have to check
- * for (PL_parser != NULL) for this variable to have any effect.
- * An always non-NULL PL_parser dummy is provided for earlier
- * perl versions.
- * If PL_parser is NULL when you try to access this variable, a
- * dummy is being accessed instead and a warning is issued unless
- * you define DPPP_PL_parser_NO_DUMMY_WARNING.
- * If DPPP_PL_parser_NO_DUMMY is defined, the code trying to access
- * this variable will croak with a panic message.
- */
-
-# define PL_expect         D_PPP_my_PL_parser_var(expect)
-# define PL_copline        D_PPP_my_PL_parser_var(copline)
-# define PL_rsfp           D_PPP_my_PL_parser_var(rsfp)
-# define PL_rsfp_filters   D_PPP_my_PL_parser_var(rsfp_filters)
-# define PL_linestr        D_PPP_my_PL_parser_var(linestr)
-# define PL_bufptr         D_PPP_my_PL_parser_var(bufptr)
-# define PL_bufend         D_PPP_my_PL_parser_var(bufend)
-# define PL_lex_state      D_PPP_my_PL_parser_var(lex_state)
-# define PL_lex_stuff      D_PPP_my_PL_parser_var(lex_stuff)
-# define PL_tokenbuf       D_PPP_my_PL_parser_var(tokenbuf)
-# define PL_in_my          D_PPP_my_PL_parser_var(in_my)
-# define PL_in_my_stash    D_PPP_my_PL_parser_var(in_my_stash)
-# define PL_error_count    D_PPP_my_PL_parser_var(error_count)
-
-
-#else
-
-/* ensure that PL_parser != NULL and cannot be dereferenced */
-# define PL_parser         ((void *) 1)
-
-#endif
-#ifndef mPUSHs
-#  define mPUSHs(s)                      PUSHs(sv_2mortal(s))
-#endif
-
-#ifndef PUSHmortal
-#  define PUSHmortal                     PUSHs(sv_newmortal())
-#endif
-
-#ifndef mPUSHp
-#  define mPUSHp(p,l)                    sv_setpvn(PUSHmortal, (p), (l))
-#endif
-
-#ifndef mPUSHn
-#  define mPUSHn(n)                      sv_setnv(PUSHmortal, (NV)(n))
-#endif
-
-#ifndef mPUSHi
-#  define mPUSHi(i)                      sv_setiv(PUSHmortal, (IV)(i))
-#endif
-
-#ifndef mPUSHu
-#  define mPUSHu(u)                      sv_setuv(PUSHmortal, (UV)(u))
-#endif
-#ifndef mXPUSHs
-#  define mXPUSHs(s)                     XPUSHs(sv_2mortal(s))
-#endif
-
-#ifndef XPUSHmortal
-#  define XPUSHmortal                    XPUSHs(sv_newmortal())
-#endif
-
-#ifndef mXPUSHp
-#  define mXPUSHp(p,l)                   STMT_START { EXTEND(sp,1); sv_setpvn(PUSHmortal, (p), (l)); } STMT_END
-#endif
-
-#ifndef mXPUSHn
-#  define mXPUSHn(n)                     STMT_START { EXTEND(sp,1); sv_setnv(PUSHmortal, (NV)(n)); } STMT_END
-#endif
-
-#ifndef mXPUSHi
-#  define mXPUSHi(i)                     STMT_START { EXTEND(sp,1); sv_setiv(PUSHmortal, (IV)(i)); } STMT_END
-#endif
-
-#ifndef mXPUSHu
-#  define mXPUSHu(u)                     STMT_START { EXTEND(sp,1); sv_setuv(PUSHmortal, (UV)(u)); } STMT_END
-#endif
-
-/* Replace: 1 */
-#ifndef call_sv
-#  define call_sv                        perl_call_sv
-#endif
-
-#ifndef call_pv
-#  define call_pv                        perl_call_pv
-#endif
-
-#ifndef call_argv
-#  define call_argv                      perl_call_argv
-#endif
-
-#ifndef call_method
-#  define call_method                    perl_call_method
-#endif
-#ifndef eval_sv
-#  define eval_sv                        perl_eval_sv
-#endif
-
-/* Replace: 0 */
-#ifndef PERL_LOADMOD_DENY
-#  define PERL_LOADMOD_DENY              0x1
-#endif
-
-#ifndef PERL_LOADMOD_NOIMPORT
-#  define PERL_LOADMOD_NOIMPORT          0x2
-#endif
-
-#ifndef PERL_LOADMOD_IMPORT_OPS
-#  define PERL_LOADMOD_IMPORT_OPS        0x4
-#endif
-
-#ifndef G_METHOD
-# define G_METHOD               64
-# ifdef call_sv
-#  undef call_sv
-# endif
-# if (PERL_BCDVERSION < 0x5006000)
-#  define call_sv(sv, flags)  ((flags) & G_METHOD ? perl_call_method((char *) SvPV_nolen_const(sv), \
-                                (flags) & ~G_METHOD) : perl_call_sv(sv, flags))
-# else
-#  define call_sv(sv, flags)  ((flags) & G_METHOD ? Perl_call_method(aTHX_ (char *) SvPV_nolen_const(sv), \
-                                (flags) & ~G_METHOD) : Perl_call_sv(aTHX_ sv, flags))
-# endif
-#endif
-
-/* Replace perl_eval_pv with eval_pv */
-
-#ifndef eval_pv
-#if defined(NEED_eval_pv)
-static SV* DPPP_(my_eval_pv)(char *p, I32 croak_on_error);
-static
-#else
-extern SV* DPPP_(my_eval_pv)(char *p, I32 croak_on_error);
-#endif
-
-#if defined(NEED_eval_pv) || defined(NEED_eval_pv_GLOBAL)
-
-#ifdef eval_pv
-#  undef eval_pv
-#endif
-#define eval_pv(a,b) DPPP_(my_eval_pv)(aTHX_ a,b)
-#define Perl_eval_pv DPPP_(my_eval_pv)
-
-
-SV*
-DPPP_(my_eval_pv)(char *p, I32 croak_on_error)
-{
-    dSP;
-    SV* sv = newSVpv(p, 0);
-
-    PUSHMARK(sp);
-    eval_sv(sv, G_SCALAR);
-    SvREFCNT_dec(sv);
-
-    SPAGAIN;
-    sv = POPs;
-    PUTBACK;
-
-    if (croak_on_error && SvTRUEx(ERRSV))
-        croak_sv(ERRSV);
-
-    return sv;
-}
-
-#endif
-#endif
-
-#ifndef vload_module
-#if defined(NEED_vload_module)
-static void DPPP_(my_vload_module)(U32 flags, SV *name, SV *ver, va_list *args);
-static
-#else
-extern void DPPP_(my_vload_module)(U32 flags, SV *name, SV *ver, va_list *args);
-#endif
-
-#if defined(NEED_vload_module) || defined(NEED_vload_module_GLOBAL)
-
-#ifdef vload_module
-#  undef vload_module
-#endif
-#define vload_module(a,b,c,d) DPPP_(my_vload_module)(aTHX_ a,b,c,d)
-#define Perl_vload_module DPPP_(my_vload_module)
-
-
-void
-DPPP_(my_vload_module)(U32 flags, SV *name, SV *ver, va_list *args)
-{
-    dTHR;
-    dVAR;
-    OP *veop, *imop;
-
-    OP * const modname = newSVOP(OP_CONST, 0, name);
-    /* 5.005 has a somewhat hacky force_normal that doesn't croak on
-       SvREADONLY() if PL_compling is true. Current perls take care in
-       ck_require() to correctly turn off SvREADONLY before calling
-       force_normal_flags(). This seems a better fix than fudging PL_compling
-     */
-    SvREADONLY_off(((SVOP*)modname)->op_sv);
-    modname->op_private |= OPpCONST_BARE;
-    if (ver) {
-        veop = newSVOP(OP_CONST, 0, ver);
-    }
-    else
-        veop = NULL;
-    if (flags & PERL_LOADMOD_NOIMPORT) {
-        imop = sawparens(newNULLLIST());
-    }
-    else if (flags & PERL_LOADMOD_IMPORT_OPS) {
-        imop = va_arg(*args, OP*);
-    }
-    else {
-        SV *sv;
-        imop = NULL;
-        sv = va_arg(*args, SV*);
-        while (sv) {
-            imop = append_elem(OP_LIST, imop, newSVOP(OP_CONST, 0, sv));
-            sv = va_arg(*args, SV*);
-        }
-    }
-    {
-        const line_t ocopline = PL_copline;
-        COP * const ocurcop = PL_curcop;
-        const int oexpect = PL_expect;
-
-#if (PERL_BCDVERSION >= 0x5004000)
-        utilize(!(flags & PERL_LOADMOD_DENY), start_subparse(FALSE, 0),
-                veop, modname, imop);
-#elif (PERL_BCDVERSION > 0x5003000)
-        utilize(!(flags & PERL_LOADMOD_DENY), start_subparse(),
-                veop, modname, imop);
-#else
-        utilize(!(flags & PERL_LOADMOD_DENY), start_subparse(),
-                modname, imop);
-#endif
-        PL_expect = oexpect;
-        PL_copline = ocopline;
-        PL_curcop = ocurcop;
-    }
-}
-
-#endif
-#endif
-
-#ifndef load_module
-#if defined(NEED_load_module)
-static void DPPP_(my_load_module)(U32 flags, SV *name, SV *ver, ...);
-static
-#else
-extern void DPPP_(my_load_module)(U32 flags, SV *name, SV *ver, ...);
-#endif
-
-#if defined(NEED_load_module) || defined(NEED_load_module_GLOBAL)
-
-#ifdef load_module
-#  undef load_module
-#endif
-#define load_module DPPP_(my_load_module)
-#define Perl_load_module DPPP_(my_load_module)
-
-
-void
-DPPP_(my_load_module)(U32 flags, SV *name, SV *ver, ...)
-{
-    va_list args;
-    va_start(args, ver);
-    vload_module(flags, name, ver, &args);
-    va_end(args);
-}
-
-#endif
-#endif
-#ifndef newRV_inc
-#  define newRV_inc(sv)                  newRV(sv)   /* Replace */
-#endif
-
-#ifndef newRV_noinc
-#if defined(NEED_newRV_noinc)
-static SV * DPPP_(my_newRV_noinc)(SV *sv);
-static
-#else
-extern SV * DPPP_(my_newRV_noinc)(SV *sv);
-#endif
-
-#if defined(NEED_newRV_noinc) || defined(NEED_newRV_noinc_GLOBAL)
-
-#ifdef newRV_noinc
-#  undef newRV_noinc
-#endif
-#define newRV_noinc(a) DPPP_(my_newRV_noinc)(aTHX_ a)
-#define Perl_newRV_noinc DPPP_(my_newRV_noinc)
-
-SV *
-DPPP_(my_newRV_noinc)(SV *sv)
-{
-  SV *rv = (SV *)newRV(sv);
-  SvREFCNT_dec(sv);
-  return rv;
-}
-#endif
-#endif
-
-/* Hint: newCONSTSUB
- * Returns a CV* as of perl-5.7.1. This return value is not supported
- * by Devel::PPPort.
- */
-
-/* newCONSTSUB from IO.xs is in the core starting with 5.004_63 */
-#if (PERL_BCDVERSION < 0x5004063) && (PERL_BCDVERSION != 0x5004005)
-#if defined(NEED_newCONSTSUB)
-static void DPPP_(my_newCONSTSUB)(HV *stash, const char *name, SV *sv);
-static
-#else
-extern void DPPP_(my_newCONSTSUB)(HV *stash, const char *name, SV *sv);
-#endif
-
-#if defined(NEED_newCONSTSUB) || defined(NEED_newCONSTSUB_GLOBAL)
-
-#ifdef newCONSTSUB
-#  undef newCONSTSUB
-#endif
-#define newCONSTSUB(a,b,c) DPPP_(my_newCONSTSUB)(aTHX_ a,b,c)
-#define Perl_newCONSTSUB DPPP_(my_newCONSTSUB)
-
-
-/* This is just a trick to avoid a dependency of newCONSTSUB on PL_parser */
-/* (There's no PL_parser in perl < 5.005, so this is completely safe)     */
-#define D_PPP_PL_copline PL_copline
-
-void
-DPPP_(my_newCONSTSUB)(HV *stash, const char *name, SV *sv)
-{
-        U32 oldhints = PL_hints;
-        HV *old_cop_stash = PL_curcop->cop_stash;
-        HV *old_curstash = PL_curstash;
-        line_t oldline = PL_curcop->cop_line;
-        PL_curcop->cop_line = D_PPP_PL_copline;
-
-        PL_hints &= ~HINT_BLOCK_SCOPE;
-        if (stash)
-                PL_curstash = PL_curcop->cop_stash = stash;
-
-        newSUB(
-
-#if   (PERL_BCDVERSION < 0x5003022)
-                start_subparse(),
-#elif (PERL_BCDVERSION == 0x5003022)
-                start_subparse(0),
-#else  /* 5.003_23  onwards */
-                start_subparse(FALSE, 0),
-#endif
-
-                newSVOP(OP_CONST, 0, newSVpv((char *) name, 0)),
-                newSVOP(OP_CONST, 0, &PL_sv_no),   /* SvPV(&PL_sv_no) == "" -- GMB */
-                newSTATEOP(0, Nullch, newSVOP(OP_CONST, 0, sv))
-        );
-
-        PL_hints = oldhints;
-        PL_curcop->cop_stash = old_cop_stash;
-        PL_curstash = old_curstash;
-        PL_curcop->cop_line = oldline;
-}
-#endif
-#endif
-
-/*
- * Boilerplate macros for initializing and accessing interpreter-local
- * data from C.  All statics in extensions should be reworked to use
- * this, if you want to make the extension thread-safe.  See ext/re/re.xs
- * for an example of the use of these macros.
- *
- * Code that uses these macros is responsible for the following:
- * 1. #define MY_CXT_KEY to a unique string, e.g. "DynaLoader_guts"
- * 2. Declare a typedef named my_cxt_t that is a structure that contains
- *    all the data that needs to be interpreter-local.
- * 3. Use the START_MY_CXT macro after the declaration of my_cxt_t.
- * 4. Use the MY_CXT_INIT macro such that it is called exactly once
- *    (typically put in the BOOT: section).
- * 5. Use the members of the my_cxt_t structure everywhere as
- *    MY_CXT.member.
- * 6. Use the dMY_CXT macro (a declaration) in all the functions that
- *    access MY_CXT.
- */
-
-#if defined(MULTIPLICITY) || defined(PERL_OBJECT) || \
-    defined(PERL_CAPI)    || defined(PERL_IMPLICIT_CONTEXT)
-
-#ifndef START_MY_CXT
-
-/* This must appear in all extensions that define a my_cxt_t structure,
- * right after the definition (i.e. at file scope).  The non-threads
- * case below uses it to declare the data as static. */
-#define START_MY_CXT
-
-#if (PERL_BCDVERSION < 0x5004068)
-/* Fetches the SV that keeps the per-interpreter data. */
-#define dMY_CXT_SV \
-        SV *my_cxt_sv = get_sv(MY_CXT_KEY, FALSE)
-#else /* >= perl5.004_68 */
-#define dMY_CXT_SV \
-        SV *my_cxt_sv = *hv_fetch(PL_modglobal, MY_CXT_KEY,             \
-                                  sizeof(MY_CXT_KEY)-1, TRUE)
-#endif /* < perl5.004_68 */
-
-/* This declaration should be used within all functions that use the
- * interpreter-local data. */
-#define dMY_CXT \
-        dMY_CXT_SV;                                                     \
-        my_cxt_t *my_cxtp = INT2PTR(my_cxt_t*,SvUV(my_cxt_sv))
-
-/* Creates and zeroes the per-interpreter data.
- * (We allocate my_cxtp in a Perl SV so that it will be released when
- * the interpreter goes away.) */
-#define MY_CXT_INIT \
-        dMY_CXT_SV;                                                     \
-        /* newSV() allocates one more than needed */                    \
-        my_cxt_t *my_cxtp = (my_cxt_t*)SvPVX(newSV(sizeof(my_cxt_t)-1));\
-        Zero(my_cxtp, 1, my_cxt_t);                                     \
-        sv_setuv(my_cxt_sv, PTR2UV(my_cxtp))
-
-/* This macro must be used to access members of the my_cxt_t structure.
- * e.g. MYCXT.some_data */
-#define MY_CXT          (*my_cxtp)
-
-/* Judicious use of these macros can reduce the number of times dMY_CXT
- * is used.  Use is similar to pTHX, aTHX etc. */
-#define pMY_CXT         my_cxt_t *my_cxtp
-#define pMY_CXT_        pMY_CXT,
-#define _pMY_CXT        ,pMY_CXT
-#define aMY_CXT         my_cxtp
-#define aMY_CXT_        aMY_CXT,
-#define _aMY_CXT        ,aMY_CXT
-
-#endif /* START_MY_CXT */
-
-#ifndef MY_CXT_CLONE
-/* Clones the per-interpreter data. */
-#define MY_CXT_CLONE \
-        dMY_CXT_SV;                                                     \
-        my_cxt_t *my_cxtp = (my_cxt_t*)SvPVX(newSV(sizeof(my_cxt_t)-1));\
-        Copy(INT2PTR(my_cxt_t*, SvUV(my_cxt_sv)), my_cxtp, 1, my_cxt_t);\
-        sv_setuv(my_cxt_sv, PTR2UV(my_cxtp))
-#endif
-
-#else /* single interpreter */
-
-#ifndef START_MY_CXT
-
-#define START_MY_CXT    static my_cxt_t my_cxt;
-#define dMY_CXT_SV      dNOOP
-#define dMY_CXT         dNOOP
-#define MY_CXT_INIT     NOOP
-#define MY_CXT          my_cxt
-
-#define pMY_CXT         void
-#define pMY_CXT_
-#define _pMY_CXT
-#define aMY_CXT
-#define aMY_CXT_
-#define _aMY_CXT
-
-#endif /* START_MY_CXT */
-
-#ifndef MY_CXT_CLONE
-#define MY_CXT_CLONE    NOOP
-#endif
-
-#endif
-
-#ifndef SvREFCNT_inc
-#  ifdef PERL_USE_GCC_BRACE_GROUPS
-#    define SvREFCNT_inc(sv)            \
-      ({                                \
-          SV * const _sv = (SV*)(sv);   \
-          if (_sv)                      \
-               (SvREFCNT(_sv))++;       \
-          _sv;                          \
-      })
-#  else
-#    define SvREFCNT_inc(sv)    \
-          ((PL_Sv=(SV*)(sv)) ? (++(SvREFCNT(PL_Sv)),PL_Sv) : NULL)
-#  endif
-#endif
-
-#ifndef SvREFCNT_inc_simple
-#  ifdef PERL_USE_GCC_BRACE_GROUPS
-#    define SvREFCNT_inc_simple(sv)     \
-      ({                                        \
-          if (sv)                               \
-               (SvREFCNT(sv))++;                \
-          (SV *)(sv);                           \
-      })
-#  else
-#    define SvREFCNT_inc_simple(sv) \
-          ((sv) ? (SvREFCNT(sv)++,(SV*)(sv)) : NULL)
-#  endif
-#endif
-
-#ifndef SvREFCNT_inc_NN
-#  ifdef PERL_USE_GCC_BRACE_GROUPS
-#    define SvREFCNT_inc_NN(sv)         \
-      ({                                        \
-          SV * const _sv = (SV*)(sv);   \
-          SvREFCNT(_sv)++;              \
-          _sv;                          \
-      })
-#  else
-#    define SvREFCNT_inc_NN(sv) \
-          (PL_Sv=(SV*)(sv),++(SvREFCNT(PL_Sv)),PL_Sv)
-#  endif
-#endif
-
-#ifndef SvREFCNT_inc_void
-#  ifdef PERL_USE_GCC_BRACE_GROUPS
-#    define SvREFCNT_inc_void(sv)               \
-      ({                                        \
-          SV * const _sv = (SV*)(sv);   \
-          if (_sv)                      \
-              (void)(SvREFCNT(_sv)++);  \
-      })
-#  else
-#    define SvREFCNT_inc_void(sv) \
-          (void)((PL_Sv=(SV*)(sv)) ? ++(SvREFCNT(PL_Sv)) : 0)
-#  endif
-#endif
-#ifndef SvREFCNT_inc_simple_void
-#  define SvREFCNT_inc_simple_void(sv)   STMT_START { if (sv) SvREFCNT(sv)++; } STMT_END
-#endif
-
-#ifndef SvREFCNT_inc_simple_NN
-#  define SvREFCNT_inc_simple_NN(sv)     (++SvREFCNT(sv), (SV*)(sv))
-#endif
-
-#ifndef SvREFCNT_inc_void_NN
-#  define SvREFCNT_inc_void_NN(sv)       (void)(++SvREFCNT((SV*)(sv)))
-#endif
-
-#ifndef SvREFCNT_inc_simple_void_NN
-#  define SvREFCNT_inc_simple_void_NN(sv) (void)(++SvREFCNT((SV*)(sv)))
-#endif
-
-#ifndef newSV_type
-
-#if defined(NEED_newSV_type)
-static SV* DPPP_(my_newSV_type)(pTHX_ svtype const t);
-static
-#else
-extern SV* DPPP_(my_newSV_type)(pTHX_ svtype const t);
-#endif
-
-#if defined(NEED_newSV_type) || defined(NEED_newSV_type_GLOBAL)
-
-#ifdef newSV_type
-#  undef newSV_type
-#endif
-#define newSV_type(a) DPPP_(my_newSV_type)(aTHX_ a)
-#define Perl_newSV_type DPPP_(my_newSV_type)
-
-
-SV*
-DPPP_(my_newSV_type)(pTHX_ svtype const t)
-{
-  SV* const sv = newSV(0);
-  sv_upgrade(sv, t);
-  return sv;
-}
-
-#endif
-
-#endif
-
-#if (PERL_BCDVERSION < 0x5006000)
-# define D_PPP_CONSTPV_ARG(x)  ((char *) (x))
-#else
-# define D_PPP_CONSTPV_ARG(x)  (x)
-#endif
-#ifndef newSVpvn
-#  define newSVpvn(data,len)             ((data)                                              \
-                                    ? ((len) ? newSVpv((data), (len)) : newSVpv("", 0)) \
-                                    : newSV(0))
-#endif
-#ifndef newSVpvn_utf8
-#  define newSVpvn_utf8(s, len, u)       newSVpvn_flags((s), (len), (u) ? SVf_UTF8 : 0)
-#endif
-#ifndef SVf_UTF8
-#  define SVf_UTF8                       0
-#endif
-
-#ifndef newSVpvn_flags
-
-#if defined(NEED_newSVpvn_flags)
-static SV * DPPP_(my_newSVpvn_flags)(pTHX_ const char *s, STRLEN len, U32 flags);
-static
-#else
-extern SV * DPPP_(my_newSVpvn_flags)(pTHX_ const char *s, STRLEN len, U32 flags);
-#endif
-
-#if defined(NEED_newSVpvn_flags) || defined(NEED_newSVpvn_flags_GLOBAL)
-
-#ifdef newSVpvn_flags
-#  undef newSVpvn_flags
-#endif
-#define newSVpvn_flags(a,b,c) DPPP_(my_newSVpvn_flags)(aTHX_ a,b,c)
-#define Perl_newSVpvn_flags DPPP_(my_newSVpvn_flags)
-
-
-SV *
-DPPP_(my_newSVpvn_flags)(pTHX_ const char *s, STRLEN len, U32 flags)
-{
-  SV *sv = newSVpvn(D_PPP_CONSTPV_ARG(s), len);
-  SvFLAGS(sv) |= (flags & SVf_UTF8);
-  return (flags & SVs_TEMP) ? sv_2mortal(sv) : sv;
-}
-
-#endif
-
-#endif
-
-/* Backwards compatibility stuff... :-( */
-#if !defined(NEED_sv_2pv_flags) && defined(NEED_sv_2pv_nolen)
-#  define NEED_sv_2pv_flags
-#endif
-#if !defined(NEED_sv_2pv_flags_GLOBAL) && defined(NEED_sv_2pv_nolen_GLOBAL)
-#  define NEED_sv_2pv_flags_GLOBAL
-#endif
-
-/* Hint: sv_2pv_nolen
- * Use the SvPV_nolen() or SvPV_nolen_const() macros instead of sv_2pv_nolen().
- */
-#ifndef sv_2pv_nolen
-#  define sv_2pv_nolen(sv)               SvPV_nolen(sv)
-#endif
-
-#ifdef SvPVbyte
-
-/* Hint: SvPVbyte
- * Does not work in perl-5.6.1, ppport.h implements a version
- * borrowed from perl-5.7.3.
- */
-
-#if (PERL_BCDVERSION < 0x5007000)
-
-#if defined(NEED_sv_2pvbyte)
-static char * DPPP_(my_sv_2pvbyte)(pTHX_ SV *sv, STRLEN *lp);
-static
-#else
-extern char * DPPP_(my_sv_2pvbyte)(pTHX_ SV *sv, STRLEN *lp);
-#endif
-
-#if defined(NEED_sv_2pvbyte) || defined(NEED_sv_2pvbyte_GLOBAL)
-
-#ifdef sv_2pvbyte
-#  undef sv_2pvbyte
-#endif
-#define sv_2pvbyte(a,b) DPPP_(my_sv_2pvbyte)(aTHX_ a,b)
-#define Perl_sv_2pvbyte DPPP_(my_sv_2pvbyte)
-
-
-char *
-DPPP_(my_sv_2pvbyte)(pTHX_ SV *sv, STRLEN *lp)
-{
-  sv_utf8_downgrade(sv,0);
-  return SvPV(sv,*lp);
-}
-
-#endif
-
-/* Hint: sv_2pvbyte
- * Use the SvPVbyte() macro instead of sv_2pvbyte().
- */
-
-#undef SvPVbyte
-
-#define SvPVbyte(sv, lp)                                                \
-        ((SvFLAGS(sv) & (SVf_POK|SVf_UTF8)) == (SVf_POK)                \
-         ? ((lp = SvCUR(sv)), SvPVX(sv)) : sv_2pvbyte(sv, &lp))
-
-#endif
-
-#else
-
-#  define SvPVbyte          SvPV
-#  define sv_2pvbyte        sv_2pv
-
-#endif
-#ifndef sv_2pvbyte_nolen
-#  define sv_2pvbyte_nolen(sv)           sv_2pv_nolen(sv)
-#endif
-
-/* Hint: sv_pvn
- * Always use the SvPV() macro instead of sv_pvn().
- */
-
-/* Hint: sv_pvn_force
- * Always use the SvPV_force() macro instead of sv_pvn_force().
- */
-
-/* If these are undefined, they're not handled by the core anyway */
-#ifndef SV_IMMEDIATE_UNREF
-#  define SV_IMMEDIATE_UNREF             0
-#endif
-
-#ifndef SV_GMAGIC
-#  define SV_GMAGIC                      0
-#endif
-
-#ifndef SV_COW_DROP_PV
-#  define SV_COW_DROP_PV                 0
-#endif
-
-#ifndef SV_UTF8_NO_ENCODING
-#  define SV_UTF8_NO_ENCODING            0
-#endif
-
-#ifndef SV_NOSTEAL
-#  define SV_NOSTEAL                     0
-#endif
-
-#ifndef SV_CONST_RETURN
-#  define SV_CONST_RETURN                0
-#endif
-
-#ifndef SV_MUTABLE_RETURN
-#  define SV_MUTABLE_RETURN              0
-#endif
-
-#ifndef SV_SMAGIC
-#  define SV_SMAGIC                      0
-#endif
-
-#ifndef SV_HAS_TRAILING_NUL
-#  define SV_HAS_TRAILING_NUL            0
-#endif
-
-#ifndef SV_COW_SHARED_HASH_KEYS
-#  define SV_COW_SHARED_HASH_KEYS        0
-#endif
-
-#if (PERL_BCDVERSION < 0x5007002)
-
-#if defined(NEED_sv_2pv_flags)
-static char * DPPP_(my_sv_2pv_flags)(pTHX_ SV *sv, STRLEN *lp, I32 flags);
-static
-#else
-extern char * DPPP_(my_sv_2pv_flags)(pTHX_ SV *sv, STRLEN *lp, I32 flags);
-#endif
-
-#if defined(NEED_sv_2pv_flags) || defined(NEED_sv_2pv_flags_GLOBAL)
-
-#ifdef sv_2pv_flags
-#  undef sv_2pv_flags
-#endif
-#define sv_2pv_flags(a,b,c) DPPP_(my_sv_2pv_flags)(aTHX_ a,b,c)
-#define Perl_sv_2pv_flags DPPP_(my_sv_2pv_flags)
-
-
-char *
-DPPP_(my_sv_2pv_flags)(pTHX_ SV *sv, STRLEN *lp, I32 flags)
-{
-  STRLEN n_a = (STRLEN) flags;
-  return sv_2pv(sv, lp ? lp : &n_a);
-}
-
-#endif
-
-#if defined(NEED_sv_pvn_force_flags)
-static char * DPPP_(my_sv_pvn_force_flags)(pTHX_ SV *sv, STRLEN *lp, I32 flags);
-static
-#else
-extern char * DPPP_(my_sv_pvn_force_flags)(pTHX_ SV *sv, STRLEN *lp, I32 flags);
-#endif
-
-#if defined(NEED_sv_pvn_force_flags) || defined(NEED_sv_pvn_force_flags_GLOBAL)
-
-#ifdef sv_pvn_force_flags
-#  undef sv_pvn_force_flags
-#endif
-#define sv_pvn_force_flags(a,b,c) DPPP_(my_sv_pvn_force_flags)(aTHX_ a,b,c)
-#define Perl_sv_pvn_force_flags DPPP_(my_sv_pvn_force_flags)
-
-
-char *
-DPPP_(my_sv_pvn_force_flags)(pTHX_ SV *sv, STRLEN *lp, I32 flags)
-{
-  STRLEN n_a = (STRLEN) flags;
-  return sv_pvn_force(sv, lp ? lp : &n_a);
-}
-
-#endif
-
-#endif
-
-#if (PERL_BCDVERSION < 0x5008008) || ( (PERL_BCDVERSION >= 0x5009000) && (PERL_BCDVERSION < 0x5009003) )
-# define D_PPP_SVPV_NOLEN_LP_ARG &PL_na
-#else
-# define D_PPP_SVPV_NOLEN_LP_ARG 0
-#endif
-#ifndef SvPV_const
-#  define SvPV_const(sv, lp)             SvPV_flags_const(sv, lp, SV_GMAGIC)
-#endif
-
-#ifndef SvPV_mutable
-#  define SvPV_mutable(sv, lp)           SvPV_flags_mutable(sv, lp, SV_GMAGIC)
-#endif
-#ifndef SvPV_flags
-#  define SvPV_flags(sv, lp, flags)      \
-                 ((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \
-                  ? ((lp = SvCUR(sv)), SvPVX(sv)) : sv_2pv_flags(sv, &lp, flags))
-#endif
-#ifndef SvPV_flags_const
-#  define SvPV_flags_const(sv, lp, flags) \
-                 ((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \
-                  ? ((lp = SvCUR(sv)), SvPVX_const(sv)) : \
-                  (const char*) sv_2pv_flags(sv, &lp, flags|SV_CONST_RETURN))
-#endif
-#ifndef SvPV_flags_const_nolen
-#  define SvPV_flags_const_nolen(sv, flags) \
-                 ((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \
-                  ? SvPVX_const(sv) : \
-                  (const char*) sv_2pv_flags(sv, D_PPP_SVPV_NOLEN_LP_ARG, flags|SV_CONST_RETURN))
-#endif
-#ifndef SvPV_flags_mutable
-#  define SvPV_flags_mutable(sv, lp, flags) \
-                 ((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \
-                  ? ((lp = SvCUR(sv)), SvPVX_mutable(sv)) : \
-                  sv_2pv_flags(sv, &lp, flags|SV_MUTABLE_RETURN))
-#endif
-#ifndef SvPV_force
-#  define SvPV_force(sv, lp)             SvPV_force_flags(sv, lp, SV_GMAGIC)
-#endif
-
-#ifndef SvPV_force_nolen
-#  define SvPV_force_nolen(sv)           SvPV_force_flags_nolen(sv, SV_GMAGIC)
-#endif
-
-#ifndef SvPV_force_mutable
-#  define SvPV_force_mutable(sv, lp)     SvPV_force_flags_mutable(sv, lp, SV_GMAGIC)
-#endif
-
-#ifndef SvPV_force_nomg
-#  define SvPV_force_nomg(sv, lp)        SvPV_force_flags(sv, lp, 0)
-#endif
-
-#ifndef SvPV_force_nomg_nolen
-#  define SvPV_force_nomg_nolen(sv)      SvPV_force_flags_nolen(sv, 0)
-#endif
-#ifndef SvPV_force_flags
-#  define SvPV_force_flags(sv, lp, flags) \
-                 ((SvFLAGS(sv) & (SVf_POK|SVf_THINKFIRST)) == SVf_POK \
-                 ? ((lp = SvCUR(sv)), SvPVX(sv)) : sv_pvn_force_flags(sv, &lp, flags))
-#endif
-#ifndef SvPV_force_flags_nolen
-#  define SvPV_force_flags_nolen(sv, flags) \
-                 ((SvFLAGS(sv) & (SVf_POK|SVf_THINKFIRST)) == SVf_POK \
-                 ? SvPVX(sv) : sv_pvn_force_flags(sv, D_PPP_SVPV_NOLEN_LP_ARG, flags))
-#endif
-#ifndef SvPV_force_flags_mutable
-#  define SvPV_force_flags_mutable(sv, lp, flags) \
-                 ((SvFLAGS(sv) & (SVf_POK|SVf_THINKFIRST)) == SVf_POK \
-                 ? ((lp = SvCUR(sv)), SvPVX_mutable(sv)) \
-                  : sv_pvn_force_flags(sv, &lp, flags|SV_MUTABLE_RETURN))
-#endif
-#ifndef SvPV_nolen
-#  define SvPV_nolen(sv)                 \
-                 ((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \
-                  ? SvPVX(sv) : sv_2pv_flags(sv, D_PPP_SVPV_NOLEN_LP_ARG, SV_GMAGIC))
-#endif
-#ifndef SvPV_nolen_const
-#  define SvPV_nolen_const(sv)           \
-                 ((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \
-                  ? SvPVX_const(sv) : sv_2pv_flags(sv, D_PPP_SVPV_NOLEN_LP_ARG, SV_GMAGIC|SV_CONST_RETURN))
-#endif
-#ifndef SvPV_nomg
-#  define SvPV_nomg(sv, lp)              SvPV_flags(sv, lp, 0)
-#endif
-
-#ifndef SvPV_nomg_const
-#  define SvPV_nomg_const(sv, lp)        SvPV_flags_const(sv, lp, 0)
-#endif
-
-#ifndef SvPV_nomg_const_nolen
-#  define SvPV_nomg_const_nolen(sv)      SvPV_flags_const_nolen(sv, 0)
-#endif
-
-#ifndef SvPV_nomg_nolen
-#  define SvPV_nomg_nolen(sv)            ((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \
-                                    ? SvPVX(sv) : sv_2pv_flags(sv, D_PPP_SVPV_NOLEN_LP_ARG, 0))
-#endif
-#ifndef SvPV_renew
-#  define SvPV_renew(sv,n)               STMT_START { SvLEN_set(sv, n); \
-                 SvPV_set((sv), (char *) saferealloc(          \
-                       (Malloc_t)SvPVX(sv), (MEM_SIZE)((n)))); \
-               } STMT_END
-#endif
-#ifndef SvMAGIC_set
-#  define SvMAGIC_set(sv, val)           \
-                STMT_START { assert(SvTYPE(sv) >= SVt_PVMG); \
-                (((XPVMG*) SvANY(sv))->xmg_magic = (val)); } STMT_END
-#endif
-
-#if (PERL_BCDVERSION < 0x5009003)
-#ifndef SvPVX_const
-#  define SvPVX_const(sv)                ((const char*) (0 + SvPVX(sv)))
-#endif
-
-#ifndef SvPVX_mutable
-#  define SvPVX_mutable(sv)              (0 + SvPVX(sv))
-#endif
-#ifndef SvRV_set
-#  define SvRV_set(sv, val)              \
-                STMT_START { assert(SvTYPE(sv) >=  SVt_RV); \
-                (((XRV*) SvANY(sv))->xrv_rv = (val)); } STMT_END
-#endif
-
-#else
-#ifndef SvPVX_const
-#  define SvPVX_const(sv)                ((const char*)((sv)->sv_u.svu_pv))
-#endif
-
-#ifndef SvPVX_mutable
-#  define SvPVX_mutable(sv)              ((sv)->sv_u.svu_pv)
-#endif
-#ifndef SvRV_set
-#  define SvRV_set(sv, val)              \
-                STMT_START { assert(SvTYPE(sv) >=  SVt_RV); \
-                ((sv)->sv_u.svu_rv = (val)); } STMT_END
-#endif
-
-#endif
-#ifndef SvSTASH_set
-#  define SvSTASH_set(sv, val)           \
-                STMT_START { assert(SvTYPE(sv) >= SVt_PVMG); \
-                (((XPVMG*) SvANY(sv))->xmg_stash = (val)); } STMT_END
-#endif
-
-#if (PERL_BCDVERSION < 0x5004000)
-#ifndef SvUV_set
-#  define SvUV_set(sv, val)              \
-                STMT_START { assert(SvTYPE(sv) == SVt_IV || SvTYPE(sv) >= SVt_PVIV); \
-                (((XPVIV*) SvANY(sv))->xiv_iv = (IV) (val)); } STMT_END
-#endif
-
-#else
-#ifndef SvUV_set
-#  define SvUV_set(sv, val)              \
-                STMT_START { assert(SvTYPE(sv) == SVt_IV || SvTYPE(sv) >= SVt_PVIV); \
-                (((XPVUV*) SvANY(sv))->xuv_uv = (val)); } STMT_END
-#endif
-
-#endif
-
-#if (PERL_BCDVERSION >= 0x5004000) && !defined(vnewSVpvf)
-#if defined(NEED_vnewSVpvf)
-static SV * DPPP_(my_vnewSVpvf)(pTHX_ const char *pat, va_list *args);
-static
-#else
-extern SV * DPPP_(my_vnewSVpvf)(pTHX_ const char *pat, va_list *args);
-#endif
-
-#if defined(NEED_vnewSVpvf) || defined(NEED_vnewSVpvf_GLOBAL)
-
-#ifdef vnewSVpvf
-#  undef vnewSVpvf
-#endif
-#define vnewSVpvf(a,b) DPPP_(my_vnewSVpvf)(aTHX_ a,b)
-#define Perl_vnewSVpvf DPPP_(my_vnewSVpvf)
-
-
-SV *
-DPPP_(my_vnewSVpvf)(pTHX_ const char *pat, va_list *args)
-{
-  register SV *sv = newSV(0);
-  sv_vsetpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*));
-  return sv;
-}
-
-#endif
-#endif
-
-#if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_vcatpvf)
-#  define sv_vcatpvf(sv, pat, args)  sv_vcatpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*))
-#endif
-
-#if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_vsetpvf)
-#  define sv_vsetpvf(sv, pat, args)  sv_vsetpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*))
-#endif
-
-#if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_catpvf_mg)
-#if defined(NEED_sv_catpvf_mg)
-static void DPPP_(my_sv_catpvf_mg)(pTHX_ SV *sv, const char *pat, ...);
-static
-#else
-extern void DPPP_(my_sv_catpvf_mg)(pTHX_ SV *sv, const char *pat, ...);
-#endif
-
-#if defined(NEED_sv_catpvf_mg) || defined(NEED_sv_catpvf_mg_GLOBAL)
-
-#define Perl_sv_catpvf_mg DPPP_(my_sv_catpvf_mg)
-
-
-void
-DPPP_(my_sv_catpvf_mg)(pTHX_ SV *sv, const char *pat, ...)
-{
-  va_list args;
-  va_start(args, pat);
-  sv_vcatpvfn(sv, pat, strlen(pat), &args, Null(SV**), 0, Null(bool*));
-  SvSETMAGIC(sv);
-  va_end(args);
-}
-
-#endif
-#endif
-
-#ifdef PERL_IMPLICIT_CONTEXT
-#if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_catpvf_mg_nocontext)
-#if defined(NEED_sv_catpvf_mg_nocontext)
-static void DPPP_(my_sv_catpvf_mg_nocontext)(SV *sv, const char *pat, ...);
-static
-#else
-extern void DPPP_(my_sv_catpvf_mg_nocontext)(SV *sv, const char *pat, ...);
-#endif
-
-#if defined(NEED_sv_catpvf_mg_nocontext) || defined(NEED_sv_catpvf_mg_nocontext_GLOBAL)
-
-#define sv_catpvf_mg_nocontext DPPP_(my_sv_catpvf_mg_nocontext)
-#define Perl_sv_catpvf_mg_nocontext DPPP_(my_sv_catpvf_mg_nocontext)
-
-
-void
-DPPP_(my_sv_catpvf_mg_nocontext)(SV *sv, const char *pat, ...)
-{
-  dTHX;
-  va_list args;
-  va_start(args, pat);
-  sv_vcatpvfn(sv, pat, strlen(pat), &args, Null(SV**), 0, Null(bool*));
-  SvSETMAGIC(sv);
-  va_end(args);
-}
-
-#endif
-#endif
-#endif
-
-/* sv_catpvf_mg depends on sv_catpvf_mg_nocontext */
-#ifndef sv_catpvf_mg
-#  ifdef PERL_IMPLICIT_CONTEXT
-#    define sv_catpvf_mg   Perl_sv_catpvf_mg_nocontext
-#  else
-#    define sv_catpvf_mg   Perl_sv_catpvf_mg
-#  endif
-#endif
-
-#if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_vcatpvf_mg)
-#  define sv_vcatpvf_mg(sv, pat, args)                                     \
-   STMT_START {                                                            \
-     sv_vcatpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*));  \
-     SvSETMAGIC(sv);                                                       \
-   } STMT_END
-#endif
-
-#if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_setpvf_mg)
-#if defined(NEED_sv_setpvf_mg)
-static void DPPP_(my_sv_setpvf_mg)(pTHX_ SV *sv, const char *pat, ...);
-static
-#else
-extern void DPPP_(my_sv_setpvf_mg)(pTHX_ SV *sv, const char *pat, ...);
-#endif
-
-#if defined(NEED_sv_setpvf_mg) || defined(NEED_sv_setpvf_mg_GLOBAL)
-
-#define Perl_sv_setpvf_mg DPPP_(my_sv_setpvf_mg)
-
-
-void
-DPPP_(my_sv_setpvf_mg)(pTHX_ SV *sv, const char *pat, ...)
-{
-  va_list args;
-  va_start(args, pat);
-  sv_vsetpvfn(sv, pat, strlen(pat), &args, Null(SV**), 0, Null(bool*));
-  SvSETMAGIC(sv);
-  va_end(args);
-}
-
-#endif
-#endif
-
-#ifdef PERL_IMPLICIT_CONTEXT
-#if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_setpvf_mg_nocontext)
-#if defined(NEED_sv_setpvf_mg_nocontext)
-static void DPPP_(my_sv_setpvf_mg_nocontext)(SV *sv, const char *pat, ...);
-static
-#else
-extern void DPPP_(my_sv_setpvf_mg_nocontext)(SV *sv, const char *pat, ...);
-#endif
-
-#if defined(NEED_sv_setpvf_mg_nocontext) || defined(NEED_sv_setpvf_mg_nocontext_GLOBAL)
-
-#define sv_setpvf_mg_nocontext DPPP_(my_sv_setpvf_mg_nocontext)
-#define Perl_sv_setpvf_mg_nocontext DPPP_(my_sv_setpvf_mg_nocontext)
-
-
-void
-DPPP_(my_sv_setpvf_mg_nocontext)(SV *sv, const char *pat, ...)
-{
-  dTHX;
-  va_list args;
-  va_start(args, pat);
-  sv_vsetpvfn(sv, pat, strlen(pat), &args, Null(SV**), 0, Null(bool*));
-  SvSETMAGIC(sv);
-  va_end(args);
-}
-
-#endif
-#endif
-#endif
-
-/* sv_setpvf_mg depends on sv_setpvf_mg_nocontext */
-#ifndef sv_setpvf_mg
-#  ifdef PERL_IMPLICIT_CONTEXT
-#    define sv_setpvf_mg   Perl_sv_setpvf_mg_nocontext
-#  else
-#    define sv_setpvf_mg   Perl_sv_setpvf_mg
-#  endif
-#endif
-
-#if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_vsetpvf_mg)
-#  define sv_vsetpvf_mg(sv, pat, args)                                     \
-   STMT_START {                                                            \
-     sv_vsetpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*));  \
-     SvSETMAGIC(sv);                                                       \
-   } STMT_END
-#endif
-
-/* Hint: newSVpvn_share
- * The SVs created by this function only mimic the behaviour of
- * shared PVs without really being shared. Only use if you know
- * what you're doing.
- */
-
-#ifndef newSVpvn_share
-
-#if defined(NEED_newSVpvn_share)
-static SV * DPPP_(my_newSVpvn_share)(pTHX_ const char *src, I32 len, U32 hash);
-static
-#else
-extern SV * DPPP_(my_newSVpvn_share)(pTHX_ const char *src, I32 len, U32 hash);
-#endif
-
-#if defined(NEED_newSVpvn_share) || defined(NEED_newSVpvn_share_GLOBAL)
-
-#ifdef newSVpvn_share
-#  undef newSVpvn_share
-#endif
-#define newSVpvn_share(a,b,c) DPPP_(my_newSVpvn_share)(aTHX_ a,b,c)
-#define Perl_newSVpvn_share DPPP_(my_newSVpvn_share)
-
-
-SV *
-DPPP_(my_newSVpvn_share)(pTHX_ const char *src, I32 len, U32 hash)
-{
-  SV *sv;
-  if (len < 0)
-    len = -len;
-  if (!hash)
-    PERL_HASH(hash, (char*) src, len);
-  sv = newSVpvn((char *) src, len);
-  sv_upgrade(sv, SVt_PVIV);
-  SvIVX(sv) = hash;
-  SvREADONLY_on(sv);
-  SvPOK_on(sv);
-  return sv;
-}
-
-#endif
-
-#endif
-#ifndef SvSHARED_HASH
-#  define SvSHARED_HASH(sv)              (0 + SvUVX(sv))
-#endif
-#ifndef HvNAME_get
-#  define HvNAME_get(hv)                 HvNAME(hv)
-#endif
-#ifndef HvNAMELEN_get
-#  define HvNAMELEN_get(hv)              (HvNAME_get(hv) ? (I32)strlen(HvNAME_get(hv)) : 0)
-#endif
-
-#ifndef gv_fetchpvn_flags
-#if defined(NEED_gv_fetchpvn_flags)
-static GV* DPPP_(my_gv_fetchpvn_flags)(pTHX_ const char* name, STRLEN len, int flags, int types);
-static
-#else
-extern GV* DPPP_(my_gv_fetchpvn_flags)(pTHX_ const char* name, STRLEN len, int flags, int types);
-#endif
-
-#if defined(NEED_gv_fetchpvn_flags) || defined(NEED_gv_fetchpvn_flags_GLOBAL)
-
-#ifdef gv_fetchpvn_flags
-#  undef gv_fetchpvn_flags
-#endif
-#define gv_fetchpvn_flags(a,b,c,d) DPPP_(my_gv_fetchpvn_flags)(aTHX_ a,b,c,d)
-#define Perl_gv_fetchpvn_flags DPPP_(my_gv_fetchpvn_flags)
-
-
-GV*
-DPPP_(my_gv_fetchpvn_flags)(pTHX_ const char* name, STRLEN len, int flags, int types) {
-        char *namepv = savepvn(name, len);
-        GV* stash = gv_fetchpv(namepv, TRUE, SVt_PVHV);
-        Safefree(namepv);
-        return stash;
-}
-
-#endif
-#endif
-#ifndef GvSVn
-#  define GvSVn(gv)                      GvSV(gv)
-#endif
-
-#ifndef isGV_with_GP
-#  define isGV_with_GP(gv)               isGV(gv)
-#endif
-
-#ifndef gv_fetchsv
-#  define gv_fetchsv(name, flags, svt)   gv_fetchpv(SvPV_nolen_const(name), flags, svt)
-#endif
-#ifndef get_cvn_flags
-#  define get_cvn_flags(name, namelen, flags) get_cv(name, flags)
-#endif
-
-#ifndef gv_init_pvn
-#  define gv_init_pvn(gv, stash, ptr, len, flags) gv_init(gv, stash, ptr, len, flags & GV_ADDMULTI ? TRUE : FALSE)
-#endif
-#ifndef WARN_ALL
-#  define WARN_ALL                       0
-#endif
-
-#ifndef WARN_CLOSURE
-#  define WARN_CLOSURE                   1
-#endif
-
-#ifndef WARN_DEPRECATED
-#  define WARN_DEPRECATED                2
-#endif
-
-#ifndef WARN_EXITING
-#  define WARN_EXITING                   3
-#endif
-
-#ifndef WARN_GLOB
-#  define WARN_GLOB                      4
-#endif
-
-#ifndef WARN_IO
-#  define WARN_IO                        5
-#endif
-
-#ifndef WARN_CLOSED
-#  define WARN_CLOSED                    6
-#endif
-
-#ifndef WARN_EXEC
-#  define WARN_EXEC                      7
-#endif
-
-#ifndef WARN_LAYER
-#  define WARN_LAYER                     8
-#endif
-
-#ifndef WARN_NEWLINE
-#  define WARN_NEWLINE                   9
-#endif
-
-#ifndef WARN_PIPE
-#  define WARN_PIPE                      10
-#endif
-
-#ifndef WARN_UNOPENED
-#  define WARN_UNOPENED                  11
-#endif
-
-#ifndef WARN_MISC
-#  define WARN_MISC                      12
-#endif
-
-#ifndef WARN_NUMERIC
-#  define WARN_NUMERIC                   13
-#endif
-
-#ifndef WARN_ONCE
-#  define WARN_ONCE                      14
-#endif
-
-#ifndef WARN_OVERFLOW
-#  define WARN_OVERFLOW                  15
-#endif
-
-#ifndef WARN_PACK
-#  define WARN_PACK                      16
-#endif
-
-#ifndef WARN_PORTABLE
-#  define WARN_PORTABLE                  17
-#endif
-
-#ifndef WARN_RECURSION
-#  define WARN_RECURSION                 18
-#endif
-
-#ifndef WARN_REDEFINE
-#  define WARN_REDEFINE                  19
-#endif
-
-#ifndef WARN_REGEXP
-#  define WARN_REGEXP                    20
-#endif
-
-#ifndef WARN_SEVERE
-#  define WARN_SEVERE                    21
-#endif
-
-#ifndef WARN_DEBUGGING
-#  define WARN_DEBUGGING                 22
-#endif
-
-#ifndef WARN_INPLACE
-#  define WARN_INPLACE                   23
-#endif
-
-#ifndef WARN_INTERNAL
-#  define WARN_INTERNAL                  24
-#endif
-
-#ifndef WARN_MALLOC
-#  define WARN_MALLOC                    25
-#endif
-
-#ifndef WARN_SIGNAL
-#  define WARN_SIGNAL                    26
-#endif
-
-#ifndef WARN_SUBSTR
-#  define WARN_SUBSTR                    27
-#endif
-
-#ifndef WARN_SYNTAX
-#  define WARN_SYNTAX                    28
-#endif
-
-#ifndef WARN_AMBIGUOUS
-#  define WARN_AMBIGUOUS                 29
-#endif
-
-#ifndef WARN_BAREWORD
-#  define WARN_BAREWORD                  30
-#endif
-
-#ifndef WARN_DIGIT
-#  define WARN_DIGIT                     31
-#endif
-
-#ifndef WARN_PARENTHESIS
-#  define WARN_PARENTHESIS               32
-#endif
-
-#ifndef WARN_PRECEDENCE
-#  define WARN_PRECEDENCE                33
-#endif
-
-#ifndef WARN_PRINTF
-#  define WARN_PRINTF                    34
-#endif
-
-#ifndef WARN_PROTOTYPE
-#  define WARN_PROTOTYPE                 35
-#endif
-
-#ifndef WARN_QW
-#  define WARN_QW                        36
-#endif
-
-#ifndef WARN_RESERVED
-#  define WARN_RESERVED                  37
-#endif
-
-#ifndef WARN_SEMICOLON
-#  define WARN_SEMICOLON                 38
-#endif
-
-#ifndef WARN_TAINT
-#  define WARN_TAINT                     39
-#endif
-
-#ifndef WARN_THREADS
-#  define WARN_THREADS                   40
-#endif
-
-#ifndef WARN_UNINITIALIZED
-#  define WARN_UNINITIALIZED             41
-#endif
-
-#ifndef WARN_UNPACK
-#  define WARN_UNPACK                    42
-#endif
-
-#ifndef WARN_UNTIE
-#  define WARN_UNTIE                     43
-#endif
-
-#ifndef WARN_UTF8
-#  define WARN_UTF8                      44
-#endif
-
-#ifndef WARN_VOID
-#  define WARN_VOID                      45
-#endif
-
-#ifndef WARN_ASSERTIONS
-#  define WARN_ASSERTIONS                46
-#endif
-#ifndef packWARN
-#  define packWARN(a)                    (a)
-#endif
-
-#ifndef ckWARN
-#  ifdef G_WARN_ON
-#    define  ckWARN(a)                  (PL_dowarn & G_WARN_ON)
-#  else
-#    define  ckWARN(a)                  PL_dowarn
-#  endif
-#endif
-
-#if (PERL_BCDVERSION >= 0x5004000) && !defined(warner)
-#if defined(NEED_warner)
-static void DPPP_(my_warner)(U32 err, const char *pat, ...);
-static
-#else
-extern void DPPP_(my_warner)(U32 err, const char *pat, ...);
-#endif
-
-#if defined(NEED_warner) || defined(NEED_warner_GLOBAL)
-
-#define Perl_warner DPPP_(my_warner)
-
-
-void
-DPPP_(my_warner)(U32 err, const char *pat, ...)
-{
-  SV *sv;
-  va_list args;
-
-  PERL_UNUSED_ARG(err);
-
-  va_start(args, pat);
-  sv = vnewSVpvf(pat, &args);
-  va_end(args);
-  sv_2mortal(sv);
-  warn("%s", SvPV_nolen(sv));
-}
-
-#define warner  Perl_warner
-
-#define Perl_warner_nocontext  Perl_warner
-
-#endif
-#endif
-
-/* concatenating with "" ensures that only literal strings are accepted as argument
- * note that STR_WITH_LEN() can't be used as argument to macros or functions that
- * under some configurations might be macros
- */
-#ifndef STR_WITH_LEN
-#  define STR_WITH_LEN(s)                (s ""), (sizeof(s)-1)
-#endif
-#ifndef newSVpvs
-#  define newSVpvs(str)                  newSVpvn(str "", sizeof(str) - 1)
-#endif
-
-#ifndef newSVpvs_flags
-#  define newSVpvs_flags(str, flags)     newSVpvn_flags(str "", sizeof(str) - 1, flags)
-#endif
-
-#ifndef newSVpvs_share
-#  define newSVpvs_share(str)            newSVpvn_share(str "", sizeof(str) - 1, 0)
-#endif
-
-#ifndef sv_catpvs
-#  define sv_catpvs(sv, str)             sv_catpvn(sv, str "", sizeof(str) - 1)
-#endif
-
-#ifndef sv_setpvs
-#  define sv_setpvs(sv, str)             sv_setpvn(sv, str "", sizeof(str) - 1)
-#endif
-
-#ifndef hv_fetchs
-#  define hv_fetchs(hv, key, lval)       hv_fetch(hv, key "", sizeof(key) - 1, lval)
-#endif
-
-#ifndef hv_stores
-#  define hv_stores(hv, key, val)        hv_store(hv, key "", sizeof(key) - 1, val, 0)
-#endif
-#ifndef gv_fetchpvs
-#  define gv_fetchpvs(name, flags, svt)  gv_fetchpvn_flags(name "", sizeof(name) - 1, flags, svt)
-#endif
-
-#ifndef gv_stashpvs
-#  define gv_stashpvs(name, flags)       gv_stashpvn(name "", sizeof(name) - 1, flags)
-#endif
-#ifndef get_cvs
-#  define get_cvs(name, flags)           get_cvn_flags(name "", sizeof(name)-1, flags)
-#endif
-
-#ifdef USE_ITHREADS
-#ifndef CopFILE
-#  define CopFILE(c)                     ((c)->cop_file)
-#endif
-
-#ifndef CopFILEGV
-#  define CopFILEGV(c)                   (CopFILE(c) ? gv_fetchfile(CopFILE(c)) : Nullgv)
-#endif
-
-#ifndef CopFILE_set
-#  define CopFILE_set(c,pv)              ((c)->cop_file = savepv(pv))
-#endif
-
-#ifndef CopFILESV
-#  define CopFILESV(c)                   (CopFILE(c) ? GvSV(gv_fetchfile(CopFILE(c))) : Nullsv)
-#endif
-
-#ifndef CopFILEAV
-#  define CopFILEAV(c)                   (CopFILE(c) ? GvAV(gv_fetchfile(CopFILE(c))) : Nullav)
-#endif
-
-#ifndef CopSTASHPV
-#  define CopSTASHPV(c)                  ((c)->cop_stashpv)
-#endif
-
-#ifndef CopSTASHPV_set
-#  define CopSTASHPV_set(c,pv)           ((c)->cop_stashpv = ((pv) ? savepv(pv) : Nullch))
-#endif
-
-#ifndef CopSTASH
-#  define CopSTASH(c)                    (CopSTASHPV(c) ? gv_stashpv(CopSTASHPV(c),GV_ADD) : Nullhv)
-#endif
-
-#ifndef CopSTASH_set
-#  define CopSTASH_set(c,hv)             CopSTASHPV_set(c, (hv) ? HvNAME(hv) : Nullch)
-#endif
-
-#ifndef CopSTASH_eq
-#  define CopSTASH_eq(c,hv)              ((hv) && (CopSTASHPV(c) == HvNAME(hv) \
-                                        || (CopSTASHPV(c) && HvNAME(hv) \
-                                        && strEQ(CopSTASHPV(c), HvNAME(hv)))))
-#endif
-
-#else
-#ifndef CopFILEGV
-#  define CopFILEGV(c)                   ((c)->cop_filegv)
-#endif
-
-#ifndef CopFILEGV_set
-#  define CopFILEGV_set(c,gv)            ((c)->cop_filegv = (GV*)SvREFCNT_inc(gv))
-#endif
-
-#ifndef CopFILE_set
-#  define CopFILE_set(c,pv)              CopFILEGV_set((c), gv_fetchfile(pv))
-#endif
-
-#ifndef CopFILESV
-#  define CopFILESV(c)                   (CopFILEGV(c) ? GvSV(CopFILEGV(c)) : Nullsv)
-#endif
-
-#ifndef CopFILEAV
-#  define CopFILEAV(c)                   (CopFILEGV(c) ? GvAV(CopFILEGV(c)) : Nullav)
-#endif
-
-#ifndef CopFILE
-#  define CopFILE(c)                     (CopFILESV(c) ? SvPVX(CopFILESV(c)) : Nullch)
-#endif
-
-#ifndef CopSTASH
-#  define CopSTASH(c)                    ((c)->cop_stash)
-#endif
-
-#ifndef CopSTASH_set
-#  define CopSTASH_set(c,hv)             ((c)->cop_stash = (hv))
-#endif
-
-#ifndef CopSTASHPV
-#  define CopSTASHPV(c)                  (CopSTASH(c) ? HvNAME(CopSTASH(c)) : Nullch)
-#endif
-
-#ifndef CopSTASHPV_set
-#  define CopSTASHPV_set(c,pv)           CopSTASH_set((c), gv_stashpv(pv,GV_ADD))
-#endif
-
-#ifndef CopSTASH_eq
-#  define CopSTASH_eq(c,hv)              (CopSTASH(c) == (hv))
-#endif
-
-#endif /* USE_ITHREADS */
-
-#if (PERL_BCDVERSION >= 0x5006000)
-#ifndef caller_cx
-
-# if defined(NEED_caller_cx) || defined(NEED_caller_cx_GLOBAL)
-static I32
-DPPP_dopoptosub_at(const PERL_CONTEXT *cxstk, I32 startingblock)
-{
-    I32 i;
-
-    for (i = startingblock; i >= 0; i--) {
-        register const PERL_CONTEXT * const cx = &cxstk[i];
-        switch (CxTYPE(cx)) {
-        default:
-            continue;
-        case CXt_EVAL:
-        case CXt_SUB:
-        case CXt_FORMAT:
-            return i;
-        }
-    }
-    return i;
-}
-# endif
-
-# if defined(NEED_caller_cx)
-static const PERL_CONTEXT * DPPP_(my_caller_cx)(pTHX_ I32 count, const PERL_CONTEXT **dbcxp);
-static
-#else
-extern const PERL_CONTEXT * DPPP_(my_caller_cx)(pTHX_ I32 count, const PERL_CONTEXT **dbcxp);
-#endif
-
-#if defined(NEED_caller_cx) || defined(NEED_caller_cx_GLOBAL)
-
-#ifdef caller_cx
-#  undef caller_cx
-#endif
-#define caller_cx(a,b) DPPP_(my_caller_cx)(aTHX_ a,b)
-#define Perl_caller_cx DPPP_(my_caller_cx)
-
-
-const PERL_CONTEXT *
-DPPP_(my_caller_cx)(pTHX_ I32 count, const PERL_CONTEXT **dbcxp)
-{
-    register I32 cxix = DPPP_dopoptosub_at(cxstack, cxstack_ix);
-    register const PERL_CONTEXT *cx;
-    register const PERL_CONTEXT *ccstack = cxstack;
-    const PERL_SI *top_si = PL_curstackinfo;
-
-    for (;;) {
-        /* we may be in a higher stacklevel, so dig down deeper */
-        while (cxix < 0 && top_si->si_type != PERLSI_MAIN) {
-            top_si = top_si->si_prev;
-            ccstack = top_si->si_cxstack;
-            cxix = DPPP_dopoptosub_at(ccstack, top_si->si_cxix);
-        }
-        if (cxix < 0)
-            return NULL;
-        /* caller() should not report the automatic calls to &DB::sub */
-        if (PL_DBsub && GvCV(PL_DBsub) && cxix >= 0 &&
-                ccstack[cxix].blk_sub.cv == GvCV(PL_DBsub))
-            count++;
-        if (!count--)
-            break;
-        cxix = DPPP_dopoptosub_at(ccstack, cxix - 1);
-    }
-
-    cx = &ccstack[cxix];
-    if (dbcxp) *dbcxp = cx;
-
-    if (CxTYPE(cx) == CXt_SUB || CxTYPE(cx) == CXt_FORMAT) {
-        const I32 dbcxix = DPPP_dopoptosub_at(ccstack, cxix - 1);
-        /* We expect that ccstack[dbcxix] is CXt_SUB, anyway, the
-           field below is defined for any cx. */
-        /* caller() should not report the automatic calls to &DB::sub */
-        if (PL_DBsub && GvCV(PL_DBsub) && dbcxix >= 0 && ccstack[dbcxix].blk_sub.cv == GvCV(PL_DBsub))
-            cx = &ccstack[dbcxix];
-    }
-
-    return cx;
-}
-
-# endif
-#endif /* caller_cx */
-#endif /* 5.6.0 */
-#ifndef IN_PERL_COMPILETIME
-#  define IN_PERL_COMPILETIME            (PL_curcop == &PL_compiling)
-#endif
-
-#ifndef IN_LOCALE_RUNTIME
-#  define IN_LOCALE_RUNTIME              (PL_curcop->op_private & HINT_LOCALE)
-#endif
-
-#ifndef IN_LOCALE_COMPILETIME
-#  define IN_LOCALE_COMPILETIME          (PL_hints & HINT_LOCALE)
-#endif
-
-#ifndef IN_LOCALE
-#  define IN_LOCALE                      (IN_PERL_COMPILETIME ? IN_LOCALE_COMPILETIME : IN_LOCALE_RUNTIME)
-#endif
-#ifndef IS_NUMBER_IN_UV
-#  define IS_NUMBER_IN_UV                0x01
-#endif
-
-#ifndef IS_NUMBER_GREATER_THAN_UV_MAX
-#  define IS_NUMBER_GREATER_THAN_UV_MAX  0x02
-#endif
-
-#ifndef IS_NUMBER_NOT_INT
-#  define IS_NUMBER_NOT_INT              0x04
-#endif
-
-#ifndef IS_NUMBER_NEG
-#  define IS_NUMBER_NEG                  0x08
-#endif
-
-#ifndef IS_NUMBER_INFINITY
-#  define IS_NUMBER_INFINITY             0x10
-#endif
-
-#ifndef IS_NUMBER_NAN
-#  define IS_NUMBER_NAN                  0x20
-#endif
-#ifndef GROK_NUMERIC_RADIX
-#  define GROK_NUMERIC_RADIX(sp, send)   grok_numeric_radix(sp, send)
-#endif
-#ifndef PERL_SCAN_GREATER_THAN_UV_MAX
-#  define PERL_SCAN_GREATER_THAN_UV_MAX  0x02
-#endif
-
-#ifndef PERL_SCAN_SILENT_ILLDIGIT
-#  define PERL_SCAN_SILENT_ILLDIGIT      0x04
-#endif
-
-#ifndef PERL_SCAN_ALLOW_UNDERSCORES
-#  define PERL_SCAN_ALLOW_UNDERSCORES    0x01
-#endif
-
-#ifndef PERL_SCAN_DISALLOW_PREFIX
-#  define PERL_SCAN_DISALLOW_PREFIX      0x02
-#endif
-
-#ifndef grok_numeric_radix
-#if defined(NEED_grok_numeric_radix)
-static bool DPPP_(my_grok_numeric_radix)(pTHX_ const char ** sp, const char * send);
-static
-#else
-extern bool DPPP_(my_grok_numeric_radix)(pTHX_ const char ** sp, const char * send);
-#endif
-
-#if defined(NEED_grok_numeric_radix) || defined(NEED_grok_numeric_radix_GLOBAL)
-
-#ifdef grok_numeric_radix
-#  undef grok_numeric_radix
-#endif
-#define grok_numeric_radix(a,b) DPPP_(my_grok_numeric_radix)(aTHX_ a,b)
-#define Perl_grok_numeric_radix DPPP_(my_grok_numeric_radix)
-
-bool
-DPPP_(my_grok_numeric_radix)(pTHX_ const char **sp, const char *send)
-{
-#ifdef USE_LOCALE_NUMERIC
-#ifdef PL_numeric_radix_sv
-    if (PL_numeric_radix_sv && IN_LOCALE) {
-        STRLEN len;
-        char* radix = SvPV(PL_numeric_radix_sv, len);
-        if (*sp + len <= send && memEQ(*sp, radix, len)) {
-            *sp += len;
-            return TRUE;
-        }
-    }
-#else
-    /* older perls don't have PL_numeric_radix_sv so the radix
-     * must manually be requested from locale.h
-     */
-#include <locale.h>
-    dTHR;  /* needed for older threaded perls */
-    struct lconv *lc = localeconv();
-    char *radix = lc->decimal_point;
-    if (radix && IN_LOCALE) {
-        STRLEN len = strlen(radix);
-        if (*sp + len <= send && memEQ(*sp, radix, len)) {
-            *sp += len;
-            return TRUE;
-        }
-    }
-#endif
-#endif /* USE_LOCALE_NUMERIC */
-    /* always try "." if numeric radix didn't match because
-     * we may have data from different locales mixed */
-    if (*sp < send && **sp == '.') {
-        ++*sp;
-        return TRUE;
-    }
-    return FALSE;
-}
-#endif
-#endif
-
-#ifndef grok_number
-#if defined(NEED_grok_number)
-static int DPPP_(my_grok_number)(pTHX_ const char * pv, STRLEN len, UV * valuep);
-static
-#else
-extern int DPPP_(my_grok_number)(pTHX_ const char * pv, STRLEN len, UV * valuep);
-#endif
-
-#if defined(NEED_grok_number) || defined(NEED_grok_number_GLOBAL)
-
-#ifdef grok_number
-#  undef grok_number
-#endif
-#define grok_number(a,b,c) DPPP_(my_grok_number)(aTHX_ a,b,c)
-#define Perl_grok_number DPPP_(my_grok_number)
-
-int
-DPPP_(my_grok_number)(pTHX_ const char *pv, STRLEN len, UV *valuep)
-{
-  const char *s = pv;
-  const char *send = pv + len;
-  const UV max_div_10 = UV_MAX / 10;
-  const char max_mod_10 = UV_MAX % 10;
-  int numtype = 0;
-  int sawinf = 0;
-  int sawnan = 0;
-
-  while (s < send && isSPACE(*s))
-    s++;
-  if (s == send) {
-    return 0;
-  } else if (*s == '-') {
-    s++;
-    numtype = IS_NUMBER_NEG;
-  }
-  else if (*s == '+')
-  s++;
-
-  if (s == send)
-    return 0;
-
-  /* next must be digit or the radix separator or beginning of infinity */
-  if (isDIGIT(*s)) {
-    /* UVs are at least 32 bits, so the first 9 decimal digits cannot
-       overflow.  */
-    UV value = *s - '0';
-    /* This construction seems to be more optimiser friendly.
-       (without it gcc does the isDIGIT test and the *s - '0' separately)
-       With it gcc on arm is managing 6 instructions (6 cycles) per digit.
-       In theory the optimiser could deduce how far to unroll the loop
-       before checking for overflow.  */
-    if (++s < send) {
-      int digit = *s - '0';
-      if (digit >= 0 && digit <= 9) {
-        value = value * 10 + digit;
-        if (++s < send) {
-          digit = *s - '0';
-          if (digit >= 0 && digit <= 9) {
-            value = value * 10 + digit;
-            if (++s < send) {
-              digit = *s - '0';
-              if (digit >= 0 && digit <= 9) {
-                value = value * 10 + digit;
-                if (++s < send) {
-                  digit = *s - '0';
-                  if (digit >= 0 && digit <= 9) {
-                    value = value * 10 + digit;
-                    if (++s < send) {
-                      digit = *s - '0';
-                      if (digit >= 0 && digit <= 9) {
-                        value = value * 10 + digit;
-                        if (++s < send) {
-                          digit = *s - '0';
-                          if (digit >= 0 && digit <= 9) {
-                            value = value * 10 + digit;
-                            if (++s < send) {
-                              digit = *s - '0';
-                              if (digit >= 0 && digit <= 9) {
-                                value = value * 10 + digit;
-                                if (++s < send) {
-                                  digit = *s - '0';
-                                  if (digit >= 0 && digit <= 9) {
-                                    value = value * 10 + digit;
-                                    if (++s < send) {
-                                      /* Now got 9 digits, so need to check
-                                         each time for overflow.  */
-                                      digit = *s - '0';
-                                      while (digit >= 0 && digit <= 9
-                                             && (value < max_div_10
-                                                 || (value == max_div_10
-                                                     && digit <= max_mod_10))) {
-                                        value = value * 10 + digit;
-                                        if (++s < send)
-                                          digit = *s - '0';
-                                        else
-                                          break;
-                                      }
-                                      if (digit >= 0 && digit <= 9
-                                          && (s < send)) {
-                                        /* value overflowed.
-                                           skip the remaining digits, don't
-                                           worry about setting *valuep.  */
-                                        do {
-                                          s++;
-                                        } while (s < send && isDIGIT(*s));
-                                        numtype |=
-                                          IS_NUMBER_GREATER_THAN_UV_MAX;
-                                        goto skip_value;
-                                      }
-                                    }
-                                  }
-                                }
-                              }
-                            }
-                          }
-                        }
-                      }
-                    }
-                  }
-                }
-              }
-            }
-          }
-        }
-      }
-    }
-    numtype |= IS_NUMBER_IN_UV;
-    if (valuep)
-      *valuep = value;
-
-  skip_value:
-    if (GROK_NUMERIC_RADIX(&s, send)) {
-      numtype |= IS_NUMBER_NOT_INT;
-      while (s < send && isDIGIT(*s))  /* optional digits after the radix */
-        s++;
-    }
-  }
-  else if (GROK_NUMERIC_RADIX(&s, send)) {
-    numtype |= IS_NUMBER_NOT_INT | IS_NUMBER_IN_UV; /* valuep assigned below */
-    /* no digits before the radix means we need digits after it */
-    if (s < send && isDIGIT(*s)) {
-      do {
-        s++;
-      } while (s < send && isDIGIT(*s));
-      if (valuep) {
-        /* integer approximation is valid - it's 0.  */
-        *valuep = 0;
-      }
-    }
-    else
-      return 0;
-  } else if (*s == 'I' || *s == 'i') {
-    s++; if (s == send || (*s != 'N' && *s != 'n')) return 0;
-    s++; if (s == send || (*s != 'F' && *s != 'f')) return 0;
-    s++; if (s < send && (*s == 'I' || *s == 'i')) {
-      s++; if (s == send || (*s != 'N' && *s != 'n')) return 0;
-      s++; if (s == send || (*s != 'I' && *s != 'i')) return 0;
-      s++; if (s == send || (*s != 'T' && *s != 't')) return 0;
-      s++; if (s == send || (*s != 'Y' && *s != 'y')) return 0;
-      s++;
-    }
-    sawinf = 1;
-  } else if (*s == 'N' || *s == 'n') {
-    /* XXX TODO: There are signaling NaNs and quiet NaNs. */
-    s++; if (s == send || (*s != 'A' && *s != 'a')) return 0;
-    s++; if (s == send || (*s != 'N' && *s != 'n')) return 0;
-    s++;
-    sawnan = 1;
-  } else
-    return 0;
-
-  if (sawinf) {
-    numtype &= IS_NUMBER_NEG; /* Keep track of sign  */
-    numtype |= IS_NUMBER_INFINITY | IS_NUMBER_NOT_INT;
-  } else if (sawnan) {
-    numtype &= IS_NUMBER_NEG; /* Keep track of sign  */
-    numtype |= IS_NUMBER_NAN | IS_NUMBER_NOT_INT;
-  } else if (s < send) {
-    /* we can have an optional exponent part */
-    if (*s == 'e' || *s == 'E') {
-      /* The only flag we keep is sign.  Blow away any "it's UV"  */
-      numtype &= IS_NUMBER_NEG;
-      numtype |= IS_NUMBER_NOT_INT;
-      s++;
-      if (s < send && (*s == '-' || *s == '+'))
-        s++;
-      if (s < send && isDIGIT(*s)) {
-        do {
-          s++;
-        } while (s < send && isDIGIT(*s));
-      }
-      else
-      return 0;
-    }
-  }
-  while (s < send && isSPACE(*s))
-    s++;
-  if (s >= send)
-    return numtype;
-  if (len == 10 && memEQ(pv, "0 but true", 10)) {
-    if (valuep)
-      *valuep = 0;
-    return IS_NUMBER_IN_UV;
-  }
-  return 0;
-}
-#endif
-#endif
-
-/*
- * The grok_* routines have been modified to use warn() instead of
- * Perl_warner(). Also, 'hexdigit' was the former name of PL_hexdigit,
- * which is why the stack variable has been renamed to 'xdigit'.
- */
-
-#ifndef grok_bin
-#if defined(NEED_grok_bin)
-static UV DPPP_(my_grok_bin)(pTHX_ const char * start, STRLEN * len_p, I32 * flags, NV * result);
-static
-#else
-extern UV DPPP_(my_grok_bin)(pTHX_ const char * start, STRLEN * len_p, I32 * flags, NV * result);
-#endif
-
-#if defined(NEED_grok_bin) || defined(NEED_grok_bin_GLOBAL)
-
-#ifdef grok_bin
-#  undef grok_bin
-#endif
-#define grok_bin(a,b,c,d) DPPP_(my_grok_bin)(aTHX_ a,b,c,d)
-#define Perl_grok_bin DPPP_(my_grok_bin)
-
-UV
-DPPP_(my_grok_bin)(pTHX_ const char *start, STRLEN *len_p, I32 *flags, NV *result)
-{
-    const char *s = start;
-    STRLEN len = *len_p;
-    UV value = 0;
-    NV value_nv = 0;
-
-    const UV max_div_2 = UV_MAX / 2;
-    bool allow_underscores = *flags & PERL_SCAN_ALLOW_UNDERSCORES;
-    bool overflowed = FALSE;
-
-    if (!(*flags & PERL_SCAN_DISALLOW_PREFIX)) {
-        /* strip off leading b or 0b.
-           for compatibility silently suffer "b" and "0b" as valid binary
-           numbers. */
-        if (len >= 1) {
-            if (s[0] == 'b') {
-                s++;
-                len--;
-            }
-            else if (len >= 2 && s[0] == '0' && s[1] == 'b') {
-                s+=2;
-                len-=2;
-            }
-        }
-    }
-
-    for (; len-- && *s; s++) {
-        char bit = *s;
-        if (bit == '0' || bit == '1') {
-            /* Write it in this wonky order with a goto to attempt to get the
-               compiler to make the common case integer-only loop pretty tight.
-               With gcc seems to be much straighter code than old scan_bin.  */
-          redo:
-            if (!overflowed) {
-                if (value <= max_div_2) {
-                    value = (value << 1) | (bit - '0');
-                    continue;
-                }
-                /* Bah. We're just overflowed.  */
-                warn("Integer overflow in binary number");
-                overflowed = TRUE;
-                value_nv = (NV) value;
-            }
-            value_nv *= 2.0;
-            /* If an NV has not enough bits in its mantissa to
-             * represent a UV this summing of small low-order numbers
-             * is a waste of time (because the NV cannot preserve
-             * the low-order bits anyway): we could just remember when
-             * did we overflow and in the end just multiply value_nv by the
-             * right amount. */
-            value_nv += (NV)(bit - '0');
-            continue;
-        }
-        if (bit == '_' && len && allow_underscores && (bit = s[1])
-            && (bit == '0' || bit == '1'))
-            {
-                --len;
-                ++s;
-                goto redo;
-            }
-        if (!(*flags & PERL_SCAN_SILENT_ILLDIGIT))
-            warn("Illegal binary digit '%c' ignored", *s);
-        break;
-    }
-
-    if (   ( overflowed && value_nv > 4294967295.0)
-#if UVSIZE > 4
-        || (!overflowed && value > 0xffffffff  )
-#endif
-        ) {
-        warn("Binary number > 0b11111111111111111111111111111111 non-portable");
-    }
-    *len_p = s - start;
-    if (!overflowed) {
-        *flags = 0;
-        return value;
-    }
-    *flags = PERL_SCAN_GREATER_THAN_UV_MAX;
-    if (result)
-        *result = value_nv;
-    return UV_MAX;
-}
-#endif
-#endif
-
-#ifndef grok_hex
-#if defined(NEED_grok_hex)
-static UV DPPP_(my_grok_hex)(pTHX_ const char * start, STRLEN * len_p, I32 * flags, NV * result);
-static
-#else
-extern UV DPPP_(my_grok_hex)(pTHX_ const char * start, STRLEN * len_p, I32 * flags, NV * result);
-#endif
-
-#if defined(NEED_grok_hex) || defined(NEED_grok_hex_GLOBAL)
-
-#ifdef grok_hex
-#  undef grok_hex
-#endif
-#define grok_hex(a,b,c,d) DPPP_(my_grok_hex)(aTHX_ a,b,c,d)
-#define Perl_grok_hex DPPP_(my_grok_hex)
-
-UV
-DPPP_(my_grok_hex)(pTHX_ const char *start, STRLEN *len_p, I32 *flags, NV *result)
-{
-    const char *s = start;
-    STRLEN len = *len_p;
-    UV value = 0;
-    NV value_nv = 0;
-
-    const UV max_div_16 = UV_MAX / 16;
-    bool allow_underscores = *flags & PERL_SCAN_ALLOW_UNDERSCORES;
-    bool overflowed = FALSE;
-    const char *xdigit;
-
-    if (!(*flags & PERL_SCAN_DISALLOW_PREFIX)) {
-        /* strip off leading x or 0x.
-           for compatibility silently suffer "x" and "0x" as valid hex numbers.
-        */
-        if (len >= 1) {
-            if (s[0] == 'x') {
-                s++;
-                len--;
-            }
-            else if (len >= 2 && s[0] == '0' && s[1] == 'x') {
-                s+=2;
-                len-=2;
-            }
-        }
-    }
-
-    for (; len-- && *s; s++) {
-        xdigit = strchr((char *) PL_hexdigit, *s);
-        if (xdigit) {
-            /* Write it in this wonky order with a goto to attempt to get the
-               compiler to make the common case integer-only loop pretty tight.
-               With gcc seems to be much straighter code than old scan_hex.  */
-          redo:
-            if (!overflowed) {
-                if (value <= max_div_16) {
-                    value = (value << 4) | ((xdigit - PL_hexdigit) & 15);
-                    continue;
-                }
-                warn("Integer overflow in hexadecimal number");
-                overflowed = TRUE;
-                value_nv = (NV) value;
-            }
-            value_nv *= 16.0;
-            /* If an NV has not enough bits in its mantissa to
-             * represent a UV this summing of small low-order numbers
-             * is a waste of time (because the NV cannot preserve
-             * the low-order bits anyway): we could just remember when
-             * did we overflow and in the end just multiply value_nv by the
-             * right amount of 16-tuples. */
-            value_nv += (NV)((xdigit - PL_hexdigit) & 15);
-            continue;
-        }
-        if (*s == '_' && len && allow_underscores && s[1]
-                && (xdigit = strchr((char *) PL_hexdigit, s[1])))
-            {
-                --len;
-                ++s;
-                goto redo;
-            }
-        if (!(*flags & PERL_SCAN_SILENT_ILLDIGIT))
-            warn("Illegal hexadecimal digit '%c' ignored", *s);
-        break;
-    }
-
-    if (   ( overflowed && value_nv > 4294967295.0)
-#if UVSIZE > 4
-        || (!overflowed && value > 0xffffffff  )
-#endif
-        ) {
-        warn("Hexadecimal number > 0xffffffff non-portable");
-    }
-    *len_p = s - start;
-    if (!overflowed) {
-        *flags = 0;
-        return value;
-    }
-    *flags = PERL_SCAN_GREATER_THAN_UV_MAX;
-    if (result)
-        *result = value_nv;
-    return UV_MAX;
-}
-#endif
-#endif
-
-#ifndef grok_oct
-#if defined(NEED_grok_oct)
-static UV DPPP_(my_grok_oct)(pTHX_ const char * start, STRLEN * len_p, I32 * flags, NV * result);
-static
-#else
-extern UV DPPP_(my_grok_oct)(pTHX_ const char * start, STRLEN * len_p, I32 * flags, NV * result);
-#endif
-
-#if defined(NEED_grok_oct) || defined(NEED_grok_oct_GLOBAL)
-
-#ifdef grok_oct
-#  undef grok_oct
-#endif
-#define grok_oct(a,b,c,d) DPPP_(my_grok_oct)(aTHX_ a,b,c,d)
-#define Perl_grok_oct DPPP_(my_grok_oct)
-
-UV
-DPPP_(my_grok_oct)(pTHX_ const char *start, STRLEN *len_p, I32 *flags, NV *result)
-{
-    const char *s = start;
-    STRLEN len = *len_p;
-    UV value = 0;
-    NV value_nv = 0;
-
-    const UV max_div_8 = UV_MAX / 8;
-    bool allow_underscores = *flags & PERL_SCAN_ALLOW_UNDERSCORES;
-    bool overflowed = FALSE;
-
-    for (; len-- && *s; s++) {
-         /* gcc 2.95 optimiser not smart enough to figure that this subtraction
-            out front allows slicker code.  */
-        int digit = *s - '0';
-        if (digit >= 0 && digit <= 7) {
-            /* Write it in this wonky order with a goto to attempt to get the
-               compiler to make the common case integer-only loop pretty tight.
-            */
-          redo:
-            if (!overflowed) {
-                if (value <= max_div_8) {
-                    value = (value << 3) | digit;
-                    continue;
-                }
-                /* Bah. We're just overflowed.  */
-                warn("Integer overflow in octal number");
-                overflowed = TRUE;
-                value_nv = (NV) value;
-            }
-            value_nv *= 8.0;
-            /* If an NV has not enough bits in its mantissa to
-             * represent a UV this summing of small low-order numbers
-             * is a waste of time (because the NV cannot preserve
-             * the low-order bits anyway): we could just remember when
-             * did we overflow and in the end just multiply value_nv by the
-             * right amount of 8-tuples. */
-            value_nv += (NV)digit;
-            continue;
-        }
-        if (digit == ('_' - '0') && len && allow_underscores
-            && (digit = s[1] - '0') && (digit >= 0 && digit <= 7))
-            {
-                --len;
-                ++s;
-                goto redo;
-            }
-        /* Allow \octal to work the DWIM way (that is, stop scanning
-         * as soon as non-octal characters are seen, complain only iff
-         * someone seems to want to use the digits eight and nine). */
-        if (digit == 8 || digit == 9) {
-            if (!(*flags & PERL_SCAN_SILENT_ILLDIGIT))
-                warn("Illegal octal digit '%c' ignored", *s);
-        }
-        break;
-    }
-
-    if (   ( overflowed && value_nv > 4294967295.0)
-#if UVSIZE > 4
-        || (!overflowed && value > 0xffffffff  )
-#endif
-        ) {
-        warn("Octal number > 037777777777 non-portable");
-    }
-    *len_p = s - start;
-    if (!overflowed) {
-        *flags = 0;
-        return value;
-    }
-    *flags = PERL_SCAN_GREATER_THAN_UV_MAX;
-    if (result)
-        *result = value_nv;
-    return UV_MAX;
-}
-#endif
-#endif
-
-#if !defined(my_snprintf)
-#if defined(NEED_my_snprintf)
-static int DPPP_(my_my_snprintf)(char * buffer, const Size_t len, const char * format, ...);
-static
-#else
-extern int DPPP_(my_my_snprintf)(char * buffer, const Size_t len, const char * format, ...);
-#endif
-
-#if defined(NEED_my_snprintf) || defined(NEED_my_snprintf_GLOBAL)
-
-#define my_snprintf DPPP_(my_my_snprintf)
-#define Perl_my_snprintf DPPP_(my_my_snprintf)
-
-
-int
-DPPP_(my_my_snprintf)(char *buffer, const Size_t len, const char *format, ...)
-{
-    dTHX;
-    int retval;
-    va_list ap;
-    va_start(ap, format);
-#ifdef HAS_VSNPRINTF
-    retval = vsnprintf(buffer, len, format, ap);
-#else
-    retval = vsprintf(buffer, format, ap);
-#endif
-    va_end(ap);
-    if (retval < 0 || (len > 0 && (Size_t)retval >= len))
-        Perl_croak(aTHX_ "panic: my_snprintf buffer overflow");
-    return retval;
-}
-
-#endif
-#endif
-
-#if !defined(my_sprintf)
-#if defined(NEED_my_sprintf)
-static int DPPP_(my_my_sprintf)(char * buffer, const char * pat, ...);
-static
-#else
-extern int DPPP_(my_my_sprintf)(char * buffer, const char * pat, ...);
-#endif
-
-#if defined(NEED_my_sprintf) || defined(NEED_my_sprintf_GLOBAL)
-
-#define my_sprintf DPPP_(my_my_sprintf)
-#define Perl_my_sprintf DPPP_(my_my_sprintf)
-
-
-int
-DPPP_(my_my_sprintf)(char *buffer, const char* pat, ...)
-{
-    va_list args;
-    va_start(args, pat);
-    vsprintf(buffer, pat, args);
-    va_end(args);
-    return strlen(buffer);
-}
-
-#endif
-#endif
-
-#ifdef NO_XSLOCKS
-#  ifdef dJMPENV
-#    define dXCPT             dJMPENV; int rEtV = 0
-#    define XCPT_TRY_START    JMPENV_PUSH(rEtV); if (rEtV == 0)
-#    define XCPT_TRY_END      JMPENV_POP;
-#    define XCPT_CATCH        if (rEtV != 0)
-#    define XCPT_RETHROW      JMPENV_JUMP(rEtV)
-#  else
-#    define dXCPT             Sigjmp_buf oldTOP; int rEtV = 0
-#    define XCPT_TRY_START    Copy(top_env, oldTOP, 1, Sigjmp_buf); rEtV = Sigsetjmp(top_env, 1); if (rEtV == 0)
-#    define XCPT_TRY_END      Copy(oldTOP, top_env, 1, Sigjmp_buf);
-#    define XCPT_CATCH        if (rEtV != 0)
-#    define XCPT_RETHROW      Siglongjmp(top_env, rEtV)
-#  endif
-#endif
-
-#if !defined(my_strlcat)
-#if defined(NEED_my_strlcat)
-static Size_t DPPP_(my_my_strlcat)(char * dst, const char * src, Size_t size);
-static
-#else
-extern Size_t DPPP_(my_my_strlcat)(char * dst, const char * src, Size_t size);
-#endif
-
-#if defined(NEED_my_strlcat) || defined(NEED_my_strlcat_GLOBAL)
-
-#define my_strlcat DPPP_(my_my_strlcat)
-#define Perl_my_strlcat DPPP_(my_my_strlcat)
-
-
-Size_t
-DPPP_(my_my_strlcat)(char *dst, const char *src, Size_t size)
-{
-    Size_t used, length, copy;
-
-    used = strlen(dst);
-    length = strlen(src);
-    if (size > 0 && used < size - 1) {
-        copy = (length >= size - used) ? size - used - 1 : length;
-        memcpy(dst + used, src, copy);
-        dst[used + copy] = '\0';
-    }
-    return used + length;
-}
-#endif
-#endif
-
-#if !defined(my_strlcpy)
-#if defined(NEED_my_strlcpy)
-static Size_t DPPP_(my_my_strlcpy)(char * dst, const char * src, Size_t size);
-static
-#else
-extern Size_t DPPP_(my_my_strlcpy)(char * dst, const char * src, Size_t size);
-#endif
-
-#if defined(NEED_my_strlcpy) || defined(NEED_my_strlcpy_GLOBAL)
-
-#define my_strlcpy DPPP_(my_my_strlcpy)
-#define Perl_my_strlcpy DPPP_(my_my_strlcpy)
-
-
-Size_t
-DPPP_(my_my_strlcpy)(char *dst, const char *src, Size_t size)
-{
-    Size_t length, copy;
-
-    length = strlen(src);
-    if (size > 0) {
-        copy = (length >= size) ? size - 1 : length;
-        memcpy(dst, src, copy);
-        dst[copy] = '\0';
-    }
-    return length;
-}
-
-#endif
-#endif
-#ifndef PERL_PV_ESCAPE_QUOTE
-#  define PERL_PV_ESCAPE_QUOTE           0x0001
-#endif
-
-#ifndef PERL_PV_PRETTY_QUOTE
-#  define PERL_PV_PRETTY_QUOTE           PERL_PV_ESCAPE_QUOTE
-#endif
-
-#ifndef PERL_PV_PRETTY_ELLIPSES
-#  define PERL_PV_PRETTY_ELLIPSES        0x0002
-#endif
-
-#ifndef PERL_PV_PRETTY_LTGT
-#  define PERL_PV_PRETTY_LTGT            0x0004
-#endif
-
-#ifndef PERL_PV_ESCAPE_FIRSTCHAR
-#  define PERL_PV_ESCAPE_FIRSTCHAR       0x0008
-#endif
-
-#ifndef PERL_PV_ESCAPE_UNI
-#  define PERL_PV_ESCAPE_UNI             0x0100
-#endif
-
-#ifndef PERL_PV_ESCAPE_UNI_DETECT
-#  define PERL_PV_ESCAPE_UNI_DETECT      0x0200
-#endif
-
-#ifndef PERL_PV_ESCAPE_ALL
-#  define PERL_PV_ESCAPE_ALL             0x1000
-#endif
-
-#ifndef PERL_PV_ESCAPE_NOBACKSLASH
-#  define PERL_PV_ESCAPE_NOBACKSLASH     0x2000
-#endif
-
-#ifndef PERL_PV_ESCAPE_NOCLEAR
-#  define PERL_PV_ESCAPE_NOCLEAR         0x4000
-#endif
-
-#ifndef PERL_PV_ESCAPE_RE
-#  define PERL_PV_ESCAPE_RE              0x8000
-#endif
-
-#ifndef PERL_PV_PRETTY_NOCLEAR
-#  define PERL_PV_PRETTY_NOCLEAR         PERL_PV_ESCAPE_NOCLEAR
-#endif
-#ifndef PERL_PV_PRETTY_DUMP
-#  define PERL_PV_PRETTY_DUMP            PERL_PV_PRETTY_ELLIPSES|PERL_PV_PRETTY_QUOTE
-#endif
-
-#ifndef PERL_PV_PRETTY_REGPROP
-#  define PERL_PV_PRETTY_REGPROP         PERL_PV_PRETTY_ELLIPSES|PERL_PV_PRETTY_LTGT|PERL_PV_ESCAPE_RE
-#endif
-
-/* Hint: pv_escape
- * Note that unicode functionality is only backported to
- * those perl versions that support it. For older perl
- * versions, the implementation will fall back to bytes.
- */
-
-#ifndef pv_escape
-#if defined(NEED_pv_escape)
-static char * DPPP_(my_pv_escape)(pTHX_ SV * dsv, char const * const str, const STRLEN count, const STRLEN max, STRLEN * const escaped, const U32 flags);
-static
-#else
-extern char * DPPP_(my_pv_escape)(pTHX_ SV * dsv, char const * const str, const STRLEN count, const STRLEN max, STRLEN * const escaped, const U32 flags);
-#endif
-
-#if defined(NEED_pv_escape) || defined(NEED_pv_escape_GLOBAL)
-
-#ifdef pv_escape
-#  undef pv_escape
-#endif
-#define pv_escape(a,b,c,d,e,f) DPPP_(my_pv_escape)(aTHX_ a,b,c,d,e,f)
-#define Perl_pv_escape DPPP_(my_pv_escape)
-
-
-char *
-DPPP_(my_pv_escape)(pTHX_ SV *dsv, char const * const str,
-  const STRLEN count, const STRLEN max,
-  STRLEN * const escaped, const U32 flags)
-{
-    const char esc = flags & PERL_PV_ESCAPE_RE ? '%' : '\\';
-    const char dq = flags & PERL_PV_ESCAPE_QUOTE ? '"' : esc;
-    char octbuf[32] = "%123456789ABCDF";
-    STRLEN wrote = 0;
-    STRLEN chsize = 0;
-    STRLEN readsize = 1;
-#if defined(is_utf8_string) && defined(utf8_to_uvchr)
-    bool isuni = flags & PERL_PV_ESCAPE_UNI ? 1 : 0;
-#endif
-    const char *pv  = str;
-    const char * const end = pv + count;
-    octbuf[0] = esc;
-
-    if (!(flags & PERL_PV_ESCAPE_NOCLEAR))
-        sv_setpvs(dsv, "");
-
-#if defined(is_utf8_string) && defined(utf8_to_uvchr)
-    if ((flags & PERL_PV_ESCAPE_UNI_DETECT) && is_utf8_string((U8*)pv, count))
-        isuni = 1;
-#endif
-
-    for (; pv < end && (!max || wrote < max) ; pv += readsize) {
-        const UV u =
-#if defined(is_utf8_string) && defined(utf8_to_uvchr)
-                     isuni ? utf8_to_uvchr((U8*)pv, &readsize) :
-#endif
-                             (U8)*pv;
-        const U8 c = (U8)u & 0xFF;
-
-        if (u > 255 || (flags & PERL_PV_ESCAPE_ALL)) {
-            if (flags & PERL_PV_ESCAPE_FIRSTCHAR)
-                chsize = my_snprintf(octbuf, sizeof octbuf,
-                                      "%" UVxf, u);
-            else
-                chsize = my_snprintf(octbuf, sizeof octbuf,
-                                      "%cx{%" UVxf "}", esc, u);
-        } else if (flags & PERL_PV_ESCAPE_NOBACKSLASH) {
-            chsize = 1;
-        } else {
-            if (c == dq || c == esc || !isPRINT(c)) {
-                chsize = 2;
-                switch (c) {
-                case '\\' : /* fallthrough */
-                case '%'  : if (c == esc)
-                                octbuf[1] = esc;
-                            else
-                                chsize = 1;
-                            break;
-                case '\v' : octbuf[1] = 'v'; break;
-                case '\t' : octbuf[1] = 't'; break;
-                case '\r' : octbuf[1] = 'r'; break;
-                case '\n' : octbuf[1] = 'n'; break;
-                case '\f' : octbuf[1] = 'f'; break;
-                case '"'  : if (dq == '"')
-                                octbuf[1] = '"';
-                            else
-                                chsize = 1;
-                            break;
-                default:    chsize = my_snprintf(octbuf, sizeof octbuf,
-                                pv < end && isDIGIT((U8)*(pv+readsize))
-                                ? "%c%03o" : "%c%o", esc, c);
-                }
-            } else {
-                chsize = 1;
-            }
-        }
-        if (max && wrote + chsize > max) {
-            break;
-        } else if (chsize > 1) {
-            sv_catpvn(dsv, octbuf, chsize);
-            wrote += chsize;
-        } else {
-            char tmp[2];
-            my_snprintf(tmp, sizeof tmp, "%c", c);
-            sv_catpvn(dsv, tmp, 1);
-            wrote++;
-        }
-        if (flags & PERL_PV_ESCAPE_FIRSTCHAR)
-            break;
-    }
-    if (escaped != NULL)
-        *escaped= pv - str;
-    return SvPVX(dsv);
-}
-
-#endif
-#endif
-
-#ifndef pv_pretty
-#if defined(NEED_pv_pretty)
-static char * DPPP_(my_pv_pretty)(pTHX_ SV * dsv, char const * const str, const STRLEN count, const STRLEN max, char const * const start_color, char const * const end_color, const U32 flags);
-static
-#else
-extern char * DPPP_(my_pv_pretty)(pTHX_ SV * dsv, char const * const str, const STRLEN count, const STRLEN max, char const * const start_color, char const * const end_color, const U32 flags);
-#endif
-
-#if defined(NEED_pv_pretty) || defined(NEED_pv_pretty_GLOBAL)
-
-#ifdef pv_pretty
-#  undef pv_pretty
-#endif
-#define pv_pretty(a,b,c,d,e,f,g) DPPP_(my_pv_pretty)(aTHX_ a,b,c,d,e,f,g)
-#define Perl_pv_pretty DPPP_(my_pv_pretty)
-
-
-char *
-DPPP_(my_pv_pretty)(pTHX_ SV *dsv, char const * const str, const STRLEN count,
-  const STRLEN max, char const * const start_color, char const * const end_color,
-  const U32 flags)
-{
-    const U8 dq = (flags & PERL_PV_PRETTY_QUOTE) ? '"' : '%';
-    STRLEN escaped;
-
-    if (!(flags & PERL_PV_PRETTY_NOCLEAR))
-        sv_setpvs(dsv, "");
-
-    if (dq == '"')
-        sv_catpvs(dsv, "\"");
-    else if (flags & PERL_PV_PRETTY_LTGT)
-        sv_catpvs(dsv, "<");
-
-    if (start_color != NULL)
-        sv_catpv(dsv, D_PPP_CONSTPV_ARG(start_color));
-
-    pv_escape(dsv, str, count, max, &escaped, flags | PERL_PV_ESCAPE_NOCLEAR);
-
-    if (end_color != NULL)
-        sv_catpv(dsv, D_PPP_CONSTPV_ARG(end_color));
-
-    if (dq == '"')
-        sv_catpvs(dsv, "\"");
-    else if (flags & PERL_PV_PRETTY_LTGT)
-        sv_catpvs(dsv, ">");
-
-    if ((flags & PERL_PV_PRETTY_ELLIPSES) && escaped < count)
-        sv_catpvs(dsv, "...");
-
-    return SvPVX(dsv);
-}
-
-#endif
-#endif
-
-#ifndef pv_display
-#if defined(NEED_pv_display)
-static char * DPPP_(my_pv_display)(pTHX_ SV * dsv, const char * pv, STRLEN cur, STRLEN len, STRLEN pvlim);
-static
-#else
-extern char * DPPP_(my_pv_display)(pTHX_ SV * dsv, const char * pv, STRLEN cur, STRLEN len, STRLEN pvlim);
-#endif
-
-#if defined(NEED_pv_display) || defined(NEED_pv_display_GLOBAL)
-
-#ifdef pv_display
-#  undef pv_display
-#endif
-#define pv_display(a,b,c,d,e) DPPP_(my_pv_display)(aTHX_ a,b,c,d,e)
-#define Perl_pv_display DPPP_(my_pv_display)
-
-
-char *
-DPPP_(my_pv_display)(pTHX_ SV *dsv, const char *pv, STRLEN cur, STRLEN len, STRLEN pvlim)
-{
-    pv_pretty(dsv, pv, cur, pvlim, NULL, NULL, PERL_PV_PRETTY_DUMP);
-    if (len > cur && pv[cur] == '\0')
-        sv_catpvs(dsv, "\\0");
-    return SvPVX(dsv);
-}
-
-#endif
-#endif
-
-#endif /* _P_P_PORTABILITY_H_ */
-
-/* End of File ppport.h */
diff --git a/script/mwrap-perl b/script/mwrap-perl
deleted file mode 100644
index 82629b4..0000000
--- a/script/mwrap-perl
+++ /dev/null
@@ -1,97 +0,0 @@
-#!/usr/bin/perl -w
-# Copyright (C) mwrap hackers <mwrap-perl@80x24.org>
-# License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt>
-use v5.12;
-use Devel::Mwrap;
-my ($so) = grep(m!/Mwrap\.so\z!, @DynaLoader::dl_shared_objects);
-defined($so) or die 'Mwrap.so not loaded';
-my $cur = $ENV{LD_PRELOAD};
-if (!@ARGV || ($ARGV[0] // '') =~ /\A(?:-h|--help)\z/) {
-        require Pod::Usage;
-        Pod::Usage::pod2usage(@ARGV ? 0 : 1);
-}
-if (defined $cur) {
-        my @cur = split(/[: \t]+/, $cur);
-        if (!grep(/\A\Q$so\E\z/, @cur)) {
-                # drop old redundant versions
-                my @keep = grep(!m!/Mwrap\.so$!, @cur);
-                $ENV{LD_PRELOAD} = join(':', $so, @keep);
-        }
-} else {
-        $ENV{LD_PRELOAD} = $so;
-}
-exec @ARGV;
-__END__
-=head1 NAME
-
-mwrap-perl - run any command under mwrap
-
-=head1 SYNOPSIS
-
-  # to trace a long-running program and access it via $DIRECTORY/$PID.sock:
-  MWRAP=socket_dir:$DIRECTORY mwrap-perl COMMAND
-
-  # to trace a short-lived command and dump its output to a log:
-  MWRAP=dump_path:$FILENAME mwrap-perl COMMAND
-
-=head1 DESCRIPTION
-
-mwrap-perl is a command-line to automatically add Mwrap.so as an
-LD_PRELOAD for any command.  It will resolve malloc-family calls
-to a Perl file and line number, and it can also provide a backtrace
-of native (C/C++) functions for non-Perl programs.
-
-=head1 ENVIRONMENT
-
-C<MWRAP> is the only environment variable read.  It contains multiple
-options delimited by C<,> with names and values delimited by C<:>
-
-=item socket_dir:$DIRECTORY
-
-This launches an embedded HTTP server in each process and binds it
-to C<$DIRECTORY/$PID.sock>.  C<curl --unix-socket $DIRECTORY/$PID.sock>
-or L<mwrap-rproxy(1p)> may be used to access various endpoints in
-the HTTP server.
-
-=item: bt:$DEPTH
-
-The backtrace depth for L<backtrace(3)> in addition to the Perl
-file and line number where C<$DEPTH> is a non-negative number.
-
-The maximum allowed value is 32, though values of 5 or less are
-typically useful.  Increasing this to even 2 or 3 can significantly
-increase the amount of memory mwrap (and liburcu) itself uses.
-
-This is only useful in conjunction with C<socket_dir>
-
-Default: 0
-
-=item dump_path:$FILENAME
-
-Dumps the output
-
-        total_bytes        call_count        location
-
-In the future, dumping to a self-describing CSV will be supported
-
-=back
-
-=head1 CONTACT
-
-Feedback welcome via plain-text mail to L<mailto:mwrap-perl@80x24.org>
-
-Mail archives are hosted at L<https://80x24.org/mwrap-perl/>
-
-=head1 COPYRIGHT
-
-Copyright all contributors L<mailto:mwrap-perl@80x24.org>
-
-License: GPL-3.0+ L<https://www.gnu.org/licenses/gpl-3.0.txt>
-
-Source code is at L<https://80x24.org/mwrap-perl.git/>
-
-=head1 SEE ALSO
-
-L<mwrap-rproxy(1)>, L<Devel::Mwrap(3pm)>
-
-=cut
diff --git a/script/mwrap-rproxy b/script/mwrap-rproxy
deleted file mode 100644
index 2498bc3..0000000
--- a/script/mwrap-rproxy
+++ /dev/null
@@ -1,115 +0,0 @@
-#!perl -w
-# Copyright (C) mwrap hackers <mwrap-perl@80x24.org>
-# License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt>
-# thin wrapper for Devel::Mwrap::Rproxy
-use v5.12; # strict
-eval { require Plack::Runner } or die "Plack not installed: $@\n";
-use Getopt::Long qw(:config no_ignore_case no_auto_abbrev pass_through);
-my $usage = "$0 --socket-dir=/path/to/socket-dir [PLACKUP_OPTIONS]\n";
-my %opt = (deflate => 1);
-GetOptions(\%opt, 'socket-dir=s', 'deflate!', 'help|h') or do {
-        require Pod::Usage; Pod::Usage::pod2usage(1);
-};
-if ($opt{help}) { require Pod::Usage; Pod::Usage::pod2usage(0) }
-my $socket_dir = delete $opt{'socket-dir'};
-$socket_dir //= ($ENV{MWRAP} // '') =~ m!\bsocket_dir:([^,]+)! ? $1 : undef;
-$socket_dir // die $usage;
-require Devel::Mwrap::Rproxy;
-my $rproxy = Devel::Mwrap::Rproxy->new($socket_dir);
-my $app = sub { $rproxy->call(@_) };
-my $runner = Plack::Runner->new;
-$runner->parse_options(@ARGV);
-if (($ENV{LISTEN_PID} // 0) == $$) {
-        my $fds = $ENV{LISTEN_FDS} // '';
-        die "only one LISTEN_FDS=1 supported (got `$fds')\n" if $fds ne '1';
-        if (open(my $s, '<&=', 3)) {
-                my $prev_was_blocking = $s->blocking(1);
-                warn <<"" unless $prev_was_blocking;
-Inherited socket (fd=3) is non-blocking, making it blocking.
-
-                bless $s, 'IO::Socket::INET';
-                $runner->set_options(listen_sock => $s);
-        }
-}
-if ($opt{deflate} && eval { require Plack::Middleware::Deflater } and !$@) {
-        $app = Plack::Middleware::Deflater->wrap($app);
-}
-
-# ensure mwrap_dtor() runs if running under mwrap-perl, ourselves
-sub sigexit { exit 0 }
-$SIG{$_} = \&sigexit for (qw(INT TERM));
-
-$runner->run($app);
-__END__
-=head1 NAME
-
-mwrap-rproxy - reverse proxy for embedded per-process mwrap httpd
-
-=head1 SYNOPSIS
-
-  # start the long-running COMMAND you wish to trace:
-  MWRAP=socket_dir:$DIRECTORY mwrap-perl COMMAND
-
-  # in a different terminal, point mwrap-proxy to the mwrap-perl socket_dir
-  mwrap-rproxy --socket-dir=$DIRECTORY -l 127.0.0.1:8080
-
-  # open http://127.0.0.1:8080/ in your favorite web browser:
-  w3m http://127.0.0.1:8080/
-
-=head1 DESCRIPTION
-
-B<mwrap-rproxy> is a PSGI reverse proxy to provide access
-via TCP to the native, Unix-socket-only httpd embedded inside
-mwrap core.  It provides a listing of process IDs of each process
-traced via mwrap.
-
-B<mwrap-rproxy> does not have a hard dependency on mwrap-perl itself,
-it exists to provide a convenient interface to programs being
-traced by mwrap-perl.
-
-=head1 OPTIONS
-
-=over 4
-
-=item --socket-dir=DIRECTORY
-
-If unset, it will attempt to parse C<socket_dir:> from the C<MWRAP>
-environment (see L<mwrap-perl(1p)>).
-
-=item --no-deflate
-
-L<Plack::Middleware::Deflater(3pm)> is loaded by default if available.
-Using C<--no-deflate> will save CPU cycles at the expense of bandwidth.
-
-=back
-
-Additionally, all options in L<plackup(1p)> are supported.  Notably,
-C<-l>/C<--listen> and C<--path=/prefix> may be useful.
-
-=head1 ENVIRONMENT
-
-mwrap-rproxy supports systemd (and compatible) socket activation via
-C<LISTEN_PID> and C<LISTEN_FDS> variables.  See L<systemd.socket(5)>
-and L<sd_listen_fds(3)>.
-
-C<PLACK_ENV> is also supported as described by L<plackup(1p)>
-
-=head1 CONTACT
-
-Feedback welcome via plain-text mail to L<mailto:mwrap-perl@80x24.org>
-
-Mail archives are hosted at L<https://80x24.org/mwrap-perl/>
-
-=head1 COPYRIGHT
-
-Copyright all contributors L<mailto:mwrap-perl@80x24.org>
-
-License: GPL-3.0+ L<https://www.gnu.org/licenses/gpl-3.0.txt>
-
-Source code is at L<https://80x24.org/mwrap-perl.git/>
-
-=head1 SEE ALSO
-
-L<mwrap-perl(1p)>
-
-=cut
diff --git a/t/httpd-unit.t b/t/httpd-unit.t
deleted file mode 100644
index e16be1d..0000000
--- a/t/httpd-unit.t
+++ /dev/null
@@ -1,116 +0,0 @@
-#!perl -w
-# Copyright (C) mwrap hackers <mwrap-perl@80x24.org>
-# License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt>
-use v5.12;
-use autodie;
-use Test::More;
-use ExtUtils::CBuilder;
-use File::Spec;
-use File::Temp;
-use File::Path;
-my ($n) = (__FILE__ =~ m!/([^/]+)\.t\z!);
-open my $fh, '<', 'build.env';
-my %build_env = map { chomp; ( split(/=/, $_, 2) ) } (<$fh>);
-my $tmp = File::Temp->newdir("$n-XXXX");
-my $err = "$tmp/err.log";
-open my $olderr, '+>&', *STDERR{IO};
-my $end_err = sub {
-        STDERR->autoflush(1);
-        open STDERR, '+>&', $olderr;
-        open my $eh, '+<', $err;
-        local $/;
-        my $buf = <$eh> // BAIL_OUT "$!";
-        truncate($eh, 0);
-        diag "err=$buf" if $ENV{V};
-        $buf;
-};
-
-my @vg = split(/ /, $ENV{VALGRIND} // '');
-
-# using predictable pathnames but outside of working directory.
-# This gives ccache-friendliness while staying clear of MakeMaker
-# aggressively trying to include every *.c file
-my $d = File::Spec->tmpdir . "/$>.mwrap-test";
-if (!-d $d) {
-        diag "# mkdir $d";
-        mkdir($d, 0700);
-}
-my $f = "$d/$n.c";
-open $fh, '>', $f;
-print $fh <<C;
-#include <sys/types.h>
-#include <unistd.h>
-#define getpid() my_getpid()
-static pid_t my_getpid(void)
-{
-        return TEST_PID;
-}
-#include "mwrap_core.h"
-
-int main(int argc, const char *argv[])
-{
-        struct mw_h1d h1d;
-        return h1d_init(&h1d, argv[1]);
-}
-C
-close $fh;
-my $TEST_PID = 10;
-my $cb = ExtUtils::CBuilder->new(quiet => $ENV{V} ? 0 : 1);
-my ($obj, $exe);
-{
-        my %be = %build_env;
-        $be{extra_compiler_flags} .= " -DTEST_PID=$TEST_PID -Wall ";
-        $obj = $cb->compile(source => $f, %be);
-        $exe = $cb->link_executable(exe_file => "$d/$n", objects => $obj, %be);
-}
-open STDERR, '>', $err;
-is(system(@vg, $exe, "socket_dir:$d"), 0, "$exe");
-is($end_err->(), '', 'silence is golden');
-
-my $s = "$d/$TEST_PID.sock";
-ok(-S $s, 'sock created');
-unlink($s);
-
-mkdir($s);
-open STDERR, '>', $err;
-isnt(system(@vg, $exe, "socket_dir:$d"), 0, "won't clobber dir");
-like($end_err->(), qr/unlink/, 'unlink fails for dir');
-rmdir($s);
-
-open STDERR, '>', $err;
-is(system(@vg, $exe, "socket_dir:$d/"), 0, "listen again");
-is($end_err->(), '', 'silence is golden');
-
-{
-        my $t_mkdir = "$d/mkdir";
-        File::Path::rmtree($t_mkdir) if -d $t_mkdir;
-        open STDERR, '>', $err;
-        is(system(@vg, $exe, "socket_dir:$t_mkdir"), 0, "listen in new dir");
-        is($end_err->(), '', 'listened quietly on extra dir');
-        File::Path::rmtree($t_mkdir);
-}
-
-ok(-S $s, 'socket untouched');
-open STDERR, '>', $err;
-isnt(system(@vg, $exe, "socket_dir:$s"), 0, "listen dir on socket fails");
-like($end_err->(), qr/stat.*directory/, 'stat failure shown');
-
-# check for fencepost errors
-my $len;
-if ($^O eq 'linux') { $len = 108 }
-elsif ($^O eq 'freebsd') { $len = 104 }
-SKIP: {
-        skip "length unknown on $^O OS", 2 if !defined($len);
-        $len -= length("$tmp");
-        $len -= length("\0//$TEST_PID.sock");
-        my $max = "$tmp/".('x'x$len);
-        open STDERR, '>', $err;
-        is(system(@vg, $exe, "socket_dir:$max"), 0, "listen dir on max");
-        is($end_err->(), '', 'nothing in stderr on max');
-
-        open STDERR, '>', $err;
-        isnt(system(@vg, $exe, "socket_dir:$max+"), 0, "listen dir too long");
-        isnt($end_err->(), '', 'stderr contains error when too long');
-}
-
-done_testing;
diff --git a/t/httpd.t b/t/httpd.t
index 7746837..9a0fae6 100644
--- a/t/httpd.t
+++ b/t/httpd.t
@@ -11,8 +11,10 @@ my $f1 = "$mwrap_tmp/f1";
 my $f2 = "$mwrap_tmp/f2";
 mkfifo($f1, 0600) // plan(skip_all => "mkfifo: $!");
 mkfifo($f2, 0600) // plan(skip_all => "mkfifo: $!");
-my $pid = mwrap_run('httpd test', $env, '-e',
-        "open my \$f1, '>', '$f1'; close \$f1; open my \$f2, '<', '$f2'");
+my $src = $mwrap_src ? # $mwrap_src is Perl-only, Ruby otherwise
+        "open my \$f1, '>', '$f1'; close \$f1; open my \$f2, '<', '$f2'" :
+        "File.open('$f1', 'w').close; File.open('$f2', 'r').close";
+my $pid = mwrap_run('httpd test', $env, '-e', $src);
 my $spid;
 my $mw_exit;
 my $cleanup = sub {
@@ -85,9 +87,21 @@ SKIP: {
 }
 
 SKIP: {
+        my (@rproxy, @missing);
+        if (-e 'script/mwrap-rproxy') { # Perl version
+                @rproxy = ($^X, '-w', './blib/script/mwrap-rproxy');
+        } else {
+                my $exe = `which mwrap-rproxy`;
+                if ($? == 0 && defined($exe)) {
+                        chomp($rproxy[0] = $exe);
+                } else {
+                        push @missing, 'mwrap-rproxy';
+                }
+        }
         for my $m (qw(Plack::Util HTTP::Tiny)) {
-                eval "require $m" or skip "$m missing", 1;
+                eval "require $m" or push(@missing, $m);
         }
+        skip join(', ', @missing).' missing', 1 if @missing;
         my $srv = IO::Socket::INET->new(LocalAddr => '127.0.0.1',
                                 ReuseAddr => 1, Proto => 'tcp',
                                 Type => SOCK_STREAM,
@@ -103,8 +117,7 @@ SKIP: {
                 }
                 local $ENV{PLACK_ENV} = 'deployment' if !$ENV{V};
                 no warnings 'exec';
-                exec $^X, '-w', './blib/script/mwrap-rproxy',
-                        "--socket-dir=$mwrap_tmp";
+                exec @rproxy, "--socket-dir=$mwrap_tmp";
                 _exit(1);
         }
         my $http = HTTP::Tiny->new;
@@ -135,19 +148,28 @@ SKIP: {
 
 SKIP: {
         skip 'no reset w/o curl --unix-socket', 1 if !$curl_unix;
-
+        my ($sqlite_v) = (`sqlite3 --version` =~ /([\d+\.]+)/);
+        if ($?) {
+                diag 'sqlite3 missing or broken';
+                $sqlite_v = 0;
+        } else {
+                my @v = split(/\./, $sqlite_v);
+                $sqlite_v = ($v[0] << 16) | ($v[1] << 8) | $v[2];
+                diag 'sqlite_v='.sprintf('0x%x', $sqlite_v);
+        }
         $rc = system(@curl, "http://0/$pid/each/100.csv");
         is($rc, 0, '.csv retrieved') or skip 'CSV failed', 1;
         my $db = "$mwrap_tmp/t.sqlite3";
-        $rc = system(qw(sqlite3), $db, ".import --csv $cout mwrap_each");
-        if ($rc == -1) {
-                diag 'sqlite3 missing';
-        } else {
+
+        if ($sqlite_v >= 0x32000) {
+                $rc = system(qw(sqlite3), $db,".import --csv $cout mwrap_each");
                 is($rc, 0, 'sqlite3 import');
                 my $n = `sqlite3 $db 'SELECT COUNT(*) FROM mwrap_each'`;
                 is($?, 0, 'sqlite3 count');
                 my $exp = split(/\n/, slurp($cout));
                 is($n + 1, $exp, 'imported all rows into sqlite');
+        } else {
+                diag "sqlite 3.32.0+ needed for `.import --csv'";
         }
 
         $rc = system(@curl, qw(-d x=y), "http://0/$pid/reset");
diff --git a/t/mwrap.t b/t/mwrap.t
deleted file mode 100644
index 6f99715..0000000
--- a/t/mwrap.t
+++ /dev/null
@@ -1,177 +0,0 @@
-#!perl -w
-# Copyright (C) mwrap hackers <mwrap-perl@80x24.org>
-# License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt>
-use v5.12;
-BEGIN { require './t/test_common.perl' };
-use_ok 'Devel::Mwrap';
-my $dump = "$mwrap_tmp/dump";
-
-{
-        my $env = { MWRAP => "dump_path:$dump,dump_min:10000" };
-        my $nr = 1000;
-        mwrap_run('dump test', $env, '-e', '$x = "hello world" x '.$nr);
-        ok(-s $dump, "dump file written to");
-        my $s = slurp($dump);
-        truncate($dump, 0);
-        my $re = qr/([0-9]+)[ \t]+([0-9]+)[ \t]+-e:1[ \t]*\n/sm;
-        my ($bytes, $n);
-        if ($s =~ $re) {
-                ($bytes, $n) = ($1, $2);
-                ok($bytes >= (length('hello world') * $nr),
-                        "counted 'hello world' x $nr");
-                ok($n >= 1, 'allocation counted');
-        } else {
-                fail("$s failed to match $re");
-        }
-}
-
-SKIP: { # C++ program which uses malloc via "new"
-        my $exp = `cmake -h`;
-        skip 'cmake missing', 2 if $?;
-        skip "`cmake -h' gave no output", 2 unless $exp =~ /\S/s;
-        mwrap_run('cmake (C++ new)', {}, '-e', 'system(qw(cmake -h)); exit $?');
-        my $res = slurp($mwrap_out);
-        is($res, $exp, "`cmake -h' works");
-        diag slurp($mwrap_err);
-};
-
-{
-        mwrap_run('total_bytes*', {}, '-e', <<'E1');
-my $A = Devel::Mwrap::total_bytes_allocated();
-my $f = Devel::Mwrap::total_bytes_freed();
-print("$A - $f\n");
-E1
-        my $o = slurp($mwrap_out);
-        like($o, qr/^([0-9]+) - ([0-9]+)\n/s, 'got allocated & freed bytes');
-}
-
-{
-        mwrap_run('source location', {}, 't/source_location.perl');
-        mwrap_run('source location via -d:', {},
-                '-d:Mwrap', 't/source_location.perl');
-}
-
-mwrap_run('Devel::Mwrap::each', {}, '-e', <<'EOF');
-open my $zero, '<', '/dev/zero' or die "open /dev/zero: $!";
-my $nbytes = 1024 * 512;
-sysread($zero, my $before, $nbytes);
-my (@keep, @uargs);
-my $uarg = 'user-arg';
-eval {
-        Devel::Mwrap::each(0, sub {
-                my $ua = shift;
-                push @uargs, $ua;
-                die "died in each";
-                push @keep, @_;
-        }, $uarg) };
-"$@" =~ /died in each at -e line \d+/ or die "did not propagate die in each";
-scalar(@keep) == 0 or die "nothing if died in sub";
-$uarg eq join('-', @uargs) or die "uarg passed to sub";
-my %h;
-my $iter;
-my $arg = "FOO";
-Devel::Mwrap::each(1, sub {
-        my ($argh, $src_loc, @more) = @_;
-        my $name = $src_loc->name;
-        $h{$name} = $src_loc;
-        sysread($zero, my $iter, $nbytes);
-        die 'extra args from ::each' if @more;
-        die "arg mismatch $arg / $argh" if $argh ne $arg;
-}, $arg);
-my $src_loc = $h{"-e:3"} or die "missing src_loc for -e:3";
-$src_loc->total >= $nbytes or die "allocated <= $nbytes";
-$src_loc = Devel::Mwrap::get("-e:8");
-if ($src_loc && $src_loc->total >= $nbytes) {
-        die "large allocation inside :each should not be tracked";
-}
-my $nr = 0;
-Devel::Mwrap::each($nbytes, sub {
-        $foo += shift;
-        push @keep, @_;
-}, 1);
-scalar(@keep) == 1 or die "got multiple matches for > $nbytes";
-$keep[0]->name eq '-e:3' or die "unexpected location for > $nbytes";
-@keep = ();
-Devel::Mwrap::reset();
-Devel::Mwrap::each($nbytes, sub { push @keep, @_ });
-scalar(@keep) == 0 or die "::reset did not work";
-EOF
-
-mwrap_run('Devel::Mwrap::SrcLoc::each', {}, '-e', <<'EOF');
-open my $zero, '<', '/dev/zero' or die "open /dev/zero: $!";
-my @keep;
-my $nr = 10;
-my $nbytes = 1024 * 10;
-sub do_read () {
-        sysread($zero, my $buf, $nbytes);
-        # this forces us to allocate a new buf with every call
-        pop @keep;
-        push @keep, $buf;
-}
-for (1..$nr) { do_read() }
-my $loc = Devel::Mwrap::get('-e:6');
-$loc && $loc->total >= ($nbytes * $nr) or die "wrong line or bad stats";
-my $ml = $loc->mean_lifespan;
-$ml >= 0.0 or die "mean_lifespan broken";
-my @sl_each;
-$loc->each($nbytes, sub { shift; push @sl_each, \@_ });
-my $n = scalar(@sl_each);
-$n == 1 or die "SrcLoc::each returned unexpected: $n";
-$sl_each[0]->[0] >= $nbytes or die "$sl_each[0]->[0] < $nbytes";
-
-my $age_before = $sl_each[0]->[1];
-$nbytes = 1024 * 1024 * 8;
-do_read() until Devel::Mwrap::current_age() > ($age_before + $nbytes);
-@sl_each = ();
-$loc->each($nbytes, sub { shift; push @sl_each, \@_ });
-$n = scalar(@sl_each);
-$n == 1 or die "SrcLoc::each returned unexpected: $n";
-$sl_each[0]->[0] >= $nbytes or die "$sl_each[0]->[0] < $nbytes";
-my $age_after = $sl_each[0]->[1];
-$age_after >= $age_before or die "age did not increment";
-EOF
-diag slurp($mwrap_out);
-
-is(Devel::Mwrap::quiet(1), 0, 'was not quiet, before');
-is(Devel::Mwrap::quiet(0), 1, 'was quiet, before');
-
-SKIP: {
-        eval { require Inline::C } or skip 'Inline::C not available', 1;
-        $ENV{TEST_ALIASES} or skip 'TEST_ALIASES unset', 1;
-        my $c_src = <<'EOM';
-#include <stdlib.h>
-void cfree(void *); /* lold glibc version */
-int test_aliases()
-{
-        size_t i;
-        void *p;
-        for (i = 0; i < 100; i++) {
-                if (i % 3 == 0)
-                        p = aligned_alloc(64, i);
-                else
-                        p = malloc(i);
-                if (i % 2 == 0)
-                        cfree(p);
-                else
-                        free(p);
-        }
-        return 3;
-}
-EOM
-        eval <<'EOM';
-use Inline C => $c_src, BUILD_NOISY => 1
-EOM
-        BAIL_OUT "cannot build $@" if $@;
-        is(test_aliases(), 3,
-                'aligned_alloc + cfree function ran w/o crashing');
-};
-
-is(Devel::Mwrap::bt_depth(), 0, 'default bt depth is zero');
-is(Devel::Mwrap::bt_depth(5), 5, 'set depth to reasonable level');
-is(Devel::Mwrap::bt_depth(), 5, 'depth stays at 5');
-is(Devel::Mwrap::bt_depth(500), 32, 'depth clamped to 32 when 500 attempted');
-is(Devel::Mwrap::bt_depth(), 32, 'depth stayed clamped at 32');
-is(Devel::Mwrap::bt_depth(undef), 32, 'depth stayed clamped at 32');
-is(Devel::Mwrap::bt_depth(-1), 32, 'depth stayed clamped at 32');
-
-done_testing;
diff --git a/t/source_location.perl b/t/source_location.perl
deleted file mode 100644
index ed81ed8..0000000
--- a/t/source_location.perl
+++ /dev/null
@@ -1,9 +0,0 @@
-use Devel::Mwrap;
-my $foo = ('hello world' x 10000);
-my $k = __FILE__ . ":2";
-my $loc = Devel::Mwrap::get($k) or die;
-$loc->name eq $k or die;
-$loc->total >= 10000 or die;
-$loc->allocations >= 1 or die;
-$loc->frees >= 0 or die;
-exit 0;
diff --git a/t/test_common.perl b/t/test_common.perl
index 8827362..3a073cf 100644
--- a/t/test_common.perl
+++ b/t/test_common.perl
@@ -6,8 +6,9 @@ use v5.12;
 use parent qw(Exporter);
 use Test::More;
 use File::Temp 0.19 (); # 0.19 for ->newdir
-our $mwrap_src = slurp('blib/script/mwrap-perl');
-our $mwrap_tmp = File::Temp->newdir('mwrap-perl-XXXX', TMPDIR => 1);
+our $mwrap_src;
+$mwrap_src = slurp('blib/script/mwrap-perl') if -e 'script/mwrap-perl';
+our $mwrap_tmp = File::Temp->newdir('mwrap-XXXX', TMPDIR => 1);
 our $mwrap_out = "$mwrap_tmp/out";
 our $mwrap_err = "$mwrap_tmp/err";
 our @EXPORT = qw(mwrap_run slurp $mwrap_err $mwrap_out $mwrap_src $mwrap_tmp);
@@ -20,9 +21,6 @@ sub slurp {
 
 sub mwrap_run {
         my ($msg, $env, @args) = @_;
-        unless (grep(/\A-.+\bMwrap\b/, @args)) {
-                unshift @args, '-MDevel::Mwrap';
-        }
         my $pid = fork;
         if ($pid == 0) {
                 while (my ($k, $v) = each %$env) {
@@ -30,8 +28,16 @@ sub mwrap_run {
                 }
                 open STDERR, '>', $mwrap_err or die "open: $!";
                 open STDOUT, '>', $mwrap_out or die "open: $!";
-                @ARGV = ($^X, @args);
-                eval $mwrap_src;
+                if (defined $mwrap_src) {
+                        unless (grep(/\A-.+\bMwrap\b/, @args)) {
+                                unshift @args, '-MDevel::Mwrap';
+                        }
+                        @ARGV = ($^X, @args);
+                        eval $mwrap_src;
+                } else {
+                        my $ruby = $ENV{RUBY} // 'ruby';
+                        exec $ruby, '-Ilib', 'bin/mwrap', $ruby, @args;
+                }
                 die "fail: $! ($@)";
         }
         if (defined(wantarray)) {
diff --git a/test/test_mwrap.rb b/test/test_mwrap.rb
new file mode 100644
index 0000000..29bbdd2
--- /dev/null
+++ b/test/test_mwrap.rb
@@ -0,0 +1,292 @@
+# frozen_string_literal: true
+# Copyright (C) mwrap hackers <mwrap-public@80x24.org>
+# License: GPL-2.0+ <https://www.gnu.org/licenses/gpl-2.0.txt>
+require 'test/unit'
+require 'mwrap'
+require 'rbconfig'
+require 'tempfile'
+
+class TestMwrap < Test::Unit::TestCase
+  RB = "#{RbConfig::CONFIG['bindir']}/#{RbConfig::CONFIG['RUBY_INSTALL_NAME']}"
+
+  mwrap_so = $".grep(%r{/mwrap\.so\z})[0]
+  env = ENV.to_hash
+  cur = env['LD_PRELOAD']
+  env['LD_PRELOAD'] = cur ? "#{mwrap_so}:#{cur}".freeze : mwrap_so
+  @@env = env.freeze
+  inc = File.dirname(mwrap_so)
+  @@cmd = %W(#{RB} -w --disable=gems -I#{inc} -rmwrap).freeze
+
+  def test_mwrap_preload
+    cmd = @@cmd + %w(
+      -e ("helloworld"*1000).clear
+      -e Mwrap.dump
+    )
+    Tempfile.create('junk') do |tmp|
+      tmp.sync = true
+      res = system(@@env, *cmd, err: tmp)
+      assert res, $?.inspect
+      tmp.rewind
+      lines = tmp.readlines
+      line_1 = lines.grep(/\s-e:1\b/)[0].strip
+      bytes = line_1.split(/\s+/)[0].to_i
+      assert_operator bytes, :>=, 10001
+    end
+  end
+
+  def test_dump_via_destructor
+    env = @@env.dup
+    env['MWRAP'] = 'dump_fd:5'
+    cmd = @@cmd + %w(-e ("0"*10000).clear)
+    Tempfile.create('junk') do |tmp|
+      tmp.sync = true
+      res = system(env, *cmd, { 5 => tmp })
+      assert res, $?.inspect
+      tmp.rewind
+      assert_match(/\b1\d{4}\s+[1-9]\d*\s+-e:1$/, tmp.read)
+
+      env['MWRAP'] = 'dump_fd:1,dump_min:10000'
+      tmp.rewind
+      tmp.truncate(0)
+      res = system(env, *cmd, { 1 => tmp })
+      assert res, $?.inspect
+      tmp.rewind
+      assert_match(/\b1\d{4}\s+[1-9]\d*\s+-e:1$/, tmp.read)
+
+      tmp.rewind
+      tmp.truncate(0)
+      env['MWRAP'] = "dump_path:#{tmp.path},dump_min:10000"
+      res = system(env, *cmd)
+      assert res, $?.inspect
+      assert_match(/\b1\d{4}\s+[1-9]\d*\s+-e:1$/, tmp.read)
+    end
+  end
+
+  def test_cmake
+    begin
+      exp = `cmake -h`
+    rescue Errno::ENOENT
+      warn 'cmake missing'
+      return
+    end
+    assert_not_predicate exp.strip, :empty?
+    env = @@env.merge('MWRAP' => 'dump_fd:1')
+    out = IO.popen(env, %w(cmake -h), &:read)
+    assert out.start_with?(exp), 'original help exists'
+    assert_not_equal exp, out, 'includes dump output'
+    dump = out.delete_prefix(exp)
+    assert_match(/\b0x[a-f0-9]+\b/s, dump, 'dump output has addresses')
+  end
+
+  def test_clear
+    cmd = @@cmd + %w(
+      -e ("0"*10000).clear
+      -e Mwrap.clear
+      -e ("0"*20000).clear
+      -e Mwrap.dump($stdout,9999)
+    )
+    Tempfile.create('junk') do |tmp|
+      tmp.sync = true
+      res = system(@@env, *cmd, { 1 => tmp })
+      assert res, $?.inspect
+      tmp.rewind
+      buf = tmp.read
+      assert_not_match(/\s+-e:1$/, buf)
+      assert_match(/\b2\d{4}\s+[0-9]\d*\s+-e:3$/, buf)
+    end
+  end
+
+  # make sure we don't break commands spawned by an mwrap-ed Ruby process:
+  def test_non_ruby_exec
+    IO.pipe do |r, w|
+      th = Thread.new { r.read }
+      Tempfile.create('junk') do |tmp|
+        tmp.sync = true
+        env = @@env.merge('MWRAP' => "dump_path:#{tmp.path}")
+        cmd = %w(perl -e print("HELLO_WORLD"))
+        res = system(env, *cmd, out: w)
+        w.close
+        assert res, $?.inspect
+        assert_match(/0x[a-f0-9]+\b/, tmp.read)
+      end
+      assert_equal "HELLO_WORLD", th.value
+    end
+  end
+
+  # some URCU flavors use USR1, ensure the one we choose does not
+  def test_sigusr1_works
+    cmd = @@cmd + %w(
+      -e STDOUT.sync=true
+      -e trap(:USR1){p("HELLO_WORLD")}
+      -e END{Mwrap.dump}
+      -e puts -e STDIN.read)
+    IO.pipe do |r, w|
+      IO.pipe do |r2, w2|
+        pid = spawn(@@env, *cmd, in: r2, out: w, err: '/dev/null')
+        r2.close
+        w.close
+        assert_equal "\n", r.gets
+        buf = +''
+        10.times { Process.kill(:USR1, pid) }
+        while IO.select([r], nil, nil, 0.1)
+          case tmp = r.read_nonblock(1000, exception: false)
+          when String
+            buf << tmp
+          end
+        end
+        w2.close
+        Process.wait(pid)
+        assert_predicate $?, :success?, $?.inspect
+        assert_equal(["\"HELLO_WORLD\"\n"], buf.split(/^/).uniq)
+      end
+    end
+  end
+
+  def test_reset
+    assert_nil Mwrap.reset
+  end
+
+  def test_each
+    cmd = @@cmd + %w(
+      -e ("0"*10000).clear
+      -e h={}
+      -e Mwrap.each(1000){|a,b,c|h[a]=[b,c]}
+      -e puts(Marshal.dump(h))
+    )
+    r = IO.popen(@@env, cmd, 'r')
+    h = Marshal.load(r.read)
+    assert_not_predicate h, :empty?
+    h.each_key { |k| assert_kind_of String, k }
+    h.each_value do |total,calls|
+      assert_operator total, :>, 0
+      assert_operator calls, :>, 0
+      assert_operator total, :>=, calls
+    end
+  end
+
+  def test_aref_each
+    cmd = @@cmd + %w(
+      -e count=GC.count
+      -e GC.disable
+      -e keep=("0"*10000)
+      -e loc=Mwrap["-e:3"]
+      -e
+    ) + [ 'loc.each{|size,gen|p([size,gen,count]) if size > 10000}' ]
+    buf = IO.popen(@@env, cmd, &:read)
+    assert_predicate $?, :success?
+    assert_match(/\A\[\s*\d+,\s*\d+,\s*\d+\]\s*\z/s, buf)
+    size, gen, count = eval(buf)
+    assert_operator size, :>=, 10000
+    assert_operator gen, :>=, count
+
+    cmd = @@cmd + %w(
+      -e count=GC.count
+      -e locs=""
+      -e Mwrap.each(1){|loc,tot,calls|locs<<loc}
+      -e m=locs.match(/(\[0x[a-f0-9]+\])/i)
+      -e m||=locs.match(/\b(0x[a-f0-9]+)\b/i)
+      -e p(loc=Mwrap["bobloblaw\t#{m[1]}"])
+      -e loc.each{|size,gen|p([size,gen,count])}
+    )
+    buf = IO.popen(@@env, cmd, &:read)
+    assert_predicate $?, :success?
+    assert_match(/\bMwrap::SourceLocation\b/, buf)
+  end
+
+  def test_benchmark
+    cmd = @@cmd + %w(-rbenchmark
+      -e puts(Benchmark.measure{1000000.times{Time.now}}))
+    r = IO.popen(@@env, cmd, 'r')
+    require 'benchmark'
+    warn Benchmark::Tms::CAPTION
+    warn r.read
+  end if ENV['BENCHMARK']
+
+  def test_mwrap_dump_check
+    assert_raise(TypeError) { Mwrap.dump(:bogus) }
+  end
+
+  def assert_separately(src, *opts)
+    Tempfile.create(%w(mwrap .rb)) do |tmp|
+      tmp.write(src.lstrip!)
+      tmp.flush
+      assert(system(@@env, *@@cmd, tmp.path, *opts))
+    end
+  end
+
+  def test_source_location
+    assert_separately(+"#{<<~"begin;"}\n#{<<~'end;'}")
+    begin;
+      require 'mwrap'
+      foo = '0' * 10000
+      k = -"#{__FILE__}:2"
+      loc = Mwrap[k]
+      loc.name == k or abort 'SourceLocation#name broken'
+      loc.total >= 10000 or abort 'SourceLocation#total broken'
+      loc.frees == 0 or abort 'SourceLocation#frees broken'
+      loc.allocations >= 1 or
+        abort "SourceLocation#allocations broken: #{loc.allocations}"
+      seen = false
+      loc.each do |*x| seen = x end
+      seen[1] == loc.total or 'SourceLocation#each broken'
+      foo.clear
+
+      # wait for call_rcu to perform real_free
+      freed = false
+      until freed
+        freed = true
+        loc.each do |size, gen|
+          freed = false if size >= 10000
+        end
+      end
+      loc.frees == 1 or abort 'SourceLocation#frees broken (after free)'
+      Float === loc.mean_lifespan or abort 'mean_lifespan broken'
+      Integer === loc.max_lifespan or abort 'max_lifespan broken'
+
+      addr = false
+      Mwrap.each do |a,|
+        if a =~ /0x[a-f0-9]+/
+          addr = a
+          break
+        end
+      end
+      addr or abort 'Mwrap.each did not see any addresses'
+      addr.frozen? or abort 'Mwrap.each returned unfrozen address'
+      loc = Mwrap[addr] or abort "Mwrap[#{addr}] broken"
+      addr == loc.name or abort 'SourceLocation#name works on address'
+      loc.name.frozen? or abort 'SourceLocation#name not frozen'
+    end;
+  end
+
+  def test_quiet
+    assert_separately(+"#{<<~"begin;"}\n#{<<~'end;'}")
+    begin;
+      require 'mwrap'
+      before = nil
+      res = Mwrap.quiet do |depth|
+        before = __LINE__
+        depth == 1 or abort 'depth is not 1'
+        ('a' * 10000).clear
+        Mwrap.quiet { |d| d == 2 or abort 'depth is not 2' }
+        :foo
+      end
+      after = __LINE__ - 1
+      (before..after).each do |lineno|
+        Mwrap["#{__FILE__}:#{lineno}"] and
+          abort "unexpectedly tracked allocation at line #{lineno}"
+      end
+      res == :foo or abort 'Mwrap.quiet did not return block result'
+    end;
+  end
+
+  def test_total_bytes
+    assert_separately(+"#{<<~"begin;"}\n#{<<~'end;'}")
+    begin;
+      require 'mwrap'
+      Mwrap.total_bytes_allocated > 0 or abort 'nothing allocated'
+      Mwrap.total_bytes_freed > 0 or abort 'nothing freed'
+      Mwrap.total_bytes_allocated > Mwrap.total_bytes_freed or
+        abort 'freed more than allocated'
+    end;
+  end
+end
diff --git a/typemap b/typemap
deleted file mode 100644
index 0b0e4a3..0000000
--- a/typemap
+++ /dev/null
@@ -1,5 +0,0 @@
-TYPEMAP
-size_t        T_UV
-const char *        T_PV
-Devel::Mwrap::SrcLoc        T_PTROBJ
-double        T_DOUBLE