1package ExtUtils::Typemaps::Cmd; 2use 5.006001; 3use strict; 4use warnings; 5our $VERSION = '3.51'; 6 7use ExtUtils::Typemaps; 8 9require Exporter; 10 11our @ISA = qw(Exporter); 12our @EXPORT = qw(embeddable_typemap); 13our %EXPORT_TAGS = (all => \@EXPORT); 14 15sub embeddable_typemap { 16 my @tms = @_; 17 18 # Get typemap objects 19 my @tm_objs = map [$_, _intuit_typemap_source($_)], @tms; 20 21 # merge or short-circuit 22 my $final_tm; 23 if (@tm_objs == 1) { 24 # just one, merge would be pointless 25 $final_tm = shift(@tm_objs)->[1]; 26 } 27 else { 28 # multiple, need merge 29 $final_tm = ExtUtils::Typemaps->new; 30 foreach my $other_tm (@tm_objs) { 31 my ($tm_ident, $tm_obj) = @$other_tm; 32 eval { 33 $final_tm->merge(typemap => $tm_obj); 34 1 35 } or do { 36 my $err = $@ || 'Zombie error'; 37 die "Failed to merge typ"; 38 } 39 } 40 } 41 42 # stringify for embedding 43 return $final_tm->as_embedded_typemap(); 44} 45 46sub _load_module { 47 my $name = shift; 48 return eval "require $name; 1"; 49} 50 51SCOPE: { 52 my %sources = ( 53 module => sub { 54 my $ident = shift; 55 my $tm; 56 if (/::/) { # looks like FQ module name, try that first 57 foreach my $module ($ident, "ExtUtils::Typemaps::$ident") { 58 if (_load_module($module)) { 59 eval { $tm = $module->new } 60 and return $tm; 61 } 62 } 63 } 64 else { 65 foreach my $module ("ExtUtils::Typemaps::$ident", "$ident") { 66 if (_load_module($module)) { 67 eval { $tm = $module->new } 68 and return $tm; 69 } 70 } 71 } 72 return(); 73 }, 74 file => sub { 75 my $ident = shift; 76 return unless -e $ident and -r _; 77 return ExtUtils::Typemaps->new(file => $ident); 78 }, 79 ); 80 # Try to find typemap either from module or file 81 sub _intuit_typemap_source { 82 my $identifier = shift; 83 84 my @locate_attempts; 85 if ($identifier =~ /::/ || $identifier !~ /[^\w_]/) { 86 @locate_attempts = qw(module file); 87 } 88 else { 89 @locate_attempts = qw(file module); 90 } 91 92 foreach my $source (@locate_attempts) { 93 my $tm = $sources{$source}->($identifier); 94 return $tm if defined $tm; 95 } 96 97 die "Unable to find typemap for '$identifier': " 98 . "Tried to load both as file or module and failed.\n"; 99 } 100} # end SCOPE 101 102=head1 NAME 103 104ExtUtils::Typemaps::Cmd - Quick commands for handling typemaps 105 106=head1 SYNOPSIS 107 108From XS: 109 110 INCLUDE_COMMAND: $^X -MExtUtils::Typemaps::Cmd \ 111 -e "print embeddable_typemap(q{Excommunicated})" 112 113Loads C<ExtUtils::Typemaps::Excommunicated>, instantiates an object, 114and dumps it as an embeddable typemap for use directly in your XS file. 115 116=head1 DESCRIPTION 117 118This is a helper module for L<ExtUtils::Typemaps> for quick 119one-liners, specifically for inclusion of shared typemaps 120that live on CPAN into an XS file (see SYNOPSIS). 121 122For this reason, the following functions are exported by default: 123 124=head1 EXPORTED FUNCTIONS 125 126=head2 embeddable_typemap 127 128Given a list of identifiers, C<embeddable_typemap> 129tries to load typemaps from a file of the given name(s), 130or from a module that is an C<ExtUtils::Typemaps> subclass. 131 132Returns a string representation of the merged typemaps that can 133be included verbatim into XS. Example: 134 135 print embeddable_typemap( 136 "Excommunicated", "ExtUtils::Typemaps::Basic", "./typemap" 137 ); 138 139This will try to load a module C<ExtUtils::Typemaps::Excommunicated> 140and use it as an C<ExtUtils::Typemaps> subclass. If that fails, it'll 141try loading C<Excommunicated> as a module, if that fails, it'll try to 142read a file called F<Excommunicated>. It'll work similarly for the 143second argument, but the third will be loaded as a file first. 144 145After loading all typemap files or modules, it will merge them in the 146specified order and dump the result as an embeddable typemap. 147 148=head1 SEE ALSO 149 150L<ExtUtils::Typemaps> 151 152L<perlxs> 153 154=head1 AUTHOR 155 156Steffen Mueller C<<smueller@cpan.org>> 157 158=head1 COPYRIGHT & LICENSE 159 160Copyright 2012 Steffen Mueller 161 162This program is free software; you can redistribute it and/or 163modify it under the same terms as Perl itself. 164 165=cut 166 1671; 168 169