diff options
author | Duke Leto <jonathan@leto.net> | 2009-06-22 00:13:53 -0700 |
---|---|---|
committer | Duke Leto <jonathan@leto.net> | 2009-06-22 00:13:53 -0700 |
commit | ad6656ab324af5697588484c4746401e1770fa57 (patch) | |
tree | 71f1fa609fa806ce6f70f6b764262c239f93d782 | |
parent | eb78bf8f0da016f321bb20da1ca06461c3356b39 (diff) | |
parent | b953482e2d970eeb88de96a38c087d03db83a5cd (diff) | |
download | perl-ad6656ab324af5697588484c4746401e1770fa57.tar.gz |
Merge branch 'blead' into debugger_symbols
85 files changed, 1337 insertions, 548 deletions
@@ -25,7 +25,7 @@ # $Id: Head.U 6 2006-08-25 22:21:46Z rmanfredi $ # -# Generated on Thu Jun 4 09:30:45 CEST 2009 [metaconfig 3.5 PL0] +# Generated on Thu Jun 18 16:33:35 CEST 2009 [metaconfig 3.5 PL0] # (with additional metaconfig patches by perlbug@perl.org) cat >c1$$ <<EOF @@ -21384,7 +21384,7 @@ $eunicefix Cppsym.try ./Cppsym < Cppsym.know > Cppsym.true : Add in any linux cpp "predefined macros": case "$osname::$gccversion" in - *linux*::*.*) + *linux*::*.*|*gnukfreebsd*::*.*) tHdrH=_tmpHdr rm -f $tHdrH'.h' $tHdrH touch $tHdrH'.h' @@ -2018,8 +2018,6 @@ lib/CPANPLUS/Shell.pm CPANPLUS lib/CPANPLUS/t/00_CPANPLUS-Internals-Utils.t CPANPLUS tests lib/CPANPLUS/t/01_CPANPLUS-Configure.t CPANPLUS tests lib/CPANPLUS/t/02_CPANPLUS-Internals.t CPANPLUS tests -lib/CPANPLUS/t/031_CPANPLUS-Internals-Source-SQLite.t CPANPLUS tests -lib/CPANPLUS/t/032_CPANPLUS-Internals-Source-via-sqlite.t CPANPLUS tests lib/CPANPLUS/t/03_CPANPLUS-Internals-Source.t CPANPLUS tests lib/CPANPLUS/t/04_CPANPLUS-Module.t CPANPLUS tests lib/CPANPLUS/t/05_CPANPLUS-Internals-Fetch.t CPANPLUS tests @@ -2573,7 +2571,6 @@ lib/Module/Build/Platform/Windows.pm Module::Build lib/Module/Build.pm Module::Build lib/Module/Build/PodParser.pm Module::Build lib/Module/Build/PPMMaker.pm Module::Build -lib/Module/Build/scripts/bundle.pl Module::Build lib/Module/Build/scripts/config_data Module::Build lib/Module/Build/t/add_property.t Module::Build lib/Module/Build/t/basic.t Module::Build @@ -3707,6 +3704,7 @@ Porting/config_H Sample config.h Porting/config_h.pl Reorder config_h.SH after metaconfig Porting/config.sh Sample config.sh Porting/Contract Social contract for contributed modules in Perl core +Porting/core-cpan-diff Compare core distros with their CPAN equivalents Porting/corecpan.pl Reports outdated dual-lived modules Porting/corelist.pl Generates data for Module::CoreList Porting/curliff.pl Curliff or liff your curliffable files. diff --git a/Porting/Maintainers.pl b/Porting/Maintainers.pl index 10a5c1ae9d..cc6f4c067c 100644 --- a/Porting/Maintainers.pl +++ b/Porting/Maintainers.pl @@ -88,6 +88,21 @@ package Maintainers; 'zefram' => 'Andrew Main <zefram@cpan.org>', ); + +# IGNORABLE: files which, if they appear in the root of a CPAN +# distribution, need not appear in core (i.e. core-cpan-diff won't +# complain if it can't find them) + +@IGNORABLE = qw( + .cvsignore .dualLivedDiffConfig .gitignore + ANNOUNCE Announce Artistic AUTHORS BENCHMARK BUGS Build.PL + CHANGELOG ChangeLog CHANGES Changes COPYING Copying CREDITS + GOALS HISTORY INSTALL INSTALL.SKIP LICENSE Makefile.PL + MANIFEST MANIFEST.SKIP META.yml NEW NOTES ppport.h README + SIGNATURE THANKS TODO Todo VERSION WHATSNEW +); + + # Each entry in the %Modules hash roughly represents a distribution, # except in the case of CPAN=1, where it *exactly* represents a single # CPAN distribution. @@ -119,6 +134,37 @@ package Maintainers; # included in core are derived from. Note that the file's version may not # necessarily match the newest version on CPAN. +# EXCLUDED is a list of files to be excluded from a CPAN tarball before +# comparing the remaining contents with core. Each item can either be a +# full pathname (eg 't/foo.t') or a pattern (e.g. qr{^t/}). +# It defaults to the empty list. + +# MAP is a hash that maps CPAN paths to their core equivalents. +# Each key reprepresents a string prefix, with longest prefixes checked +# first. The first match causes that prefix to be replaced with the +# corresponding key. For example, with the following MAP: +# { +# 'lib/' => 'lib/', +# '' => 'lib/Foo/', +# }, +# +# these files are mapped as shown: +# +# README becomes lib/Foo/README +# lib/Foo.pm becomes lib/Foo.pm +# +# The default is dependent on the type of module. +# For distributions which appear to be stored under ext/, it defaults to: +# +# { '' => 'ext/Foo-Bar/' } +# +# otherwise, it's +# +# { +# 'lib/' => 'lib/', +# '' => 'lib/Foo/Bar/', +# } + %Modules = ( 'Archive::Extract' => @@ -419,6 +465,8 @@ package Maintainers; 'EXCLUDED' => [ qr{^inc/}, qr{^t/dummy-.*\.hidden$}, qw{ bin/cpanp-boxed + t/031_CPANPLUS-Internals-Source-SQLite.t + t/032_CPANPLUS-Internals-Source-via-sqlite.t }, ], 'CPAN' => 1, @@ -1122,11 +1170,11 @@ package Maintainers; 'Module::Build' => { 'MAINTAINER' => 'kwilliams', - 'DISTRIBUTION' => 'EWILHELM/Module-Build-0.32.tar.gz', + 'DISTRIBUTION' => 'DAGOLDEN/Module-Build-0.33_02.tar.gz', 'FILES' => q[lib/Module/Build lib/Module/Build.pm], - 'EXCLUDED' => [ qw{ t/par.t t/signature.t }, ], + 'EXCLUDED' => [ qw{ t/par.t t/signature.t scripts/bundle.pl}, ], 'CPAN' => 1, - 'UPSTREAM' => undef, + 'UPSTREAM' => 'cpan', }, 'Module::CoreList' => @@ -1195,7 +1243,7 @@ package Maintainers; 'NEXT' => { 'MAINTAINER' => 'rafl', - 'DISTRIBUTION' => 'FLORA/NEXT-0.63.tar.gz', + 'DISTRIBUTION' => 'FLORA/NEXT-0.64.tar.gz', 'FILES' => q[lib/NEXT.pm lib/NEXT], 'EXCLUDED' => [ qr{^demo/} ], 'CPAN' => 1, @@ -1795,7 +1843,7 @@ package Maintainers; 'threads' => { 'MAINTAINER' => 'jdhedden', - 'DISTRIBUTION' => 'JDHEDDEN/threads-1.72.tar.gz', + 'DISTRIBUTION' => 'JDHEDDEN/threads-1.73.tar.gz', 'FILES' => q[ext/threads], 'EXCLUDED' => [ qw(examples/pool.pl t/pod.t diff --git a/Porting/add-package.pl b/Porting/add-package.pl index c8fe807cf6..20947c0b53 100644 --- a/Porting/add-package.pl +++ b/Porting/add-package.pl @@ -75,12 +75,12 @@ my @LibFiles; @LibFiles = map { chomp; $_ } ### should we get rid of this file? grep { $ExcludeRe && $_ =~ $ExcludeRe - ? do { warn "Removing $_\n"; - system("rm $_") and die "rm '$_' failed: $?"; + ? do { warn "Removing $Repo/$_\n"; + system("rm $Repo/$_") and die "rm '$Repo/$_' failed: $?"; undef } : 1 - } `find lib -type f` + } `find $Repo/lib -type f` or die "Could not detect library files\n"; print "done\n" if $Verbose; diff --git a/Porting/core-cpan-diff b/Porting/core-cpan-diff new file mode 100755 index 0000000000..80d6b7d211 --- /dev/null +++ b/Porting/core-cpan-diff @@ -0,0 +1,591 @@ +#!/usr/bin/env perl + +# core-cpan-diff: Compare CPAN modules with their equivalent in core + +# Originally based on App::DualLivedDiff by Steffen Mueller. + +use strict; +use warnings; + +use 5.010; + +use Getopt::Long; +use File::Temp (); +use File::Path (); +use File::Spec; +use Archive::Extract; +use IO::Uncompress::Gunzip (); +use File::Compare (); +use ExtUtils::Manifest; + +BEGIN { die "Must be run from root of perl source tree\n" unless -d 'Porting' } +use lib 'Porting'; +use Maintainers (); + +# if running from blead, we may be doing -Ilib, which means when we +# 'chdir /tmp/foo', Archive::Extract may not find Archive::Tar etc. +# So preload the things we need, and tell it to check %INC first: + +use Archive::Tar; +use IPC::Open3; +use IO::Select; +$Module::Load::Conditional::CHECK_INC_HASH = 1; +# stop Archive::Extract whinging about lack of Archive::Zip +$Archive::Extract::WARN = 0; + + +# Files, which if they exist in CPAN but not in perl, will not generate +# an 'Only in CPAN' listing +# +our %IGNORABLE = map { ($_ => 1) } + qw(.cvsignore .dualLivedDiffConfig .gitignore + ANNOUNCE Announce Artistic AUTHORS BENCHMARK BUGS Build.PL + CHANGELOG ChangeLog CHANGES Changes COPYING Copying CREDITS + GOALS HISTORY INSTALL INSTALL.SKIP LICENSE Makefile.PL + MANIFEST MANIFEST.SKIP META.yml NEW NOTES ppport.h README + SIGNATURE THANKS TODO Todo VERSION WHATSNEW); + +# where, under the cache dir, to untar stuff to + +use constant UNTAR_DIR => 'untarred'; + +use constant DIFF_CMD => 'diff'; +use constant WGET_CMD => 'wget'; + +sub usage { + print STDERR "\n@_\n\n" if @_; + print STDERR <<HERE; +Usage: $0 [opts] [ -d | -v | -x ] [ -a | module ... ] + +-a/--all Scan all dual-life modules. + +-c/--cachedir Where to save downloaded CPAN tarball files + (defaults to /tmp/something/ with deletion after each run). + +-d/--diff Display file differences using diff(1), rather than just + listing which files have changed. + The diff(1) command is assumed to be in your PATH. + +--diffopts Options to pass to the diff command. Defaults to '-u'. + +-f|force Force download from CPAN of new 02packages.details.txt file + (with --crosscheck only). + +-o/--output File name to write output to (defaults to STDOUT). + +-r/--reverse Reverses the diff (perl to CPAN). + +-v/--verbose List the fate of *all* files in the tarball, not just those + that differ or are missing. + +-x|crosscheck List the distributions whose current CPAN version differs from + that in blead (i.e. the DISTRIBUTION field in Maintainers.pl). + +By default (i.e. without the --crosscheck option), for each listed module +(or with -a, all CPAN modules listed in Maintainers.pl), grab the tarball +from CPAN associated with that module, and compare the files in it with +those in the perl source tree. + +Must be run from the root of the perl source tree. +Module names must match the keys of %Modules in Maintainers.pl. +HERE + exit(1); +} + + +sub run { + my $scan_all; + my $diff_opts; + my $reverse = 0; + my $cache_dir; + my $use_diff; + my $output_file; + my $verbose; + my $force; + my $do_crosscheck; + + GetOptions( + 'a|all' => \$scan_all, + 'c|cachedir=s' => \$cache_dir, + 'd|diff' => \$use_diff, + 'diffopts:s' => \$diff_opts, + 'f|force' => \$force, + 'h|help' => \&usage, + 'o|output=s' => \$output_file, + 'r|reverse' => \$reverse, + 'v|verbose' => \$verbose, + 'x|crosscheck' => \$do_crosscheck, + ) or usage; + + + my @modules; + + usage("Cannot mix -a with module list") if $scan_all && @ARGV; + + if ($do_crosscheck) { + usage("can't use -r, -d, --diffopts, -v with --crosscheck") + if ($reverse || $use_diff || $diff_opts || $verbose); + } + else { + $diff_opts = '-u' unless defined $diff_opts; + usage("can't use -f without --crosscheck") if $force; + } + + @modules = $scan_all + ? grep $Maintainers::Modules{$_}{CPAN}, + (sort {lc $a cmp lc $b } keys %Maintainers::Modules) + : @ARGV; + usage("No modules specified") unless @modules; + + + my $outfh; + if (defined $output_file) { + open $outfh, '>', $output_file + or die "ERROR: could not open file '$output_file' for writing: $!"; + } + else { + open $outfh, ">&STDOUT" + or die "ERROR: can't dup STDOUT: $!"; + } + + if (defined $cache_dir) { + die "ERROR: no such directory: '$cache_dir'\n" unless -d $cache_dir; + } + + if ($do_crosscheck) { + do_crosscheck($outfh, $cache_dir, $force, \@modules); + } + else { + do_compare(\@modules, $outfh, $cache_dir, $verbose, $use_diff, + $reverse, $diff_opts); + } +} + + + +# compare a list of modules against their CPAN equivalents + +sub do_compare { + my ($modules, $outfh, $cache_dir, $verbose, + $use_diff, $reverse, $diff_opts) = @_; + + + # first, make sure we have a directory where they can all be untarred, + # and if its a permanent directory, clear any previous content + my $untar_dir; + if ($cache_dir) { + $untar_dir = File::Spec->catdir($cache_dir, UNTAR_DIR); + if (-d $untar_dir) { + File::Path::rmtree($untar_dir) + or die "failed to remove $untar_dir\n"; + } + mkdir $untar_dir + or die "mkdir $untar_dir: $!\n"; + } + else { + $untar_dir = File::Temp::tempdir( CLEANUP => 1 ); + } + + my %ignorable = map { ($_ => 1) } @Maintainers::IGNORABLE; + + my %seen_dist; + for my $module (@$modules) { + print $outfh "\n$module\n" unless $use_diff; + + my $m = $Maintainers::Modules{$module} + or die "ERROR: No such module in Maintainers.pl: '$module'\n"; + + unless ($m->{CPAN}) { + print $outfh "WARNING: $module is not dual-life; skipping\n"; + next; + } + + my $dist = $m->{DISTRIBUTION}; + die "ERROR: $module has no DISTRIBUTION entry\n" unless defined $dist; + + if ($seen_dist{$dist}) { + warn "WARNING: duplicate entry for $dist in $module\n" + } + $seen_dist{$dist}++; + + my $cpan_dir = get_distribution($cache_dir, $untar_dir, $module, $dist); + + + my @perl_files = Maintainers::get_module_files($module); + + my $manifest = File::Spec->catfile($cpan_dir, 'MANIFEST'); + die "ERROR: no such file: $manifest\n" unless -f $manifest; + + my $cpan_files = ExtUtils::Manifest::maniread($manifest); + my @cpan_files = sort keys %$cpan_files; + + my ($excluded, $map) = get_map($m, $module, \@perl_files); + + my %perl_unseen; + @perl_unseen{@perl_files} = (); + my %perl_files = %perl_unseen; + + foreach my $cpan_file (@cpan_files) { + my $mapped_file = cpan_to_perl($excluded, $map, $cpan_file); + unless (defined $mapped_file) { + print $outfh " Excluded: $cpan_file\n" if $verbose; + next; + } + + if (exists $perl_files{$mapped_file}) { + delete $perl_unseen{$mapped_file}; + } + else { + # some CPAN files foo are stored in core as foo.packed, + # which are then unpacked by 'make test_prep' + my $packed_file = "$mapped_file.packed"; + if (exists $perl_files{$packed_file} ) { + if (! -f $mapped_file and -f $packed_file) { + print $outfh <<EOF; +WARNING: $mapped_file not found, but .packed variant exists. +Perhaps you need to run 'make test_prep'? +EOF + next; + } + delete $perl_unseen{$packed_file}; + } + else { + if ($ignorable{$cpan_file}) { + print $outfh " Ignored: $cpan_file\n" if $verbose; + next; + } + + unless ($use_diff) { + print $outfh " CPAN only: $cpan_file", + ($cpan_file eq $mapped_file) ? "\n" + : " (expected $mapped_file)\n"; + } + next; + } + } + + + my $abs_cpan_file = File::Spec->catfile($cpan_dir, $cpan_file); + + # should never happen + die "ERROR: can't find file $abs_cpan_file\n" unless -f $abs_cpan_file; + + # might happen if the FILES entry in Maintainers.pl is wrong + unless (-f $mapped_file) { + print $outfh "WARNING: perl file not found: $mapped_file\n"; + next; + } + + + if (File::Compare::compare($abs_cpan_file, $mapped_file)) { + if ($use_diff) { + file_diff($outfh, $abs_cpan_file, $mapped_file, + $reverse, $diff_opts); + } + else { + if ($cpan_file eq $mapped_file) { + print $outfh " Modified: $cpan_file\n"; + } + else { + print $outfh " Modified: $cpan_file $mapped_file\n"; + } + } + } + elsif ($verbose) { + if ($cpan_file eq $mapped_file) { + print $outfh " Unchanged: $cpan_file\n"; + } + else { + print $outfh " Unchanged: $cpan_file $mapped_file\n"; + } + } + } + for (sort keys %perl_unseen) { + print $outfh " Perl only: $_\n" unless $use_diff; + } + } +} + +# given FooBar-1.23_45.tar.gz, return FooBar + +sub distro_base { + my $d = shift; + $d =~ s/\.tar\.gz$//; + $d =~ s/\.gip$//; + $d =~ s/[\d\-_\.]+$//; + return $d; +} + +# process --crosscheck action: +# ie list all distributions whose CPAN versions differ from that listed in +# Maintainers.pl + +sub do_crosscheck { + my ($outfh, $cache_dir, $force, $modules) = @_; + + my $file = '02packages.details.txt'; + my $download_dir = $cache_dir || File::Temp::tempdir( CLEANUP => 1 ); + my $path = File::Spec->catfile($download_dir, $file); + my $gzfile = "$path.gz"; + + # grab 02packages.details.txt + + my $url = 'http://www.cpan.org/modules/02packages.details.txt.gz'; + + if (! -f $gzfile or $force) { + unlink $gzfile; + my_getstore($url, $gzfile); + } + unlink $path; + IO::Uncompress::Gunzip::gunzip($gzfile, $path) + or die "ERROR: failed to ungzip $gzfile: $IO::Uncompress::Gunzip::GunzipError\n"; + + # suck in the data from it + + open my $fh, '<', $path + or die "ERROR: open: $file: $!\n"; + + my %distros; + my %modules; + + while (<$fh>) { + next if 1../^$/; + chomp; + my @f = split ' ', $_; + if (@f != 3) { + warn "WARNING: $file:$.: line doesn't have three fields (skipping)\n"; + next; + } + $modules{$f[0]} = $f[2]; + + my $distro = $f[2]; + $distro =~ s{^.*/}{}; + + $distros{distro_base($distro)}{$distro} = 1; + } + + for my $module (@$modules) { + my $m = $Maintainers::Modules{$module} + or die "ERROR: No such module in Maintainers.pl: '$module'\n"; + + unless ($m->{CPAN}) { + print $outfh "\nWARNING: $module is not dual-life; skipping\n"; + next; + } + + + # given an try like + # Foo::Bar 1.23 foo-bar-1.23.tar.gz, + # first compare the module name against Foo::Bar, and failing that, + # against foo-bar + + my $pdist = $m->{DISTRIBUTION}; + die "ERROR: $module has no DISTRIBUTION entry\n" unless defined $pdist; + $pdist =~ s{^.*/}{}; + + my $cdist = $modules{$module}; + + if (defined $cdist) { + $cdist =~ s{^.*/}{}; + } + else { + my $d = $distros{distro_base($pdist)}; + unless (defined $d) { + print $outfh "\n$module: Can't determine current CPAN entry\n"; + next; + } + if (keys %$d > 1) { + print $outfh "\n$module: (found more than one CPAN candidate):\n"; + print $outfh " perl: $pdist\n"; + print $outfh " CPAN: $_\n" for sort keys %$d; + next; + } + $cdist = (keys %$d)[0]; + } + + if ($cdist ne $pdist) { + print $outfh "\n$module:\n Perl: $pdist\n CPAN: $cdist\n"; + } + } +} + + + +# get the EXCLUDED and MAP entries for this module, or +# make up defauts if they don't exist + +sub get_map { + my ($m, $module_name, $perl_files) = @_; + + my ($excluded, $map) = @$m{qw(EXCLUDED MAP)}; + + $excluded ||= []; + + return $excluded, $map if $map; + + # all files under ext/foo-bar (plus maybe some under t/lib)??? + + my $ext; + for (@$perl_files) { + if (m{^(ext/[^/]+/)}) { + if (defined $ext and $ext ne $1) { + # more than one ext/$ext/ + undef $ext; + last; + } + $ext = $1; + } + elsif (m{^t/lib/}) { + next; + } + else { + undef $ext; + last; + } + } + + if (defined $ext) { + $map = { '' => $ext }, + } + else { + (my $base = $module_name) =~ s{::}{/}g; + $base ="lib/$base"; + $map = { + 'lib/' => 'lib/', + '' => "$base/", + }; + } + return $excluded, $map; +} + + +# Given an exclude list and a mapping hash, convert a CPAN filename +# (eg 't/bar.t') to the equivalent perl filename (eg 'lib/Foo/Bar/t/bar.t'). +# Returns an empty list for an excluded file + +sub cpan_to_perl { + my ($excluded, $map, $cpan_file) = @_; + + for my $exclude (@$excluded) { + # may be a simple string to match exactly, or a pattern + if (ref $exclude) { + return if $cpan_file =~ $exclude; + } + else { + return if $cpan_file eq $exclude; + } + } + + my $perl_file = $cpan_file; + + # try longest prefix first, then alphabetically on tie-break + for my $prefix (sort { length($b) <=> length($a) || $a cmp $b } keys %$map) + { + last if $perl_file =~ s/^\Q$prefix/$map->{$prefix}/; + } + return $perl_file; +} + + + +# do LWP::Simple::getstore, possibly without LWP::Simple being available + +my $lwp_simple_available; + +sub my_getstore { + my ($url, $file) = @_; + unless (defined $lwp_simple_available) { + eval { require LWP::Simple }; + $lwp_simple_available = $@ eq ''; + } + if ($lwp_simple_available) { + return LWP::Simple::is_success(LWP::Simple::getstore($url, $file)); + } + else { + return system(WGET_CMD, "-O", $file, $url) == 0; + } +} + + +# download and unpack a distribution +# Returns the full pathname of the extracted directory +# (eg '/tmp/XYZ/Foo_bar-1.23') + +# cache_dir: where to dowenload the .tar.gz file to +# untar_dir: where to untar or unzup the file +# module: name of module +# dist: name of the distribution + +sub get_distribution { + my ($cache_dir, $untar_dir, $module, $dist) = @_; + + $dist =~ m{.+/([^/]+)$} + or die "ERROR: $module: invalid DISTRIBUTION name (no AUTHOR/ prefix): $dist"; + my $filename = $1; + + my $download_dir = $cache_dir || File::Temp::tempdir( CLEANUP => 1 ); + my $download_file = File::Spec->catfile($download_dir, $filename); + + # download distribution + + if (-f $download_file and ! -s $download_file ) { + # wget can leave a zero-length file on failed download + unlink $download_file; + } + + unless (-f $download_file) { + # not cached + $dist =~ /^([A-Z])([A-Z])/ + or die "ERROR: $module: invalid DISTRIBUTION name (not /^[A-Z]{2}/): $dist"; + + my $url = "http://www.cpan.org/modules/by-authors/id/$1/$1$2/$dist"; + my_getstore($url, $download_file) + or die "ERROR: Could not fetch '$url'"; + } + + # extract distribution + + my $ae = Archive::Extract->new( archive => $download_file); + $ae->extract( to => $untar_dir ) + or die "ERROR: failed to extract distribution '$download_file to temp. dir: " . $ae->error(); + + # get the name of the extracted distribution dir + + my $path = File::Spec->catfile($untar_dir, $filename); + + $path =~ s/\.tar\.gz$// or + $path =~ s/\.zip$// or + die "ERROR: downloaded file does not have a recognised suffix: $path\n"; + + die "ERROR: Extracted tarball does not appear as $path\n" unless -d $path; + + return $path; +} + + +# produce the diff of a single file +sub file_diff { + my $outfh = shift; + my $cpan_file = shift; + my $perl_file = shift; + my $reverse = shift; + my $diff_opts = shift; + + + my @cmd = (DIFF_CMD, split ' ', $diff_opts); + if ($reverse) { + push @cmd, $perl_file, $cpan_file; + } + else { + push @cmd, $cpan_file, $perl_file; + } + my $result = `@cmd`; + + $result =~ s{^(--- |\+\+\+ )/tmp/[^/]+/}{$1}gm; + + print $outfh $result; +} + + +run(); + diff --git a/Porting/expand-macro.pl b/Porting/expand-macro.pl index 2cdaa79727..ed8e188efa 100644 --- a/Porting/expand-macro.pl +++ b/Porting/expand-macro.pl @@ -32,6 +32,7 @@ if (!(@ARGV = @headers)) { while (<$fh>) { push @ARGV, $1 if m!^([^/]+\.h)\t!; } + push @ARGV, 'config.h' if -f 'config.h'; } my $header; @@ -56,7 +57,12 @@ my $sentinel = "$macro expands to"; print $out <<"EOF"; #include "EXTERN.h" #include "perl.h" -#include "$header" +EOF + +print qq{#include "$header"\n} + unless $header eq 'perl.h' or $header eq 'EXTERN.h'; + +print $out <<"EOF"; #line 4 "$sentinel" $macro$args EOF @@ -1354,6 +1354,7 @@ paRxo |void* |get_arena |const size_t svtype|const U32 misc #if defined(PERL_IN_HV_C) || defined(PERL_DECL_PROT) s |void |hsplit |NN HV *hv s |void |hfreeentries |NN HV *hv +s |I32 |anonymise_cv |NULLOK const char *stash|NN SV *val sa |HE* |new_he sanR |HEK* |save_hek_flags |NN const char *str|I32 len|U32 hash|int flags sn |void |hv_magic_check |NN HV *hv|NN bool *needs_copy|NN bool *needs_store @@ -1593,7 +1594,7 @@ Es |UV |reg_recode |const char value|NN SV **encp Es |regnode*|regpiece |NN struct RExC_state_t *pRExC_state \ |NN I32 *flagp|U32 depth Es |regnode*|reg_namedseq |NN struct RExC_state_t *pRExC_state \ - |NULLOK UV *valuep + |NULLOK UV *valuep|NULLOK I32 *flagp Es |void |reginsert |NN struct RExC_state_t *pRExC_state \ |U8 op|NN regnode *opnd|U32 depth Es |void |regtail |NN struct RExC_state_t *pRExC_state \ @@ -1833,7 +1834,7 @@ s |const char *|vdie_croak_common|NULLOK const char *pat|NULLOK va_list *args \ s |bool |vdie_common |NULLOK const char *message|STRLEN msglen\ |I32 utf8|bool warn sr |char * |write_no_mem -#if defined(PERL_MEM_LOG) && defined(PERL_MEM_LOG_STDERR) +#if defined(PERL_MEM_LOG) && !defined(PERL_MEM_LOG_NOIMPL) sn |void |mem_log_common |enum mem_log_type mlt|const UV n|const UV typesize \ |NN const char *type_name|NULLOK const SV *sv \ |Malloc_t oldalloc|Malloc_t newalloc \ @@ -1179,6 +1179,7 @@ #ifdef PERL_CORE #define hsplit S_hsplit #define hfreeentries S_hfreeentries +#define anonymise_cv S_anonymise_cv #define new_he S_new_he #define save_hek_flags S_save_hek_flags #define hv_magic_check S_hv_magic_check @@ -1621,7 +1622,7 @@ #define vdie_common S_vdie_common #define write_no_mem S_write_no_mem #endif -#if defined(PERL_MEM_LOG) && defined(PERL_MEM_LOG_STDERR) +#if defined(PERL_MEM_LOG) && !defined(PERL_MEM_LOG_NOIMPL) #ifdef PERL_CORE #define mem_log_common S_mem_log_common #endif @@ -3515,6 +3516,7 @@ #ifdef PERL_CORE #define hsplit(a) S_hsplit(aTHX_ a) #define hfreeentries(a) S_hfreeentries(aTHX_ a) +#define anonymise_cv(a,b) S_anonymise_cv(aTHX_ a,b) #define new_he() S_new_he(aTHX) #define save_hek_flags S_save_hek_flags #define hv_magic_check S_hv_magic_check @@ -3756,7 +3758,7 @@ #define reg_node(a,b) S_reg_node(aTHX_ a,b) #define reg_recode(a,b) S_reg_recode(aTHX_ a,b) #define regpiece(a,b,c) S_regpiece(aTHX_ a,b,c) -#define reg_namedseq(a,b) S_reg_namedseq(aTHX_ a,b) +#define reg_namedseq(a,b,c) S_reg_namedseq(aTHX_ a,b,c) #define reginsert(a,b,c,d) S_reginsert(aTHX_ a,b,c,d) #define regtail(a,b,c,d) S_regtail(aTHX_ a,b,c,d) #define reg_scan_name(a,b) S_reg_scan_name(aTHX_ a,b) @@ -3968,7 +3970,7 @@ #define vdie_common(a,b,c,d) S_vdie_common(aTHX_ a,b,c,d) #define write_no_mem() S_write_no_mem(aTHX) #endif -#if defined(PERL_MEM_LOG) && defined(PERL_MEM_LOG_STDERR) +#if defined(PERL_MEM_LOG) && !defined(PERL_MEM_LOG_NOIMPL) #ifdef PERL_CORE #define mem_log_common S_mem_log_common #endif diff --git a/ext/threads-shared/Makefile.PL b/ext/threads-shared/Makefile.PL index 78566171db..05c738397f 100755 --- a/ext/threads-shared/Makefile.PL +++ b/ext/threads-shared/Makefile.PL @@ -62,7 +62,7 @@ if (not grep { $_ eq 'PERL_CORE=1' } @ARGV) { 'Carp' => 0, 'XSLoader' => 0, 'Scalar::Util' => 0, - 'threads' => 1.71, + 'threads' => 1.73, 'Test' => 0, 'Test::More' => 0, diff --git a/ext/threads-shared/shared.pm b/ext/threads-shared/shared.pm index 6f606b0181..722e3ceb73 100644 --- a/ext/threads-shared/shared.pm +++ b/ext/threads-shared/shared.pm @@ -7,7 +7,7 @@ use warnings; use Scalar::Util qw(reftype refaddr blessed); -our $VERSION = '1.28'; +our $VERSION = '1.29'; my $XS_VERSION = $VERSION; $VERSION = eval $VERSION; @@ -187,7 +187,7 @@ threads::shared - Perl extension for sharing data structures between threads =head1 VERSION -This document describes threads::shared version 1.28 +This document describes threads::shared version 1.29 =head1 SYNOPSIS @@ -401,7 +401,7 @@ important to check the value of the variable and go back to waiting if the requirement is not fulfilled. For example, to pause until a shared counter drops to zero: - { lock($counter); cond_wait($count) until $counter == 0; } + { lock($counter); cond_wait($counter) until $counter == 0; } =item cond_timedwait VARIABLE, ABS_TIMEOUT @@ -588,7 +588,7 @@ L<threads::shared> Discussion Forum on CPAN: L<http://www.cpanforum.com/dist/threads-shared> Annotated POD for L<threads::shared>: -L<http://annocpan.org/~JDHEDDEN/threads-shared-1.28/shared.pm> +L<http://annocpan.org/~JDHEDDEN/threads-shared-1.29/shared.pm> Source repository: L<http://code.google.com/p/threads-shared/> diff --git a/ext/threads-shared/t/0nothread.t b/ext/threads-shared/t/0nothread.t index 36b1564a52..7609fbee1e 100644 --- a/ext/threads-shared/t/0nothread.t +++ b/ext/threads-shared/t/0nothread.t @@ -1,13 +1,6 @@ use strict; use warnings; -BEGIN { - if ($ENV{'PERL_CORE'}){ - chdir 't'; - unshift @INC, '../lib'; - } -} - use Test::More (tests => 53); ### Start of Testing ### @@ -65,7 +58,7 @@ sub array ok((require threads::shared),"Require module"); -if ($threads::shared::VERSION && ! exists($ENV{'PERL_CORE'})) { +if ($threads::shared::VERSION && ! $ENV{'PERL_CORE'}) { diag('Testing threads::shared ' . $threads::shared::VERSION); } diff --git a/ext/threads-shared/t/av_refs.t b/ext/threads-shared/t/av_refs.t index 2e77031280..8106e3253a 100644 --- a/ext/threads-shared/t/av_refs.t +++ b/ext/threads-shared/t/av_refs.t @@ -2,10 +2,6 @@ use strict; use warnings; BEGIN { - if ($ENV{'PERL_CORE'}){ - chdir 't'; - unshift @INC, '../lib'; - } use Config; if (! $Config{'useithreads'}) { print("1..0 # SKIP Perl not compiled with 'useithreads'\n"); diff --git a/ext/threads-shared/t/av_simple.t b/ext/threads-shared/t/av_simple.t index 67d9a32f3a..7fab9b2b76 100644 --- a/ext/threads-shared/t/av_simple.t +++ b/ext/threads-shared/t/av_simple.t @@ -2,10 +2,6 @@ use strict; use warnings; BEGIN { - if ($ENV{'PERL_CORE'}){ - chdir 't'; - unshift @INC, '../lib'; - } use Config; if (! $Config{'useithreads'}) { print("1..0 # SKIP Perl not compiled with 'useithreads'\n"); diff --git a/ext/threads-shared/t/blessed.t b/ext/threads-shared/t/blessed.t index 225725f6f9..2599423434 100644 --- a/ext/threads-shared/t/blessed.t +++ b/ext/threads-shared/t/blessed.t @@ -2,10 +2,6 @@ use strict; use warnings; BEGIN { - if ($ENV{'PERL_CORE'}){ - chdir 't'; - unshift @INC, '../lib'; - } use Config; if (! $Config{'useithreads'}) { print("1..0 # SKIP Perl not compiled with 'useithreads'\n"); diff --git a/ext/threads-shared/t/clone.t b/ext/threads-shared/t/clone.t index 64ef93a74e..fd31181126 100644 --- a/ext/threads-shared/t/clone.t +++ b/ext/threads-shared/t/clone.t @@ -2,10 +2,6 @@ use strict; use warnings; BEGIN { - if ($ENV{'PERL_CORE'}){ - chdir 't'; - unshift @INC, '../lib'; - } use Config; if (! $Config{'useithreads'}) { print("1..0 # SKIP Perl not compiled with 'useithreads'\n"); diff --git a/ext/threads-shared/t/cond.t b/ext/threads-shared/t/cond.t index 3a6bfdf438..c2f02a42ed 100644 --- a/ext/threads-shared/t/cond.t +++ b/ext/threads-shared/t/cond.t @@ -2,10 +2,6 @@ use strict; use warnings; BEGIN { - if ($ENV{'PERL_CORE'}){ - chdir 't'; - unshift @INC, '../lib'; - } use Config; if (! $Config{'useithreads'}) { print("1..0 # SKIP Perl not compiled with 'useithreads'\n"); diff --git a/ext/threads-shared/t/disabled.t b/ext/threads-shared/t/disabled.t index 161bc7909e..46e781e494 100644 --- a/ext/threads-shared/t/disabled.t +++ b/ext/threads-shared/t/disabled.t @@ -1,13 +1,6 @@ use strict; use warnings; -BEGIN { - if ($ENV{'PERL_CORE'}){ - chdir 't'; - unshift @INC, '../lib'; - } -} - use Test; plan tests => 31; diff --git a/ext/threads-shared/t/hv_refs.t b/ext/threads-shared/t/hv_refs.t index 3985b3c3bb..ecefdc6d5b 100644 --- a/ext/threads-shared/t/hv_refs.t +++ b/ext/threads-shared/t/hv_refs.t @@ -2,10 +2,6 @@ use strict; use warnings; BEGIN { - if ($ENV{'PERL_CORE'}){ - chdir 't'; - unshift @INC, '../lib'; - } use Config; if (! $Config{'useithreads'}) { print("1..0 # SKIP Perl not compiled with 'useithreads'\n"); diff --git a/ext/threads-shared/t/hv_simple.t b/ext/threads-shared/t/hv_simple.t index e80cd0882d..574d8d5508 100644 --- a/ext/threads-shared/t/hv_simple.t +++ b/ext/threads-shared/t/hv_simple.t @@ -2,10 +2,6 @@ use strict; use warnings; BEGIN { - if ($ENV{'PERL_CORE'}){ - chdir 't'; - unshift @INC, '../lib'; - } use Config; if (! $Config{'useithreads'}) { print("1..0 # SKIP Perl not compiled with 'useithreads'\n"); diff --git a/ext/threads-shared/t/no_share.t b/ext/threads-shared/t/no_share.t index 7c97b228ab..21703ae664 100644 --- a/ext/threads-shared/t/no_share.t +++ b/ext/threads-shared/t/no_share.t @@ -2,10 +2,6 @@ use strict; use warnings; BEGIN { - if ($ENV{'PERL_CORE'}){ - chdir 't'; - unshift @INC, '../lib'; - } use Config; if (! $Config{'useithreads'}) { print("1..0 # SKIP Perl not compiled with 'useithreads'\n"); diff --git a/ext/threads-shared/t/object.t b/ext/threads-shared/t/object.t index 394ed6a581..4e3c189037 100644 --- a/ext/threads-shared/t/object.t +++ b/ext/threads-shared/t/object.t @@ -2,10 +2,6 @@ use strict; use warnings; BEGIN { - if ($ENV{'PERL_CORE'}){ - chdir 't'; - unshift @INC, '../lib'; - } use Config; if (! $Config{'useithreads'}) { print("1..0 # SKIP Perl not compiled with 'useithreads'\n"); diff --git a/ext/threads-shared/t/shared_attr.t b/ext/threads-shared/t/shared_attr.t index 09f231032e..9085e27f30 100644 --- a/ext/threads-shared/t/shared_attr.t +++ b/ext/threads-shared/t/shared_attr.t @@ -2,10 +2,6 @@ use strict; use warnings; BEGIN { - if ($ENV{'PERL_CORE'}){ - chdir 't'; - unshift @INC, '../lib'; - } use Config; if (! $Config{'useithreads'}) { print("1..0 # SKIP Perl not compiled with 'useithreads'\n"); diff --git a/ext/threads-shared/t/stress.t b/ext/threads-shared/t/stress.t index 9fe1c217d1..e36ab0ab3a 100644 --- a/ext/threads-shared/t/stress.t +++ b/ext/threads-shared/t/stress.t @@ -2,10 +2,6 @@ use strict; use warnings; BEGIN { - if ($ENV{'PERL_CORE'}){ - chdir 't'; - unshift @INC, '../lib'; - } use Config; if (! $Config{'useithreads'}) { print("1..0 # SKIP Perl not compiled with 'useithreads'\n"); diff --git a/ext/threads-shared/t/sv_refs.t b/ext/threads-shared/t/sv_refs.t index 30173bd29e..5cc6a22ecd 100644 --- a/ext/threads-shared/t/sv_refs.t +++ b/ext/threads-shared/t/sv_refs.t @@ -2,10 +2,6 @@ use strict; use warnings; BEGIN { - if ($ENV{'PERL_CORE'}){ - chdir 't'; - unshift @INC, '../lib'; - } use Config; if (! $Config{'useithreads'}) { print("1..0 # SKIP Perl not compiled with 'useithreads'\n"); diff --git a/ext/threads-shared/t/sv_simple.t b/ext/threads-shared/t/sv_simple.t index f4cbcf280b..9d264f7d31 100644 --- a/ext/threads-shared/t/sv_simple.t +++ b/ext/threads-shared/t/sv_simple.t @@ -2,10 +2,6 @@ use strict; use warnings; BEGIN { - if ($ENV{'PERL_CORE'}){ - chdir 't'; - unshift @INC, '../lib'; - } use Config; if (! $Config{'useithreads'}) { print("1..0 # SKIP Perl not compiled with 'useithreads'\n"); diff --git a/ext/threads-shared/t/utf8.t b/ext/threads-shared/t/utf8.t index 42e7c3f414..6e0e664d1c 100644 --- a/ext/threads-shared/t/utf8.t +++ b/ext/threads-shared/t/utf8.t @@ -2,10 +2,6 @@ use strict; use warnings; BEGIN { - if ($ENV{'PERL_CORE'}){ - chdir 't'; - unshift @INC, '../lib'; - } use Config; if (! $Config{'useithreads'}) { print("1..0 # SKIP Perl not compiled with 'useithreads'\n"); diff --git a/ext/threads-shared/t/wait.t b/ext/threads-shared/t/wait.t index b0a7cc1e85..2c367fd075 100644 --- a/ext/threads-shared/t/wait.t +++ b/ext/threads-shared/t/wait.t @@ -2,11 +2,6 @@ use strict; use warnings; BEGIN { - if ($ENV{'PERL_CORE'}){ - chdir 't'; - unshift @INC, '../lib'; - } - # Import test.pl into its own package { package Test; diff --git a/ext/threads-shared/t/waithires.t b/ext/threads-shared/t/waithires.t index 4cda602f9e..ae82448f57 100644 --- a/ext/threads-shared/t/waithires.t +++ b/ext/threads-shared/t/waithires.t @@ -2,11 +2,6 @@ use strict; use warnings; BEGIN { - if ($ENV{'PERL_CORE'}){ - chdir 't'; - unshift @INC, '../lib'; - } - # Import test.pl into its own package { package Test; @@ -761,7 +761,7 @@ PoisonWith(0xEF) for catching access to freed memory. * which more importantly get the immediate calling environment (file and * line number, and C function name if available) passed in. This info can * then be used for logging the calls, for which one gets a sample - * implementation if PERL_MEM_LOG_STDERR is defined. + * implementation unless -DPERL_MEM_LOG_NOIMPL is also defined. * * Known problems: * - all memory allocs do not get logged, only those @@ -783,6 +783,8 @@ PoisonWith(0xEF) for catching access to freed memory. * (keyed by the allocation address?), and maintain that * through reallocs and frees, but how to do that without * any News() happening...? + * - lots of -Ddefines to get useful/controllable output + * - lots of ENV reads */ PERL_EXPORT_C Malloc_t Perl_mem_log_alloc(const UV n, const UV typesize, const char *type_name, Malloc_t newalloc, const char *filename, const int linenumber, const char *funcname); @@ -792,7 +794,7 @@ PERL_EXPORT_C Malloc_t Perl_mem_log_realloc(const UV n, const UV typesize, const PERL_EXPORT_C Malloc_t Perl_mem_log_free(Malloc_t oldalloc, const char *filename, const int linenumber, const char *funcname); # ifdef PERL_CORE -# ifdef PERL_MEM_LOG_STDERR +# ifndef PERL_MEM_LOG_NOIMPL enum mem_log_type { MLT_ALLOC, MLT_REALLOC, @@ -1468,8 +1468,8 @@ Perl_hv_free_ent(pTHX_ HV *hv, register HE *entry) if (!entry) return; val = HeVAL(entry); - if (val && isGV(val) && isGV_with_GP(val) && GvCVu(val) && HvNAME_get(hv)) - mro_method_changed_in(hv); /* deletion of method from stash */ + if (HvNAME(hv) && anonymise_cv(HvNAME(hv), val) && GvCVu(val)) + mro_method_changed_in(hv); SvREFCNT_dec(val); if (HeKLEN(entry) == HEf_SVKEY) { SvREFCNT_dec(HeKEY_sv(entry)); @@ -1482,6 +1482,29 @@ Perl_hv_free_ent(pTHX_ HV *hv, register HE *entry) del_HE(entry); } +static I32 +S_anonymise_cv(pTHX_ const char *stash, SV *val) +{ + CV *cv; + + PERL_ARGS_ASSERT_ANONYMISE_CV; + + if (val && isGV(val) && isGV_with_GP(val) && (cv = GvCV(val))) { + if ((SV *)CvGV(cv) == val) { + SV *gvname; + GV *anongv; + + gvname = Perl_newSVpvf(aTHX_ "%s::__ANON__", stash ? stash : "__ANON__"); + anongv = gv_fetchsv(gvname, GV_ADDMULTI, SVt_PVCV); + SvREFCNT_dec(gvname); + CvGV(cv) = anongv; + CvANON_on(cv); + return 1; + } + } + return 0; +} + void Perl_hv_delayfree_ent(pTHX_ HV *hv, register HE *entry) { @@ -1646,6 +1669,22 @@ S_hfreeentries(pTHX_ HV *hv) if (!orig_array) return; + if (HvNAME(hv) && orig_array != NULL) { + /* symbol table: make all the contained subs ANON */ + STRLEN i; + XPVHV *xhv = (XPVHV*)SvANY(hv); + + for (i = 0; i <= xhv->xhv_max; i++) { + HE *entry = (HvARRAY(hv))[i]; + for (; entry; entry = HeNEXT(entry)) { + SV *val = HeVAL(entry); + /* we need to put the subs in the __ANON__ symtable, as + * this one is being cleared. */ + anonymise_cv(NULL, val); + } + } + } + if (SvOOK(hv)) { /* If the hash is actually a symbol table with a name, look after the name. */ diff --git a/lib/CPANPLUS/t/031_CPANPLUS-Internals-Source-SQLite.t b/lib/CPANPLUS/t/031_CPANPLUS-Internals-Source-SQLite.t deleted file mode 100644 index 730e04bd14..0000000000 --- a/lib/CPANPLUS/t/031_CPANPLUS-Internals-Source-SQLite.t +++ /dev/null @@ -1,80 +0,0 @@ -### make sure we can find our conf.pl file -BEGIN { - use FindBin; - require "$FindBin::Bin/inc/conf.pl"; -} - -use strict; - -use Module::Load; -use Test::More eval { load 'CPANPLUS::Internals::Source::SQLite'; 1 } - ? 'no_plan' - : (skip_all => "SQLite engine not available"); - -use Data::Dumper; -use File::Basename qw[dirname]; -use CPANPLUS::Error; -use CPANPLUS::Backend; -use CPANPLUS::Internals::Constants; - -my $conf = gimme_conf(); - -### make sure we use the SQLite engine -$conf->set_conf( source_engine => 'CPANPLUS::Internals::Source::SQLite' ); - -my $cb = CPANPLUS::Backend->new( $conf ); -my $mod = TEST_CONF_MODULE; -my $auth = TEST_CONF_AUTHOR; - -ok( $cb->reload_indices( update_source => 1 ), - "Building trees" ); -ok( $cb->__sqlite_dbh, " Got a DBH " ); -ok( $cb->__sqlite_file, " Got a DB file" ); - - -### make sure we have trees and they're hashes -{ ok( $cb->author_tree, "Got author tree" ); - isa_ok( $cb->author_tree, "HASH" ); - - ok( $cb->module_tree, "Got module tree" ); - isa_ok( $cb->module_tree, "HASH" ); -} - -### save state, shouldn't work -{ CPANPLUS::Error->flush; - my $rv = $cb->save_state; - - ok( !$rv, "Saving state not implemented" ); - like( CPANPLUS::Error->stack_as_string, qr/not implemented/i, - " Diagnostics confirmed" ); -} - -### test look ups -{ my %map = ( - $auth => 'author_tree', - $mod => 'module_tree', - ); - - while( my($str, $meth) = each %map ) { - - ok( $str, "Trying to retrieve $str" ); - ok( $cb->$meth( $str ), " Got $str object via ->$meth" ); - ok( $cb->$meth->{$str}, " Got author object via ->{ $str }" ); - ok( exists $cb->$meth->{ $str }, - " Testing exists() " ); - ok( not(exists( $cb->$meth->{ $$ } )), - " And non-exists() " ); - cmp_ok( scalar(keys(%{ $cb->$meth })), ">", 1, - " Got keys()" ); - - cmp_ok( scalar(keys(%{ $cb->$meth })), '==', scalar(keys(%{ $cb->$meth })), - " Keys == Values" ); - - while( my($key,$val) = each %{ $cb->$meth } ) { - ok( $key, " Retrieved $key via each()" ); - ok( $val, " And value" ); - ok( ref $val, " Value is a ref: $val" ); - can_ok( $val, '_id' ); - } - } -} diff --git a/lib/CPANPLUS/t/032_CPANPLUS-Internals-Source-via-sqlite.t b/lib/CPANPLUS/t/032_CPANPLUS-Internals-Source-via-sqlite.t deleted file mode 100644 index 46505f53e8..0000000000 --- a/lib/CPANPLUS/t/032_CPANPLUS-Internals-Source-via-sqlite.t +++ /dev/null @@ -1,14 +0,0 @@ -use strict; -use FindBin; - -use Module::Load; - -local $ENV{CPANPLUS_SOURCE_ENGINE} = 'CPANPLUS::Internals::Source::SQLite'; - -my $old = select STDERR; $|++; -select $old; $|++; -my $rv = do("$FindBin::Bin/03_CPANPLUS-Internals-Source.t") or do { - die $@ if $@; - die $! if $!; -}; - diff --git a/lib/Module/Build.pm b/lib/Module/Build.pm index fe453b5d67..ae9639a512 100644 --- a/lib/Module/Build.pm +++ b/lib/Module/Build.pm @@ -15,7 +15,7 @@ use Module::Build::Base; use vars qw($VERSION @ISA); @ISA = qw(Module::Build::Base); -$VERSION = '0.32_01'; +$VERSION = '0.33_02'; $VERSION = eval $VERSION; # Okay, this is the brute-force method of finding out what kind of @@ -312,10 +312,9 @@ module for source distribution through a medium like CPAN. It will create a tarball of the files listed in F<MANIFEST> and compress the tarball using GZIP compression. -By default, this action will use the external C<tar> and C<gzip> -executables on Unix-like platforms, and the C<Archive::Tar> module -elsewhere. However, you can force it to use whatever executable you -want by supplying an explicit C<tar> (and optional C<gzip>) parameter: +By default, this action will use the C<Archive::Tar> module. However, you can +force it to use binary "tar" and "gzip" executables by supplying an explicit +C<tar> (and optional C<gzip>) parameter: ./Build dist --tar C:\path\to\tar.exe --gzip C:\path\to\zip.exe diff --git a/lib/Module/Build/API.pod b/lib/Module/Build/API.pod index 83e93f5ccb..ab0691bf30 100644 --- a/lib/Module/Build/API.pod +++ b/lib/Module/Build/API.pod @@ -182,6 +182,16 @@ installed. See the documentation for L<Module::Build::Authoring/"PREREQUISITES"> for the details of how requirements can be specified. +=item create_license + +[version 0.31] + +This parameter tells Module::Build to automatically create a +F<LICENSE> file at the top level of your distribution, containing the +full text of the author's chosen license. This requires +C<Software::License> on the author's machine, and further requires +that the C<license> parameter specifies a license that it knows about. + =item create_makefile_pl [version 0.19] diff --git a/lib/Module/Build/Authoring.pod b/lib/Module/Build/Authoring.pod index 871effdf69..a0a7dc37be 100644 --- a/lib/Module/Build/Authoring.pod +++ b/lib/Module/Build/Authoring.pod @@ -159,7 +159,8 @@ or C<CPANPLUS> will be expected to pick C<configure_requires> out of the F<META.yml> file and install these items before running the C<Build.PL>. -*TODO* auto-add M::B? In what circumstances? +If no configure_requires is specified, the current version of Module::Build +is automatically added to configure_requires. =item build_requires diff --git a/lib/Module/Build/Base.pm b/lib/Module/Build/Base.pm index 703218b56c..2f6282e871 100644 --- a/lib/Module/Build/Base.pm +++ b/lib/Module/Build/Base.pm @@ -4,7 +4,7 @@ package Module::Build::Base; use strict; use vars qw($VERSION); -$VERSION = '0.32_01'; +$VERSION = '0.33_02'; $VERSION = eval $VERSION; BEGIN { require 5.00503 } @@ -129,6 +129,7 @@ sub _construct { %input, }, phash => {}, + stash => {}, # temporary caching, not stored in _build }, $package; $self->_set_defaults; @@ -1039,7 +1040,7 @@ sub dist_version { my $version_from = File::Spec->catfile( split( qr{/}, $dist_version_from ) ); my $pm_info = Module::Build::ModuleInfo->new_from_file( $version_from ) or die "Can't find file $version_from to determine version"; - $p->{dist_version} = $pm_info->version(); + $p->{dist_version} = $self->normalize_version( $pm_info->version() ); } die ("Can't determine distribution version, must supply either 'dist_version',\n". @@ -3424,7 +3425,7 @@ sub file_qr { sub dist_dir { my ($self) = @_; - return "$self->{properties}{dist_name}-$self->{properties}{dist_version}"; + return join "-", $self->dist_name, $self->dist_version; } sub ppm_name { @@ -3566,34 +3567,71 @@ sub do_create_metafile { push @INC, File::Spec->catdir($self->blib, 'lib'); } - $self->write_metafile; + if ( $self->write_metafile( $self->metafile, $self->generate_metadata ) ) { + $self->{wrote_metadata} = 1; + $self->_add_to_manifest('MANIFEST', $metafile); + } + + return 1; } -sub write_metafile { +sub generate_metadata { my $self = shift; - my $metafile = $self->metafile; + my $node = {}; if ($self->_mb_feature('YAML_support')) { require YAML; require YAML::Node; - # We use YAML::Node to get the order nice in the YAML file. - $self->prepare_metadata( my $node = YAML::Node->new({}) ); - + $self->prepare_metadata( $node = YAML::Node->new({}) ); + } else { + require Module::Build::YAML; + my @order_keys; + $self->prepare_metadata($node, \@order_keys); + $node->{_order} = \@order_keys; + } + return $node; +} + +sub write_metafile { + my $self = shift; + my ($metafile, $node) = @_; + + if ($self->_mb_feature('YAML_support')) { + # XXX this is probably redundant, but stick with it + require YAML; + require YAML::Node; + delete $node->{_order}; # XXX also probably redundant, but for safety # YAML API changed after version 0.30 my $yaml_sub = $YAML::VERSION le '0.30' ? \&YAML::StoreFile : \&YAML::DumpFile; - $self->{wrote_metadata} = $yaml_sub->($metafile, $node ); - + $yaml_sub->( $metafile, $node ); } else { + # XXX probably redundant require Module::Build::YAML; - my (%node, @order_keys); - $self->prepare_metadata(\%node, \@order_keys); - $node{_order} = \@order_keys; - &Module::Build::YAML::DumpFile($metafile, \%node); - $self->{wrote_metadata} = 1; + &Module::Build::YAML::DumpFile($metafile, $node); } + return 1; +} - $self->_add_to_manifest('MANIFEST', $metafile); +sub normalize_version { + my ($self, $version) = @_; + if ( $version =~ /[=<>!,]/ ) { # logic, not just version + # take as is without modification + } + elsif ( ref $version eq 'version' || + ref $version eq 'Module::Build::Version' ) { # version objects + my $string = $version->stringify; + # normalize leading-v: "v1.2" -> "v1.2.0" + $version = substr($string,0,1) eq 'v' ? $version->normal : $string; + } + elsif ( $version =~ /^[^v][^.]*\.[^.]+\./ ) { # no leading v, multiple dots + # normalize string tuples without "v": "1.2.3" -> "v1.2.3" + $version = "v$version"; + } + else { + # leave alone + } + return $version; } sub prepare_metadata { @@ -3613,38 +3651,57 @@ sub prepare_metadata { die "ERROR: Missing required field '$_' for META.yml\n" unless defined($node->{$name}) && length($node->{$name}); } - $node->{version} = '' . $node->{version}; # Stringify version objects + $node->{version} = $self->normalize_version($node->{version}); if (defined( my $l = $self->license )) { die "Unknown license string '$l'" - unless exists $self->valid_licenses->{ $self->license }; + unless exists $self->valid_licenses->{ $l }; - if (my $key = $self->valid_licenses->{ $self->license }) { + if (my $key = $self->valid_licenses->{ $l }) { my $class = "Software::License::$key"; if (eval "use $class; 1") { # S::L requires a 'holder' key $node->{resources}{license} = $class->new({holder=>"nobody"})->url; - } else { - $node->{resources}{license} = $self->_license_url($key); + } + else { + $node->{resources}{license} = $self->_license_url($l); } } + # XXX we are silently omitting the url for any unknown license } if (exists $p->{configure_requires}) { foreach my $spec (keys %{$p->{configure_requires}}) { warn ("Warning: $spec is listed in 'configure_requires', but ". - "it is not found in any of the other prereq fields.\n") - unless grep exists $p->{$_}{$spec}, - grep !/conflicts$/, @{$self->prereq_action_types}; + "it is not found in any of the other prereq fields.\n") + unless grep exists $p->{$_}{$spec}, + grep !/conflicts$/, @{$self->prereq_action_types}; + } + } + + # copy prereq data structures so we can modify them before writing to META + my %prereq_types; + for my $type ( 'configure_requires', @{$self->prereq_action_types} ) { + if (exists $p->{$type}) { + for my $mod ( keys %{ $p->{$type} } ) { + $prereq_types{$type}{$mod} = + $self->normalize_version($p->{$type}{$mod}); + } } } - foreach ( 'configure_requires', @{$self->prereq_action_types} ) { - if (exists $p->{$_} and keys %{ $p->{$_} }) { - $add_node->($_, $p->{$_}); + # add current Module::Build to configure_requires if there + # isn't a configure_requires already specified + if ( ! $prereq_types{'configure_requires'} ) { + for my $t ('configure_requires', 'build_requires') { + $prereq_types{$t}{'Module::Build'} = $VERSION; } } + for my $t ( keys %prereq_types ) { + $add_node->($t, $prereq_types{$t}); + } + if (exists $p->{dynamic_config}) { $add_node->('dynamic_config', $p->{dynamic_config}); } @@ -3663,8 +3720,8 @@ sub prepare_metadata { $add_node->('generated_by', "Module::Build version $Module::Build::VERSION"); $add_node->('meta-spec', - {version => '1.2', - url => 'http://module-build.sourceforge.net/META-spec-v1.2.html', + {version => '1.4', + url => 'http://module-build.sourceforge.net/META-spec-v1.4.html', }); while (my($k, $v) = each %{$self->meta_add}) { @@ -3801,9 +3858,10 @@ sub find_dist_packages { } } - # Stringify versions. Can't use exists() here because of bug in YAML::Node. + # Normalize versions. Can't use exists() here because of bug in YAML::Node. + # XXX "bug in YAML::Node" comment seems irrelvant -- dagolden, 2009-05-18 for (grep defined $_->{version}, values %prime) { - $_->{version} = '' . $_->{version}; + $_->{version} = $self->normalize_version( $_->{version} ); } return \%prime; @@ -4144,13 +4202,13 @@ sub cbuilder { # Returns a CBuilder object my $self = shift; - my $p = $self->{properties}; - return $p->{_cbuilder} if $p->{_cbuilder}; + my $s = $self->{stash}; + return $s->{_cbuilder} if $s->{_cbuilder}; die "Module::Build is not configured with C_support" unless $self->_mb_feature('C_support'); require ExtUtils::CBuilder; - return $p->{_cbuilder} = ExtUtils::CBuilder->new( + return $s->{_cbuilder} = ExtUtils::CBuilder->new( config => $self->config, ($self->quiet ? (quiet => 1 ) : ()), ); diff --git a/lib/Module/Build/Compat.pm b/lib/Module/Build/Compat.pm index 7025f1cef3..b3ace5c5da 100644 --- a/lib/Module/Build/Compat.pm +++ b/lib/Module/Build/Compat.pm @@ -2,7 +2,7 @@ package Module::Build::Compat; use strict; use vars qw($VERSION); -$VERSION = '0.32_01'; +$VERSION = '0.33_02'; use File::Spec; use IO::File; @@ -143,7 +143,9 @@ EOF eval "use Module::Build::Compat 0.02; 1" or die $@; %s Module::Build::Compat->run_build_pl(args => \@ARGV); - exit(0) unless(-e 'Build'); # cpantesters convention + my $build_script = 'Build'; + $build_script .= '.com' if $^O eq 'VMS'; + exit(0) unless(-e $build_script); # cpantesters convention require %s; Module::Build::Compat->write_makefile(build_class => '%s'); EOF @@ -176,7 +178,7 @@ EOF $MM_Args{EXE_FILES} = [ sort keys %{$build->script_files} ] if $build->script_files; - $MM_Args{PL_FILES} = $build->PL_files if $build->PL_files; + $MM_Args{PL_FILES} = $build->PL_files || {}; local $Data::Dumper::Terse = 1; my $args = Data::Dumper::Dumper(\%MM_Args); @@ -288,13 +290,17 @@ all : force_do_it realclean : force_do_it $perl $Build realclean $unlink +distclean : force_do_it + $perl $Build distclean + $unlink + force_do_it : @ $noop EOF foreach my $action ($class->known_actions) { - next if $action =~ /^(all|realclean|force_do_it)$/; # Don't double-define + next if $action =~ /^(all|distclean|realclean|force_do_it)$/; # Don't double-define $maketext .= <<"EOF"; $action : force_do_it $perl $Build $action @@ -501,11 +507,7 @@ ever have to install Module::Build if they use the Makefile.PL, but they won't get to take advantage of Module::Build's extra features either. -If you go this route, make sure you explicitly set C<PL_FILES> in the -call to C<WriteMakefile()> (probably to an empty hash reference), or -else MakeMaker will mistakenly run the Build.PL and you'll get an -error message about "Too early to run Build script" or something. For -good measure, of course, test both the F<Makefile.PL> and the +For good measure, of course, test both the F<Makefile.PL> and the F<Build.PL> before shipping. =item 3. diff --git a/lib/Module/Build/Config.pm b/lib/Module/Build/Config.pm index 194b050973..bf543eb4eb 100644 --- a/lib/Module/Build/Config.pm +++ b/lib/Module/Build/Config.pm @@ -2,7 +2,7 @@ package Module::Build::Config; use strict; use vars qw($VERSION); -$VERSION = '0.32'; +$VERSION = '0.33_02'; $VERSION = eval $VERSION; use Config; diff --git a/lib/Module/Build/ConfigData.pm b/lib/Module/Build/ConfigData.pm index 7bc3998bf1..3f539afd47 100644 --- a/lib/Module/Build/ConfigData.pm +++ b/lib/Module/Build/ConfigData.pm @@ -22,6 +22,9 @@ sub config_names { keys %$config } sub write { my $me = __FILE__; require IO::File; + + # Can't use Module::Build::Dumper here because M::B is only a + # build-time prereq of this module require Data::Dumper; my $mode_orig = (stat $me)[2] & 07777; @@ -33,9 +36,11 @@ sub write { } die "Couldn't find __DATA__ token in $me" if eof($fh); - local $Data::Dumper::Terse = 1; seek($fh, tell($fh), 0); - $fh->print( Data::Dumper::Dumper([$config, $features, $auto_features]) ); + my $data = [$config, $features, $auto_features]; + $fh->print( 'do{ my ' + . Data::Dumper->new([$data],['x'])->Purity(1)->Dump() + . '$x; }' ); truncate($fh, tell($fh)); $fh->close; @@ -159,36 +164,37 @@ authorship claim or copyright claim to the contents of C<Module::Build::ConfigDa __DATA__ -[ - {}, - {}, - { - 'YAML_support' => { - 'requires' => { - 'YAML' => ' >= 0.35, != 0.49_01 ' - }, - 'description' => 'Use YAML.pm to write META.yml files' - }, - 'manpage_support' => { - 'requires' => { - 'Pod::Man' => 0 - }, - 'description' => 'Create Unix man pages' - }, - 'C_support' => { +do{ my $x = [ + {}, + {}, + { + 'YAML_support' => { 'requires' => { - 'ExtUtils::CBuilder' => '0.15' + 'YAML' => ' >= 0.35, != 0.49_01 ' }, - 'recommends' => { - 'ExtUtils::ParseXS' => '1.02' - }, - 'description' => 'Compile/link C & XS code' + 'description' => 'Use YAML.pm to write META.yml files' }, - 'HTML_support' => { + 'manpage_support' => { 'requires' => { - 'Pod::Html' => 0 + 'Pod::Man' => 0 }, - 'description' => 'Create HTML documentation' - } - } - ] + 'description' => 'Create Unix man pages' + }, + 'C_support' => { + 'requires' => { + 'ExtUtils::CBuilder' => '0.15' + }, + 'recommends' => { + 'ExtUtils::ParseXS' => '1.02' + }, + 'description' => 'Compile/link C & XS code' + }, + 'HTML_support' => { + 'requires' => { + 'Pod::Html' => 0 + }, + 'description' => 'Create HTML documentation' + } + } + ]; +$x; }
\ No newline at end of file diff --git a/lib/Module/Build/Cookbook.pm b/lib/Module/Build/Cookbook.pm index e0c85df949..9a76ba095a 100644 --- a/lib/Module/Build/Cookbook.pm +++ b/lib/Module/Build/Cookbook.pm @@ -1,14 +1,13 @@ package Module::Build::Cookbook; use strict; use vars qw($VERSION); -$VERSION = '0.32'; +$VERSION = '0.33_02'; =head1 NAME Module::Build::Cookbook - Examples of Module::Build Usage - =head1 DESCRIPTION C<Module::Build> isn't conceptually very complicated, but examples are diff --git a/lib/Module/Build/Dumper.pm b/lib/Module/Build/Dumper.pm index f3751bfeb2..3765c84c51 100644 --- a/lib/Module/Build/Dumper.pm +++ b/lib/Module/Build/Dumper.pm @@ -1,7 +1,7 @@ package Module::Build::Dumper; use strict; use vars qw($VERSION); -$VERSION = '0.32'; +$VERSION = '0.33_02'; # This is just a split-out of a wrapper function to do Data::Dumper # stuff "the right way". See: diff --git a/lib/Module/Build/ModuleInfo.pm b/lib/Module/Build/ModuleInfo.pm index d9821fe031..eb1d9bf70f 100644 --- a/lib/Module/Build/ModuleInfo.pm +++ b/lib/Module/Build/ModuleInfo.pm @@ -8,7 +8,7 @@ package Module::Build::ModuleInfo; use strict; use vars qw($VERSION); -$VERSION = '0.32'; +$VERSION = '0.33_02'; $VERSION = eval $VERSION; use File::Spec; diff --git a/lib/Module/Build/Notes.pm b/lib/Module/Build/Notes.pm index fca40b7496..3a83b01012 100644 --- a/lib/Module/Build/Notes.pm +++ b/lib/Module/Build/Notes.pm @@ -4,7 +4,7 @@ package Module::Build::Notes; use strict; use vars qw($VERSION); -$VERSION = '0.32'; +$VERSION = '0.33_02'; $VERSION = eval $VERSION; use Data::Dumper; use IO::File; diff --git a/lib/Module/Build/PPMMaker.pm b/lib/Module/Build/PPMMaker.pm index 413608631c..11909ce5c9 100644 --- a/lib/Module/Build/PPMMaker.pm +++ b/lib/Module/Build/PPMMaker.pm @@ -2,7 +2,7 @@ package Module::Build::PPMMaker; use strict; use vars qw($VERSION); -$VERSION = '0.32'; +$VERSION = '0.33_02'; $VERSION = eval $VERSION; # This code is mostly borrowed from ExtUtils::MM_Unix 6.10_03, with a @@ -130,8 +130,10 @@ sub _varchname { # Copied from PPM.pm my ($self, $config) = @_; my $varchname = $config->{archname}; # Append "-5.8" to architecture name for Perl 5.8 and later - if (defined($^V) && ord(substr($^V,1)) >= 8) { - $varchname .= sprintf("-%d.%d", ord($^V), ord(substr($^V,1))); + if ($] >= 5.008) { + my $vstring = sprintf "%vd", $^V; + $vstring =~ s/\.\d+$//; + $varchname .= "-$vstring"; } return $varchname; } diff --git a/lib/Module/Build/Platform/Amiga.pm b/lib/Module/Build/Platform/Amiga.pm index 4f5eb14bfd..ee5c4f9e0e 100644 --- a/lib/Module/Build/Platform/Amiga.pm +++ b/lib/Module/Build/Platform/Amiga.pm @@ -2,7 +2,7 @@ package Module::Build::Platform::Amiga; use strict; use vars qw($VERSION); -$VERSION = '0.32'; +$VERSION = '0.33_02'; $VERSION = eval $VERSION; use Module::Build::Base; diff --git a/lib/Module/Build/Platform/Default.pm b/lib/Module/Build/Platform/Default.pm index c3f6a504ba..98128e259d 100644 --- a/lib/Module/Build/Platform/Default.pm +++ b/lib/Module/Build/Platform/Default.pm @@ -2,7 +2,7 @@ package Module::Build::Platform::Default; use strict; use vars qw($VERSION); -$VERSION = '0.32'; +$VERSION = '0.33_02'; $VERSION = eval $VERSION; use Module::Build::Base; diff --git a/lib/Module/Build/Platform/EBCDIC.pm b/lib/Module/Build/Platform/EBCDIC.pm index 26c3ee5892..9d8a88ac1a 100644 --- a/lib/Module/Build/Platform/EBCDIC.pm +++ b/lib/Module/Build/Platform/EBCDIC.pm @@ -2,7 +2,7 @@ package Module::Build::Platform::EBCDIC; use strict; use vars qw($VERSION); -$VERSION = '0.32'; +$VERSION = '0.33_02'; $VERSION = eval $VERSION; use Module::Build::Base; diff --git a/lib/Module/Build/Platform/MPEiX.pm b/lib/Module/Build/Platform/MPEiX.pm index f59902023c..e4d531c8a0 100644 --- a/lib/Module/Build/Platform/MPEiX.pm +++ b/lib/Module/Build/Platform/MPEiX.pm @@ -2,7 +2,7 @@ package Module::Build::Platform::MPEiX; use strict; use vars qw($VERSION); -$VERSION = '0.32'; +$VERSION = '0.33_02'; $VERSION = eval $VERSION; use Module::Build::Base; diff --git a/lib/Module/Build/Platform/MacOS.pm b/lib/Module/Build/Platform/MacOS.pm index f7e22a3b84..f3b5dcf798 100644 --- a/lib/Module/Build/Platform/MacOS.pm +++ b/lib/Module/Build/Platform/MacOS.pm @@ -2,7 +2,7 @@ package Module::Build::Platform::MacOS; use strict; use vars qw($VERSION); -$VERSION = '0.32'; +$VERSION = '0.33_02'; $VERSION = eval $VERSION; use Module::Build::Base; use vars qw(@ISA); diff --git a/lib/Module/Build/Platform/RiscOS.pm b/lib/Module/Build/Platform/RiscOS.pm index 1f732f5808..458c02d7a9 100644 --- a/lib/Module/Build/Platform/RiscOS.pm +++ b/lib/Module/Build/Platform/RiscOS.pm @@ -2,7 +2,7 @@ package Module::Build::Platform::RiscOS; use strict; use vars qw($VERSION); -$VERSION = '0.32'; +$VERSION = '0.33_02'; $VERSION = eval $VERSION; use Module::Build::Base; diff --git a/lib/Module/Build/Platform/Unix.pm b/lib/Module/Build/Platform/Unix.pm index 498e248d73..e6177c8a17 100644 --- a/lib/Module/Build/Platform/Unix.pm +++ b/lib/Module/Build/Platform/Unix.pm @@ -2,20 +2,13 @@ package Module::Build::Platform::Unix; use strict; use vars qw($VERSION); -$VERSION = '0.32'; +$VERSION = '0.33_02'; $VERSION = eval $VERSION; use Module::Build::Base; use vars qw(@ISA); @ISA = qw(Module::Build::Base); -sub make_tarball { - my $self = shift; - $self->{args}{tar} ||= ['tar']; - $self->{args}{gzip} ||= ['gzip']; - $self->SUPER::make_tarball(@_); -} - sub is_executable { # We consider the owner bit to be authoritative on a file, because # -x will always return true if the user is root and *any* diff --git a/lib/Module/Build/Platform/VMS.pm b/lib/Module/Build/Platform/VMS.pm index 69912c8afc..8175f6cbd2 100644 --- a/lib/Module/Build/Platform/VMS.pm +++ b/lib/Module/Build/Platform/VMS.pm @@ -2,7 +2,7 @@ package Module::Build::Platform::VMS; use strict; use vars qw($VERSION); -$VERSION = '0.32_01'; +$VERSION = '0.33_02'; $VERSION = eval $VERSION; use Module::Build::Base; @@ -229,8 +229,9 @@ sub _infer_xs_spec { =item rscan_dir -Inherit the standard version but remove dots at end of name. This may not be -necessary if File::Find has been fixed or DECC$FILENAME_UNIX_REPORT is in effect. +Inherit the standard version but remove dots at end of name. +If the extended character set is in effect, do not remove dots from filenames +with Unix path delimiters. =cut @@ -239,7 +240,11 @@ sub rscan_dir { my $result = $self->SUPER::rscan_dir( $dir, $pattern ); - for my $file (@$result) { $file =~ s/\.$//; } + for my $file (@$result) { + if (!_efs() && ($file =~ m#/#)) { + $file =~ s/\.$//; + } + } return $result; } @@ -254,7 +259,7 @@ sub dist_dir { my $self = shift; my $dist_dir = $self->SUPER::dist_dir; - $dist_dir =~ s/\./_/g; + $dist_dir =~ s/\./_/g unless _efs(); return $dist_dir; } @@ -322,6 +327,11 @@ sub _detildefy { # break up the paths for the merge my $home = VMS::Filespec::unixify($ENV{HOME}); + # In the default VMS mode, the trailing slash is present. + # In Unix report mode it is not. The parsing logic assumes that + # it is present. + $home .= '/' unless $home =~ m#/$#; + # Trivial case of just ~ by it self if ($spec eq '') { $home =~ s#/$##; @@ -361,9 +371,8 @@ sub _detildefy { # Now put the two cases back together $arg = File::Spec::Unix->catpath($hvol, $newdirs, $file); - } else { - return $arg; } + return $arg; } @@ -376,7 +385,9 @@ lossy. =cut -sub find_perl_interpreter { return $^X; } +sub find_perl_interpreter { + return VMS::Filespec::vmsify($^X); +} =item localize_file_path @@ -386,8 +397,9 @@ Convert the file path to the local syntax sub localize_file_path { my ($self, $path) = @_; + $path = VMS::Filespec::vmsify($path); $path =~ s/\.\z//; - return VMS::Filespec::vmsify($path); + return $path; } =item localize_dir_path @@ -415,6 +427,43 @@ sub ACTION_clean { } } + +# Need to look up the feature settings. The preferred way is to use the +# VMS::Feature module, but that may not be available to dual life modules. + +my $use_feature; +BEGIN { + if (eval { local $SIG{__DIE__}; require VMS::Feature; }) { + $use_feature = 1; + } +} + +# Need to look up the UNIX report mode. This may become a dynamic mode +# in the future. +sub _unix_rpt { + my $unix_rpt; + if ($use_feature) { + $unix_rpt = VMS::Feature::current("filename_unix_report"); + } else { + my $env_unix_rpt = $ENV{'DECC$FILENAME_UNIX_REPORT'} || ''; + $unix_rpt = $env_unix_rpt =~ /^[ET1]/i; + } + return $unix_rpt; +} + +# Need to look up the EFS character set mode. This may become a dynamic +# mode in the future. +sub _efs { + my $efs; + if ($use_feature) { + $efs = VMS::Feature::current("efs_charset"); + } else { + my $env_efs = $ENV{'DECC$EFS_CHARSET'} || ''; + $efs = $env_efs =~ /^[ET1]/i; + } + return $efs; +} + =back =head1 AUTHOR diff --git a/lib/Module/Build/Platform/VOS.pm b/lib/Module/Build/Platform/VOS.pm index ca77134a77..ca7270ff18 100644 --- a/lib/Module/Build/Platform/VOS.pm +++ b/lib/Module/Build/Platform/VOS.pm @@ -2,7 +2,7 @@ package Module::Build::Platform::VOS; use strict; use vars qw($VERSION); -$VERSION = '0.32'; +$VERSION = '0.33_02'; $VERSION = eval $VERSION; use Module::Build::Base; diff --git a/lib/Module/Build/Platform/Windows.pm b/lib/Module/Build/Platform/Windows.pm index c8b412c510..72f0444859 100644 --- a/lib/Module/Build/Platform/Windows.pm +++ b/lib/Module/Build/Platform/Windows.pm @@ -2,7 +2,7 @@ package Module::Build::Platform::Windows; use strict; use vars qw($VERSION); -$VERSION = '0.32'; +$VERSION = '0.33_02'; $VERSION = eval $VERSION; use Config; diff --git a/lib/Module/Build/Platform/aix.pm b/lib/Module/Build/Platform/aix.pm index c8c5b49abc..e2f3eb6861 100644 --- a/lib/Module/Build/Platform/aix.pm +++ b/lib/Module/Build/Platform/aix.pm @@ -2,7 +2,7 @@ package Module::Build::Platform::aix; use strict; use vars qw($VERSION); -$VERSION = '0.32'; +$VERSION = '0.33_02'; $VERSION = eval $VERSION; use Module::Build::Platform::Unix; diff --git a/lib/Module/Build/Platform/cygwin.pm b/lib/Module/Build/Platform/cygwin.pm index 62c6573a61..d9bc6e1c51 100644 --- a/lib/Module/Build/Platform/cygwin.pm +++ b/lib/Module/Build/Platform/cygwin.pm @@ -2,7 +2,7 @@ package Module::Build::Platform::cygwin; use strict; use vars qw($VERSION); -$VERSION = '0.32'; +$VERSION = '0.33_02'; $VERSION = eval $VERSION; use Module::Build::Platform::Unix; diff --git a/lib/Module/Build/Platform/darwin.pm b/lib/Module/Build/Platform/darwin.pm index aa87fb6ef2..173d2b5f85 100644 --- a/lib/Module/Build/Platform/darwin.pm +++ b/lib/Module/Build/Platform/darwin.pm @@ -2,7 +2,7 @@ package Module::Build::Platform::darwin; use strict; use vars qw($VERSION); -$VERSION = '0.32'; +$VERSION = '0.33_02'; $VERSION = eval $VERSION; use Module::Build::Platform::Unix; diff --git a/lib/Module/Build/Platform/os2.pm b/lib/Module/Build/Platform/os2.pm index ba124dd7c9..3e22affe62 100644 --- a/lib/Module/Build/Platform/os2.pm +++ b/lib/Module/Build/Platform/os2.pm @@ -2,7 +2,7 @@ package Module::Build::Platform::os2; use strict; use vars qw($VERSION); -$VERSION = '0.32'; +$VERSION = '0.33_02'; $VERSION = eval $VERSION; use Module::Build::Platform::Unix; diff --git a/lib/Module/Build/PodParser.pm b/lib/Module/Build/PodParser.pm index 0012aab621..142ddfecf8 100644 --- a/lib/Module/Build/PodParser.pm +++ b/lib/Module/Build/PodParser.pm @@ -2,7 +2,7 @@ package Module::Build::PodParser; use strict; use vars qw($VERSION); -$VERSION = '0.32'; +$VERSION = '0.33_02'; $VERSION = eval $VERSION; use vars qw(@ISA); diff --git a/lib/Module/Build/scripts/bundle.pl b/lib/Module/Build/scripts/bundle.pl deleted file mode 100755 index 78de143426..0000000000 --- a/lib/Module/Build/scripts/bundle.pl +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/perl - -# this is just a first crack and it uses File::Fu because I'm lazy. - -=head1 using - -This installs from a fresh Module::Build to your inc/inc_Module-Build -directory. Use it from within your dist: - - perl /path/to/Module-Build/scripts/bundle.pl - -You still need to manually add the following to your Build.PL - - use lib 'inc'; - use latest 'Module::Build'; - -You also need to regen your manifest. - - perl Build.PL - ./Build distmeta; >MANIFEST; ./Build manifest; svn diff MANIFEST - -=cut - -use warnings; -use strict; - -use File::Fu; -use File::Copy (); - -my $inc_dir = shift(@ARGV); -$inc_dir = File::Fu->dir($inc_dir || 'inc/inc_Module-Build'); -$inc_dir->create unless($inc_dir->e); -$inc_dir = $inc_dir->absolutely; - - -my $mb_dir = File::Fu->program_dir->dirname; - -$mb_dir->chdir_for(sub { - my $temp = File::Fu->temp_dir('mb_bundle'); - local @INC = @INC; - unshift(@INC, 'lib', 'inc'); - require Module::Build; - my $builder = Module::Build->new_from_context; - $builder->dispatch(install => - install_base => $temp, - install_path => {lib => $inc_dir}, - ); -}); - -my $latest = $mb_dir/'inc'+'latest.pm'; -File::Copy::copy($latest, 'inc'); - -# vim:ts=2:sw=2:et:sta diff --git a/lib/Module/Build/t/bundled/Tie/CPHash.pm b/lib/Module/Build/t/bundled/Tie/CPHash.pm index 8bf69bbd14..36aea85a8c 100644 --- a/lib/Module/Build/t/bundled/Tie/CPHash.pm +++ b/lib/Module/Build/t/bundled/Tie/CPHash.pm @@ -5,7 +5,7 @@ package Tie::CPHash; # # Author: Christopher J. Madsen <cjm@pobox.com> # Created: 08 Nov 1997 -# $Revision: 5841 $ $Date: 2006-03-21 05:27:29 -0800 (Tue, 21 Mar 2006) $ +# $Revision: 5841 $ $Date: 2006-03-21 08:27:29 -0500 (Tue, 21 Mar 2006) $ # # This program is free software; you can redistribute it and/or modify # it under the same terms as Perl itself. diff --git a/lib/Module/Build/t/compat.t b/lib/Module/Build/t/compat.t index cb219aab42..a5d880cb7c 100644 --- a/lib/Module/Build/t/compat.t +++ b/lib/Module/Build/t/compat.t @@ -135,8 +135,7 @@ ok $mb, "Module::Build->new_from_context"; $foo_builder = Foo::Builder->new_from_context; }); foreach my $style ('passthrough', 'small') { - Module::Build::Compat->create_makefile_pl($style, $foo_builder); - ok -e 'Makefile.PL', "$style Makefile.PL created"; + create_makefile_pl($style, $foo_builder); # Should fail with "can't find Foo/Builder.pm" my $result; @@ -153,8 +152,7 @@ ok $mb, "Module::Build->new_from_context"; $bar_builder = Module::Build->subclass( class => 'Bar::Builder' )->new_from_context; }); foreach my $style ('passthrough', 'small') { - Module::Build::Compat->create_makefile_pl($style, $bar_builder); - ok -e 'Makefile.PL', "$style Makefile.PL created via subclass"; + create_makefile_pl($style, $bar_builder); my $result; stdout_of( sub { $result = $mb->run_perl_script('Makefile.PL'); @@ -165,7 +163,7 @@ ok $mb, "Module::Build->new_from_context"; { # Make sure various Makefile.PL arguments are supported - Module::Build::Compat->create_makefile_pl('passthrough', $mb); + create_makefile_pl('passthrough', $mb); my $libdir = File::Spec->catdir( $tmp, 'libdir' ); my $result; @@ -255,7 +253,7 @@ ok $mb, "Module::Build->new_from_context"; # C<glob> on MSWin32 uses $ENV{HOME} if defined to do tilde-expansion local $ENV{HOME} = 'C:/' if $^O =~ /MSWin/ && !exists( $ENV{HOME} ); - Module::Build::Compat->create_makefile_pl('passthrough', $mb); + create_makefile_pl('passthrough', $mb); stdout_of( sub { $mb->run_perl_script('Makefile.PL', [], ['INSTALL_BASE=~/foo']); @@ -290,8 +288,8 @@ sub test_makefile_types { ok $mb, "Module::Build->new_from_context"; # Create and test Makefile.PL - Module::Build::Compat->create_makefile_pl($type, $mb); - ok -e 'Makefile.PL', "$type Makefile.PL created"; + create_makefile_pl($type, $mb); + test_makefile_pl_requires_perl( $opts{requires}{perl} ); test_makefile_creation($mb); test_makefile_prereq_pm( $opts{requires} ); @@ -321,8 +319,11 @@ sub test_makefile_types { ok $success, "make realclean ran without error"; # Try again with some Makefile.PL arguments - test_makefile_creation($mb, [], 'INSTALLDIRS=vendor', 1); + test_makefile_creation($mb, [], 'INSTALLDIRS=vendor', 'realclean'); + # Try again using distclean + test_makefile_creation($mb, [], '', 'distclean'); + 1 while unlink 'Makefile.PL'; ok ! -e 'Makefile.PL', "cleaned up Makefile"; } @@ -344,10 +345,12 @@ sub test_makefile_creation { ok -e $makefile, "$makefile exists"; if ($cleanup) { - $output = stdout_of( sub { - $build->do_system(@make, 'realclean'); + # default to 'realclean' unless we recognize the clean method + $cleanup = 'realclean' unless $cleanup =~ /^(dist|real)clean$/; + my ($stdout, $stderr ) = stdout_stderr_of (sub { + $build->do_system(@make, $cleanup); }); - ok ! -e '$makefile', "$makefile cleaned up"; + ok ! -e $makefile, "$makefile cleaned up with $cleanup"; } else { pass '(skipping cleanup)'; # keep test count constant @@ -369,17 +372,17 @@ sub test_makefile_pl_files { my $expected = shift; SKIP: { - skip "$makefile not found", 1 unless -e $makefile; - my $pl_files = find_params_in_makefile()->{PL_FILES} || {}; - is_deeply $pl_files, $expected, - "$makefile has correct PL_FILES line"; + skip 1, 'Makefile.PL not found' unless -e 'Makefile.PL'; + my $args = extract_writemakefile_args() || {}; + is_deeply $args->{PL_FILES}, $expected, + "Makefile.PL has correct PL_FILES line"; } } sub test_makefile_pl_requires_perl { my $perl_version = shift || q{}; SKIP: { - skip 'Makefile.PL not found', 1 unless -e 'Makefile.PL'; + skip 1, 'Makefile.PL not found' unless -e 'Makefile.PL'; my $file_contents = slurp 'Makefile.PL'; my $found_requires = $file_contents =~ m{^require $perl_version;}ms; if (length $perl_version) { @@ -417,3 +420,29 @@ sub find_params_in_makefile { return \%params; } + +sub extract_writemakefile_args { + SKIP: { + skip 1, 'Makefile.PL not found' unless -e 'Makefile.PL'; + my $file_contents = slurp 'Makefile.PL'; + my ($args) = $file_contents =~ m{^WriteMakefile\n\((.*)\).*;}ms; + ok $args, "Found WriteMakefile arguments" + or diag "Makefile.PL:\n$file_contents"; + my %args = eval $args or diag $args; ## no critic + return \%args; + } +} + +sub create_makefile_pl { + Module::Build::Compat->create_makefile_pl(@_); + my $ok = ok -e 'Makefile.PL', "$_[0] Makefile.PL created"; + + # Some really conservative make's, like HP/UX, assume files with the same + # timestamp are out of date. Send the Makefile.PL one second into the past + # so its older than the Makefile it will generate. + # See [rt.cpan.org 45700] + my $mtime = (stat("Makefile.PL"))[9]; + utime $mtime, $mtime - 1, "Makefile.PL"; + + return $ok; +} diff --git a/lib/Module/Build/t/ext.t b/lib/Module/Build/t/ext.t index 3b01a799af..30c648bbb3 100644 --- a/lib/Module/Build/t/ext.t +++ b/lib/Module/Build/t/ext.t @@ -129,7 +129,7 @@ foreach my $test (@win_splits) { my @data = map values(%$_), @unix_splits, @win_splits; for my $d (@data) { - chomp(my $out = Module::Build->_backticks('perl', '-le', 'print join " ", map "{$_}", @ARGV', @$d)); + chomp(my $out = Module::Build->_backticks($^X, '-le', 'print join " ", map "{$_}", @ARGV', @$d)); is($out, join(' ', map "{$_}", @$d), "backticks round trip for ".join('',map "{$_}", @$d)); } } @@ -137,6 +137,12 @@ foreach my $test (@win_splits) { { # Make sure run_perl_script() propagates @INC my $dir = MBTest->tmpdir; + if ($^O eq 'VMS') { + # VMS can store INC paths in Unix format with out the trailing + # directory delimiter. + $dir = VMS::Filespec::unixify($dir); + $dir =~ s#/$##; + } local @INC = ($dir, @INC); my $output = stdout_of( sub { Module::Build->run_perl_script('-le', [], ['print for @INC']) } ); like $output, qr{^\Q$dir\E}m; diff --git a/lib/Module/Build/t/extend.t b/lib/Module/Build/t/extend.t index 4c964216ec..f939defaaf 100644 --- a/lib/Module/Build/t/extend.t +++ b/lib/Module/Build/t/extend.t @@ -50,7 +50,9 @@ print "Hello, World!\n"; $mb->test_files('*t*'); my $files = $mb->test_files; ok grep {$_ eq 'script'} @$files; - ok grep {$_ eq File::Spec->catfile('t', 'basic.t')} @$files; + my $t_basic_t = File::Spec->catfile('t', 'basic.t'); + $t_basic_t = VMS::Filespec::vmsify($t_basic_t) if $^O eq 'VMS'; + ok grep {$_ eq $t_basic_t} @$files; ok !grep {$_ eq 'Build.PL' } @$files; # Make sure order is preserved diff --git a/lib/Module/Build/t/metadata.t b/lib/Module/Build/t/metadata.t index caa7d473fa..1def8af377 100644 --- a/lib/Module/Build/t/metadata.t +++ b/lib/Module/Build/t/metadata.t @@ -33,14 +33,24 @@ $dist->regen; my $simple_file = 'lib/Simple.pm'; my $simple2_file = 'lib/Simple2.pm'; - #TODO: # Traditional VMS will return the file in in lower case, and is_deeply # does exact case comparisons. - # When ODS-5 support is active for preserved case file names, this will - # need to be changed. + # When ODS-5 support is active for preserved case file names we do not + # change the case. if ($^O eq 'VMS') { - $simple_file = lc($simple_file); - $simple2_file = lc($simple2_file); + my $lower_case_expect = 1; + my $vms_efs_case = 0; + if (eval 'require VMS::Feature') { + $vms_efs_case = VMS::Feature::current("efs_case_preserve"); + } else { + my $efs_case = $ENV{'DECC$EFS_CASE_PRESERVE'} || ''; + $vms_efs_case = $efs_case =~ /^[ET1]/i; + } + $lower_case_expect = 0 if $vms_efs_case; + if ($lower_case_expect) { + $simple_file = lc($simple_file); + $simple2_file = lc($simple2_file); + } } diff --git a/lib/Module/Build/t/runthrough.t b/lib/Module/Build/t/runthrough.t index e095a60a59..98913281d2 100644 --- a/lib/Module/Build/t/runthrough.t +++ b/lib/Module/Build/t/runthrough.t @@ -73,11 +73,22 @@ ok -e $mb->build_script; my $dist_dir = 'Simple-0.01'; -# VMS may or may not need to modify the name, vmsify will do this if -# the name looks like a UNIX directory. +# VMS in traditional mode needs the $dist_dir name to not have a '.' in it +# as this is a directory delimiter. In extended character set mode the dot +# is permitted for Unix format file specifications. if ($^O eq 'VMS') { - my @dist_dirs = File::Spec->splitdir(VMS::Filespec::vmsify($dist_dir.'/')); - $dist_dir = $dist_dirs[0]; + my $Is_VMS_noefs = 1; + my $vms_efs = 0; + if (eval 'require VMS::Feature') { + $vms_efs = VMS::Feature::current("efs_charset"); + } else { + my $efs_charset = $ENV{'DECC$EFS_CHARSET'} || ''; + $vms_efs = $efs_charset =~ /^[ET1]/i; + } + $Is_VMS_noefs = 0 if $vms_efs; + if ($Is_VMS_noefs) { + $dist_dir = 'Simple-0_01'; + } } is $mb->dist_dir, $dist_dir; diff --git a/make_patchnum.pl b/make_patchnum.pl index 2bacd4bcad..1644d419d6 100644 --- a/make_patchnum.pl +++ b/make_patchnum.pl @@ -13,7 +13,7 @@ make_patchnum.pl - make patchnum perl make_patchnum.pl -=head1 DESCRITPTION +=head1 DESCRIPTION This program creates the files holding the information about locally applied patches to the source code. The created @@ -23,7 +23,7 @@ files are C<git_version.h> and C<lib/Config_git.pl>. Contains status information from git in a form meant to be processed by the tied hash logic of Config.pm. It is actually optional, -although -V will look strange without it. +although -V:git.\* will be uninformative without it. C<git_version.h> contains similar information in a C header file format, designed to be used by patchlevel.h. This file is obtained @@ -40,8 +40,25 @@ Same terms as Perl itself. =cut +# from a -Dmksymlink target dir, I need to cd to the git-src tree to +# use git (like script does). Presuming that's not unique, one fix is +# to follow Configure's symlink-path to run git. Maybe GIT_DIR or +# path-args can solve it, if so we should advise here, I tried only +# very briefly ('cd -' works too). + +my ($subcd, $srcdir); +our $opt_v = scalar grep $_ eq '-v', @ARGV; + BEGIN { my $root="."; + # test 1st to see if we're a -Dmksymlinks target dir + $subcd = ''; + $srcdir = $root; + if (-l "./Configure") { + $srcdir = readlink("./Configure"); + $srcdir =~ s/Configure//; + $subcd = "cd $srcdir &&"; # activate backtick fragment + } while (!-e "$root/perl.c" and length($root)<100) { if ($root eq '.') { $root=".."; @@ -71,14 +88,20 @@ sub write_file { } sub backtick { + # only for git. If we're in a -Dmksymlinks build-dir, we need to + # cd to src so git will work . Probably a better way. my $command = shift; if (wantarray) { - my @result= `$command`; + my @result= `$subcd $command`; + warn "$subcd $command: \$?=$?\n" if $?; + print "#> $subcd $command ->\n @result\n" if !$? and $opt_v; chomp @result; return @result; } else { - my $result= `$command`; + my $result= `$subcd $command`; $result="" if ! defined $result; + warn "$subcd $command: \$?=$?\n" if $?; + print "#> $subcd $command ->\n $result\n" if !$? and $opt_v; chomp $result; return $result; } @@ -102,14 +125,15 @@ sub write_files { my $unpushed_commits = '/*no-op*/'; my ($read, $branch, $snapshot_created, $commit_id, $describe)= ("") x 5; my ($changed, $extra_info, $commit_title, $new_patchnum, $status)= ("") x 5; + if (my $patch_file= read_file(".patch")) { ($branch, $snapshot_created, $commit_id, $describe) = split /\s+/, $patch_file; $extra_info = "git_snapshot_date='$snapshot_created'"; $commit_title = "Snapshot of:"; } -elsif (-d path_to('.git')) { +elsif (-d "$srcdir/.git") { # git branch | awk 'BEGIN{ORS=""} /\*/ { print $2 }' - ($branch) = map { /\* ([^(]\S*)/ ? $1 : () } backtick('git branch'); + ($branch) = map { /\* ([^(]\S*)/ ? $1 : () } backtick("git branch"); my ($remote,$merge); if (length $branch) { $merge= backtick("git config branch.$branch.merge"); @@ -139,12 +163,12 @@ git_remote_branch='$remote/$merge' git_unpushed='$unpushed_commit_list'"; } } - if ($changed) { + if ($changed) { # not touched since init'd. never true. $changed = 'true'; $commit_title = "Derived from:"; $status='"uncommitted-changes"' } else { - $status='/*clean-working-directory*/' + $status='/*clean-working-directory-maybe*/' } $commit_title ||= "Commit id:"; } @@ -1772,17 +1772,8 @@ S_parse_body(pTHX_ char **env, XSINIT_t xsinit) # ifdef PERL_MEM_LOG " PERL_MEM_LOG" # endif -# ifdef PERL_MEM_LOG_ENV - " PERL_MEM_LOG_ENV" -# endif -# ifdef PERL_MEM_LOG_ENV_FD - " PERL_MEM_LOG_ENV_FD" -# endif -# ifdef PERL_MEM_LOG_STDERR - " PERL_MEM_LOG_STDERR" -# endif -# ifdef PERL_MEM_LOG_TIMESTAMP - " PERL_MEM_LOG_TIMESTAMP" +# ifdef PERL_MEM_LOG_NOIMPL + " PERL_MEM_LOG_NOIMPL" # endif # ifdef PERL_USE_DEVEL " PERL_USE_DEVEL" @@ -1773,10 +1773,7 @@ PerlIO_has_base(PerlIO *f) if (tab) return (tab->Get_base != NULL); - SETERRNO(EINVAL, LIB_INVARG); } - else - SETERRNO(EBADF, SS_IVCHAN); return 0; } @@ -1790,11 +1787,8 @@ PerlIO_fast_gets(PerlIO *f) if (tab) return (tab->Set_ptrcnt != NULL); - SETERRNO(EINVAL, LIB_INVARG); } } - else - SETERRNO(EBADF, SS_IVCHAN); return 0; } @@ -1807,10 +1801,7 @@ PerlIO_has_cntptr(PerlIO *f) if (tab) return (tab->Get_ptr != NULL && tab->Get_cnt != NULL); - SETERRNO(EINVAL, LIB_INVARG); } - else - SETERRNO(EBADF, SS_IVCHAN); return 0; } @@ -1823,10 +1814,7 @@ PerlIO_canset_cnt(PerlIO *f) if (tab) return (tab->Set_ptrcnt != NULL); - SETERRNO(EINVAL, LIB_INVARG); } - else - SETERRNO(EBADF, SS_IVCHAN); return 0; } diff --git a/pod/perl5110delta.pod b/pod/perl5110delta.pod index afd1b35492..720b5d273b 100644 --- a/pod/perl5110delta.pod +++ b/pod/perl5110delta.pod @@ -109,6 +109,14 @@ to avoid relying on the object's underlying structure). This pragma allows you to lexically disable or enable overloading for some or all operations. (Yuval Kogman) +=head2 C<\N> regex escape + +A new regex escape has been added, C<\N>. It will match any character that +is not a newline, independently from the presence or absence of the single +line match modifier C</s>. (If C<\N> is followed by an opening brace and +by a letter, perl will still assume that a Unicode character name is +coming, so compatibility is preserved.) (Rafael Garcia-Suarez) + =head1 Modules and Pragmata =head2 Pragmata Changes diff --git a/pod/perlfunc.pod b/pod/perlfunc.pod index 826df27ef0..4593352f7c 100644 --- a/pod/perlfunc.pod +++ b/pod/perlfunc.pod @@ -4349,8 +4349,8 @@ steps to ensure that C<readline> was successful. for (;;) { undef $!; unless (defined( $line = <> )) { + last if eof; die $! if $!; - last; # reached EOF } # ... } diff --git a/pod/perlhack.pod b/pod/perlhack.pod index 72c2fc06fc..b4cfc4fe6d 100644 --- a/pod/perlhack.pod +++ b/pod/perlhack.pod @@ -321,10 +321,12 @@ might start to make sense - don't worry if it doesn't yet, because the best way to study it is to read it in conjunction with poking at Perl source, and we'll do that later on. -You might also want to look at Gisle Aas's illustrated perlguts - -there's no guarantee that this will be absolutely up-to-date with the -latest documentation in the Perl core, but the fundamentals will be -right. ( http://gisle.aas.no/perl/illguts/ ) +Gisle Aas's illustrated perlguts (also known as I<illguts>) is wonderful, +although a little out of date with regard to some size details; the +various SV structures have since been reworked for smaller memory footprint. +The fundamentals are right however, and the pictures are very helpful. + +L<http://www.perl.org/tpc/1998/Perl_Language_and_Modules/Perl%20Illustrated/> =item L<perlxstut> and L<perlxs> @@ -2940,27 +2942,29 @@ by C<-DPERL_MEM_LOG> instead. =head2 PERL_MEM_LOG -If compiled with C<-DPERL_MEM_LOG>, all Newx() and Renew() allocations -and Safefree() in the Perl core go through logging functions, which is -handy for breakpoint setting. If also compiled with C<-DPERL_MEM_LOG_STDERR>, -the allocations and frees are logged to STDERR (or more precisely, to the -file descriptor 2) in these logging functions, with the calling source code -file and line number (and C function name, if supported by the C compiler). - -This logging is somewhat similar to C<-Dm> but independent of C<-DDEBUGGING>, -and at a higher level (the C<-Dm> is directly at the point of C<malloc()>, -while the C<PERL_MEM_LOG> is at the level of C<New()>). - -In addition to memory allocations, SV allocations will be logged, just as -with C<-Dm>. However, since the logging doesn't use PerlIO, all SV allocations -are logged and no extra SV allocations are introduced by enabling the logging. -If compiled with C<-DDEBUG_LEAKING_SCALARS>, the serial number for each SV -allocation is also logged. - -You can control the logging from your environment if you compile with -C<-DPERL_MEM_LOG_ENV>. Then you need to explicitly set C<PERL_MEM_LOG> and/or -C<PERL_SV_LOG> to a non-zero value to enable logging of memory and/or SV -allocations. +If compiled with C<-DPERL_MEM_LOG>, both memory and SV allocations go +through logging functions, which is handy for breakpoint setting. + +Unless C<-DPERL_MEM_LOG_NOIMPL> is also compiled, the logging +functions read $ENV{PERL_MEM_LOG} to determine whether to log the +event, and if so how: + + $ENV{PERL_MEM_LOG} =~ /m/ Log all memory ops + $ENV{PERL_MEM_LOG} =~ /s/ Log all SV ops + $ENV{PERL_MEM_LOG} =~ /t/ include timestamp in Log + $ENV{PERL_MEM_LOG} =~ /^(\d+)/ write to FD given (default is 2) + +Memory logging is somewhat similar to C<-Dm> but is independent of +C<-DDEBUGGING>, and at a higher level; all uses of Newx(), Renew(), +and Safefree() are logged with the caller's source code file and line +number (and C function name, if supported by the C compiler). In +contrast, C<-Dm> is directly at the point of C<malloc()>. SV logging +is similar. + +Since the logging doesn't use PerlIO, all SV allocations are logged +and no extra SV allocations are introduced by enabling the logging. +If compiled with C<-DDEBUG_LEAKING_SCALARS>, the serial number for +each SV allocation is also logged. =head2 Profiling diff --git a/pod/perlre.pod b/pod/perlre.pod index a076d3ad66..ee1c2cb940 100644 --- a/pod/perlre.pod +++ b/pod/perlre.pod @@ -271,6 +271,7 @@ X<word> X<whitespace> X<character class> X<backreference> \g{name} Named backreference \k<name> Named backreference \K Keep the stuff left of the \K, don't include it in $& + \N Any character but \n \v Vertical whitespace \V Not vertical whitespace \h Horizontal whitespace diff --git a/pod/perlrebackslash.pod b/pod/perlrebackslash.pod index ddd7abee38..40f73fcbc1 100644 --- a/pod/perlrebackslash.pod +++ b/pod/perlrebackslash.pod @@ -83,6 +83,7 @@ quoted constructs>. \l Lowercase next character. \L Lowercase till \E. \n (Logical) newline character. + \N Any character but newline. \N{} Named (Unicode) character. \p{}, \pP Character with a Unicode property. \P{}, \PP Character without a Unicode property. diff --git a/pod/perlrecharclass.pod b/pod/perlrecharclass.pod index a626dd9bb9..930c0fc4e4 100644 --- a/pod/perlrecharclass.pod +++ b/pod/perlrecharclass.pod @@ -38,7 +38,6 @@ Here are some examples: "\n" =~ /(?s:.)/ # Match (local 'single line' modifier) "ab" =~ /^.$/ # No match (dot matches one character) - =head2 Backslashed sequences Perl regular expressions contain many backslashed sequences that @@ -59,6 +58,7 @@ more detail below. \S Match a non-white space character. \h Match a horizontal white space character. \H Match a character that isn't horizontal white space. + \N Match a character that isn't newline. \v Match a vertical white space character. \V Match a character that isn't vertical white space. \pP, \p{Prop} Match a character matching a Unicode property. @@ -94,7 +94,7 @@ Any character that isn't matched by C<\w> will be matched by C<\W>. =head3 White space -C<\s> matches any single character that is consider white space. In the +C<\s> matches any single character that is considered white space. In the ASCII range, C<\s> matches the horizontal tab (C<\t>), the new line (C<\n>), the form feed (C<\f>), the carriage return (C<\r>), and the space (the vertical tab, C<\cK> is not matched by C<\s>). The exact set @@ -113,6 +113,12 @@ C<\h> will match any character that is considered horizontal white space; this includes the space and the tab characters. C<\H> will match any character that is not considered horizontal white space. +C<\N>, like the dot, will match any character that is not a newline. The +difference is that C<\N> will not be influenced by the single line C</s> +regular expression modifier. (Note that, since C<\N{}> is also used for +Unicode named characters, if C<\N> is followed by an opening brace and +by a letter, perl will assume that a Unicode character name is coming.) + C<\v> will match any character that is considered vertical white space; this includes the carriage return and line feed characters (newline). C<\V> will match any character that is not considered vertical white space. diff --git a/pod/perlreref.pod b/pod/perlreref.pod index b9fb3b0202..87baab25e8 100644 --- a/pod/perlreref.pod +++ b/pod/perlreref.pod @@ -125,6 +125,7 @@ and L<perlunicode> for details. \S A non-whitespace character \h An horizontal white space \H A non horizontal white space + \N A non newline (like . without /s) \v A vertical white space \V A non vertical white space \R A generic newline (?>\v|\x0D\x0A) diff --git a/pod/perltodo.pod b/pod/perltodo.pod index cf0304aae9..c84b51e368 100644 --- a/pod/perltodo.pod +++ b/pod/perltodo.pod @@ -1101,12 +1101,6 @@ combines the code in pp_entersub, pp_leavesub. This should probably be done 1st in XS, and using B::Generate to patch the new OP into the optrees. -=head2 C<\N> - -It should be possible to add a C<\N> regex assertion, meaning "every -character except C<\n>° independently of the context. That would -of course imply that C<\N> couldn't be followed by an opening C<{>. - =head1 Big projects Tasks that will get your name mentioned in the description of the "Highlights @@ -4254,6 +4254,11 @@ STATIC void S_hfreeentries(pTHX_ HV *hv) #define PERL_ARGS_ASSERT_HFREEENTRIES \ assert(hv) +STATIC I32 S_anonymise_cv(pTHX_ const char *stash, SV *val) + __attribute__nonnull__(pTHX_2); +#define PERL_ARGS_ASSERT_ANONYMISE_CV \ + assert(val) + STATIC HE* S_new_he(pTHX) __attribute__malloc__ __attribute__warn_unused_result__; @@ -5178,7 +5183,7 @@ STATIC regnode* S_regpiece(pTHX_ struct RExC_state_t *pRExC_state, I32 *flagp, U #define PERL_ARGS_ASSERT_REGPIECE \ assert(pRExC_state); assert(flagp) -STATIC regnode* S_reg_namedseq(pTHX_ struct RExC_state_t *pRExC_state, UV *valuep) +STATIC regnode* S_reg_namedseq(pTHX_ struct RExC_state_t *pRExC_state, UV *valuep, I32 *flagp) __attribute__nonnull__(pTHX_1); #define PERL_ARGS_ASSERT_REG_NAMEDSEQ \ assert(pRExC_state) @@ -5884,7 +5889,7 @@ STATIC bool S_vdie_common(pTHX_ const char *message, STRLEN msglen, I32 utf8, bo STATIC char * S_write_no_mem(pTHX) __attribute__noreturn__; -#if defined(PERL_MEM_LOG) && defined(PERL_MEM_LOG_STDERR) +#if defined(PERL_MEM_LOG) && !defined(PERL_MEM_LOG_NOIMPL) STATIC void S_mem_log_common(enum mem_log_type mlt, const UV n, const UV typesize, const char *type_name, const SV *sv, Malloc_t oldalloc, Malloc_t newalloc, const char *filename, const int linenumber, const char *funcname) __attribute__nonnull__(4) __attribute__nonnull__(8) @@ -6553,7 +6553,7 @@ S_regpiece(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth) /* reg_namedseq(pRExC_state,UVp) This is expected to be called by a parser routine that has - recognized'\N' and needs to handle the rest. RExC_parse is + recognized '\N' and needs to handle the rest. RExC_parse is expected to point at the first char following the N at the time of the call. @@ -6567,11 +6567,11 @@ S_regpiece(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth) be returned to indicate failure. (This will NOT be a valid pointer to a regnode.) - If value is null then it is assumed that we are parsing normal text + If valuep is null then it is assumed that we are parsing normal text and inserts a new EXACT node into the program containing the resolved string and returns a pointer to the new node. If the string is zerolength a NOTHING node is emitted. - + On success RExC_parse is set to the char following the endbrace. Parsing failures will generate a fatal errorvia vFAIL(...) @@ -6585,7 +6585,7 @@ S_regpiece(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth) */ STATIC regnode * -S_reg_namedseq(pTHX_ RExC_state_t *pRExC_state, UV *valuep) +S_reg_namedseq(pTHX_ RExC_state_t *pRExC_state, UV *valuep, I32 *flagp) { char * name; /* start of the content of the name */ char * endbrace; /* endbrace following the name */ @@ -6597,8 +6597,22 @@ S_reg_namedseq(pTHX_ RExC_state_t *pRExC_state, UV *valuep) PERL_ARGS_ASSERT_REG_NAMEDSEQ; - if (*RExC_parse != '{') { - vFAIL("Missing braces on \\N{}"); + if (*RExC_parse != '{' || + (*RExC_parse == '{' && RExC_parse[1] + && strchr("0123456789", RExC_parse[1]))) + { + GET_RE_DEBUG_FLAGS_DECL; + if (valuep) + /* no bare \N in a charclass */ + vFAIL("Missing braces on \\N{}"); + GET_RE_DEBUG_FLAGS; + nextchar(pRExC_state); + ret = reg_node(pRExC_state, REG_ANY); + *flagp |= HASWIDTH|SIMPLE; + RExC_naughty++; + RExC_parse--; + Set_Node_Length(ret, 1); /* MJD */ + return ret; } name = RExC_parse+1; endbrace = strchr(RExC_parse, '}'); @@ -7159,12 +7173,12 @@ tryagain: } break; case 'N': - /* Handle \N{NAME} here and not below because it can be + /* Handle \N and \N{NAME} here and not below because it can be multicharacter. join_exact() will join them up later on. Also this makes sure that things like /\N{BLAH}+/ and \N{BLAH} being multi char Just Happen. dmq*/ ++RExC_parse; - ret= reg_namedseq(pRExC_state, NULL); + ret= reg_namedseq(pRExC_state, NULL, flagp); break; case 'k': /* Handle \k<NAME> and \k'NAME' */ parse_named_seq: @@ -7964,7 +7978,7 @@ parseit: from earlier versions, OTOH that behaviour was broken as well. */ UV v; /* value is register so we cant & it /grrr */ - if (reg_namedseq(pRExC_state, &v)) { + if (reg_namedseq(pRExC_state, &v, NULL)) { goto parseit; } value= v; @@ -902,7 +902,7 @@ in gv.h: */ #endif /* -=for apidoc Am|char*|SvGAMAGIC|SV* sv +=for apidoc Am|U32|SvGAMAGIC|SV* sv Returns true if the SV has get magic or overloading. If either is true then the scalar is active data, and has the potential to return a new value every diff --git a/t/op/re_tests b/t/op/re_tests index f9b070d62c..0c04840117 100644 --- a/t/op/re_tests +++ b/t/op/re_tests @@ -31,6 +31,12 @@ ab*bc abbbbc y $+[0] 6 .{3,4} abbbbc y $& abbb .{3,4} abbbbc y $-[0] 0 .{3,4} abbbbc y $+[0] 4 +\N{1} abbbbc y $& a +\N{1} abbbbc y $-[0] 0 +\N{1} abbbbc y $+[0] 1 +\N{3,4} abbbbc y $& abbb +\N{3,4} abbbbc y $-[0] 0 +\N{3,4} abbbbc y $+[0] 4 ab{0,}bc abbbbc y $& abbbbc ab{0,}bc abbbbc y $-[0] 0 ab{0,}bc abbbbc y $+[0] 6 @@ -69,8 +75,11 @@ abc$ aabcd n - - $ abc y $& a.c abc y $& abc a.c axc y $& axc +a\Nc abc y $& abc a.*c axyzc y $& axyzc +a\N*c axyzc y $& axyzc a.*c axyzd n - - +a\N*c axyzd n - - a[bc]d abc n - - a[bc]d abd y $& abd a[b]d abd y $& abd @@ -78,6 +87,7 @@ a[b]d abd y $& abd .[b]. abd y $& abd .[b]. aBd n - - (?i:.[b].) abd y $& abd +(?i:\N[b]\N) abd y $& abd a[b-d]e abd n - - a[b-d]e ace y $& ace a[b-d] aac y $& ac @@ -315,6 +325,7 @@ a[-]?c ac y $& ac '$'i ABC y $& 'a.c'i ABC y $& ABC 'a.c'i AXC y $& AXC +'a\Nc'i ABC y $& ABC 'a.*?c'i AXYZC y $& AXYZC 'a.*c'i AXYZD n - - 'a[bc]d'i ABC n - - @@ -497,8 +508,11 @@ a(?:b|(c|e){1,2}?|d)+?(.) ace y $1$2 ce '(?-i:a)b'i AB n - - '((?-i:a))b'i AB n - - '((?-i:a.))b'i a\nB n - - +'((?-i:a\N))b'i a\nB n - - '((?s-i:a.))b'i a\nB y $1 a\n +'((?s-i:a\N))b'i a\nB n - - '((?s-i:a.))b'i B\nB n - - +'((?s-i:a\N))b'i B\nB n - - (?:c|d)(?:)(?:a(?:)(?:b)(?:b(?:))(?:b(?:)(?:b))) cabbbb y $& cabbbb (?:c|d)(?:)(?:aaaaaaaa(?:)(?:bbbbbbbb)(?:bbbbbbbb(?:))(?:bbbbbbbb(?:)(?:bbbbbbbb))) caaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb y $& caaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb '(ab)\d\1'i Ab4ab y $1 Ab @@ -531,6 +545,8 @@ x(~~)*(?:(?:F)?)? x~~ y - - ((?s).)c(?!.) a\nb\nc\n y $1:$& \n:\nc ((?s)b.)c(?!.) a\nb\nc\n y $1 b\n ((?s)b.)c(?!.) a\nb\nc\n y $1:$& b\n:b\nc +((?s)b.)c(?!\N) a\nb\nc\n y $1:$& b\n:b\nc +'(b.)c(?!\N)'s a\nb\nc\n y $1:$& b\n:b\nc ^b a\nb\nc\n n - - ()^b a\nb\nc\n n - - ((?m)^b) a\nb\nc\n y $1 b @@ -1294,6 +1310,7 @@ X(\w+)(?=\s)|X(\w+) Xab y [$1-$2] [-ab] (?|(?|(a)|(b))|(?|(c)|(d))) c y $1 c (?|(?|(a)|(b))|(?|(c)|(d))) d y $1 d (.)(?|(.)(.)x|(.)d)(.) abcde y $1-$2-$3-$4-$5- b-c--e-- +(\N)(?|(\N)(\N)x|(\N)d)(\N) abcde y $1-$2-$3-$4-$5- b-c--e-- #Bug #41492 (?(DEFINE)(?<A>(?&B)+)(?<B>a))(?&A) a y $& a (?(DEFINE)(?<A>(?&B)+)(?<B>a))(?&A) aa y $& aa @@ -1340,7 +1357,10 @@ foo(\h)bar foo\tbar y $1 \t (\H)(\h) foo\tbar y $1-$2 o-\t (\h)(\H) foo\tbar y $1-$2 \t-b -.*\z foo\n y - - +.*\z foo\n y -$&- -- +\N*\z foo\n y -$&- -- +.*\Z foo\n y -$&- -foo- +\N*\Z foo\n y -$&- -foo- ^(?:(\d)x)?\d$ 1 y ${\(defined($1)?1:0)} 0 .*?(?:(\w)|(\w))x abx y $1-$2 b- diff --git a/t/op/stash.t b/t/op/stash.t index 4d8bc7c54d..e2f8901011 100644 --- a/t/op/stash.t +++ b/t/op/stash.t @@ -7,7 +7,7 @@ BEGIN { BEGIN { require "./test.pl"; } -plan( tests => 13 ); +plan( tests => 30 ); # Used to segfault (bug #15479) fresh_perl_is( @@ -58,6 +58,84 @@ ok( !eval q{ defined %schoenmaker:: }, 'works in eval("")' ); # now tests with strictures -use strict; -ok( !defined %pig::, q(referencing a non-existent stash doesn't produce stricture errors) ); -ok( !exists $pig::{bodine}, q(referencing a non-existent stash element doesn't produce stricture errors) ); +{ + use strict; + ok( !defined %pig::, q(referencing a non-existent stash doesn't produce stricture errors) ); + ok( !exists $pig::{bodine}, q(referencing a non-existent stash element doesn't produce stricture errors) ); +} + +SKIP: { + eval { require B; 1 } or skip "no B", 12; + + *b = \&B::svref_2object; + my $CVf_ANON = B::CVf_ANON(); + + my $sub = do { + package one; + \&{"one"}; + }; + delete $one::{one}; + my $gv = b($sub)->GV; + + isa_ok( $gv, "B::GV", "deleted stash entry leaves CV with valid GV"); + is( b($sub)->CvFLAGS & $CVf_ANON, $CVf_ANON, "...and CVf_ANON set"); + is( eval { $gv->NAME }, "__ANON__", "...and an __ANON__ name"); + is( eval { $gv->STASH->NAME }, "one", "...but leaves stash intact"); + + $sub = do { + package two; + \&{"two"}; + }; + %two:: = (); + $gv = b($sub)->GV; + + isa_ok( $gv, "B::GV", "cleared stash leaves CV with valid GV"); + is( b($sub)->CvFLAGS & $CVf_ANON, $CVf_ANON, "...and CVf_ANON set"); + is( eval { $gv->NAME }, "__ANON__", "...and an __ANON__ name"); + is( eval { $gv->STASH->NAME }, "__ANON__", "...and an __ANON__ stash"); + + $sub = do { + package three; + \&{"three"}; + }; + undef %three::; + $gv = b($sub)->GV; + + isa_ok( $gv, "B::GV", "undefed stash leaves CV with valid GV"); + is( b($sub)->CvFLAGS & $CVf_ANON, $CVf_ANON, "...and CVf_ANON set"); + is( eval { $gv->NAME }, "__ANON__", "...and an __ANON__ name"); + is( eval { $gv->STASH->NAME }, "__ANON__", "...and an __ANON__ stash"); + + TODO: { + local $TODO = "anon CVs not accounted for yet"; + + $sub = do { + package four; + sub { 1 }; + }; + %four:: = (); + $gv = b($sub)->GV; + + isa_ok( $gv, "B::GV", "cleared stash leaves anon CV with valid GV"); + is( eval { $gv->STASH->NAME }, "__ANON__", "...and an __ANON__ stash"); + + $sub = do { + package five; + sub { 1 }; + }; + undef %five::; + $gv = b($sub)->GV; + + isa_ok( $gv, "B::GV", "undefed stash leaves anon CV with valid GV"); + is( eval { $gv->STASH->NAME }, "__ANON__", "...and an __ANON__ stash"); + } + + # [perl #58530] + fresh_perl_is( + 'sub foo { 1 }; use overload q/""/ => \&foo;' . + 'delete $main::{foo}; bless []', + "", + {}, + "no segfault with overload/deleted stash entry [#58530]", + ); +} @@ -5471,38 +5471,35 @@ Perl_free_global_struct(pTHX_ struct perl_vars *plvarsp) #ifdef PERL_MEM_LOG -/* - * PERL_MEM_LOG: the Perl_mem_log_..() will be compiled. +/* -DPERL_MEM_LOG: the Perl_mem_log_..() is compiled, including the + * the default implementation, unless -DPERL_MEM_LOG_NOIMPL is also + * given, and you supply your own implementation. + * + * The default implementation reads a single env var, PERL_MEM_LOG, + * expecting one or more of the following: * - * PERL_MEM_LOG_ENV: if defined, during run time the environment - * variables PERL_MEM_LOG and PERL_SV_LOG will be consulted, and - * if the integer value of that is true, the logging will happen. - * (The default is to always log if the PERL_MEM_LOG define was - * in effect.) + * \d+ - fd fd to write to : must be 1st (atoi) + * 'm' - memlog was PERL_MEM_LOG=1 + * 's' - svlog was PERL_SV_LOG=1 + * 't' - timestamp was PERL_MEM_LOG_TIMESTAMP=1 * - * PERL_MEM_LOG_TIMESTAMP: if defined, a timestamp will be logged - * before every memory logging entry. This can be turned off at run - * time by setting the environment variable PERL_MEM_LOG_TIMESTAMP - * to zero. + * This makes the logger controllable enough that it can reasonably be + * added to the system perl. */ -/* - * PERL_MEM_LOG_SPRINTF_BUF_SIZE: size of a (stack-allocated) buffer +/* -DPERL_MEM_LOG_SPRINTF_BUF_SIZE=X: size of a (stack-allocated) buffer * the Perl_mem_log_...() will use (either via sprintf or snprintf). */ #define PERL_MEM_LOG_SPRINTF_BUF_SIZE 128 -/* - * PERL_MEM_LOG_FD: the file descriptor the Perl_mem_log_...() will - * log to. You can also define in compile time PERL_MEM_LOG_ENV_FD, - * in which case the environment variable PERL_MEM_LOG_FD will be - * consulted for the file descriptor number to use. +/* -DPERL_MEM_LOG_FD=N: the file descriptor the Perl_mem_log_...() + * writes to. In the default logger, this is settable at runtime. */ #ifndef PERL_MEM_LOG_FD # define PERL_MEM_LOG_FD 2 /* If STDERR is too boring for you. */ #endif -#ifdef PERL_MEM_LOG_STDERR +#ifndef PERL_MEM_LOG_NOIMPL # ifdef DEBUG_LEAKING_SCALARS # define SV_LOG_SERIAL_FMT " [%lu]" @@ -5513,23 +5510,25 @@ Perl_free_global_struct(pTHX_ struct perl_vars *plvarsp) # endif static void -S_mem_log_common(enum mem_log_type mlt, const UV n, const UV typesize, const char *type_name, const SV *sv, Malloc_t oldalloc, Malloc_t newalloc, const char *filename, const int linenumber, const char *funcname) +S_mem_log_common(enum mem_log_type mlt, const UV n, + const UV typesize, const char *type_name, const SV *sv, + Malloc_t oldalloc, Malloc_t newalloc, + const char *filename, const int linenumber, + const char *funcname) { -# if defined(PERL_MEM_LOG_ENV) || defined(PERL_MEM_LOG_ENV_FD) - const char *s; -# endif + const char *pmlenv; PERL_ARGS_ASSERT_MEM_LOG_COMMON; -# ifdef PERL_MEM_LOG_ENV - s = PerlEnv_getenv(mlt < MLT_NEW_SV ? "PERL_MEM_LOG" : "PERL_SV_LOG"); - if (s ? atoi(s) : 0) -# endif + pmlenv = PerlEnv_getenv("PERL_MEM_LOG"); + if (!pmlenv) + return; + if (mlt < MLT_NEW_SV ? strchr(pmlenv,'m') : strchr(pmlenv,'s')) { /* We can't use SVs or PerlIO for obvious reasons, * so we'll use stdio and low-level IO instead. */ char buf[PERL_MEM_LOG_SPRINTF_BUF_SIZE]; -# ifdef PERL_MEM_LOG_TIMESTAMP + # ifdef HAS_GETTIMEOFDAY # define MEM_LOG_TIME_FMT "%10d.%06d: " # define MEM_LOG_TIME_ARG (int)tv.tv_sec, (int)tv.tv_usec @@ -5545,24 +5544,17 @@ S_mem_log_common(enum mem_log_type mlt, const UV n, const UV typesize, const cha * gettimeofday() (see ext/Time-HiRes), the easiest way is * probably that they would be used to fill in the struct * timeval. */ -# endif { - int fd = PERL_MEM_LOG_FD; STRLEN len; + int fd = atoi(pmlenv); + if (!fd) + fd = PERL_MEM_LOG_FD; -# ifdef PERL_MEM_LOG_ENV_FD - if ((s = PerlEnv_getenv("PERL_MEM_LOG_FD"))) { - fd = atoi(s); - } -# endif -# ifdef PERL_MEM_LOG_TIMESTAMP - s = PerlEnv_getenv("PERL_MEM_LOG_TIMESTAMP"); - if (!s || atoi(s)) { + if (strchr(pmlenv, 't')) { len = my_snprintf(buf, sizeof(buf), MEM_LOG_TIME_FMT, MEM_LOG_TIME_ARG); PerlLIO_write(fd, buf, len); } -# endif switch (mlt) { case MLT_ALLOC: len = my_snprintf(buf, sizeof(buf), @@ -5593,54 +5585,78 @@ S_mem_log_common(enum mem_log_type mlt, const UV n, const UV typesize, const cha filename, linenumber, funcname, PTR2UV(sv) _SV_LOG_SERIAL_ARG(sv)); break; + default: + len = 0; } PerlLIO_write(fd, buf, len); } } } +#endif /* !PERL_MEM_LOG_NOIMPL */ + +#ifndef PERL_MEM_LOG_NOIMPL +# define \ + mem_log_common_if(alty, num, tysz, tynm, sv, oal, nal, flnm, ln, fnnm) \ + mem_log_common (alty, num, tysz, tynm, sv, oal, nal, flnm, ln, fnnm) +#else +/* this is suboptimal, but bug compatible. User is providing their + own implemenation, but is getting these functions anyway, and they + do nothing. But _NOIMPL users should be able to cope or fix */ +# define \ + mem_log_common_if(alty, num, tysz, tynm, u, oal, nal, flnm, ln, fnnm) \ + /* mem_log_common_if_PERL_MEM_LOG_NOIMPL */ #endif Malloc_t -Perl_mem_log_alloc(const UV n, const UV typesize, const char *type_name, Malloc_t newalloc, const char *filename, const int linenumber, const char *funcname) -{ -#ifdef PERL_MEM_LOG_STDERR - mem_log_common(MLT_ALLOC, n, typesize, type_name, NULL, NULL, newalloc, filename, linenumber, funcname); -#endif +Perl_mem_log_alloc(const UV n, const UV typesize, const char *type_name, + Malloc_t newalloc, + const char *filename, const int linenumber, + const char *funcname) +{ + mem_log_common_if(MLT_ALLOC, n, typesize, type_name, + NULL, NULL, newalloc, + filename, linenumber, funcname); return newalloc; } Malloc_t -Perl_mem_log_realloc(const UV n, const UV typesize, const char *type_name, Malloc_t oldalloc, Malloc_t newalloc, const char *filename, const int linenumber, const char *funcname) -{ -#ifdef PERL_MEM_LOG_STDERR - mem_log_common(MLT_REALLOC, n, typesize, type_name, NULL, oldalloc, newalloc, filename, linenumber, funcname); -#endif +Perl_mem_log_realloc(const UV n, const UV typesize, const char *type_name, + Malloc_t oldalloc, Malloc_t newalloc, + const char *filename, const int linenumber, + const char *funcname) +{ + mem_log_common_if(MLT_REALLOC, n, typesize, type_name, + NULL, oldalloc, newalloc, + filename, linenumber, funcname); return newalloc; } Malloc_t -Perl_mem_log_free(Malloc_t oldalloc, const char *filename, const int linenumber, const char *funcname) +Perl_mem_log_free(Malloc_t oldalloc, + const char *filename, const int linenumber, + const char *funcname) { -#ifdef PERL_MEM_LOG_STDERR - mem_log_common(MLT_FREE, 0, 0, "", NULL, oldalloc, NULL, filename, linenumber, funcname); -#endif + mem_log_common_if(MLT_FREE, 0, 0, "", NULL, oldalloc, NULL, + filename, linenumber, funcname); return oldalloc; } void -Perl_mem_log_new_sv(const SV *sv, const char *filename, const int linenumber, const char *funcname) +Perl_mem_log_new_sv(const SV *sv, + const char *filename, const int linenumber, + const char *funcname) { -#ifdef PERL_MEM_LOG_STDERR - mem_log_common(MLT_NEW_SV, 0, 0, "", sv, NULL, NULL, filename, linenumber, funcname); -#endif + mem_log_common_if(MLT_NEW_SV, 0, 0, "", sv, NULL, NULL, + filename, linenumber, funcname); } void -Perl_mem_log_del_sv(const SV *sv, const char *filename, const int linenumber, const char *funcname) +Perl_mem_log_del_sv(const SV *sv, + const char *filename, const int linenumber, + const char *funcname) { -#ifdef PERL_MEM_LOG_STDERR - mem_log_common(MLT_DEL_SV, 0, 0, "", sv, NULL, NULL, filename, linenumber, funcname); -#endif + mem_log_common_if(MLT_DEL_SV, 0, 0, "", sv, NULL, NULL, + filename, linenumber, funcname); } #endif /* PERL_MEM_LOG */ diff --git a/vms/ext/filespec.t b/vms/ext/filespec.t index 5dd27c9b9d..b40cc816f3 100644 --- a/vms/ext/filespec.t +++ b/vms/ext/filespec.t @@ -83,6 +83,7 @@ __DATA__ # Basic VMS to Unix filespecs __some_:[__where_.__over_]__the_.__rainbow_ unixify /__some_/__where_/__over_/__the_.__rainbow_ ^ +__some_:<__where_.__over_>__the_.__rainbow_ unixify /__some_/__where_/__over_/__the_.__rainbow_ ^ [.__some_.__where_.__over_]__the_.__rainbow_ unixify __some_/__where_/__over_/__the_.__rainbow_ ^ [-.__some_.__where_.__over_]__the_.__rainbow_ unixify ../__some_/__where_/__over_/__the_.__rainbow_ ^ [.__some_.--.__where_.__over_]__the_.__rainbow_ unixify __some_/../../__where_/__over_/__the_.__rainbow_ ^ @@ -7346,7 +7346,7 @@ static char *int_tounixspec(const char *spec, char *rslt, int * utf8_fl) } if (*cp2 == ':') { *(cp1++) = '/'; - if (*(cp2+1) == '[') cp2++; + if (*(cp2+1) == '[' || *(cp2+1) == '<') cp2++; } else if (*cp2 == ']' || *cp2 == '>') { if (*(cp1-1) != '/') *(cp1++) = '/'; /* Don't double after ellipsis */ |