ext/Devel/PPPort/parts/inc/ppphdoc Devel::PPPort include
ext/Devel/PPPort/parts/inc/ppphtest Devel::PPPort include
ext/Devel/PPPort/parts/inc/pvs Devel::PPPort include
+ext/Devel/PPPort/parts/inc/shared_pv Devel::PPPort include
ext/Devel/PPPort/parts/inc/snprintf Devel::PPPort include
ext/Devel/PPPort/parts/inc/strlfuncs Devel::PPPort include
ext/Devel/PPPort/parts/inc/SvPV Devel::PPPort include
ext/Devel/PPPort/t/podtest.t Devel::PPPort test file
ext/Devel/PPPort/t/ppphtest.t Devel::PPPort test file
ext/Devel/PPPort/t/pvs.t Devel::PPPort test file
+ext/Devel/PPPort/t/shared_pv.t Devel::PPPort test file
ext/Devel/PPPort/t/snprintf.t Devel::PPPort test file
ext/Devel/PPPort/t/strlfuncs.t Devel::PPPort test file
ext/Devel/PPPort/t/SvPV.t Devel::PPPort test file
+3.11_05 - 2007-08-20
+
+ * fix: PERL_HASH() was emitting a warning when passed in a
+ const char pointer
+ * fix: sv_magic_portable() was emitting a warning when
+ passed in a const char pointer
+ * fix: make sure arguments to sv_magic_portable() are only
+ evaluated once
+
+3.11_04 - 2007-08-20
+
+ * fix: ignore strings and XS comments when scanning and
+ patching files
+ * added support for the following API
+ newSVpvn_share
+ PERL_HASH
+ SvSHARED_HASH
+ * use PERL_BCDREVISION for version checking to save some
+ bytes in ppport.h
+ * improve the --strip option
+ - strip all C comments
+ - strip most superfluous whitespace
+ with these changes, the stripped ppport.h is now almost
+ 30% smaller:
+ 3.11_03 3.11_04 delta
+ ------------------------------------------
+ uncompressed 87988 62573 -28.9%
+ gzip'd 17985 12725 -29.2%
+
3.11_03 - 2007-08-14
* fix an infinite recursion in ppport.h that could be
^parts/base-
^ppport\.h$
^PPPort\.c$
+^testing
Devel-PPPort.*\.tar\.gz$
#
################################################################################
#
-# $Revision: 54 $
+# $Revision: 55 $
# $Author: mhx $
-# $Date: 2007/08/13 00:03:11 +0200 $
+# $Date: 2007/08/19 19:41:37 +0200 $
#
################################################################################
#
#
################################################################################
#
-# $Revision: 54 $
+# $Revision: 55 $
# $Author: mhx $
-# $Date: 2007/08/13 00:03:11 +0200 $
+# $Date: 2007/08/19 19:41:37 +0200 $
#
################################################################################
#
use strict;
use vars qw($VERSION $data);
-$VERSION = do { my @r = '$Snapshot: /Devel-PPPort/3.11_03 $' =~ /(\d+\.\d+(?:_\d+)?)/; @r ? $r[0] : '9.99' };
+$VERSION = do { my @r = '$Snapshot: /Devel-PPPort/3.11_05 $' =~ /(\d+\.\d+(?:_\d+)?)/; @r ? $r[0] : '9.99' };
sub _init_data
{
%include sv_xpvf
+%include shared_pv
+
%include warn
%include pvs
TODO:
+* bump __MAX_PERL__ before 5.10
+
* > 3. In several cases, "perl ppport.h --copy=.new" output a new file in
> which the only change was the addition of "#include "ppport.h"". In each
> case, that actually wasn't necessary because the source file in question
#
################################################################################
#
-# $Revision: 25 $
+# $Revision: 27 $
# $Author: mhx $
-# $Date: 2007/08/12 23:23:40 +0200 $
+# $Date: 2007/08/19 19:41:03 +0200 $
#
################################################################################
#
#define NEED_my_strlcpy
#define NEED_newCONSTSUB
#define NEED_newRV_noinc
+#define NEED_newSVpvn_share
#define NEED_sv_2pv_flags
-#define NEED_sv_pvn_force_flags
#define NEED_sv_2pvbyte
#define NEED_sv_catpvf_mg
#define NEED_sv_catpvf_mg_nocontext
+#define NEED_sv_pvn_force_flags
#define NEED_sv_setpvf_mg
#define NEED_sv_setpvf_mg_nocontext
#define NEED_vload_module
boolSV # added by devel/scanprov
memEQ # added by devel/scanprov
memNE # added by devel/scanprov
+PERL_HASH # added by devel/scanprov
SvPV_nolen_const # added by devel/scanprov
SvPV_nomg_const # added by devel/scanprov
SvPV_nomg_const_nolen # added by devel/scanprov
+SvSHARED_HASH # added by devel/scanprov
################################################################################
##
-## $Revision: 14 $
+## $Revision: 15 $
## $Author: mhx $
-## $Date: 2007/08/12 23:57:09 +0200 $
+## $Date: 2007/08/18 20:16:11 +0200 $
##
################################################################################
##
ok(&Devel::PPPort::eval_pv('f(qw(a b c))', 0), 'y');
ok(!defined $::{'less::'}, 1, "Hadn't loaded less yet");
-Devel::PPPort::load_module(0, "less", undef);
+Devel::PPPort::load_module(0, "less", undef);
ok(defined $::{'less::'}, 1, "Have now loaded less");
################################################################################
##
-## $Revision: 13 $
+## $Revision: 14 $
## $Author: mhx $
-## $Date: 2007/08/12 23:24:34 +0200 $
+## $Date: 2007/08/20 19:19:24 +0200 $
##
################################################################################
##
#elif { VERSION < 5.8.0 }
-# define sv_magic_portable(sv, obj, how, name, namlen) \
- STMT_START { \
- if (name && namlen == 0) \
- { \
- MAGIC *mg; \
- sv_magic(sv, obj, how, 0, 0); \
- mg = SvMAGIC(sv); \
- mg->mg_len = -42; /* XXX: this is the tricky part */ \
- mg->mg_ptr = name; \
- } \
- else \
- { \
- sv_magic(sv, obj, how, name, namlen); \
- } \
+# 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
################################################################################
##
-## $Revision: 39 $
+## $Revision: 41 $
## $Author: mhx $
-## $Date: 2007/07/18 13:09:15 +0200 $
+## $Date: 2007/08/20 18:33:10 +0200 $
##
################################################################################
##
INT2PTR
PTRV
NUM2PTR
+PERL_HASH
PTR2IV
PTR2UV
PTR2NV
__UNDEFINED__ SVf "_"
-__UNDEFINED__ UTF8_MAXBYTES UTF8_MAXLEN
+__UNDEFINED__ UTF8_MAXBYTES UTF8_MAXLEN
+
+__UNDEFINED__ 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
=xsmisc
################################################################################
##
-## $Revision: 41 $
+## $Revision: 44 $
## $Author: mhx $
-## $Date: 2007/08/13 21:08:26 +0200 $
+## $Date: 2007/08/20 18:21:09 +0200 $
##
################################################################################
##
use strict;
+# Disable broken TRIE-optimization
+BEGIN { eval '${^RE_TRIE_MAXBUF} = -1' if $] >= 5.009004 && $] <= 5.009005 }
+
my $VERSION = __VERSION__;
my %opt = (
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(
$opt{'compat-version'} = 5;
}
-# Never use C comments in this file!!!!!
-my $ccs = '/'.'*';
-my $cce = '*'.'/';
-my $rccs = quotemeta $ccs;
-my $rcce = quotemeta $cce;
-
my %API = map { /^(\w+)\|([^|]*)\|([^|]*)\|(\w*)$/
? ( $1 => {
($2 ? ( base => $2 ) : ()),
{
my $code = shift;
$code =~ s{
- ([^"'/]+)
- | / (?: \*[^*]*\*+(?:[^$ccs][^*]*\*+)* / | /[^\r\n]*)
- | (?:"[^"\\]*(?:\\.[^"\\]*)*" [^"'/]*)+
- | (?:'[^'\\]*(?:\\.[^'\\]*)*' [^"'/]*)+
- }{ defined $1 ? $1 : '' }egsx;
+ / (?: \*[^*]*\*+(?:[^$ccs][^*]*\*+)* / | /[^\r\n]*)
+ | "[^"\\]*(?:\\.[^"\\]*)*"
+ | '[^'\\]*(?:\\.[^'\\]*)*' }{}egsx;
grep { exists $API{$_} } $code =~ /(\w+)/mg;
}
$h->{$_} .= "$1\n";
}
}
- else {
- undef $hint;
- }
+ else { undef $hint }
}
- $hint = [$1, [split /,?\s+/, $2]] if m{^\s*$rccs\s+(Hint|Warning):\s+(\w+(?:,?\s+\w+)*)\s*$};
+ $hint = [$1, [split /,?\s+/, $2]]
+ if m{^\s*$rccs\s+(Hint|Warning):\s+(\w+(?:,?\s+\w+)*)\s*$};
if ($define) {
if ($define->[1] =~ /\\$/) {
print "\nWARNING:\n$warnings{$f}" if exists $warnings{$f};
$info++;
}
- unless ($info) {
- print "No portability information available.\n";
- }
+ print "No portability information available.\n" unless $info;
$count++;
}
- if ($count > 0) {
- print "\n";
- }
- else {
- print "Found no API matching '$opt{'api-info'}'.\n";
- }
+ $count or print "Found no API matching '$opt{'api-info'}'.";
+ print "\n";
exit 0;
}
@files = @in;
}
-unless (@files) {
- die "No input files given!\n";
-}
+die "No input files given!\n" unless @files;
my(%files, %global, %revreplace);
%revreplace = reverse %replace;
my %file = (orig => $c, changes => 0);
- # temporarily remove C comments from the code
+ # Temporarily remove C/XS comments and strings from the code
my @ccom;
+
$c =~ s{
- ( [^"'/]+
- | (?:"[^"\\]*(?:\\.[^"\\]*)*" [^"'/]*)+
- | (?:'[^'\\]*(?:\\.[^'\\]*)*' [^"'/]*)+ )
- | (/ (?: \*[^*]*\*+(?:[^$ccs][^*]*\*+)* /
- | /[^\r\n]* ) )
+ ( ^$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" }egsx;
+ defined $1 ? $1 : "$ccs$#ccom$cce" }mgsex;
$file{ccom} = \@ccom;
$file{code} = $c;
- $file{has_inc_ppport} = ($c =~ /#.*include.*\Q$ppport\E/);
+ $file{has_inc_ppport} = $c =~ /^$HS*#$HS*include[^\r\n]+\b\Q$ppport\E\b/m;
my $func;
}
}
for ($func, @deps) {
- if (exists $need{$_}) {
- $file{needs}{$_} = 'static';
- }
+ $file{needs}{$_} = 'static' if exists $need{$_};
}
}
}
if (exists $need{$2}) {
$file{defined $3 ? 'needed_global' : 'needed_static'}{$2}++;
}
- else {
- warning("Possibly wrong #define $1 in $filename");
- }
+ else { warning("Possibly wrong #define $1 in $filename") }
}
for (qw(uses needs uses_todo needed_global needed_static)) {
#######################################################################
+sub try_use { eval "use @_;"; return $@ eq '' }
+
sub mydiff
{
local *F = shift;
$diff = run_diff($opt{diff}, $file, $str);
}
- if (!defined $diff and can_use('Text::Diff')) {
+ if (!defined $diff and try_use('Text::Diff')) {
$diff = Text::Diff::diff($file, \$str, { STYLE => 'Unified' });
$diff = <<HEADER . $diff;
--- $file
}
print F $diff;
-
}
sub run_diff
return undef;
}
-sub can_use
-{
- eval "use @_;";
- return $@ eq '';
-}
-
sub rec_depend
{
my($func, $seen) = @_;
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 $self;
+ print OUT "$pl$c\n";
exit 0;
}
################################################################################
##
-## $Revision: 38 $
+## $Revision: 40 $
## $Author: mhx $
-## $Date: 2007/08/12 23:58:29 +0200 $
+## $Date: 2007/08/20 18:06:48 +0200 $
##
################################################################################
##
##
################################################################################
-=tests plan => 221
+=tests plan => 225
BEGIN {
if ($ENV{'SKIP_SLOW_TESTS'}) {
- for (1 .. 221) {
+ for (1 .. 225) {
skip("skip: SKIP_SLOW_TESTS", 0);
}
exit 0;
my $t;
for $t (@tests) {
+ print "#\n", ('# ', '-'x70, "\n")x3, "#\n";
my $f;
for $f (keys %{$t->{files}}) {
my @f = split /\//, $f;
print "# *** writing $f ***\n$txt\n";
}
+ my $code = $t->{code};
+ $code =~ s/^/# | /mg;
+
+ print "# *** evaluating test code ***\n$code\n";
+
eval $t->{code};
if ($@) {
my $err = $@;
SvUOK
PL_copline
+===============================================================================
+
+my $o = ppport(qw(--copy=f));
+
+for (qw(file.xs)) {
+ ok($o =~ /^Writing copy of.*\Q$_\E.*with changes/mi);
+ ok(-e "${_}f");
+ ok(eq_files("${_}f", "${_}r"));
+ unlink "${_}f";
+}
+
+---------------------------- file.xs -----------------------------------------
+
+a_string = "sv_undef"
+a_char = 'sv_yes'
+#define SOMETHING defgv
+/* C-comment: sv_tainted */
+#
+# This is just a big XS comment using sv_no
+#
+/* The following, is NOT an XS comment! */
+# define SOMETHING_ELSE defgv + \
+ sv_undef
+
+---------------------------- file.xsr -----------------------------------------
+
+#include "ppport.h"
+a_string = "sv_undef"
+a_char = 'sv_yes'
+#define SOMETHING PL_defgv
+/* C-comment: sv_tainted */
+#
+# This is just a big XS comment using sv_no
+#
+/* The following, is NOT an XS comment! */
+# define SOMETHING_ELSE PL_defgv + \
+ PL_sv_undef
+
--- /dev/null
+################################################################################
+##
+## $Revision: 1 $
+## $Author: mhx $
+## $Date: 2007/08/19 19:38:17 +0200 $
+##
+################################################################################
+##
+## Version 3.x, Copyright (C) 2004-2007, 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.
+##
+################################################################################
+
+=provides
+
+newSVpvn_share
+__UNDEFINED__
+
+=implementation
+
+#ifndef newSVpvn_share
+
+#if { NEED newSVpvn_share }
+
+SV *
+newSVpvn_share(pTHX_ const char *src, I32 len, U32 hash)
+{
+ SV *sv;
+ if (len < 0)
+ len = -len;
+ if (!hash)
+ PERL_HASH(hash, 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
+
+__UNDEFINED__ SvSHARED_HASH(sv) (0 + SvUVX(sv))
+
+=xsinit
+
+#define NEED_newSVpvn_share
+
+=xsubs
+
+int
+newSVpvn_share()
+ PREINIT:
+ const char *s;
+ SV *sv;
+ STRLEN len;
+ U32 hash;
+ CODE:
+ RETVAL = 0;
+ s = "mhx";
+ len = 3;
+ PERL_HASH(hash, s, len);
+ sv = newSVpvn_share(s, len, 0);
+ s = 0;
+ RETVAL += strEQ(SvPV_nolen_const(sv), "mhx");
+ RETVAL += SvCUR(sv) == len;
+ RETVAL += SvSHARED_HASH(sv) == hash;
+ SvREFCNT_dec(sv);
+ s = "foobar";
+ len = 6;
+ PERL_HASH(hash, s, len);
+ sv = newSVpvn_share(s, -len, hash);
+ s = 0;
+ RETVAL += strEQ(SvPV_nolen_const(sv), "foobar");
+ RETVAL += SvCUR(sv) == len;
+ RETVAL += SvSHARED_HASH(sv) == hash;
+ SvREFCNT_dec(sv);
+ OUTPUT:
+ RETVAL
+
+
+=tests plan => 1
+
+ok(&Devel::PPPort::newSVpvn_share(), 6);
+
################################################################################
##
-## $Revision: 8 $
+## $Revision: 9 $
## $Author: mhx $
-## $Date: 2007/01/02 12:32:32 +0100 $
+## $Date: 2007/08/18 20:16:12 +0200 $
##
################################################################################
##
#if { VERSION < 5.6.0 }
# ifdef USE_THREADS
# define aTHXR thr
-# define aTHXR_ thr,
+# define aTHXR_ thr,
# else
# define aTHXR
# define aTHXR_
#
################################################################################
#
-# $Revision: 19 $
+# $Revision: 22 $
# $Author: mhx $
-# $Date: 2007/08/13 22:59:58 +0200 $
+# $Date: 2007/08/19 01:18:23 +0200 $
#
################################################################################
#
my($op, $ver) = @_;
my($r, $v, $s) = parse_version($ver);
$r == 5 or die "only Perl revision 5 is supported\n";
- $op eq '==' and return "((PERL_VERSION == $v) && (PERL_SUBVERSION == $s))";
- $op eq '!=' and return "((PERL_VERSION != $v) || (PERL_SUBVERSION != $s))";
- $op =~ /([<>])/ and return "((PERL_VERSION $1 $v) || ((PERL_VERSION == $v) && (PERL_SUBVERSION $op $s)))";
- die "cannot expand version expression ($op $ver)\n";
+ my $bcdver = sprintf "0x%d%03d%03d", $r, $v, $s;
+ return "(PERL_BCDVERSION $op $bcdver)";
}
sub parse_partspec
open F, $file or die "$file: $!\n";
while (<F>) {
+ /[ \t]+$/ and warn "$file:$.: warning: trailing whitespace\n";
+ if ($section eq 'implementation') {
+ m!//! && !m!(?:=~|s/).*//! && !m!(?:ht|f)tp://!
+ and warn "$file:$.: warning: potential C++ comment\n";
+ }
/^##/ and next;
if (/^=($vsec)(?:\s+(.*))?/) {
$section = $1;
if (defined $2) {
my $opt = $2;
$options{$section} = eval "{ $opt }";
- $@ and die "Invalid options ($opt) in section $section of $file: $@\n";
+ $@ and die "$file:$.: invalid options ($opt) in section $section: $@\n";
}
next;
}
gv_handler # U
is_lvalue_sub # U
my_popen_list # U
-newSVpvn_share # U
save_mortalizesv # U
save_padsv # U
scan_num # E (Perl_scan_num)
use List::Util qw(max);
use Config;
-my $VERSION = do { my @r = '$Snapshot: /Devel-PPPort/3.11_03 $' =~ /(\d+\.\d+(?:_\d+)?)/; @r ? $r[0] : '9.99' };
+my $VERSION = do { my @r = '$Snapshot: /Devel-PPPort/3.11_05 $' =~ /(\d+\.\d+(?:_\d+)?)/; @r ? $r[0] : '9.99' };
$| = 1;
my %OPT = (
ok(&Devel::PPPort::eval_pv('f(qw(a b c))', 0), 'y');
ok(!defined $::{'less::'}, 1, "Hadn't loaded less yet");
-Devel::PPPort::load_module(0, "less", undef);
+Devel::PPPort::load_module(0, "less", undef);
ok(defined $::{'less::'}, 1, "Have now loaded less");
require 'testutil.pl' if $@;
}
- if (221) {
+ if (225) {
load();
- plan(tests => 221);
+ plan(tests => 225);
}
}
BEGIN {
if ($ENV{'SKIP_SLOW_TESTS'}) {
- for (1 .. 221) {
+ for (1 .. 225) {
skip("skip: SKIP_SLOW_TESTS", 0);
}
exit 0;
my $t;
for $t (@tests) {
+ print "#\n", ('# ', '-'x70, "\n")x3, "#\n";
my $f;
for $f (keys %{$t->{files}}) {
my @f = split /\//, $f;
print "# *** writing $f ***\n$txt\n";
}
+ my $code = $t->{code};
+ $code =~ s/^/# | /mg;
+
+ print "# *** evaluating test code ***\n$code\n";
+
eval $t->{code};
if ($@) {
my $err = $@;
SvUOK
PL_copline
+===============================================================================
+
+my $o = ppport(qw(--copy=f));
+
+for (qw(file.xs)) {
+ ok($o =~ /^Writing copy of.*\Q$_\E.*with changes/mi);
+ ok(-e "${_}f");
+ ok(eq_files("${_}f", "${_}r"));
+ unlink "${_}f";
+}
+
+---------------------------- file.xs -----------------------------------------
+
+a_string = "sv_undef"
+a_char = 'sv_yes'
+#define SOMETHING defgv
+/* C-comment: sv_tainted */
+#
+# This is just a big XS comment using sv_no
+#
+/* The following, is NOT an XS comment! */
+# define SOMETHING_ELSE defgv + \
+ sv_undef
+
+---------------------------- file.xsr -----------------------------------------
+
+#include "ppport.h"
+a_string = "sv_undef"
+a_char = 'sv_yes'
+#define SOMETHING PL_defgv
+/* C-comment: sv_tainted */
+#
+# This is just a big XS comment using sv_no
+#
+/* The following, is NOT an XS comment! */
+# define SOMETHING_ELSE PL_defgv + \
+ PL_sv_undef
+
--- /dev/null
+################################################################################
+#
+# !!!!! Do NOT edit this file directly! !!!!!
+#
+# Edit mktests.PL and/or parts/inc/shared_pv instead.
+#
+# This file was automatically generated from the definition files in the
+# parts/inc/ subdirectory by mktests.PL. To learn more about how all this
+# works, please read the F<HACKERS> file that came with this distribution.
+#
+################################################################################
+
+BEGIN {
+ if ($ENV{'PERL_CORE'}) {
+ chdir 't' if -d 't';
+ @INC = ('../lib', '../ext/Devel/PPPort/t') if -d '../lib' && -d '../ext';
+ require Config; import Config;
+ use vars '%Config';
+ if (" $Config{'extensions'} " !~ m[ Devel/PPPort ]) {
+ print "1..0 # Skip -- Perl configured without Devel::PPPort module\n";
+ exit 0;
+ }
+ }
+ else {
+ unshift @INC, 't';
+ }
+
+ sub load {
+ eval "use Test";
+ require 'testutil.pl' if $@;
+ }
+
+ if (1) {
+ load();
+ plan(tests => 1);
+ }
+}
+
+use Devel::PPPort;
+use strict;
+$^W = 1;
+
+package Devel::PPPort;
+use vars '@ISA';
+require DynaLoader;
+@ISA = qw(DynaLoader);
+bootstrap Devel::PPPort;
+
+package main;
+
+ok(&Devel::PPPort::newSVpvn_share(), 6);
+