Skip to content
Closed
1 change: 0 additions & 1 deletion dist/ExtUtils-ParseXS/lib/ExtUtils/ParseXS.pm
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ BEGIN {
$VERSION = eval $VERSION if $VERSION =~ /_/;

use ExtUtils::ParseXS::Utilities qw(
standard_typemap_locations
trim_whitespace
C_string
valid_proto_string
Expand Down
144 changes: 64 additions & 80 deletions dist/ExtUtils-ParseXS/lib/ExtUtils/ParseXS/Utilities.pm
Original file line number Diff line number Diff line change
Expand Up @@ -64,94 +64,75 @@ They are documented here for the benefit of future maintainers of this module.

=item * Purpose

Provide a list of filepaths where F<typemap> files may be found. The
filepaths -- relative paths to files (not just directory paths) -- appear in this list in lowest-to-highest priority.

The highest priority is to look in the current directory.

'typemap'

The second and third highest priorities are to look in the parent of the
current directory and a directory called F<lib/ExtUtils> underneath the parent
directory.

'../typemap',
'../lib/ExtUtils/typemap',

The fourth through ninth highest priorities are to look in the corresponding
grandparent, great-grandparent and great-great-grandparent directories.

'../../typemap',
'../../lib/ExtUtils/typemap',
'../../../typemap',
'../../../lib/ExtUtils/typemap',
'../../../../typemap',
'../../../../lib/ExtUtils/typemap',

The tenth and subsequent priorities are to look in directories named
F<ExtUtils> which are subdirectories of directories found in C<@INC> --
I<provided> a file named F<typemap> actually exists in such a directory.
Example:

'/usr/local/lib/perl5/5.10.1/ExtUtils/typemap',

However, these filepaths appear in the list returned by
C<standard_typemap_locations()> in reverse order, I<i.e.>, lowest-to-highest.

'/usr/local/lib/perl5/5.10.1/ExtUtils/typemap',
'../../../../lib/ExtUtils/typemap',
'../../../../typemap',
'../../../lib/ExtUtils/typemap',
'../../../typemap',
'../../lib/ExtUtils/typemap',
'../../typemap',
'../lib/ExtUtils/typemap',
'../typemap',
'typemap'
Returns a standard list of filepaths where F<typemap> files may be found.
This will typically be something like:

map("$_/ExtUtils/typemap", reverse @INC),
qw(
../../../../lib/ExtUtils/typemap
../../../../typemap
../../../lib/ExtUtils/typemap
../../../typemap
../../lib/ExtUtils/typemap
../../typemap
../lib/ExtUtils/typemap
../typemap
typemap
)

but the style of the pathnames may vary with OS. Note that the value to
use for C<@INC> is passed as an array reference, and can be something
other than C<@INC> itself.

Pathnames are returned in the order they are expected to be processed;
this means that later files will update or override entries found in
earlier files. So in particular, F<typemap> in the current directory has
highest priority. C<@INC> is searched in reverse order so that earlier
entries in C<@INC> are processed later and so have higher priority.

The values of C<-typemap> switches are not used here; they should be added
by the caller to the list of pathnames returned by this function.

=item * Arguments

my @stl = standard_typemap_locations( \@INC );
my @stl = standard_typemap_locations(\@INC);

Reference to C<@INC>.
A single argument: a reference to an array to use as if it were C<@INC>.

=item * Return Value

Array holding list of directories to be searched for F<typemap> files.
A list of F<typemap> pathnames.

=back

=cut

SCOPE: {
my @tm_template;
sub standard_typemap_locations {
my $include_ref = shift;

sub standard_typemap_locations {
my $include_ref = shift;
my @tm;

if (not @tm_template) {
@tm_template = qw(typemap);

my $updir = File::Spec->updir();
foreach my $dir (
File::Spec->catdir(($updir) x 1),
File::Spec->catdir(($updir) x 2),
File::Spec->catdir(($updir) x 3),
File::Spec->catdir(($updir) x 4),
) {
unshift @tm_template, File::Spec->catfile($dir, 'typemap');
unshift @tm_template, File::Spec->catfile($dir, lib => ExtUtils => 'typemap');
}
}
# See function description above for why 'reverse' is used here.
foreach my $dir (reverse @{$include_ref}) {
my $file = File::Spec->catfile($dir, ExtUtils => 'typemap');
push @tm, $file;
}

my @tm = @tm_template;
foreach my $dir (@{ $include_ref}) {
my $file = File::Spec->catfile($dir, ExtUtils => 'typemap');
unshift @tm, $file if -e $file;
}
return @tm;
my $updir = File::Spec->updir();
foreach my $dir (
File::Spec->catdir(($updir) x 4),
File::Spec->catdir(($updir) x 3),
File::Spec->catdir(($updir) x 2),
File::Spec->catdir(($updir) x 1),
) {
push @tm, File::Spec->catfile($dir, lib => ExtUtils => 'typemap');
push @tm, File::Spec->catfile($dir, 'typemap');
}
} # end SCOPE

push @tm, 'typemap';

return @tm;
}

=head2 C<trim_whitespace()>

Expand Down Expand Up @@ -245,18 +226,21 @@ sub valid_proto_string {

=item * Purpose

Process all typemap files.
Process all typemap files. Reads in any typemap files specified explicitly
with C<-typemap> switches or similar, plus any typemap files found in
standard locations relative to C<@INC> and the current directory.

=item * Arguments

my $typemaps_object = process_typemaps( $args{typemap}, $pwd );

List of two elements: C<typemap> element from C<%args>; current working
directory.
The first argument is the C<typemap> element from C<%args>; the second is
the current working directory (which is only needed for error messages).

=item * Return Value

Upon success, returns an L<ExtUtils::Typemaps> object.
Upon success, returns an L<ExtUtils::Typemaps> object which contains the
accumulated results of all processed typemap files.

=back

Expand All @@ -265,13 +249,13 @@ Upon success, returns an L<ExtUtils::Typemaps> object.
sub process_typemaps {
my ($tmap, $pwd) = @_;

my @tm = ref $tmap ? @{$tmap} : ($tmap);
my @tm = standard_typemap_locations( \@INC );

foreach my $typemap (@tm) {
my @explicit = ref $tmap ? @{$tmap} : ($tmap);
foreach my $typemap (@explicit) {
die "Can't find $typemap in $pwd\n" unless -r $typemap;
}

push @tm, standard_typemap_locations( \@INC );
push @tm, @explicit;

require ExtUtils::Typemaps;
my $typemap = ExtUtils::Typemaps->new;
Expand Down
32 changes: 23 additions & 9 deletions dist/ExtUtils-ParseXS/lib/ExtUtils/xsubpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,18 +67,31 @@ B<xsubpp> [B<-v>] [B<-except>] [B<-s pattern>] [B<-prototypes>] [B<-noversionche
This compiler is typically run by the makefiles created by L<ExtUtils::MakeMaker>
or by L<Module::Build> or other Perl module build tools.

I<xsubpp> is just a thin wrapper over C<ExtUtils::ParseXS>.

I<xsubpp> will compile XS code into C code by embedding the constructs
necessary to let C functions manipulate Perl values and creates the glue
necessary to let Perl access those functions. The compiler uses typemaps to
determine how to map C function parameters and variables to Perl values.
determine how to map C function parameters and variables to Perl values
and vice versa.

The compiler will search for typemap files called I<typemap>. It will use
the following search path to find typemaps and apply them in that order,
so later typemaps take precedence:

The compiler will search for typemap files called I<typemap>. It will use
the following search path to find default typemaps, with the rightmost
typemap taking precedence.
map("$_/ExtUtils/typemap", reverse @INC),

../../../typemap:../../typemap:../typemap:typemap
../../../../lib/ExtUtils/typemap
../../../../typemap
../../../lib/ExtUtils/typemap
../../../typemap
../../lib/ExtUtils/typemap
../../typemap
../lib/ExtUtils/typemap
../typemap
typemap

It will also use a default typemap installed as C<ExtUtils::typemap>.
any files specifed by -typemap

=head1 OPTIONS

Expand All @@ -97,9 +110,10 @@ Adds exception handling stubs to the C code.

=item B<-typemap typemap>

Indicates that a user-supplied typemap should take precedence over the
default typemaps. This option may be used multiple times, with the last
typemap having the highest precedence.
Indicates that a user-supplied typemap should be applied in additon to any
files found in the standard search path. This option may be used multiple
times, with the last typemap having the highest precedence, and all such
files processed after ones found in the standard path.

=item B<-output filename>

Expand Down
51 changes: 40 additions & 11 deletions dist/ExtUtils-ParseXS/t/101-standard_typemap_locations.t
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/perl
use strict;
use warnings;
use Test::More tests => 3;
use Test::More tests => 5;
use ExtUtils::ParseXS::Utilities qw(
standard_typemap_locations
);
Expand All @@ -17,21 +17,50 @@ use ExtUtils::ParseXS::Utilities qw(
1
unless @stl > 9;

# We check only as many location entries from the start of the array
# (where the @INC-related entries are) as there are entries from @INC.
# We manage to do that by stopping when we find the "updir" related
# entries, which we assume is never contained in a default @INC entry.
my $updir = File::Spec->updir;
# Check that at least one typemap file can be found under @INC
my $max = $#INC;
$max = $#stl if $#stl < $max;
foreach my $i (0.. $max) {
$max = $i, last if $stl[$i] =~ /\Q$updir\E/;
}

ok(
( 0 < (grep -f $_, @stl[0..$max]) ),
"At least one typemap file exists underneath \@INC directories"
);
}
}

{
my @fake_INC = qw(a/b/c d/e/f /g/h/i);
my @expected =
(
map("$_/ExtUtils/typemap", reverse @fake_INC),
qw(
../../../../lib/ExtUtils/typemap
../../../../typemap
../../../lib/ExtUtils/typemap
../../../typemap
../../lib/ExtUtils/typemap
../../typemap
../lib/ExtUtils/typemap
../typemap
typemap
)
);

my @stl = standard_typemap_locations( \@fake_INC );

is(scalar @stl, scalar @expected,
"with fake INC: corrrect number of entries in typemap locations list" );

SKIP: {
# Only do a full string comparison on platforms which handle
# "standard" pathname formats and '..' updirs. We *always* test
# on linux, and otherwise test unless the second from last doesn't
# look standard. Always testing on Linux means there is at least
# one platform that won't falsely skip the test if garbage is
# returned.
skip "platform doesn't use ../..", 1
if $^O ne 'linux'
and $stl[-2] ne '../typemap';

is_deeply(\@stl, \@expected, "with fake INC: list of paths match");
}
}

19 changes: 18 additions & 1 deletion dist/ExtUtils-ParseXS/t/106-process_typemaps.t
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ use warnings;
use Carp;
use Cwd qw(cwd);
use File::Temp qw( tempdir );
use Test::More tests => 2;
use File::Spec;
use Test::More tests => 6;
use ExtUtils::ParseXS::Utilities qw(
process_typemaps
);
Expand Down Expand Up @@ -41,3 +42,19 @@ my $startdir = cwd();
chdir $startdir;
}

# Confirm that explicit typemaps via -typemap etc override standard
# entries.

{
my $tm_obj = process_typemaps(
[ File::Spec->catfile("t", "data", "conflicting.typemap") ], '.');
ok($tm_obj, "got typemap object");

my $tm_entry = $tm_obj->get_typemap(ctype => 'double');
ok($tm_entry, "got typemap entry object");

my $xs = $tm_entry->xstype;
ok($xs, "got typemap XS type");
# should be overridden from T_NV
is($xs, "T_DIFFERENT", "got typemap XS type");
}
10 changes: 7 additions & 3 deletions dist/ExtUtils-ParseXS/t/600-t-compat.t
Original file line number Diff line number Diff line change
Expand Up @@ -97,16 +97,20 @@ foreach my $test (@tests) {
# typemap-parsing/handling code in ExtUtils::ParseXS looked like. For
# bug-compatibility, we want to produce the same data structures as that
# code as much as possible.
# Except in 2025 the ordering was changed so that local files via -typemap
# are now processed afterwards; the order has been changed here to reflect
# that change.
sub _process_typemaps {
my ($tmap, $pwd) = @_;

my @tm = ref $tmap ? @{$tmap} : ($tmap);
my @tm = standard_typemap_locations( \@INC );

foreach my $typemap (@tm) {
my @explicit = ref $tmap ? @{$tmap} : ($tmap);
foreach my $typemap (@explicit) {
die "Can't find $typemap in $pwd\n" unless -r $typemap;
}
push @tm, @explicit;

push @tm, standard_typemap_locations( \@INC );

my ($type_kind_ref, $proto_letter_ref, $input_expr_ref, $output_expr_ref)
= ( {}, {}, {}, {} );
Expand Down
8 changes: 8 additions & 0 deletions pod/perldelta.pod
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,14 @@ means it now requires a scalar argument, not a list, just like C<CORE::sleep>:
# Evaluates @t in scalar context (giving the number of elements)
# and sleeps for one second. It used to sleep for 42 seconds.

=item *

L<ExtUtils::ParseXS> has been upgraded from version 3.59 to 3.60. This
release changes the ordering of the processing of typemap files which have
been specified via C<xsubpp -typemap> arguments so that (as was the case
prior to Perl 5.10.0) these files are applied last rather than first, and
thus take priority over any system typemap files.

=back

=head2 Removed Modules and Pragmata
Expand Down
Loading